merge/upstream-full #105

Manually merged
jabber.developer merged 407 commits from merge/upstream-full into master 2026-05-26 17:54:34 +00:00
320 changed files with 10541 additions and 30728 deletions
Showing only changes of commit 9cb11bdec2 - Show all commits

View File

@@ -296,15 +296,15 @@ tests_unittests_unittests_LDADD = -lcmocka
# https://github.com/profanity-im/stabber/issues/5
# Once this issue is resolved functional tests should be enabled again
#
#if HAVE_STABBER
#if HAVE_EXPECT
#TESTS += tests/functionaltests/functionaltests
#check_PROGRAMS += tests/functionaltests/functionaltests
#tests_functionaltests_functionaltests_SOURCES = $(functionaltest_sources)
#tests_functionaltests_functionaltests_CFLAGS = $(AM_CFLAGS) -I/usr/include/tcl8.6 -I/usr/include/tcl8.5
#tests_functionaltests_functionaltests_LDADD = -lcmocka -lstabber -lexpect
#endif
#endif
if HAVE_STABBER
if HAVE_UTIL
TESTS += tests/functionaltests/functionaltests
check_PROGRAMS += tests/functionaltests/functionaltests
tests_functionaltests_functionaltests_SOURCES = $(functionaltest_sources)
tests_functionaltests_functionaltests_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/tests
tests_functionaltests_functionaltests_LDADD = -lcmocka -lstabber -lutil
endif
endif
man1_MANS = $(man1_sources)

View File

