Merge pull request #2101 from profanity-im/functionaltests

Reenable functional tests
This commit is contained in:
Michael Vetter
2026-03-06 11:13:56 +01:00
committed by GitHub
22 changed files with 528 additions and 222 deletions

View File

@@ -171,6 +171,53 @@ When adding a new test file:
2. Register the test functions in `tests/unittests/unittests.c` within the `all_tests` array.
3. Add the new source file to `unittest_sources` in both `meson.build` and `Makefile.am`.
### Running functional tests
Functional tests use [stabber](https://github.com/profanity-im/stabber) to simulate an XMPP server.
**Performance Note:** It is highly recommended to run functional tests **without** sanitizers (**ASan** and **UBSan**). These sanitizers add significant overhead that can cause functional tests to time out or take an excessively long time to complete.
* **Meson:** Ensure `-Db_sanitize=none` is set in your build configuration. You can check your current configuration with `meson configure build_run | grep b_sanitize`.
* **Autotools:** Ensure your `CFLAGS` does not contain `-fsanitize=address` or `-fsanitize=undefined`.
To run functional tests, you need the same dependencies as unit tests (`cmocka`) plus `stabber` and `libutil`.
Functional tests will be automatically enabled if these dependencies are detected during configuration.
Using Meson:
1. Setup build directory: `meson setup build_run -Dtests=true` (check the summary to ensure "Functional tests" is `true`)
2. Compile and run all tests (unit and functional): `meson test -C build_run`
3. To run only functional tests: `meson test -C build_run "functional tests"`
4. To run manually: `./build_run/functionaltests`
5. To run a specific test manually: `CMOCKA_TEST_FILTER=test_name ./build_run/functionaltests` (use `./build_run/functionaltests --list` to see all available tests)
Using Autotools:
1. Configure: `./configure` (check the summary to ensure `cmocka`, `stabber` and `libutil` were found)
2. Build and run all tests: `make check`
3. To run manually: `./tests/functionaltests/functionaltests`
4. To run a specific test manually: `CMOCKA_TEST_FILTER=test_name ./tests/functionaltests/functionaltests`
### Writing functional tests
Functional tests simulate real world usage by running Profanity and interacting with it. They verify Profanitys responses to an XMPP server.
They are located in `tests/functionaltests/`.
#### Helper Functions
We provide a set of helper functions:
- `prof_input(const char* input)`: Sends a command or message to Profanity.
- `prof_output_regex(const char* regex)`: Verifies that Profanity's output matches the given regular expression.
- `prof_output_exact(const char* text)`: Verifies that Profanity's output exactly matches the given text.
- `prof_connect()`: Connects Profanity to the simulated stabber server.
- `stbbr_for_id(const char* id, const char* xml)`: Tells stabber to respond with `xml` when it receives a stanza with the given `id`.
- `stbbr_for_query(const char* xmlns, const char* xml): Tells the server to respond with xml whenever a query for a specific namespace is received.
To see the complete list check `proftest.h`.
#### Adding a new test
1. Create a new test file (`test_new_feature.c` and `test_new_feature.h`) in `tests/functionaltests/`.
2. Define your test functions using the `void test_name(void** state)` signature.
3. Use the `PROF_FUNC_TEST(test_name)` macro to register your test in `tests/functionaltests/functionaltests.c`. This macro automatically handles the setup (`init_prof_test`) and teardown (`close_prof_test`) for each test.
4. Add the new source file to `functionaltest_sources` in both `meson.build` and `Makefile.am`.
### Valgrind
We provide a suppressions file `prof.supp`. It is a combination of the suppressions for shipped with glib2, python and custom rules.

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

@@ -59,6 +59,7 @@ add_project_arguments([
'-Wno-unused-parameter',
], language: 'c')
analyzer_args = []
if is_debug
add_project_arguments([
'-ggdb3',
@@ -71,7 +72,7 @@ if is_debug
'-Wpointer-arith'
], language: 'c')
if cc.get_id() == 'gcc'
add_project_arguments('-fanalyzer', language: 'c')
analyzer_args += '-fanalyzer'
endif
endif
@@ -160,6 +161,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
@@ -497,6 +502,7 @@ profanity_exe = executable(
profanity_sources,
files('src/main.c'),
config_h,
c_args: analyzer_args,
dependencies: profanity_deps,
include_directories: inc,
install: true,
@@ -547,9 +553,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 +683,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, timeout: 1800)
endif
else
warning('cmocka not found, tests will not be built')
endif
@@ -704,3 +745,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

@@ -143,7 +143,7 @@ static const struct cmd_t command_defs[] = {
},
{ CMD_PREAMBLE("/connect",
parse_args, 0, 7, NULL)
parse_args, 0, 9, NULL)
CMD_MAINFUNC(cmd_connect)
CMD_TAGS(
CMD_TAG_CONNECTION)

View File

@@ -5290,6 +5290,9 @@ cmd_time(ProfWin* window, const char* const command, gchar** args)
cons_bad_cmd_usage(command);
return TRUE;
}
if (!set_all) {
break;
}
}
if (!set_all && n == ARRAY_SIZE(time_prefs)) {
cons_bad_cmd_usage(command);

View File

@@ -135,6 +135,10 @@ cl_ev_send_msg_correct(ProfChatWin* chatwin, const char* const msg, const char*
chat_state_active(chatwin->state);
gboolean request_receipt = prefs_get_boolean(PREF_RECEIPTS_REQUEST);
if (request_receipt) {
auto_char char* jid = chat_session_get_jid(chatwin->barejid);
request_receipt = caps_jid_has_feature(jid, XMPP_FEATURE_RECEIPTS);
}
auto_char char* plugin_msg = plugins_pre_chat_message_send(chatwin->barejid, msg);
const char* const message = plugin_msg ?: msg;

View File

@@ -8,17 +8,141 @@
#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;
GError *error = NULL;
GRegex *ansi = g_regex_new("\\x1b\\[[0-9;]*[a-zA-Z]|\\x1b\\([a-zA-Z]", 0, 0, &error);
if (error) {
g_error_free(error);
return 0;
}
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);
error = NULL;
GRegex *regex = g_regex_new(escaped, G_REGEX_DOTALL | G_REGEX_OPTIMIZE, 0, &error);
if (error) {
g_error_free(error);
g_free(escaped);
g_free(clean_output);
g_timer_destroy(timer);
g_regex_unref(ansi);
return 0;
}
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;
error = NULL;
GRegex *regex = g_regex_new(pattern, G_REGEX_DOTALL | G_REGEX_OPTIMIZE, 0, &error);
if (error) {
g_error_free(error);
g_free(clean_output);
g_timer_destroy(timer);
g_regex_unref(ansi);
return 0;
}
if (g_regex_match(regex, clean_output, 0, &match_info)) {
gint start_pos, end_pos;
g_match_info_fetch_pos(match_info, 0, &start_pos, &end_pos);
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,43 +236,59 @@ _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);
FILE* fp = fdopen(fd, "r+");
assert_true(fp != NULL);
setbuf(fp, (char*)0);
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;
}
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 +297,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
prof_expect_timeout = 30;
assert_true(prof_output_regex("Profanity"));
// 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 +337,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 +382,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* 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;
}
int
prof_output_regex(const char* text)
{
return (1 == exp_expectl(fd, exp_regexp, text, 1, exp_end));
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;
}
void
@@ -239,32 +424,40 @@ 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:*");
//usleep(1000 * 2000); // 2s delay
}
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

@@ -1,2 +1,7 @@
export COLUMNS=300
./profanity -l DEBUG
if [ -f "./build_run/profanity" ]; then
./build_run/profanity -l DEBUG
else
# Fallback for autotools
./profanity -l DEBUG
fi

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"
@@ -25,7 +24,6 @@ connect_with_carbons_enabled(void** state)
prof_input("/carbons on");
prof_connect();
assert_true(stbbr_received(
"<iq id='*' type='set'><enable xmlns='urn:xmpp:carbons:2'/></iq>"));
}
@@ -36,9 +34,10 @@ send_disable_carbons(void** state)
prof_input("/carbons on");
prof_connect();
assert_true(stbbr_received(
"<iq id='*' type='set'><enable xmlns='urn:xmpp:carbons:2'/></iq>"));
prof_input("/carbons off");
assert_true(stbbr_received(
"<iq id='*' type='set'><disable xmlns='urn:xmpp:carbons:2'/></iq>"));
}
@@ -47,6 +46,7 @@ void
receive_carbon(void** state)
{
prof_input("/carbons on");
stbbr_for_xmlns("urn:xmpp:carbons:2", "<iq type='result'/>");
prof_connect();
assert_true(stbbr_received(
@@ -65,20 +65,21 @@ receive_carbon(void** state)
"<message type='chat' to='stabber@localhost/profanity' from='stabber@localhost'>"
"<received xmlns='urn:xmpp:carbons:2'>"
"<forwarded xmlns='urn:xmpp:forward:0'>"
"<message id='prof_msg_7' xmlns='jabber:client' type='chat' lang='en' to='stabber@localhost/profanity' from='buddy1@localhost/mobile'>"
"<message id='*' xmlns='jabber:client' type='chat' lang='en' to='stabber@localhost/profanity' from='buddy1@localhost/mobile'>"
"<body>test carbon from recipient</body>"
"</message>"
"</forwarded>"
"</received>"
"</message>");
assert_true(prof_output_regex("Buddy1/mobile: .+test carbon from recipient"));
assert_true(prof_output_regex("Buddy1/mobile: test carbon from recipient"));
}
void
receive_self_carbon(void** state)
{
prof_input("/carbons on");
stbbr_for_xmlns("urn:xmpp:carbons:2", "<iq type='result'/>");
prof_connect();
assert_true(stbbr_received(
@@ -97,20 +98,21 @@ receive_self_carbon(void** state)
"<message type='chat' to='stabber@localhost/profanity' from='stabber@localhost'>"
"<sent xmlns='urn:xmpp:carbons:2'>"
"<forwarded xmlns='urn:xmpp:forward:0'>"
"<message id='59' xmlns='jabber:client' type='chat' to='buddy1@localhost/mobile' lang='en' from='stabber@localhost/profanity'>"
"<body>self sent carbon</body>"
"<message id='*' xmlns='jabber:client' type='chat' lang='en' to='buddy1@localhost/mobile' from='stabber@localhost/mobile'>"
"<body>test carbon from sender</body>"
"</message>"
"</forwarded>"
"</sent>"
"</message>");
assert_true(prof_output_regex("me: .+self sent carbon"));
assert_true(prof_output_regex("me: test carbon from sender"));
}
void
receive_private_carbon(void** state)
{
prof_input("/carbons on");
stbbr_for_xmlns("urn:xmpp:carbons:2", "<iq type='result'/>");
prof_connect();
assert_true(stbbr_received(
@@ -126,10 +128,16 @@ receive_private_carbon(void** state)
assert_true(prof_output_exact("unencrypted"));
stbbr_send(
"<message type='chat' to='stabber@localhost/profanity' from='buddy1@localhost/mobile'>"
"<message type='chat' to='stabber@localhost/profanity' from='stabber@localhost'>"
"<received xmlns='urn:xmpp:carbons:2'>"
"<forwarded xmlns='urn:xmpp:forward:0'>"
"<message id='*' xmlns='jabber:client' type='chat' lang='en' to='stabber@localhost/profanity' from='buddy1@localhost/mobile'>"
"<body>Private carbon</body>"
"<private xmlns='urn:xmpp:carbons:2'/>"
"</message>"
"</forwarded>"
"</received>"
"</message>");
assert_true(prof_output_regex("Buddy1/mobile: .+Private carbon"));
assert_true(prof_output_regex("Buddy1/mobile: Private carbon"));
}

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"
@@ -30,7 +29,7 @@ sends_message_to_barejid_when_contact_online(void** state)
"<presence to='stabber@localhost/profanity' from='buddy1@localhost/mobile'>"
"<priority>10</priority>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (mobile) is online"));
assert_true(prof_output_regex("Buddy1 \\(mobile\\) is online"));
prof_input("/msg buddy1@localhost Hi there");
@@ -49,13 +48,13 @@ sends_message_to_fulljid_when_received_from_fulljid(void** state)
"<presence to='stabber@localhost' from='buddy1@localhost/mobile'>"
"<priority>10</priority>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (mobile) is online"));
assert_true(prof_output_regex("Buddy1 \\(mobile\\) is online"));
stbbr_send(
"<message id='message1' to='stabber@localhost' from='buddy1@localhost/mobile' type='chat'>"
"<body>First message</body>"
"</message>");
assert_true(prof_output_exact("<< chat message: Buddy1/mobile (win 2)"));
assert_true(prof_output_regex("chat message: Buddy1/mobile \\(win 2\\)"));
prof_input("/msg buddy1@localhost Hi there");
@@ -74,13 +73,13 @@ sends_subsequent_messages_to_fulljid(void** state)
"<presence to='stabber@localhost' from='buddy1@localhost/mobile'>"
"<priority>10</priority>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (mobile) is online"));
assert_true(prof_output_regex("Buddy1 \\(mobile\\) is online"));
stbbr_send(
"<message id='message1' to='stabber@localhost' from='buddy1@localhost/mobile' type='chat'>"
"<body>First message</body>"
"</message>");
assert_true(prof_output_exact("<< chat message: Buddy1/mobile (win 2)"));
assert_true(prof_output_regex("chat message: Buddy1/mobile \\(win 2\\)"));
prof_input("/msg buddy1@localhost Outgoing 1");
assert_true(stbbr_received(
@@ -110,13 +109,13 @@ resets_to_barejid_after_presence_received(void** state)
"<presence to='stabber@localhost' from='buddy1@localhost/mobile'>"
"<priority>10</priority>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (mobile) is online"));
assert_true(prof_output_regex("Buddy1 \\(mobile\\) is online"));
stbbr_send(
"<message id='message1' to='stabber@localhost' from='buddy1@localhost/mobile' type='chat'>"
"<body>First message</body>"
"</message>");
assert_true(prof_output_exact("<< chat message: Buddy1/mobile (win 2)"));
assert_true(prof_output_regex("chat message: Buddy1/mobile \\(win 2\\)"));
prof_input("/msg buddy1@localhost Outgoing 1");
assert_true(stbbr_received(
@@ -124,12 +123,14 @@ resets_to_barejid_after_presence_received(void** state)
"<body>Outgoing 1</body>"
"</message>"));
prof_input("/presence chat all");
stbbr_send(
"<presence to='stabber@localhost' from='buddy1@localhost/laptop'>"
"<priority>5</priority>"
"<show>dnd</show>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (laptop) is dnd"));
assert_true(prof_output_regex("Buddy1 \\(laptop\\) is dnd"));
prof_input("/msg buddy1@localhost Outgoing 2");
assert_true(stbbr_received(
@@ -147,20 +148,20 @@ new_session_when_message_received_from_different_fulljid(void** state)
"<presence to='stabber@localhost' from='buddy1@localhost/mobile'>"
"<priority>10</priority>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (mobile) is online"));
assert_true(prof_output_regex("Buddy1 \\(mobile\\) is online"));
stbbr_send(
"<presence to='stabber@localhost' from='buddy1@localhost/laptop'>"
"<priority>8</priority>"
"<show>away</show>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (laptop) is away"));
assert_true(prof_output_regex("Buddy1 \\(laptop\\) is away"));
stbbr_send(
"<message id='message1' to='stabber@localhost' from='buddy1@localhost/mobile' type='chat'>"
"<body>From first resource</body>"
"</message>");
assert_true(prof_output_exact("<< chat message: Buddy1/mobile (win 2)"));
assert_true(prof_output_regex("chat message: Buddy1/mobile \\(win 2\\)"));
prof_input("/msg buddy1@localhost Outgoing 1");
assert_true(stbbr_received(

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"
@@ -60,26 +59,26 @@ connect_shows_presence_updates(void** state)
"<show>dnd</show>"
"<status>busy!</status>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (mobile) is dnd, \"busy!\""));
assert_true(prof_output_exact("++ Buddy1 (mobile) is dnd, \"busy!\""));
stbbr_send(
"<presence to='stabber@localhost' from='buddy1@localhost/laptop'>"
"<show>chat</show>"
"<status>Talk to me!</status>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (laptop) is chat, \"Talk to me!\""));
assert_true(prof_output_exact("++ Buddy1 (laptop) is chat, \"Talk to me!\""));
stbbr_send(
"<presence to='stabber@localhost' from='buddy2@localhost/work'>"
"<show>away</show>"
"<status>Out of office</status>"
"</presence>");
assert_true(prof_output_exact("Buddy2 (work) is away, \"Out of office\""));
assert_true(prof_output_exact("++ Buddy2 (work) is away, \"Out of office\""));
stbbr_send(
"<presence to='stabber@localhost' from='buddy1@localhost/mobile'>"
"<show>xa</show>"
"<status>Gone :(</status>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (mobile) is xa, \"Gone :(\""));
assert_true(prof_output_exact("++ Buddy1 (mobile) is xa, \"Gone :(\""));
}

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"
@@ -20,7 +19,7 @@ message_send(void** state)
"<body>Hi there</body>"
"</message>"));
assert_true(prof_output_regex("me: .+Hi there"));
assert_true(prof_output_exact("me: Hi there"));
}
void
@@ -42,12 +41,11 @@ message_receive_chatwin(void** state)
prof_connect();
prof_input("/msg someuser@chatserv.org");
assert_true(prof_output_exact("someuser@chatserv.org"));
stbbr_send(
"<message id='message1' to='stabber@localhost' from='someuser@chatserv.org/laptop' type='chat'>"
"<body>How are you?</body>"
"</message>");
assert_true(prof_output_regex("someuser@chatserv.org/laptop: .+How are you?"));
assert_true(prof_output_regex("someuser@chatserv.org/laptop: How are you\\?"));
}

View File

@@ -4,7 +4,6 @@
#include <string.h>
#include <stabber.h>
#include <expect.h>
#include "proftest.h"
@@ -15,10 +14,10 @@ sends_room_join(void** state)
prof_input("/join testroom@conference.localhost");
assert_true(stbbr_last_received(
"<presence id='*' to='testroom@conference.localhost/stabber'>"
"<x xmlns='http://jabber.org/protocol/muc'/>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
assert_true(stbbr_received(
"<presence id=\"*\" to=\"testroom@conference.localhost/stabber\">"
"<x xmlns=\"http://jabber.org/protocol/muc\"/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
}
@@ -29,10 +28,10 @@ sends_room_join_with_nick(void** state)
prof_input("/join testroom@conference.localhost nick testnick");
assert_true(stbbr_last_received(
"<presence id='*' to='testroom@conference.localhost/testnick'>"
"<x xmlns='http://jabber.org/protocol/muc'/>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
assert_true(stbbr_received(
"<presence id=\"*\" to=\"testroom@conference.localhost/testnick\">"
"<x xmlns=\"http://jabber.org/protocol/muc\"/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
}
@@ -43,12 +42,12 @@ sends_room_join_with_password(void** state)
prof_input("/join testroom@conference.localhost password testpassword");
assert_true(stbbr_last_received(
"<presence id='*' to='testroom@conference.localhost/stabber'>"
"<x xmlns='http://jabber.org/protocol/muc'>"
assert_true(stbbr_received(
"<presence id=\"*\" to=\"testroom@conference.localhost/stabber\">"
"<x xmlns=\"http://jabber.org/protocol/muc\">"
"<password>testpassword</password>"
"</x>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
}
@@ -59,12 +58,12 @@ sends_room_join_with_nick_and_password(void** state)
prof_input("/join testroom@conference.localhost nick testnick password testpassword");
assert_true(stbbr_last_received(
"<presence id='*' to='testroom@conference.localhost/testnick'>"
"<x xmlns='http://jabber.org/protocol/muc'>"
assert_true(stbbr_received(
"<presence id=\"*\" to=\"testroom@conference.localhost/testnick\">"
"<x xmlns=\"http://jabber.org/protocol/muc\">"
"<password>testpassword</password>"
"</x>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
}
@@ -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("presence:*",
"<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("presence:*",
"<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'/>"
@@ -110,7 +109,7 @@ shows_subject_on_join(void** state)
"<body>anothernick has set the subject to: Test room subject</body>"
"</message>");
assert_true(prof_output_regex("Room subject: .+Test room subject"));
assert_true(prof_output_exact("Room subject: Test room subject"));
}
void
@@ -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("presence:*",
"<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'/>"
@@ -137,16 +136,18 @@ shows_history_message(void** state)
"<x xmlns='jabber:x:delay' stamp='20151219T23:55:25'/>"
"</message>");
assert_true(prof_output_regex("testoccupant: an old message"));
assert_true(prof_output_exact("testoccupant: an old message"));
}
void
shows_occupant_join(void** state)
{
prof_connect();
prof_input("/presence room all");
assert_true(prof_output_exact("All presence updates will appear in chat room windows."));
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("presence:*",
"<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 +173,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("presence:*",
"<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'/>"
@@ -189,7 +190,7 @@ shows_message(void** state)
"<body>a new message</body>"
"</message>");
assert_true(prof_output_regex("testoccupant: .+a new message"));
assert_true(prof_output_exact("testoccupant: a new message"));
}
void
@@ -197,8 +198,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("presence:*",
"<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 +223,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("presence:*",
"<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 +248,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("presence:*",
"<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 +286,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("presence:*",
"<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'/>"
@@ -305,7 +306,7 @@ shows_first_message_in_console_when_window_not_focussed(void** state)
"<body>a new message</body>"
"</message>");
assert_true(prof_output_exact("<< room message: testroom@conference.localhost (win 2)"));
assert_true(prof_output_exact("<< room message: testoccupant in testroom@conference.localhost (win 2)"));
prof_input("/clear");
prof_input("/about");
assert_true(prof_output_exact("Type '/help' to show complete help."));
@@ -316,7 +317,7 @@ shows_first_message_in_console_when_window_not_focussed(void** state)
"</message>");
prof_timeout(2);
assert_false(prof_output_exact("<< room message: testroom@conference.localhost (win 2)"));
assert_false(prof_output_exact("<< room message: anotheroccupant in testroom@conference.localhost (win 2)"));
prof_timeout_reset();
}
@@ -328,8 +329,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("presence:*",
"<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,35 @@
#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_query("http://jabber.org/protocol/disco#info",
"<iq id='*' 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_xmlns("urn:xmpp:ping",
"<iq id='*' type='result' to='stabber@localhost/profanity'/>");
prof_connect();
prof_input("/ping");
assert_true(stbbr_received(
"<iq id='prof_ping_4' type='get'>"
"<iq id='*' 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='*' type='get'>"
"<ping xmlns='urn:xmpp:ping'/>"
"</iq>"));
assert_true(prof_output_exact("Ping response from server"));
@@ -44,8 +41,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_query("http://jabber.org/protocol/disco#info",
"<iq id='*' to='stabber@localhost/profanity' type='result' from='localhost'>"
"<query xmlns='http://jabber.org/protocol/disco#info'>"
"<identity category='server' type='im' name='Stabber'/>"
"</query>"
@@ -54,7 +51,7 @@ ping_server_not_supported(void** state)
prof_connect();
prof_input("/ping");
assert_true(prof_output_exact("Server does not support ping requests."));
assert_true(prof_output_exact("Server does not support ping requests (urn:xmpp:ping)."));
}
void
@@ -68,14 +65,14 @@ ping_responds_to_server_request(void** state)
"</iq>");
assert_true(stbbr_received(
"<iq id='pingtest1' type='result' from='stabber@localhost/profanity' to='localhost'/>"));
"<iq id='pingtest1' to='localhost' from='stabber@localhost/profanity' type='result'/>"));
}
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("*",
"<iq id='*' 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'/>"
@@ -84,6 +81,9 @@ ping_jid(void** state)
"</query>"
"</iq>");
stbbr_for_xmlns("urn:xmpp:ping",
"<iq id='*' type='result' from='buddy1@localhost/mobile' to='stabber@localhost/profanity'/>");
prof_connect();
stbbr_send(
@@ -97,20 +97,17 @@ ping_jid(void** state)
"ver='LpT2xs3nun7jC2sq4gg3WRDQFZ4='"
"/>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (mobile) is online, \"I'm here\""));
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='*' 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'/>");
prof_input("/ping buddy1@localhost/mobile");
assert_true(stbbr_received(
"<iq id='prof_ping_5' type='get' to='buddy1@localhost/mobile'>"
"<iq id='*' 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 +116,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("*",
"<iq id='*' 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'/>"
@@ -141,10 +138,10 @@ ping_jid_not_supported(void** state)
"ver='LpT2xs3nun7jC2sq4gg3WRDQFZ4='"
"/>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (mobile) is online, \"I'm here\""));
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='*' 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"
@@ -13,11 +12,11 @@ presence_online(void** state)
{
prof_connect();
prof_input("/online");
prof_input("/status set online");
assert_true(stbbr_received(
"<presence id='prof_presence_3'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<presence id=\"*\">"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to online (priority 0)"));
@@ -28,12 +27,12 @@ presence_online_with_message(void** state)
{
prof_connect();
prof_input("/online \"Hi there\"");
prof_input("/status set online \"Hi there\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<status>Hi there</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to online (priority 0), \"Hi there\"."));
@@ -44,12 +43,12 @@ presence_away(void** state)
{
prof_connect();
prof_input("/away");
prof_input("/status set away");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<show>away</show>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to away (priority 0)"));
@@ -60,13 +59,13 @@ presence_away_with_message(void** state)
{
prof_connect();
prof_input("/away \"I'm not here for a bit\"");
prof_input("/status set away \"I'm not here for a bit\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<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'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to away (priority 0), \"I'm not here for a bit\"."));
@@ -77,12 +76,12 @@ presence_xa(void** state)
{
prof_connect();
prof_input("/xa");
prof_input("/status set xa");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<show>xa</show>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to xa (priority 0)"));
@@ -93,13 +92,13 @@ presence_xa_with_message(void** state)
{
prof_connect();
prof_input("/xa \"Gone to the shops\"");
prof_input("/status set xa \"Gone to the shops\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<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'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to xa (priority 0), \"Gone to the shops\"."));
@@ -110,12 +109,12 @@ presence_dnd(void** state)
{
prof_connect();
prof_input("/dnd");
prof_input("/status set dnd");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<show>dnd</show>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to dnd (priority 0)"));
@@ -126,13 +125,13 @@ presence_dnd_with_message(void** state)
{
prof_connect();
prof_input("/dnd \"Working\"");
prof_input("/status set dnd \"Working\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<show>dnd</show>"
"<status>Working</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to dnd (priority 0), \"Working\"."));
@@ -143,12 +142,12 @@ presence_chat(void** state)
{
prof_connect();
prof_input("/chat");
prof_input("/status set chat");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<show>chat</show>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to chat (priority 0)"));
@@ -159,13 +158,13 @@ presence_chat_with_message(void** state)
{
prof_connect();
prof_input("/chat \"Free to talk\"");
prof_input("/status set chat \"Free to talk\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<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'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to chat (priority 0), \"Free to talk\"."));
@@ -179,9 +178,9 @@ presence_set_priority(void** state)
prof_input("/priority 25");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<priority>25</priority>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Priority set to 25."));
@@ -194,19 +193,19 @@ presence_includes_priority(void** state)
prof_input("/priority 25");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<priority>25</priority>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Priority set to 25."));
prof_input("/chat \"Free to talk\"");
prof_input("/status set chat \"Free to talk\"");
assert_true(stbbr_received(
"<presence id='prof_presence_5'>"
"<presence id=\"*\">"
"<priority>25</priority>"
"<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'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to chat (priority 25), \"Free to talk\"."));
}
@@ -216,22 +215,22 @@ presence_keeps_status(void** state)
{
prof_connect();
prof_input("/chat \"Free to talk\"");
prof_input("/status set chat \"Free to talk\"");
assert_true(stbbr_received(
"<presence id='prof_presence_4'>"
"<presence id=\"*\">"
"<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'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Status set to chat (priority 0), \"Free to talk\"."));
prof_input("/priority 25");
assert_true(stbbr_received(
"<presence id='prof_presence_5'>"
"<presence id=\"*\">"
"<show>chat</show>"
"<status>Free to talk</status>"
"<priority>25</priority>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>"
"<c hash=\"sha-1\" xmlns=\"http://jabber.org/protocol/caps\" ver=\"*\" node=\"http://profanity-im.github.io\"/>"
"</presence>"));
assert_true(prof_output_exact("Priority set to 25."));
}
@@ -247,7 +246,7 @@ presence_received(void** state)
"<status>I'm here</status>"
"</presence>");
assert_true(prof_output_exact("Buddy1 (mobile) is online, \"I'm here\""));
assert_true(prof_output_regex("Buddy1 \\(mobile\\) is online, \"I'm here\""));
}
// Typical use case for gateways that don't support resources

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("iq:*",
"<iq from='buddy1@localhost/laptop' to='stabber@localhost' id='*' 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'/>"
@@ -45,7 +44,7 @@ send_receipt_request(void** state)
"<c hash='sha-256' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='hAkb1xZdJV9BQpgGNw8zG5Xsals='/>"
"</presence>");
prof_output_exact("Buddy1 is online, \"My status\"");
assert_true(prof_output_regex("Buddy1 \\(laptop\\) is online, \"My status\""));
prof_input("/msg Buddy1");
prof_input("/resource set laptop");

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_query("http://jabber.org/protocol/disco#items",
"<iq id='*' 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'/>"
@@ -23,11 +22,10 @@ rooms_query(void** state)
prof_input("/rooms service conference.localhost");
assert_true(prof_output_exact("chatroom@conference.localhost (A chat room)"));
assert_true(prof_output_exact("hangout@conference.localhost (Another chat room)"));
assert_true(prof_output_regex("Room list request sent: conference.localhost[\\s\\S]*chatroom@conference.localhost[\\s\\S]*hangout@conference.localhost"));
assert_true(stbbr_last_received(
"<iq id='prof_confreq_4' to='conference.localhost' type='get'>"
"<iq id='*' 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"