@@ -391,9 +391,9 @@ PKG_CHECK_MODULES([cmocka], [cmocka], [],
AM_CONDITIONAL([HAVE_STABBER], [false])
AC_CHECK_LIB([stabber], [stbbr_start], [AM_CONDITIONAL([HAVE_STABBER], [true])],
[AC_MSG_NOTICE([libstabber not found, will not be able to run functional tests])])
AM_CONDITIONAL([HAVE_EXPECT], [false])
AC_CHECK_LIB([expect], [exp_expectl], [AM_CONDITIONAL([HAVE_EXPECT], [true])],
[AC_MSG_NOTICE([libexpect not found, will not be able to run functional tests])])
AM_CONDITIONAL([HAVE_UTIL], [false])
AC_CHECK_LIB([util], [forkpty], [AM_CONDITIONAL([HAVE_UTIL], [true])],
[AC_MSG_NOTICE([libutil not found, will not be able to run functional tests])])
## Default parameters
AM_CFLAGS="$AM_CFLAGS -Wall -Wno-deprecated-declarations -std=gnu99 -ggdb3"

View File

@@ -160,6 +160,10 @@ libsignal_dep = disabler()
gcrypt_dep = disabler()
qrencode_dep = disabler()
# Dependencies for functional tests
stabber_dep = cc.find_library('stabber', required: false)
util_dep = cc.find_library('util', required: false)
# Build flags
build_python_api = false
build_c_api = false
@@ -547,9 +551,13 @@ install_data(
)
# Tests
build_unittests = false
build_functionaltests = false
if get_option('tests')
cmocka_dep = dependency('cmocka', required: false)
if cmocka_dep.found()
build_unittests = true
unittest_sources = files(
'src/xmpp/contact.c',
'src/common.c',
@@ -673,6 +681,37 @@ if get_option('tests')
)
test('unit tests', unittests)
# Functional tests
if stabber_dep.found() and util_dep.found()
build_functionaltests = true
functionaltest_sources = files(
'tests/functionaltests/proftest.c',
'tests/functionaltests/test_connect.c',
'tests/functionaltests/test_ping.c',
'tests/functionaltests/test_rooms.c',
'tests/functionaltests/test_presence.c',
'tests/functionaltests/test_message.c',
'tests/functionaltests/test_chat_session.c',
'tests/functionaltests/test_carbons.c',
'tests/functionaltests/test_receipts.c',
'tests/functionaltests/test_roster.c',
'tests/functionaltests/test_software.c',
'tests/functionaltests/test_muc.c',
'tests/functionaltests/test_disconnect.c',
'tests/functionaltests/functionaltests.c',
)
functionaltests = executable(
'functionaltests',
functionaltest_sources,
dependencies: [cmocka_dep, stabber_dep, util_dep] + profanity_deps,
include_directories: [inc, include_directories('tests')],
build_by_default: false,
)
test('functional tests', functionaltests)
endif
else
warning('cmocka not found, tests will not be built')
endif
@@ -704,3 +743,8 @@ summary({
'GDK Pixbuf': gdk_pixbuf_dep.found(),
'QR Code': qrencode_dep.found(),
}, section: 'Features')
summary({
'Unit tests': build_unittests,
'Functional tests': build_functionaltests,
}, section: 'Testing')

View File

@@ -8,17 +8,115 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pty.h>
#include <utmp.h>
#include <poll.h>
#include <stdarg.h>
#include <termios.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"
int prof_expect_timeout = 10;
int prof_pid = 0;
char* config_orig;
char* data_orig;
int current_port = 5230;
int fd = 0;
static GString* accumulated_output = NULL;
int
prof_expect(int fd, ...)
{
va_list args;
va_start(args, fd);
enum prof_expect_type type = va_arg(args, enum prof_expect_type);
if (type == prof_expect_end) {
va_end(args);
return 0;
}
char* pattern = va_arg(args, char*);
int result_val = va_arg(args, int);
va_end(args);
if (accumulated_output == NULL) {
accumulated_output = g_string_new("");
}
usleep(1000 * 100); // Wait 100ms for buffer to settle
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
GRegex *ansi = g_regex_new("\\x1b\\[[0-9;]*[a-zA-Z]|\\x1b\\([a-zA-Z]", 0, 0, NULL);
GTimer* timer = g_timer_new();
while (g_timer_elapsed(timer, NULL) < prof_expect_timeout) {
// Check if pattern is already in accumulated output
gchar* clean_output = g_regex_replace(ansi, accumulated_output->str, -1, 0, "", 0, NULL);
if (type == prof_expect_exact) {
gchar* escaped = g_regex_escape_string(pattern, -1);
GRegex *regex = g_regex_new(escaped, G_REGEX_DOTALL | G_REGEX_OPTIMIZE, 0, NULL);
g_free(escaped);
GMatchInfo *match_info;
if (g_regex_match(regex, clean_output, 0, &match_info)) {
g_string_truncate(accumulated_output, 0);
g_match_info_free(match_info);
g_regex_unref(regex);
g_free(clean_output);
g_timer_destroy(timer);
g_regex_unref(ansi);
return result_val;
}
g_match_info_free(match_info);
g_regex_unref(regex);
} else if (type == prof_expect_regexp) {
GMatchInfo *match_info;
GRegex *regex = g_regex_new(pattern, G_REGEX_DOTALL | G_REGEX_OPTIMIZE, 0, NULL);
if (g_regex_match(regex, clean_output, 0, &match_info)) {
g_string_truncate(accumulated_output, 0);
g_match_info_free(match_info);
g_regex_unref(regex);
g_free(clean_output);
g_timer_destroy(timer);
g_regex_unref(ansi);
return result_val;
}
g_match_info_free(match_info);
g_regex_unref(regex);
}
g_free(clean_output);
int ret = poll(&pfd, 1, 10); // 10ms timeout for poll
if (ret > 0 && (pfd.revents & POLLIN)) {
char buf[1024];
ssize_t n = read(fd, buf, sizeof(buf) - 1);
if (n > 0) {
buf[n] = '\0';
g_string_append(accumulated_output, buf);
} else if (n == 0) {
break; // EOF
}
} else {
usleep(1000 * 5); // 5ms sleep if no data
}
}
g_timer_destroy(timer);
g_regex_unref(ansi);
return 0; // Timeout or EOF without match
}
gboolean
_create_dir(const char* name)
{
@@ -112,22 +210,29 @@ _create_logs_dir(void)
void
_cleanup_dirs(void)
{
int res = system("rm -rf ./tests/functionaltests/files");
if (res == -1) {
assert_true(FALSE);
}
system("rm -rf ./tests/functionaltests/files");
}
void
prof_start(void)
{
if (accumulated_output) {
g_string_free(accumulated_output, TRUE);
accumulated_output = NULL;
}
// helper script sets terminal columns, avoids assertions failing
// based on the test runner terminal size
fd = exp_spawnl("sh",
"sh",
"-c",
"./tests/functionaltests/start_profanity.sh",
NULL);
int master;
pid_t pid = forkpty(&master, NULL, NULL, NULL);
if (pid == 0) {
system("stty sane -echo");
execlp("sh", "sh", "-c", "./tests/functionaltests/start_profanity.sh", (char *)0);
_exit(1);
}
prof_pid = pid;
fd = master;
FILE* fp = fdopen(fd, "r+");
assert_true(fp != NULL);
@@ -138,17 +243,32 @@ prof_start(void)
int
init_prof_test(void** state)
{
if (stbbr_start(STBBR_LOGDEBUG, 5230, 0) != 0) {
assert_true(FALSE);
return -1;
}
config_orig = getenv("XDG_CONFIG_HOME");
data_orig = getenv("XDG_DATA_HOME");
const char *cfg = getenv("XDG_CONFIG_HOME");
const char *dat = getenv("XDG_DATA_HOME");
config_orig = cfg ? g_strdup(cfg) : NULL;
data_orig = dat ? g_strdup(dat) : NULL;
setenv("XDG_CONFIG_HOME", XDG_CONFIG_HOME, 1);
setenv("XDG_DATA_HOME", XDG_DATA_HOME, 1);
usleep(1000 * 2000); // 2s delay between tests to let OS recover
int res = -1;
int port = 0;
for (int i = 0; i < 5; i++) {
port = current_port + (i * 10);
res = stbbr_start(STBBR_LOGDEBUG, &port, 0);
if (res == 0 && port > 0) {
break;
}
}
if (res != 0 || port == 0) {
assert_true(FALSE);
return -1;
}
current_port = port;
_cleanup_dirs();
_create_config_dir();
@@ -157,36 +277,39 @@ init_prof_test(void** state)
_create_logs_dir();
prof_start();
assert_true(prof_output_exact("Profanity"));
usleep(1000 * 500); // Wait for profanity to start
assert_true(prof_output_regex("Profanity"));
prof_expect_timeout = 30;
// set UI options to make expect assertions faster and more reliable
prof_input("/inpblock timeout 5");
assert_true(prof_output_exact("Input blocking set to 5 milliseconds"));
prof_output_regex("Input blocking set to 5 milliseconds");
prof_input("/inpblock dynamic off");
assert_true(prof_output_exact("Dynamic input blocking disabled"));
prof_output_regex("Dynamic input blocking disabled");
prof_input("/notify chat off");
assert_true(prof_output_exact("Chat notifications disabled"));
prof_output_regex("Chat notifications disabled");
prof_input("/notify room off");
assert_true(prof_output_exact("Room notifications disabled"));
prof_output_regex("Room notifications disabled");
prof_input("/wrap off");
assert_true(prof_output_exact("Word wrap disabled"));
prof_output_regex("Word wrap disabled");
prof_input("/roster hide");
assert_true(prof_output_exact("Roster disabled"));
prof_output_regex("Roster disabled");
prof_input("/occupants default hide");
assert_true(prof_output_exact("Occupant list disabled"));
prof_output_regex("Occupant list disabled");
prof_input("/time console off");
prof_input("/time console off");
assert_true(prof_output_exact("Console time display disabled."));
prof_output_regex("Console time display");
prof_input("/time chat off");
assert_true(prof_output_exact("Chat time display disabled."));
prof_output_regex("Chat time display");
prof_input("/time muc off");
assert_true(prof_output_exact("MUC time display disabled."));
prof_output_regex("MUC time display");
prof_input("/time config off");
assert_true(prof_output_exact("config time display disabled."));
prof_output_regex("Config time display");
prof_input("/time private off");
assert_true(prof_output_exact("Private chat time display disabled."));
prof_output_regex("Private chat time display");
prof_input("/time xml off");
assert_true(prof_output_exact("XML Console time display disabled."));
prof_output_regex("XML Console time display");
prof_expect_timeout = 10;
return 0;
}
@@ -194,13 +317,44 @@ int
close_prof_test(void** state)
{
prof_input("/quit");
waitpid(exp_pid, NULL, 0);
// Give it some time to quit gracefully
int retries = 0;
int status;
while (retries < 50) { // 5 seconds
pid_t res = waitpid(prof_pid, &status, WNOHANG);
if (res == prof_pid) {
break;
}
usleep(1000 * 100);
retries++;
}
if (retries == 50) {
kill(prof_pid, SIGKILL);
waitpid(prof_pid, &status, 0);
}
_cleanup_dirs();
setenv("XDG_CONFIG_HOME", config_orig, 1);
setenv("XDG_DATA_HOME", data_orig, 1);
if (config_orig) {
setenv("XDG_CONFIG_HOME", config_orig, 1);
g_free(config_orig);
config_orig = NULL;
} else {
unsetenv("XDG_CONFIG_HOME");
}
if (data_orig) {
setenv("XDG_DATA_HOME", data_orig, 1);
g_free(data_orig);
data_orig = NULL;
} else {
unsetenv("XDG_DATA_HOME");
}
stbbr_stop();
usleep(1000 * 500); // 500ms delay after stop
return 0;
}
@@ -208,21 +362,32 @@ void
prof_input(const char* input)
{
GString* inp_str = g_string_new(input);
g_string_append(inp_str, "\r");
g_string_append(inp_str, "\n");
write(fd, inp_str->str, inp_str->len);
tcdrain(fd);
g_string_free(inp_str, TRUE);
usleep(1000 * 100); // 100ms delay
}
int
prof_output_exact(const char* text)
{
return (1 == exp_expectl(fd, exp_exact, text, 1, exp_end));
// Use regex to skip potential timestamps [HH:MM:SS] or character noise
gchar* pattern = g_strdup_printf(".*%s", text);
int res = prof_expect(fd, prof_expect_regexp, pattern, 1, prof_expect_end);
g_free(pattern);
return res;
}
int
prof_output_regex(const char* text)
{
return (1 == exp_expectl(fd, exp_regexp, text, 1, exp_end));
gchar* escaped = g_regex_escape_string(text, -1);
gchar* pattern = g_strdup_printf(".*%s", escaped);
int res = prof_expect(fd, prof_expect_regexp, pattern, 1, prof_expect_end);
g_free(pattern);
g_free(escaped);
return res;
}
void
@@ -239,32 +404,39 @@ prof_connect_with_roster(const char* roster)
stbbr_for_query("jabber:iq:roster", roster_str->str);
g_string_free(roster_str, TRUE);
stbbr_for_id("prof_presence_1",
"<presence id='prof_presence_1' lang='en' to='stabber@localhost/profanity' from='stabber@localhost/profanity'>"
stbbr_for_id("presence:*",
"<presence id='prof_presence_*' lang='en' to='stabber@localhost/profanity' from='stabber@localhost/profanity'>"
"<priority>0</priority>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io/' ver='f8mrtdyAmhnj8Ca+630bThSL718='/>"
"</presence>");
prof_input("/connect stabber@localhost server 127.0.0.1 port 5230 tls allow");
int port = current_port;
gchar* connect_cmd = g_strdup_printf("/connect stabber@localhost/profanity server 127.0.0.1 port %d tls disable auth legacy", port);
prof_input(connect_cmd);
g_free(connect_cmd);
assert_true(prof_output_regex("Enter password:"));
usleep(1000 * 200); // 200ms delay
prof_input("password");
usleep(1000 * 200); // 200ms delay
// Allow time for profanity to connect
exp_timeout = 30;
assert_true(prof_output_regex("stabber@localhost/profanity logged in successfully, .+online.+ \\(priority 0\\)\\."));
exp_timeout = 10;
stbbr_wait_for("prof_presence_*");
prof_expect_timeout = 30;
assert_true(prof_output_regex("successfully"));
prof_expect_timeout = 10;
stbbr_wait_for("presence:*");
}
void
prof_timeout(int timeout)
{
exp_timeout = timeout;
prof_expect_timeout = timeout;
}
void
prof_timeout_reset(void)
{
exp_timeout = 10;
prof_expect_timeout = 10;
}
void

View File

@@ -4,6 +4,15 @@
#define XDG_CONFIG_HOME "./tests/functionaltests/files/xdg_config_home"
#define XDG_DATA_HOME "./tests/functionaltests/files/xdg_data_home"
enum prof_expect_type {
prof_expect_end = 0,
prof_expect_exact,
prof_expect_regexp
};
extern int prof_expect_timeout;
extern int prof_pid;
int init_prof_test(void** state);
int close_prof_test(void** state);
@@ -18,4 +27,6 @@ int prof_output_regex(const char* text);
void prof_timeout(int timeout);
void prof_timeout_reset(void);
int prof_expect(int fd, ...);
#endif

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"
@@ -73,8 +72,8 @@ shows_role_and_affiliation_on_join(void** state)
{
prof_connect();
stbbr_for_id("prof_join_4",
"<presence id='prof_join_4' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
stbbr_for_id("prof_join_*",
"<presence id='prof_join_*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
@@ -92,8 +91,8 @@ shows_subject_on_join(void** state)
{
prof_connect();
stbbr_for_id("prof_join_4",
"<presence id='prof_join_4' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
stbbr_for_id("prof_join_*",
"<presence id='prof_join_*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
@@ -118,8 +117,8 @@ shows_history_message(void** state)
{
prof_connect();
stbbr_for_id("prof_join_4",
"<presence id='prof_join_4' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
stbbr_for_id("prof_join_*",
"<presence id='prof_join_*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
@@ -145,8 +144,8 @@ shows_occupant_join(void** state)
{
prof_connect();
stbbr_for_id("prof_join_4",
"<presence id='prof_join_4' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
stbbr_for_id("prof_join_*",
"<presence id='prof_join_*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
@@ -172,8 +171,8 @@ shows_message(void** state)
{
prof_connect();
stbbr_for_id("prof_join_4",
"<presence id='prof_join_4' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
stbbr_for_id("prof_join_*",
"<presence id='prof_join_*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
@@ -197,8 +196,8 @@ shows_me_message_from_occupant(void** state)
{
prof_connect();
stbbr_for_id("prof_join_4",
"<presence id='prof_join_4' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
stbbr_for_id("prof_join_*",
"<presence id='prof_join_*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
@@ -222,8 +221,8 @@ shows_me_message_from_self(void** state)
{
prof_connect();
stbbr_for_id("prof_join_4",
"<presence id='prof_join_4' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
stbbr_for_id("prof_join_*",
"<presence id='prof_join_*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
@@ -247,8 +246,8 @@ shows_all_messages_in_console_when_window_not_focussed(void** state)
{
prof_connect();
stbbr_for_id("prof_join_4",
"<presence id='prof_join_4' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
stbbr_for_id("prof_join_*",
"<presence id='prof_join_*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
@@ -285,8 +284,8 @@ shows_first_message_in_console_when_window_not_focussed(void** state)
prof_input("/console muc first");
assert_true(prof_output_exact("Console MUC messages set: first"));
stbbr_for_id("prof_join_4",
"<presence id='prof_join_4' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
stbbr_for_id("prof_join_*",
"<presence id='prof_join_*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
@@ -328,8 +327,8 @@ shows_no_message_in_console_when_window_not_focussed(void** state)
prof_input("/console muc none");
assert_true(prof_output_exact("Console MUC messages set: none"));
stbbr_for_id("prof_join_4",
"<presence id='prof_join_4' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
stbbr_for_id("prof_join_*",
"<presence id='prof_join_*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"

View File

@@ -4,38 +4,37 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"
void
ping_server(void** state)
{
stbbr_for_id("prof_disco_info_onconnect_2",
"<iq id='prof_disco_info_onconnect_2' to='stabber@localhost/profanity' type='result' from='localhost'>"
stbbr_for_id("prof_disco_info_onconnect_*",
"<iq id='prof_disco_info_onconnect_*' to='stabber@localhost/profanity' type='result' from='localhost'>"
"<query xmlns='http://jabber.org/protocol/disco#info'>"
"<identity category='server' type='im' name='Prosody'/>"
"<feature var='urn:xmpp:ping'/>"
"</query>"
"</iq>");
stbbr_for_id("prof_ping_4",
"<iq id='prof_ping_4' type='result' to='stabber@localhost/profanity'/>");
stbbr_for_id("prof_ping_5",
"<iq id='prof_ping_5' type='result' to='stabber@localhost/profanity'/>");
stbbr_for_id("prof_ping_*",
"<iq id='prof_ping_*' type='result' to='stabber@localhost/profanity'/>");
stbbr_for_id("prof_ping_*",
"<iq id='prof_ping_*' type='result' to='stabber@localhost/profanity'/>");
prof_connect();
prof_input("/ping");
assert_true(stbbr_received(
"<iq id='prof_ping_4' type='get'>"
"<iq id='prof_ping_*' type='get'>"
"<ping xmlns='urn:xmpp:ping'/>"
"</iq>"));
assert_true(prof_output_exact("Ping response from server"));
prof_input("/ping");
assert_true(stbbr_received(
"<iq id='prof_ping_5' type='get'>"
"<iq id='prof_ping_*' type='get'>"
"<ping xmlns='urn:xmpp:ping'/>"
"</iq>"));
assert_true(prof_output_exact("Ping response from server"));
@@ -44,8 +43,8 @@ ping_server(void** state)
void
ping_server_not_supported(void** state)
{
stbbr_for_id("prof_disco_info_onconnect_2",
"<iq id='prof_disco_info_onconnect_2' to='stabber@localhost/profanity' type='result' from='localhost'>"
stbbr_for_id("prof_disco_info_onconnect_*",
"<iq id='prof_disco_info_onconnect_*' to='stabber@localhost/profanity' type='result' from='localhost'>"
"<query xmlns='http://jabber.org/protocol/disco#info'>"
"<identity category='server' type='im' name='Stabber'/>"
"</query>"
@@ -74,8 +73,8 @@ ping_responds_to_server_request(void** state)
void
ping_jid(void** state)
{
stbbr_for_id("prof_caps_4",
"<iq id='prof_caps_4' to='stabber@localhost/profanity' type='result' from='buddy1@localhost/mobile'>"
stbbr_for_id("prof_caps_*",
"<iq id='prof_caps_*' to='stabber@localhost/profanity' type='result' from='buddy1@localhost/mobile'>"
"<query xmlns='http://jabber.org/protocol/disco#info' node='http://profanity-im.github.io#LpT2xs3nun7jC2sq4gg3WRDQFZ4='>"
"<identity category='client' type='console' name='Profanity0.6.0'/>"
"<feature var='urn:xmpp:ping'/>"
@@ -100,17 +99,17 @@ ping_jid(void** state)
assert_true(prof_output_exact("Buddy1 (mobile) is online, \"I'm here\""));
assert_true(stbbr_received(
"<iq id='prof_caps_4' to='buddy1@localhost/mobile' type='get'>"
"<iq id='prof_caps_*' to='buddy1@localhost/mobile' type='get'>"
"<query xmlns='http://jabber.org/protocol/disco#info' node='http://profanity-im.github.io#LpT2xs3nun7jC2sq4gg3WRDQFZ4='/>"
"</iq>"));
stbbr_for_id("prof_ping_5",
"<iq from='buddy1@localhost/mobile' to='stabber@localhost' id='prof_ping_5' type='result'/>");
stbbr_for_id("prof_ping_*",
"<iq from='buddy1@localhost/mobile' to='stabber@localhost' id='prof_ping_*' type='result'/>");
prof_input("/ping buddy1@localhost/mobile");
assert_true(stbbr_received(
"<iq id='prof_ping_5' type='get' to='buddy1@localhost/mobile'>"
"<iq id='prof_ping_*' type='get' to='buddy1@localhost/mobile'>"
"<ping xmlns='urn:xmpp:ping'/>"
"</iq>"));
assert_true(prof_output_exact("Ping response from buddy1@localhost/mobile"));
@@ -119,8 +118,8 @@ ping_jid(void** state)
void
ping_jid_not_supported(void** state)
{
stbbr_for_id("prof_caps_4",
"<iq id='prof_caps_4' to='stabber@localhost/profanity' type='result' from='buddy1@localhost/mobile'>"
stbbr_for_id("prof_caps_*",
"<iq id='prof_caps_*' to='stabber@localhost/profanity' type='result' from='buddy1@localhost/mobile'>"
"<query xmlns='http://jabber.org/protocol/disco#info' node='http://profanity-im.github.io#LpT2xs3nun7jC2sq4gg3WRDQFZ4='>"
"<identity category='client' type='console' name='Profanity0.6.0'/>"
"<feature var='http://jabber.org/protocol/disco#info'/>"
@@ -144,7 +143,7 @@ ping_jid_not_supported(void** state)
assert_true(prof_output_exact("Buddy1 (mobile) is online, \"I'm here\""));
assert_true(stbbr_received(
"<iq id='prof_caps_4' to='buddy1@localhost/mobile' type='get'>"
"<iq id='prof_caps_*' to='buddy1@localhost/mobile' type='get'>"
"<query xmlns='http://jabber.org/protocol/disco#info' node='http://profanity-im.github.io#LpT2xs3nun7jC2sq4gg3WRDQFZ4='/>"
"</iq>"));

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"
@@ -16,7 +15,7 @@ presence_online(void** state)
prof_input("/online");
assert_true(stbbr_received(
"<presence id='prof_presence_3'>"
"<presence id='prof_presence_*'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"</presence>"));
@@ -31,7 +30,7 @@ presence_online_with_message(void** state)
prof_input("/online \"Hi there\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<status>Hi there</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"</presence>"));
@@ -47,7 +46,7 @@ presence_away(void** state)
prof_input("/away");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<show>away</show>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"</presence>"));
@@ -63,7 +62,7 @@ presence_away_with_message(void** state)
prof_input("/away \"I'm not here for a bit\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<show>away</show>"
"<status>I'm not here for a bit</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
@@ -80,7 +79,7 @@ presence_xa(void** state)
prof_input("/xa");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<show>xa</show>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"</presence>"));
@@ -96,7 +95,7 @@ presence_xa_with_message(void** state)
prof_input("/xa \"Gone to the shops\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<show>xa</show>"
"<status>Gone to the shops</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
@@ -113,7 +112,7 @@ presence_dnd(void** state)
prof_input("/dnd");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<show>dnd</show>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"</presence>"));
@@ -129,7 +128,7 @@ presence_dnd_with_message(void** state)
prof_input("/dnd \"Working\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<show>dnd</show>"
"<status>Working</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
@@ -146,7 +145,7 @@ presence_chat(void** state)
prof_input("/chat");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<show>chat</show>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"</presence>"));
@@ -162,7 +161,7 @@ presence_chat_with_message(void** state)
prof_input("/chat \"Free to talk\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<show>chat</show>"
"<status>Free to talk</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
@@ -179,7 +178,7 @@ presence_set_priority(void** state)
prof_input("/priority 25");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<priority>25</priority>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"</presence>"));
@@ -194,7 +193,7 @@ presence_includes_priority(void** state)
prof_input("/priority 25");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<priority>25</priority>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"</presence>"));
@@ -202,7 +201,7 @@ presence_includes_priority(void** state)
prof_input("/chat \"Free to talk\"");
assert_true(stbbr_received(
"<presence id='prof_presence_5'>"
"<presence id='prof_presence_*'>"
"<priority>25</priority>"
"<show>chat</show>"
"<status>Free to talk</status>"
@@ -218,7 +217,7 @@ presence_keeps_status(void** state)
prof_input("/chat \"Free to talk\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id='prof_presence_*'>"
"<show>chat</show>"
"<status>Free to talk</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
@@ -227,7 +226,7 @@ presence_keeps_status(void** state)
prof_input("/priority 25");
assert_true(stbbr_received(
"<presence id='prof_presence_5'>"
"<presence id='prof_presence_*'>"
"<show>chat</show>"
"<status>Free to talk</status>"
"<priority>25</priority>"

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"
@@ -30,8 +29,8 @@ send_receipt_request(void** state)
prof_connect();
stbbr_for_id("prof_caps_4",
"<iq from='buddy1@localhost/laptop' to='stabber@localhost' id='prof_caps_4' type='result'>"
stbbr_for_id("prof_caps_*",
"<iq from='buddy1@localhost/laptop' to='stabber@localhost' id='prof_caps_*' type='result'>"
"<query xmlns='http://jabber.org/protocol/disco#info' node='http://profanity-im.github.io#hAkb1xZdJV9BQpgGNw8zG5Xsals='>"
"<identity category='client' name='Profanity 0.5.0' type='console'/>"
"<feature var='urn:xmpp:receipts'/>"

View File

@@ -4,15 +4,14 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"
void
rooms_query(void** state)
{
stbbr_for_id("prof_confreq_4",
"<iq id='prof_confreq_4' type='result' to='stabber@localhost/profanity' from='conference.localhost'>"
stbbr_for_id("prof_confreq_*",
"<iq id='prof_confreq_*' type='result' to='stabber@localhost/profanity' from='conference.localhost'>"
"<query xmlns='http://jabber.org/protocol/disco#items'>"
"<item jid='chatroom@conference.localhost' name='A chat room'/>"
"<item jid='hangout@conference.localhost' name='Another chat room'/>"
@@ -27,7 +26,7 @@ rooms_query(void** state)
assert_true(prof_output_exact("hangout@conference.localhost (Another chat room)"));
assert_true(stbbr_last_received(
"<iq id='prof_confreq_4' to='conference.localhost' type='get'>"
"<iq id='prof_confreq_*' to='conference.localhost' type='get'>"
"<query xmlns='http://jabber.org/protocol/disco#items'/>"
"</iq>"));
}

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"