Compare commits
4 Commits
fix/functi
...
fbe73a07f3
| Author | SHA1 | Date | |
|---|---|---|---|
| fbe73a07f3 | |||
| efad679e59 | |||
| a2fc1032a9 | |||
| 4bb4a43487 |
@@ -137,38 +137,3 @@ You can run the `make spell` command for this.
|
||||
|
||||
`make doublecheck` will run the code formatter, spell checker and unit tests.
|
||||
|
||||
|
||||
### Functional tests: moving away from brittle ID hooks
|
||||
|
||||
Historically the functional test suite relied on stabber's id based helpers like `stbbr_for_id("prof_presence_1", ...)` to register canned responses that would be sent once Profanity emitted a stanza carrying that exact `id` attribute. This made the tests fragile:
|
||||
|
||||
* Changes to stanza id generation (sequence, format) broke tests unexpectedly.
|
||||
* Reordering internal requests produced hard-to-debug race conditions when an `id` no longer matched.
|
||||
* Parallel additions of new features could shift which stanzas received a given id causing unrelated test failures.
|
||||
|
||||
We have migrated to content based stubbing using direct sends (`stbbr_send`) and query hooks (`stbbr_for_query`). Instead of tying a response to a predicted id we now send the required server stanzas explicitly after initiating actions. Example (see `tests/functionaltests/proftest.c`):
|
||||
|
||||
```c
|
||||
// Old brittle approach
|
||||
stbbr_for_id("prof_presence_1", "<presence id='prof_presence_1' ...>");
|
||||
|
||||
// New approach: after authentication, send presence directly
|
||||
stbbr_send("<presence from='stabber@localhost/profanity' to='stabber@localhost/profanity'>...caps...</presence>");
|
||||
```
|
||||
|
||||
Benefits:
|
||||
|
||||
* Eliminates dependency on internal id sequencing.
|
||||
* Clearer intent inside test code ("send presence now" vs "register hook and hope client triggers it").
|
||||
* Simplifies adding new tests—no need to inspect logs for generated ids.
|
||||
|
||||
Guidelines when writing new functional tests:
|
||||
|
||||
1. Prefer `stbbr_for_query(namespace, xml)` for IQ roster or disco queries where the namespace is stable.
|
||||
2. Use `stbbr_send(xml)` for presence, message, and other push style stanzas.
|
||||
3. Avoid `stbbr_for_id` unless the protocol flow genuinely requires correlating a specific request/response pair not covered by a namespace query.
|
||||
4. Keep assertions tolerant of ordering when possible; rely on `prof_output_regex()` matches rather than hard-coded positions.
|
||||
5. If timing flakiness appears, temporarily raise `prof_timeout()` around the critical expectation and reset it immediately afterwards.
|
||||
|
||||
The migration from `stbbr_for_id` is complete. All functional tests now use content-based stubbing. When adding new tests, follow the guidelines above.
|
||||
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
FROM archlinux
|
||||
|
||||
ENV TERM=xterm
|
||||
|
||||
RUN pacman -Syu --noconfirm
|
||||
# reflector is optional - if it fails due to network issues, continue with default mirrorlist
|
||||
RUN pacman -S --needed --noconfirm reflector && \
|
||||
(reflector --latest 20 --protocol https --sort rate --save /etc/pacman.d/mirrorlist || true)
|
||||
RUN pacman-key --init
|
||||
RUN pacman -S --needed --noconfirm \
|
||||
RUN pacman -Syu --noconfirm && pacman -S --needed --noconfirm \
|
||||
autoconf \
|
||||
autoconf-archive \
|
||||
automake \
|
||||
@@ -22,7 +15,7 @@ RUN pacman -S --needed --noconfirm \
|
||||
gcc \
|
||||
git \
|
||||
gpgme \
|
||||
gtk3 \
|
||||
gtk2 \
|
||||
libgcrypt \
|
||||
libmicrohttpd \
|
||||
libnotify \
|
||||
@@ -61,13 +54,13 @@ USER root
|
||||
RUN pacman -U --noconfirm libstrophe-git/libstrophe-git-*.pkg.tar.zst
|
||||
|
||||
WORKDIR /usr/src
|
||||
RUN git clone -c http.sslverify=false https://git.jabber.space/devs/stabber
|
||||
#RUN git clone https://github.com/boothj5/stabber
|
||||
|
||||
WORKDIR /usr/src/stabber
|
||||
RUN ./bootstrap.sh
|
||||
RUN ./configure --prefix=/usr --disable-dependency-tracking
|
||||
RUN make
|
||||
RUN make install
|
||||
#WORKDIR /usr/src/stabber
|
||||
#RUN ./bootstrap.sh
|
||||
#RUN ./configure --prefix=/usr --disable-dependency-tracking
|
||||
#RUN make
|
||||
#RUN make install
|
||||
|
||||
WORKDIR /usr/src/profanity
|
||||
COPY . /usr/src/profanity
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
# Build the latest Debian testing image
|
||||
FROM debian:testing
|
||||
|
||||
ENV DEBIAN_FRONTEND="noninteractive"
|
||||
ENV TERM=xterm
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
autoconf \
|
||||
autoconf-archive \
|
||||
automake \
|
||||
expect \
|
||||
gcc \
|
||||
git \
|
||||
libcmocka-dev \
|
||||
@@ -37,14 +35,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
RUN mkdir -p /usr/src/{stabber,libstrophe,profanity}
|
||||
WORKDIR /usr/src
|
||||
|
||||
RUN git clone -c http.sslverify=false https://git.jabber.space/devs/stabber
|
||||
#RUN git clone https://github.com/boothj5/stabber
|
||||
RUN git clone -c http.sslverify=false https://github.com/strophe/libstrophe
|
||||
|
||||
WORKDIR /usr/src/stabber
|
||||
RUN ./bootstrap.sh
|
||||
RUN ./configure --prefix=/usr --disable-dependency-tracking
|
||||
RUN make
|
||||
RUN make install
|
||||
#WORKDIR /usr/src/stabber
|
||||
#RUN ./bootstrap.sh
|
||||
#RUN ./configure --prefix=/usr --disable-dependency-tracking
|
||||
#RUN make
|
||||
#RUN make install
|
||||
|
||||
WORKDIR /usr/src/libstrophe
|
||||
RUN ./bootstrap.sh
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Build the latest Fedora image
|
||||
FROM fedora:latest
|
||||
|
||||
# expect - for functional tests
|
||||
# libmicrohttpd - for stabber
|
||||
# glibc-locale - to have en_US locale
|
||||
RUN dnf install -y \
|
||||
@@ -8,6 +9,7 @@ RUN dnf install -y \
|
||||
autoconf-archive \
|
||||
automake \
|
||||
awk \
|
||||
expect-devel \
|
||||
gcc \
|
||||
git \
|
||||
glib2-devel \
|
||||
@@ -40,17 +42,17 @@ RUN dnf install -y \
|
||||
ENV LANG en_US.UTF-8
|
||||
ENV LANGUAGE en_US:en
|
||||
ENV LC_ALL en_US.UTF-8
|
||||
ENV TERM=xterm
|
||||
|
||||
RUN mkdir -p /usr/src
|
||||
WORKDIR /usr/src
|
||||
|
||||
RUN git clone -c http.sslverify=false https://git.jabber.space/devs/stabber
|
||||
WORKDIR /usr/src/stabber
|
||||
RUN ./bootstrap.sh
|
||||
RUN ./configure --prefix=/usr --disable-dependency-tracking
|
||||
RUN make
|
||||
RUN make install
|
||||
#RUN mkdir -p /usr/src/stabber
|
||||
#RUN git clone https://github.com/boothj5/stabber
|
||||
#WORKDIR /usr/src/stabber
|
||||
#RUN ./bootstrap.sh
|
||||
#RUN ./configure --prefix=/usr --disable-dependency-tracking
|
||||
#RUN make
|
||||
#RUN make install
|
||||
|
||||
WORKDIR /usr/src
|
||||
RUN mkdir -p /usr/src/libstrophe
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
# Build the latest openSUSE Tumbleweed image
|
||||
FROM opensuse/tumbleweed
|
||||
|
||||
# expect - for functional tests
|
||||
# libmicrohttpd - for stabber
|
||||
# glibc-locale - to have en_US locale
|
||||
RUN zypper --non-interactive in --no-recommends \
|
||||
autoconf \
|
||||
autoconf-archive \
|
||||
automake \
|
||||
expect-devel \
|
||||
gcc \
|
||||
git \
|
||||
glib2-devel \
|
||||
@@ -39,17 +41,17 @@ RUN zypper --non-interactive in --no-recommends \
|
||||
ENV LANG en_US.UTF-8
|
||||
ENV LANGUAGE en_US:en
|
||||
ENV LC_ALL en_US.UTF-8
|
||||
ENV TERM=xterm
|
||||
|
||||
RUN mkdir -p /usr/src
|
||||
WORKDIR /usr/src
|
||||
|
||||
RUN git clone -c http.sslverify=false https://git.jabber.space/devs/stabber
|
||||
WORKDIR /usr/src/stabber
|
||||
RUN ./bootstrap.sh
|
||||
RUN ./configure --prefix=/usr --disable-dependency-tracking
|
||||
RUN make
|
||||
RUN make install
|
||||
#RUN mkdir -p /usr/src/stabber
|
||||
#RUN git clone git://github.com/boothj5/stabber.git
|
||||
#WORKDIR /usr/src/stabber
|
||||
#RUN ./bootstrap.sh
|
||||
#RUN ./configure --prefix=/usr --disable-dependency-tracking
|
||||
#RUN make
|
||||
#RUN make install
|
||||
|
||||
RUN mkdir -p /usr/src/profanity
|
||||
WORKDIR /usr/src/profanity
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
FROM ubuntu:latest
|
||||
|
||||
ENV DEBIAN_FRONTEND="noninteractive"
|
||||
ENV TERM=xterm
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
autoconf \
|
||||
autoconf-archive \
|
||||
automake \
|
||||
expect \
|
||||
gcc \
|
||||
git \
|
||||
libcmocka-dev \
|
||||
@@ -36,14 +36,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
RUN mkdir -p /usr/src/{stabber,libstrophe,profanity}
|
||||
WORKDIR /usr/src
|
||||
|
||||
RUN git clone -c http.sslverify=false https://git.jabber.space/devs/stabber
|
||||
#RUN git clone https://github.com/boothj5/stabber
|
||||
RUN git clone -c http.sslverify=false https://github.com/strophe/libstrophe
|
||||
|
||||
WORKDIR /usr/src/stabber
|
||||
RUN ./bootstrap.sh
|
||||
RUN ./configure --prefix=/usr --disable-dependency-tracking
|
||||
RUN make
|
||||
RUN make install
|
||||
# TODO: Re-enable once libmicrohttpd-dev has been updated.
|
||||
#WORKDIR /usr/src/stabber
|
||||
#RUN ./bootstrap.sh
|
||||
#RUN ./configure --prefix=/usr --disable-dependency-tracking
|
||||
#RUN make
|
||||
#RUN make install
|
||||
|
||||
WORKDIR /usr/src/libstrophe
|
||||
RUN ./bootstrap.sh
|
||||
|
||||
30
Makefile.am
30
Makefile.am
@@ -290,23 +290,21 @@ tests_unittests_unittests_CPPFLAGS = -Itests/
|
||||
tests_unittests_unittests_SOURCES = $(unittest_sources)
|
||||
tests_unittests_unittests_LDADD = -lcmocka
|
||||
|
||||
# Functional tests require libstabber.
|
||||
# They are only built when libstabber is available.
|
||||
# See: https://github.com/profanity-im/profanity/pull/1010
|
||||
# https://github.com/profanity-im/stabber/issues/5
|
||||
# Functional test were commented out because of:
|
||||
# https://github.com/profanity-im/profanity/pull/1010
|
||||
# An issue was raised for stabber:
|
||||
# https://github.com/profanity-im/stabber/issues/5
|
||||
# Once this issue is resolved functional tests should be enabled again
|
||||
#
|
||||
# Note: We use forkpty() instead of libexpect for PTY handling.
|
||||
|
||||
if HAVE_STABBER
|
||||
if HAVE_FORKPTY
|
||||
TESTS += tests/functionaltests/functionaltests
|
||||
check_PROGRAMS += tests/functionaltests/functionaltests
|
||||
tests_functionaltests_functionaltests_SOURCES = $(functionaltest_sources)
|
||||
tests_functionaltests_functionaltests_CPPFLAGS = -Itests/
|
||||
tests_functionaltests_functionaltests_CFLAGS = $(AM_CFLAGS)
|
||||
tests_functionaltests_functionaltests_LDADD = -lcmocka -lstabber @FORKPTY_LIB@
|
||||
endif
|
||||
endif
|
||||
#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
|
||||
|
||||
man1_MANS = $(man1_sources)
|
||||
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
typedef char* PROF_WIN_TAG;
|
||||
|
||||
/** Function pointer for command callbacks, accepting an array of arguments. */
|
||||
typedef void (*CMD_CB)(char** args);
|
||||
typedef void(*CMD_CB)(char **args);
|
||||
|
||||
/** Function pointer for timed callbacks, accepting no arguments. */
|
||||
typedef void (*TIMED_CB)(void);
|
||||
typedef void(*TIMED_CB)(void);
|
||||
|
||||
/** Function pointer for window callbacks, accepting a window tag and input line. */
|
||||
typedef void (*WINDOW_CB)(PROF_WIN_TAG win, char* line);
|
||||
typedef void(*WINDOW_CB)(PROF_WIN_TAG win, char *line);
|
||||
|
||||
/** Highlights the console window in the status bar. */
|
||||
void prof_cons_alert(void);
|
||||
@@ -41,7 +41,7 @@ void prof_cons_alert(void);
|
||||
* prof_cons_show("This will appear in the console window");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_cons_show(const char* const message);
|
||||
int prof_cons_show(const char * const message);
|
||||
|
||||
/**
|
||||
* Shows a message in the console with a specified theme.
|
||||
@@ -57,7 +57,7 @@ int prof_cons_show(const char* const message);
|
||||
* prof_cons_show_themed("myplugin", "text", NULL, "Plugin themed message");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_cons_show_themed(const char* const group, const char* const item, const char* const def, const char* const message);
|
||||
int prof_cons_show_themed(const char *const group, const char *const item, const char *const def, const char *const message);
|
||||
|
||||
/**
|
||||
* Shows a message indicating a command was used incorrectly.
|
||||
@@ -69,7 +69,7 @@ int prof_cons_show_themed(const char* const group, const char* const item, const
|
||||
* prof_cons_bad_cmd_usage("/mycommand");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_cons_bad_cmd_usage(const char* const cmd);
|
||||
int prof_cons_bad_cmd_usage(const char *const cmd);
|
||||
|
||||
/**
|
||||
* Registers a new command with help information and callback.
|
||||
@@ -91,9 +91,9 @@ int prof_cons_bad_cmd_usage(const char* const cmd);
|
||||
* prof_register_command("/newcommand", 1, 2, synopsis, "Example command", args, examples, my_function);
|
||||
* @endcode
|
||||
*/
|
||||
void prof_register_command(const char* command_name, int min_args, int max_args,
|
||||
char** synopsis, const char* description, char* arguments[][2], char** examples,
|
||||
CMD_CB callback);
|
||||
void prof_register_command(const char *command_name, int min_args, int max_args,
|
||||
char **synopsis, const char *description, char *arguments[][2], char **examples,
|
||||
CMD_CB callback);
|
||||
|
||||
/**
|
||||
* Registers a function to be called periodically by CProof.
|
||||
@@ -118,7 +118,7 @@ void prof_register_timed(TIMED_CB callback, int interval_seconds);
|
||||
* prof_completer_add("/mycommand", items);
|
||||
* @endcode
|
||||
*/
|
||||
void prof_completer_add(const char* key, char** items);
|
||||
void prof_completer_add(const char *key, char **items);
|
||||
|
||||
/**
|
||||
* Removes autocomplete values for a command or argument.
|
||||
@@ -131,7 +131,7 @@ void prof_completer_add(const char* key, char** items);
|
||||
* prof_completer_remove("/mycommand", items);
|
||||
* @endcode
|
||||
*/
|
||||
void prof_completer_remove(const char* key, char** items);
|
||||
void prof_completer_remove(const char *key, char **items);
|
||||
|
||||
/**
|
||||
* Clears all autocomplete values for a command or argument.
|
||||
@@ -142,7 +142,7 @@ void prof_completer_remove(const char* key, char** items);
|
||||
* prof_completer_clear("/mycommand");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_completer_clear(const char* key);
|
||||
void prof_completer_clear(const char *key);
|
||||
|
||||
/**
|
||||
* Adds filepath autocompletion for a command or argument.
|
||||
@@ -153,7 +153,7 @@ void prof_completer_clear(const char* key);
|
||||
* prof_filepath_completer_add("/filecmd");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_filepath_completer_add(const char* prefix);
|
||||
void prof_filepath_completer_add(const char *prefix);
|
||||
|
||||
/**
|
||||
* Sends a desktop notification.
|
||||
@@ -166,7 +166,7 @@ void prof_filepath_completer_add(const char* prefix);
|
||||
* prof_notify("Example notification", 5000, "Example plugin");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_notify(const char* message, int timeout_ms, const char* category);
|
||||
void prof_notify(const char *message, int timeout_ms, const char *category);
|
||||
|
||||
/**
|
||||
* Sends a line of input to CProof to execute.
|
||||
@@ -177,7 +177,7 @@ void prof_notify(const char* message, int timeout_ms, const char* category);
|
||||
* prof_send_line("/who online");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_send_line(char* line);
|
||||
void prof_send_line(char *line);
|
||||
|
||||
/**
|
||||
* Gets the Jabber ID of the current chat recipient.
|
||||
@@ -185,17 +185,6 @@ void prof_send_line(char* line);
|
||||
*/
|
||||
char* prof_get_current_recipient(void);
|
||||
|
||||
/**
|
||||
* Gets the title of the current window as shown in the titlebar.
|
||||
*
|
||||
* Special cases:
|
||||
* - MUC configuration window: Includes "config" and an asterisk if modified (e.g., "room@example.com config *").
|
||||
* - vCard window: Includes the bare JID and an asterisk if modified (e.g., "vCard user@example.com *").
|
||||
*
|
||||
* @return A null-terminated string containing the window title. The caller must free the returned string.
|
||||
*/
|
||||
char* prof_get_current_window(void);
|
||||
|
||||
/**
|
||||
* Gets the Jabber ID of the current chat room.
|
||||
* @return The room Jabber ID (e.g., "metalchat@conference.example.com") or NULL if not in a room.
|
||||
@@ -209,7 +198,7 @@ char* prof_get_current_muc(void);
|
||||
int prof_current_win_is_console(void);
|
||||
|
||||
/**
|
||||
* Gets the user's nickname in the current chat room.
|
||||
* Gets the user’s nickname in the current chat room.
|
||||
* @return The nickname (e.g., "eddie") or NULL if not in a room.
|
||||
*/
|
||||
char* prof_get_current_nick(void);
|
||||
@@ -219,14 +208,14 @@ char* prof_get_current_nick(void);
|
||||
* @param barejid The Jabber ID.
|
||||
* @return The nickname (e.g., "eddie") or the barejid if not in the roster.
|
||||
*/
|
||||
char* prof_get_name_from_roster(const char* barejid);
|
||||
char* prof_get_name_from_roster(const char *barejid);
|
||||
|
||||
/**
|
||||
* Gets the barejid for a nickname from the roster.
|
||||
* @param name The nickname.
|
||||
* @return The barejid (e.g., "eddie@server.tld") or NULL if not in the roster.
|
||||
*/
|
||||
char* prof_get_barejid_from_roster(const char* name);
|
||||
char* prof_get_barejid_from_roster(const char *name);
|
||||
|
||||
/**
|
||||
* Gets nicknames of all occupants in the current chat room.
|
||||
@@ -236,10 +225,10 @@ char** prof_get_current_occupants(void);
|
||||
|
||||
/**
|
||||
* Gets the current nickname in a chat room.
|
||||
* @param barejid The room's Jabber ID.
|
||||
* @param barejid The room’s Jabber ID.
|
||||
* @return The nickname.
|
||||
*/
|
||||
char* prof_get_room_nick(const char* barejid);
|
||||
char* prof_get_room_nick(const char *barejid);
|
||||
|
||||
/**
|
||||
* Logs a debug message to the CProof log.
|
||||
@@ -250,7 +239,7 @@ char* prof_get_room_nick(const char* barejid);
|
||||
* prof_log_debug("Debug message");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_log_debug(const char* message);
|
||||
void prof_log_debug(const char *message);
|
||||
|
||||
/**
|
||||
* Logs an info message to the CProof log.
|
||||
@@ -261,7 +250,7 @@ void prof_log_debug(const char* message);
|
||||
* prof_log_info("Info message");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_log_info(const char* message);
|
||||
void prof_log_info(const char *message);
|
||||
|
||||
/**
|
||||
* Logs a warning message to the CProof log.
|
||||
@@ -272,7 +261,7 @@ void prof_log_info(const char* message);
|
||||
* prof_log_warning("Warning message");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_log_warning(const char* message);
|
||||
void prof_log_warning(const char *message);
|
||||
|
||||
/**
|
||||
* Logs an error message to the CProof log.
|
||||
@@ -283,7 +272,7 @@ void prof_log_warning(const char* message);
|
||||
* prof_log_error("Error message");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_log_error(const char* message);
|
||||
void prof_log_error(const char *message);
|
||||
|
||||
/**
|
||||
* Creates a plugin window.
|
||||
@@ -332,7 +321,7 @@ int prof_win_focus(PROF_WIN_TAG win);
|
||||
* prof_win_show("My Plugin", "Message in plugin window");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_win_show(PROF_WIN_TAG win, char* message);
|
||||
int prof_win_show(PROF_WIN_TAG win, char *message);
|
||||
|
||||
/**
|
||||
* Shows a message in a plugin window with a specified theme.
|
||||
@@ -349,7 +338,7 @@ int prof_win_show(PROF_WIN_TAG win, char* message);
|
||||
* prof_win_show_themed("My Plugin", "myplugin", "text", NULL, "Themed message");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_win_show_themed(PROF_WIN_TAG tag, char* group, char* key, char* def, char* message);
|
||||
int prof_win_show_themed(PROF_WIN_TAG tag, char *group, char *key, char *def, char *message);
|
||||
|
||||
/**
|
||||
* Sends an XMPP stanza.
|
||||
@@ -361,7 +350,7 @@ int prof_win_show_themed(PROF_WIN_TAG tag, char* group, char* key, char* def, ch
|
||||
* prof_send_stanza("<iq to='juliet@capulet.lit' id='s2c1' type='get'><ping xmlns='urn:xmpp:ping'/></iq>");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_send_stanza(char* stanza);
|
||||
int prof_send_stanza(char *stanza);
|
||||
|
||||
/**
|
||||
* Gets a boolean setting.
|
||||
@@ -376,7 +365,7 @@ int prof_send_stanza(char* stanza);
|
||||
* prof_settings_boolean_get("myplugin", "notify", 0);
|
||||
* @endcode
|
||||
*/
|
||||
int prof_settings_boolean_get(char* group, char* key, int def);
|
||||
int prof_settings_boolean_get(char *group, char *key, int def);
|
||||
|
||||
/**
|
||||
* Sets a boolean setting.
|
||||
@@ -390,7 +379,7 @@ int prof_settings_boolean_get(char* group, char* key, int def);
|
||||
* prof_settings_boolean_set("myplugin", "activate", 1);
|
||||
* @endcode
|
||||
*/
|
||||
void prof_settings_boolean_set(char* group, char* key, int value);
|
||||
void prof_settings_boolean_set(char *group, char *key, int value);
|
||||
|
||||
/**
|
||||
* Gets a string setting.
|
||||
@@ -405,7 +394,7 @@ void prof_settings_boolean_set(char* group, char* key, int value);
|
||||
* prof_settings_string_get("myplugin", "prefix", "prefix-->");
|
||||
* @endcode
|
||||
*/
|
||||
char* prof_settings_string_get(char* group, char* key, char* def);
|
||||
char* prof_settings_string_get(char *group, char *key, char *def);
|
||||
|
||||
/**
|
||||
* Sets a string setting.
|
||||
@@ -419,7 +408,7 @@ char* prof_settings_string_get(char* group, char* key, char* def);
|
||||
* prof_settings_string_set("myplugin", "prefix", "myplugin, ");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_settings_string_set(char* group, char* key, char* value);
|
||||
void prof_settings_string_set(char *group, char *key, char *value);
|
||||
|
||||
/**
|
||||
* Gets a string list setting, separated by semicolons.
|
||||
@@ -433,7 +422,7 @@ void prof_settings_string_set(char* group, char* key, char* value);
|
||||
* prof_settings_string_list_get("myplugin", "somelist");
|
||||
* @endcode
|
||||
*/
|
||||
char** prof_settings_string_list_get(char* group, char* key);
|
||||
char** prof_settings_string_list_get(char *group, char *key);
|
||||
|
||||
/**
|
||||
* Adds an item to a string list setting.
|
||||
@@ -448,7 +437,7 @@ char** prof_settings_string_list_get(char* group, char* key);
|
||||
* prof_settings_string_list_add("myplugin", "somelist", "anelement");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_settings_string_list_add(char* group, char* key, char* value);
|
||||
void prof_settings_string_list_add(char *group, char *key, char *value);
|
||||
|
||||
/**
|
||||
* Removes an item from a string list setting.
|
||||
@@ -463,7 +452,7 @@ void prof_settings_string_list_add(char* group, char* key, char* value);
|
||||
* prof_settings_string_list_remove("myplugin", "somelist", "anelement");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_settings_string_list_remove(char* group, char* key, char* value);
|
||||
int prof_settings_string_list_remove(char *group, char *key, char *value);
|
||||
|
||||
/**
|
||||
* Clears all items from a string list setting.
|
||||
@@ -477,7 +466,7 @@ int prof_settings_string_list_remove(char* group, char* key, char* value);
|
||||
* prof_settings_string_list_clear("myplugin", "somelist");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_settings_string_list_clear(char* group, char* key);
|
||||
int prof_settings_string_list_clear(char *group, char *key);
|
||||
|
||||
/**
|
||||
* Gets an integer setting.
|
||||
@@ -492,7 +481,7 @@ int prof_settings_string_list_clear(char* group, char* key);
|
||||
* prof_settings_int_get("myplugin", "timeout", 10);
|
||||
* @endcode
|
||||
*/
|
||||
int prof_settings_int_get(char* group, char* key, int def);
|
||||
int prof_settings_int_get(char *group, char *key, int def);
|
||||
|
||||
/**
|
||||
* Sets an integer setting.
|
||||
@@ -506,7 +495,7 @@ int prof_settings_int_get(char* group, char* key, int def);
|
||||
* prof_settings_int_set("myplugin", "timeout", 100);
|
||||
* @endcode
|
||||
*/
|
||||
void prof_settings_int_set(char* group, char* key, int value);
|
||||
void prof_settings_int_set(char *group, char *key, int value);
|
||||
|
||||
/**
|
||||
* Triggers handling of an incoming message as if received by CProof.
|
||||
@@ -519,10 +508,10 @@ void prof_settings_int_set(char* group, char* key, int value);
|
||||
* prof_incoming_message("bob@server.org", "laptop", "Hello there");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_incoming_message(char* barejid, char* resource, char* message);
|
||||
void prof_incoming_message(char *barejid, char *resource, char *message);
|
||||
|
||||
/**
|
||||
* Adds a service discovery feature to CProof's supported features.
|
||||
* Adds a service discovery feature to CProof’s supported features.
|
||||
* Sends a presence update if a session is connected.
|
||||
* @param feature The feature to add.
|
||||
*
|
||||
@@ -531,7 +520,7 @@ void prof_incoming_message(char* barejid, char* resource, char* message);
|
||||
* prof_disco_add_feature("urn:xmpp:omemo:0:devicelist+notify");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_disco_add_feature(char* feature);
|
||||
void prof_disco_add_feature(char *feature);
|
||||
|
||||
/**
|
||||
* Ends an encrypted session with a user.
|
||||
@@ -542,7 +531,7 @@ void prof_disco_add_feature(char* feature);
|
||||
* prof_encryption_reset("alice@server.org");
|
||||
* @endcode
|
||||
*/
|
||||
void prof_encryption_reset(char* barejid);
|
||||
void prof_encryption_reset(char *barejid);
|
||||
|
||||
/**
|
||||
* Sets the titlebar encryption indicator text for a recipient.
|
||||
@@ -555,10 +544,10 @@ void prof_encryption_reset(char* barejid);
|
||||
* prof_chat_set_titlebar_enctext("bob@example.com", "safe");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_chat_set_titlebar_enctext(char* barejid, char* enctext);
|
||||
int prof_chat_set_titlebar_enctext(char *barejid, char *enctext);
|
||||
|
||||
/**
|
||||
* Resets the titlebar encryption indicator for a recipient to CProof's default.
|
||||
* Resets the titlebar encryption indicator for a recipient to CProof’s default.
|
||||
* @param barejid Jabber ID of the recipient.
|
||||
* @return 1 on success, 0 on failure.
|
||||
*
|
||||
@@ -567,7 +556,7 @@ int prof_chat_set_titlebar_enctext(char* barejid, char* enctext);
|
||||
* prof_chat_unset_titlebar_enctext("bob@example.com");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_chat_unset_titlebar_enctext(char* barejid);
|
||||
int prof_chat_unset_titlebar_enctext(char *barejid);
|
||||
|
||||
/**
|
||||
* Sets the incoming message prefix character for a contact.
|
||||
@@ -580,7 +569,7 @@ int prof_chat_unset_titlebar_enctext(char* barejid);
|
||||
* prof_chat_set_incoming_char("kristine@example.com", "*");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_chat_set_incoming_char(char* barejid, char* ch);
|
||||
int prof_chat_set_incoming_char(char *barejid, char *ch);
|
||||
|
||||
/**
|
||||
* Resets the incoming message prefix character for a contact.
|
||||
@@ -592,7 +581,7 @@ int prof_chat_set_incoming_char(char* barejid, char* ch);
|
||||
* prof_chat_unset_incoming_char("kristine@example.com");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_chat_unset_incoming_char(char* barejid);
|
||||
int prof_chat_unset_incoming_char(char *barejid);
|
||||
|
||||
/**
|
||||
* Sets the outgoing message prefix character for a contact.
|
||||
@@ -605,7 +594,7 @@ int prof_chat_unset_incoming_char(char* barejid);
|
||||
* prof_chat_set_outgoing_char("david@example.com", "+");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_chat_set_outgoing_char(char* barejid, char* ch);
|
||||
int prof_chat_set_outgoing_char(char *barejid, char *ch);
|
||||
|
||||
/**
|
||||
* Resets the outgoing message prefix character for a contact.
|
||||
@@ -617,7 +606,7 @@ int prof_chat_set_outgoing_char(char* barejid, char* ch);
|
||||
* prof_chat_unset_outgoing_char("david@example.com");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_chat_unset_outgoing_char(char* barejid);
|
||||
int prof_chat_unset_outgoing_char(char *barejid);
|
||||
|
||||
/**
|
||||
* Sets the titlebar encryption indicator text for a room.
|
||||
@@ -630,10 +619,10 @@ int prof_chat_unset_outgoing_char(char* barejid);
|
||||
* prof_room_set_titlebar_enctext("generalchat@conference.service.com", "secret");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_room_set_titlebar_enctext(char* roomjid, char* enctext);
|
||||
int prof_room_set_titlebar_enctext(char *roomjid, char *enctext);
|
||||
|
||||
/**
|
||||
* Resets the titlebar encryption indicator for a room to CProof's default.
|
||||
* Resets the titlebar encryption indicator for a room to CProof’s default.
|
||||
* @param roomjid Jabber ID of the room.
|
||||
* @return 1 on success, 0 on failure.
|
||||
*
|
||||
@@ -642,7 +631,7 @@ int prof_room_set_titlebar_enctext(char* roomjid, char* enctext);
|
||||
* prof_room_unset_titlebar_enctext("generalchat@conference.service.com");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_room_unset_titlebar_enctext(char* roomjid);
|
||||
int prof_room_unset_titlebar_enctext(char *roomjid);
|
||||
|
||||
/**
|
||||
* Sets the message prefix character for a room.
|
||||
@@ -655,7 +644,7 @@ int prof_room_unset_titlebar_enctext(char* roomjid);
|
||||
* prof_room_set_message_char("ohnoes@conference.example.com", "^");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_room_set_message_char(char* roomjid, char* ch);
|
||||
int prof_room_set_message_char(char *roomjid, char *ch);
|
||||
|
||||
/**
|
||||
* Resets the message prefix character for a room.
|
||||
@@ -667,7 +656,7 @@ int prof_room_set_message_char(char* roomjid, char* ch);
|
||||
* prof_room_unset_message_char("ohnoes@conference.example.com");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_room_unset_message_char(char* roomjid);
|
||||
int prof_room_unset_message_char(char *roomjid);
|
||||
|
||||
/**
|
||||
* Shows a message in a chat window.
|
||||
@@ -680,7 +669,7 @@ int prof_room_unset_message_char(char* roomjid);
|
||||
* prof_chat_show("bob@server.org", "From a plugin in the chat window");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_chat_show(char* barejid, char* message);
|
||||
int prof_chat_show(char *barejid, char *message);
|
||||
|
||||
/**
|
||||
* Shows a message in a chat window with a theme and prefix character.
|
||||
@@ -698,7 +687,7 @@ int prof_chat_show(char* barejid, char* message);
|
||||
* prof_chat_show_themed("bob@server.org", "myplugin", "text", NULL, "!", "Themed message");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_chat_show_themed(char* barejid, char* group, char* item, char* def, char* ch, char* message);
|
||||
int prof_chat_show_themed(char *barejid, char *group, char *item, char *def, char *ch, char *message);
|
||||
|
||||
/**
|
||||
* Shows a message in a chat room window.
|
||||
@@ -711,7 +700,7 @@ int prof_chat_show_themed(char* barejid, char* group, char* item, char* def, cha
|
||||
* prof_room_show("chat@conference.example.com", "From a plugin in the chat room");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_room_show(char* roomjid, char* message);
|
||||
int prof_room_show(char *roomjid, char *message);
|
||||
|
||||
/**
|
||||
* Shows a message in a chat room window with a theme and prefix character.
|
||||
@@ -729,4 +718,4 @@ int prof_room_show(char* roomjid, char* message);
|
||||
* prof_room_show_themed("chat@conference.example.com", "myplugin", "text", NULL, "!", "Themed message");
|
||||
* @endcode
|
||||
*/
|
||||
int prof_room_show_themed(char* roomjid, char* group, char* item, char* def, char* ch, char* message);
|
||||
int prof_room_show_themed(char *roomjid, char *group, char *item, char *def, char *ch, char *message);
|
||||
|
||||
@@ -830,22 +830,6 @@ def get_current_recipient() -> str | None:
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_current_window() -> str:
|
||||
"""Retrieves the title of the current window as shown in the titlebar.
|
||||
|
||||
Returns the title of the currently active window, matching the titlebar display.
|
||||
Special cases:
|
||||
- For MUC configuration windows, includes "config" and an asterisk if modified (e.g., "room@example.com config \*").
|
||||
- For vCard windows, includes the bare JID and an asterisk if modified (e.g., "vCard user@example.com \*").
|
||||
|
||||
:return: The window title as a string.
|
||||
|
||||
Example::
|
||||
|
||||
title = prof.get_current_window()
|
||||
prof.cons_show(f"Current window: {title}")
|
||||
"""
|
||||
|
||||
def get_current_muc() -> str | None:
|
||||
"""Retrieves the Jabber ID of the current chat room.
|
||||
|
||||
|
||||
66
ci-build.sh
66
ci-build.sh
@@ -44,43 +44,49 @@ ARCH="$(uname | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
case "$ARCH" in
|
||||
linux*)
|
||||
# Reduced set of configurations for faster CI
|
||||
tests=(
|
||||
# 1. Full build (all features enabled)
|
||||
"--enable-notifications --enable-icons-and-clipboard --enable-otr --enable-pgp
|
||||
--enable-omemo --enable-plugins --enable-c-plugins
|
||||
--enable-python-plugins --with-xscreensaver --enable-omemo-qrcode --enable-gdk-pixbuf"
|
||||
# 2. Minimal build (all optional features disabled)
|
||||
"--disable-notifications --disable-icons-and-clipboard --disable-otr --disable-pgp
|
||||
--disable-omemo --disable-plugins --disable-c-plugins
|
||||
--disable-python-plugins --without-xscreensaver --disable-omemo-qrcode --disable-gdk-pixbuf"
|
||||
# 3. No encryption (disable otr, pgp, omemo)
|
||||
"--disable-pgp --disable-otr --disable-omemo --disable-omemo-qrcode"
|
||||
# 4. No plugins
|
||||
"--disable-plugins --disable-c-plugins --disable-python-plugins"
|
||||
# 5. Default configuration
|
||||
""
|
||||
)
|
||||
--disable-python-plugins --without-xscreensaver"
|
||||
"--disable-notifications"
|
||||
"--disable-icons-and-clipboard"
|
||||
"--disable-otr"
|
||||
"--disable-pgp"
|
||||
"--disable-omemo --disable-omemo-qrcode"
|
||||
"--disable-pgp --disable-otr"
|
||||
"--disable-pgp --disable-otr --disable-omemo"
|
||||
"--disable-plugins"
|
||||
"--disable-python-plugins"
|
||||
"--disable-c-plugins"
|
||||
"--disable-c-plugins --disable-python-plugins"
|
||||
"--without-xscreensaver"
|
||||
"--disable-gdk-pixbuf"
|
||||
"")
|
||||
source /etc/profile.d/debuginfod.sh 2>/dev/null || true
|
||||
;;
|
||||
darwin*)
|
||||
# Reduced set of configurations for faster CI
|
||||
tests=(
|
||||
# 1. Full build (all features enabled)
|
||||
"--enable-notifications --enable-icons-and-clipboard --enable-otr --enable-pgp
|
||||
--enable-omemo --enable-plugins --enable-c-plugins
|
||||
--enable-python-plugins"
|
||||
# 2. Minimal build (all optional features disabled)
|
||||
"--disable-notifications --disable-icons-and-clipboard --disable-otr --disable-pgp
|
||||
--disable-omemo --disable-plugins --disable-c-plugins
|
||||
--disable-python-plugins"
|
||||
# 3. No encryption (disable otr, pgp, omemo)
|
||||
"--disable-notifications"
|
||||
"--disable-icons-and-clipboard"
|
||||
"--disable-otr"
|
||||
"--disable-pgp"
|
||||
"--disable-omemo"
|
||||
"--disable-pgp --disable-otr"
|
||||
"--disable-pgp --disable-otr --disable-omemo"
|
||||
# 4. No plugins
|
||||
"--disable-plugins --disable-c-plugins --disable-python-plugins"
|
||||
# 5. Default configuration
|
||||
""
|
||||
)
|
||||
"--disable-plugins"
|
||||
"--disable-python-plugins"
|
||||
"--disable-c-plugins"
|
||||
"--disable-c-plugins --disable-python-plugins"
|
||||
"")
|
||||
;;
|
||||
openbsd*)
|
||||
MAKE="gmake"
|
||||
@@ -90,23 +96,25 @@ case "$ARCH" in
|
||||
# src/event/server_events.c:1454:19: error: universal character names are only valid in C++ and C99
|
||||
CC="egcc -std=gnu99 -fexec-charset=UTF-8"
|
||||
|
||||
# Reduced set of configurations for faster CI
|
||||
tests=(
|
||||
# 1. Full build (all features enabled)
|
||||
"--enable-notifications --enable-icons-and-clipboard --enable-otr --enable-pgp
|
||||
--enable-omemo --enable-plugins --enable-c-plugins
|
||||
--enable-python-plugins"
|
||||
# 2. Minimal build (all optional features disabled)
|
||||
"--disable-notifications --disable-icons-and-clipboard --disable-otr --disable-pgp
|
||||
--disable-omemo --disable-plugins --disable-c-plugins
|
||||
--disable-python-plugins"
|
||||
# 3. No encryption (disable otr, pgp, omemo)
|
||||
"--disable-notifications"
|
||||
"--disable-icons-and-clipboard"
|
||||
"--disable-otr"
|
||||
"--disable-pgp"
|
||||
"--disable-omemo"
|
||||
"--disable-pgp --disable-otr"
|
||||
"--disable-pgp --disable-otr --disable-omemo"
|
||||
# 4. No plugins
|
||||
"--disable-plugins --disable-c-plugins --disable-python-plugins"
|
||||
# 5. Default configuration
|
||||
""
|
||||
)
|
||||
"--disable-plugins"
|
||||
"--disable-python-plugins"
|
||||
"--disable-c-plugins"
|
||||
"--disable-c-plugins --disable-python-plugins"
|
||||
"")
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
10
configure.ac
10
configure.ac
@@ -374,13 +374,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])])
|
||||
dnl Check for forkpty (needed for functional tests PTY handling)
|
||||
dnl On Linux it's in libutil, on some BSDs it's in libc
|
||||
AM_CONDITIONAL([HAVE_FORKPTY], [false])
|
||||
AC_CHECK_LIB([util], [forkpty], [AM_CONDITIONAL([HAVE_FORKPTY], [true]) FORKPTY_LIB="-lutil"],
|
||||
[AC_CHECK_FUNC([forkpty], [AM_CONDITIONAL([HAVE_FORKPTY], [true]) FORKPTY_LIB=""],
|
||||
[AC_MSG_NOTICE([forkpty not found, will not be able to run functional tests])])])
|
||||
AC_SUBST([FORKPTY_LIB])
|
||||
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])])
|
||||
|
||||
## Default parameters
|
||||
AM_CFLAGS="$AM_CFLAGS -Wall -Wno-deprecated-declarations -std=gnu99 -ggdb3"
|
||||
|
||||
358
prof.supp
358
prof.supp
@@ -8,83 +8,6 @@
|
||||
# * python suppressions file from https://github.com/python/cpython/blob/main/Misc/valgrind-python.supp
|
||||
#
|
||||
|
||||
# ============================================
|
||||
# Functional tests suppressions (stabber/pthread)
|
||||
# ============================================
|
||||
|
||||
{
|
||||
stabber_pthread_create
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
...
|
||||
fun:allocate_dtv
|
||||
fun:_dl_allocate_tls
|
||||
...
|
||||
fun:pthread_create*
|
||||
...
|
||||
fun:server_run
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
stabber_server_run
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
...
|
||||
fun:pthread_create*
|
||||
...
|
||||
obj:*/libstabber*
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
glib_time_zone_cache
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
...
|
||||
fun:g_time_zone_new*
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
glib_time_zone_local
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
...
|
||||
fun:g_strdup
|
||||
...
|
||||
fun:g_time_zone_new_identifier
|
||||
fun:g_time_zone_new_local
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
glib_date_time_format
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
...
|
||||
fun:g_date_time_format
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
glib_date_time_format_locale
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:*alloc
|
||||
...
|
||||
obj:*/libglib*
|
||||
...
|
||||
fun:g_date_time_format
|
||||
...
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Original suppressions
|
||||
# ============================================
|
||||
|
||||
{
|
||||
_dl_init
|
||||
Memcheck:Leak
|
||||
@@ -2780,284 +2703,3 @@
|
||||
fun:calloc
|
||||
fun:_dl_allocate_tls
|
||||
}
|
||||
|
||||
# pthread TLS allocation in stabber server threads
|
||||
{
|
||||
pthread_create_tls_stabber
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
...
|
||||
fun:allocate_dtv
|
||||
fun:_dl_allocate_tls
|
||||
fun:allocate_stack
|
||||
fun:pthread_create*
|
||||
fun:server_run
|
||||
}
|
||||
|
||||
# expect/tcl library allocations
|
||||
{
|
||||
tcl_alloc_expect
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:malloc
|
||||
...
|
||||
fun:TclpAlloc
|
||||
fun:Tcl_Alloc
|
||||
...
|
||||
fun:exp_expectl
|
||||
}
|
||||
|
||||
{
|
||||
exp_printify
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:malloc
|
||||
...
|
||||
fun:exp_printify
|
||||
...
|
||||
fun:exp_expectl
|
||||
}
|
||||
|
||||
|
||||
# Additional suppressions for functional tests
|
||||
|
||||
# libexpect still reachable allocations
|
||||
{
|
||||
exp_spawnv_malloc
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:malloc
|
||||
...
|
||||
fun:exp_spawnv
|
||||
fun:exp_spawnl
|
||||
}
|
||||
|
||||
{
|
||||
exp_spawnl_realloc
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:realloc
|
||||
...
|
||||
fun:exp_spawnv
|
||||
fun:exp_spawnl
|
||||
}
|
||||
|
||||
# libtcl memory pool allocations (expected)
|
||||
{
|
||||
tcl_alloc_pool
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:malloc
|
||||
...
|
||||
fun:TclpAlloc
|
||||
fun:Tcl_Alloc
|
||||
}
|
||||
|
||||
{
|
||||
tcl_alloc_pool_calloc
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:calloc
|
||||
...
|
||||
fun:TclpAlloc
|
||||
fun:Tcl_Alloc
|
||||
}
|
||||
|
||||
# pthread thread-local storage (normal for multi-threaded programs)
|
||||
{
|
||||
pthread_tls_allocate_dtv
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
fun:calloc
|
||||
fun:allocate_dtv
|
||||
fun:_dl_allocate_tls
|
||||
fun:allocate_stack
|
||||
fun:pthread_create*
|
||||
}
|
||||
|
||||
# glib static initializations
|
||||
{
|
||||
glib_hash_table_init
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
fun:g_hash_table_new_full
|
||||
...
|
||||
fun:call_init
|
||||
fun:_dl_init
|
||||
}
|
||||
|
||||
{
|
||||
glib_array_init
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:realloc
|
||||
fun:g_realloc
|
||||
...
|
||||
fun:call_init
|
||||
fun:_dl_init
|
||||
}
|
||||
|
||||
# fdopen/fopen allocations (FILE* buffers - normal)
|
||||
{
|
||||
fdopen_file_buffer
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:malloc
|
||||
...
|
||||
fun:fdopen*
|
||||
}
|
||||
|
||||
{
|
||||
fopen_file_buffer
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:malloc
|
||||
...
|
||||
fun:fopen*
|
||||
}
|
||||
|
||||
# stabber log_init (server log file)
|
||||
{
|
||||
stabber_log_init
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:malloc
|
||||
...
|
||||
fun:log_init
|
||||
fun:server_run
|
||||
}
|
||||
|
||||
# glib time zone (static allocation)
|
||||
{
|
||||
g_time_zone_new_local
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
...
|
||||
fun:g_time_zone_new_local
|
||||
}
|
||||
|
||||
{
|
||||
g_time_zone_array
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:realloc
|
||||
fun:g_realloc
|
||||
...
|
||||
fun:g_array_sized_new
|
||||
fun:g_time_zone_new_identifier
|
||||
}
|
||||
|
||||
# stabber log g_date_time_format invalid read - benign race in logging
|
||||
{
|
||||
stabber_g_date_time_format_invalid_read
|
||||
Memcheck:Addr1
|
||||
...
|
||||
fun:g_date_time_format
|
||||
fun:log_println
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
stabber_g_date_time_format_invalid_read2
|
||||
Memcheck:Addr2
|
||||
...
|
||||
fun:g_date_time_format
|
||||
fun:log_println
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
stabber_g_date_time_format_invalid_read4
|
||||
Memcheck:Addr4
|
||||
...
|
||||
fun:g_date_time_format
|
||||
fun:log_println
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
stabber_g_date_time_format_invalid_read8
|
||||
Memcheck:Addr8
|
||||
...
|
||||
fun:g_date_time_format
|
||||
fun:log_println
|
||||
...
|
||||
}
|
||||
|
||||
# More generic suppression for g_date_time_format race condition
|
||||
{
|
||||
g_date_time_format_cond
|
||||
Memcheck:Cond
|
||||
...
|
||||
fun:g_date_time_format
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_date_time_format_value1
|
||||
Memcheck:Value1
|
||||
...
|
||||
fun:g_date_time_format
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_date_time_format_value2
|
||||
Memcheck:Value2
|
||||
...
|
||||
fun:g_date_time_format
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_date_time_format_value4
|
||||
Memcheck:Value4
|
||||
...
|
||||
fun:g_date_time_format
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_date_time_format_value8
|
||||
Memcheck:Value8
|
||||
...
|
||||
fun:g_date_time_format
|
||||
...
|
||||
}
|
||||
|
||||
# Suppress all Addr errors in log_println
|
||||
{
|
||||
log_println_addr1
|
||||
Memcheck:Addr1
|
||||
...
|
||||
fun:log_println
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
log_println_addr2
|
||||
Memcheck:Addr2
|
||||
...
|
||||
fun:log_println
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
log_println_addr4
|
||||
Memcheck:Addr4
|
||||
...
|
||||
fun:log_println
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
log_println_addr8
|
||||
Memcheck:Addr8
|
||||
...
|
||||
fun:log_println
|
||||
...
|
||||
}
|
||||
|
||||
@@ -139,9 +139,8 @@ static const struct cmd_t command_defs[] = {
|
||||
"Show version and license information.")
|
||||
},
|
||||
|
||||
// Max args: account + server <s> + port <p> + tls <t> + auth <a> = 9
|
||||
{ CMD_PREAMBLE("/connect",
|
||||
parse_args, 0, 9, NULL)
|
||||
parse_args, 0, 7, NULL)
|
||||
CMD_MAINFUNC(cmd_connect)
|
||||
CMD_TAGS(
|
||||
CMD_TAG_CONNECTION)
|
||||
|
||||
@@ -5356,8 +5356,6 @@ 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);
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
#include "plugins/settings.h"
|
||||
#include "plugins/disco.h"
|
||||
#include "ui/ui.h"
|
||||
#include "ui/win_types.h"
|
||||
#include "ui/window_list.h"
|
||||
#include "xmpp/roster_list.h"
|
||||
|
||||
@@ -206,13 +205,6 @@ api_get_current_recipient(void)
|
||||
}
|
||||
}
|
||||
|
||||
gchar*
|
||||
api_get_current_window(void)
|
||||
{
|
||||
ProfWin* current = wins_get_current();
|
||||
return win_get_title(current);
|
||||
}
|
||||
|
||||
char*
|
||||
api_get_current_muc(void)
|
||||
{
|
||||
|
||||
@@ -46,7 +46,6 @@ void api_notify(const char* message, const char* category, int timeout_ms);
|
||||
void api_send_line(char* line);
|
||||
|
||||
char* api_get_current_recipient(void);
|
||||
gchar* api_get_current_window(void);
|
||||
char* api_get_current_muc(void);
|
||||
gboolean api_current_win_is_console(void);
|
||||
char* api_get_current_nick(void);
|
||||
|
||||
@@ -165,12 +165,6 @@ c_api_get_current_recipient(void)
|
||||
return api_get_current_recipient();
|
||||
}
|
||||
|
||||
static char*
|
||||
c_api_get_current_window(void)
|
||||
{
|
||||
return api_get_current_window();
|
||||
}
|
||||
|
||||
static char*
|
||||
c_api_get_current_muc(void)
|
||||
{
|
||||
@@ -483,7 +477,6 @@ c_api_init(void)
|
||||
prof_notify = c_api_notify;
|
||||
prof_send_line = c_api_send_line;
|
||||
prof_get_current_recipient = c_api_get_current_recipient;
|
||||
prof_get_current_window = c_api_get_current_window;
|
||||
prof_get_current_muc = c_api_get_current_muc;
|
||||
prof_current_win_is_console = c_api_current_win_is_console;
|
||||
prof_get_current_nick = c_api_get_current_nick;
|
||||
|
||||
@@ -62,7 +62,6 @@ void (*prof_notify)(const char* message, int timeout_ms, const char* category) =
|
||||
void (*prof_send_line)(char* line) = NULL;
|
||||
|
||||
char* (*prof_get_current_recipient)(void) = NULL;
|
||||
char* (*prof_get_current_window)(void) = NULL;
|
||||
char* (*prof_get_current_muc)(void) = NULL;
|
||||
int (*prof_current_win_is_console)(void) = NULL;
|
||||
char* (*prof_get_current_nick)(void) = NULL;
|
||||
|
||||
@@ -71,7 +71,6 @@ void (*prof_notify)(const char* message, int timeout_ms, const char* category);
|
||||
void (*prof_send_line)(char* line);
|
||||
|
||||
char* (*prof_get_current_recipient)(void);
|
||||
char* (*prof_get_current_window)(void);
|
||||
char* (*prof_get_current_muc)(void);
|
||||
int (*prof_current_win_is_console)(void);
|
||||
char* (*prof_get_current_nick)(void);
|
||||
|
||||
@@ -415,15 +415,6 @@ python_api_get_current_recipient(PyObject* self, PyObject* args)
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
python_api_get_current_window(PyObject* self, PyObject* args)
|
||||
{
|
||||
allow_python_threads();
|
||||
auto_gchar gchar* recipient = api_get_current_window();
|
||||
disable_python_threads();
|
||||
return Py_BuildValue("s", recipient);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
python_api_get_current_muc(PyObject* self, PyObject* args)
|
||||
{
|
||||
@@ -1539,7 +1530,6 @@ static PyMethodDef apiMethods[] = {
|
||||
{ "send_line", python_api_send_line, METH_VARARGS, "Send a line of input." },
|
||||
{ "notify", python_api_notify, METH_VARARGS, "Send desktop notification." },
|
||||
{ "get_current_recipient", python_api_get_current_recipient, METH_VARARGS, "Return the jid of the recipient of the current window." },
|
||||
{ "get_current_window", python_api_get_current_window, METH_VARARGS, "Return title of the current window." },
|
||||
{ "get_current_muc", python_api_get_current_muc, METH_VARARGS, "Return the jid of the room of the current window." },
|
||||
{ "get_current_nick", python_api_get_current_nick, METH_VARARGS, "Return nickname in current room." },
|
||||
{ "get_name_from_roster", python_api_get_name_from_roster, METH_VARARGS, "Return nickname in roster of barejid." },
|
||||
|
||||
@@ -99,6 +99,7 @@ _buffer_add(ProfBuff buffer, const char* show_char, int pad_indent, GDateTime* t
|
||||
|
||||
// With 10% margin to ensure overflow prevention
|
||||
while (buffer->lines >= PAD_SIZE - (PAD_SIZE / 10) && g_slist_length(buffer->entries) > 1) {
|
||||
log_debug("DELETING");
|
||||
// Delete message from the opposite size to free buffer
|
||||
GSList* buffer_entry_to_delete = append ? buffer->entries : g_slist_last(buffer->entries);
|
||||
ProfBuffEntry* entry_to_delete = (ProfBuffEntry*)buffer_entry_to_delete->data;
|
||||
|
||||
@@ -268,7 +268,11 @@ _show_scrolled(ProfWin* current)
|
||||
wattroff(win, bracket_attrs);
|
||||
|
||||
wattron(win, scrolled_attrs);
|
||||
wprintw(win, "SCROLLED");
|
||||
if (current->layout->unread_msg == 0) {
|
||||
wprintw(win, "SCROLLED");
|
||||
} else {
|
||||
wprintw(win, "SCROLLED, NEW MESSAGES");
|
||||
}
|
||||
wattroff(win, scrolled_attrs);
|
||||
|
||||
wattron(win, bracket_attrs);
|
||||
|
||||
@@ -120,6 +120,7 @@ typedef struct prof_layout_t
|
||||
ProfBuff buffer;
|
||||
int y_pos;
|
||||
int paged;
|
||||
int unread_msg;
|
||||
} ProfLayout;
|
||||
|
||||
typedef struct prof_layout_simple_t
|
||||
|
||||
@@ -103,6 +103,7 @@ _win_create_simple_layout(void)
|
||||
layout->base.buffer = buffer_create();
|
||||
layout->base.y_pos = 0;
|
||||
layout->base.paged = 0;
|
||||
layout->base.unread_msg = 0;
|
||||
scrollok(layout->base.win, TRUE);
|
||||
|
||||
return &layout->base;
|
||||
@@ -120,6 +121,7 @@ _win_create_split_layout(void)
|
||||
layout->base.buffer = buffer_create();
|
||||
layout->base.y_pos = 0;
|
||||
layout->base.paged = 0;
|
||||
layout->base.unread_msg = 0;
|
||||
scrollok(layout->base.win, TRUE);
|
||||
layout->subwin = NULL;
|
||||
layout->sub_y_pos = 0;
|
||||
@@ -197,6 +199,7 @@ win_create_muc(const char* const roomjid)
|
||||
layout->base.buffer = buffer_create();
|
||||
layout->base.y_pos = 0;
|
||||
layout->base.paged = 0;
|
||||
layout->base.unread_msg = 0;
|
||||
scrollok(layout->base.win, TRUE);
|
||||
new_win->window.layout = (ProfLayout*)layout;
|
||||
|
||||
@@ -709,7 +712,7 @@ win_page_down(ProfWin* window, int scroll_size)
|
||||
*page_start += scroll_size;
|
||||
|
||||
// Scrolled down after reaching the bottom of the page
|
||||
if ((*page_start > total_rows - page_space || (*page_start == page_space && *page_start >= total_rows)) && window->type == WIN_CHAT) {
|
||||
if (((*page_start > total_rows + window->layout->unread_msg - page_space) || ((*page_start == page_space + window->layout->unread_msg) && *page_start >= (total_rows + window->layout->unread_msg))) && window->type == WIN_CHAT) {
|
||||
int bf_size = buffer_size(window->layout->buffer);
|
||||
if (bf_size > 0 && *scroll_state != WIN_SCROLL_REACHED_BOTTOM) {
|
||||
// How many lines are left until end of the screen
|
||||
@@ -743,13 +746,15 @@ win_page_down(ProfWin* window, int scroll_size)
|
||||
window->layout->paged = 1;
|
||||
|
||||
// update only if position has changed
|
||||
if (page_start_initial != *page_start) {
|
||||
if ((page_start_initial != *page_start) || (window->layout->unread_msg)) {
|
||||
win_update_virtual(window);
|
||||
}
|
||||
|
||||
// switch off page if last line and space line visible
|
||||
if (total_rows - *page_start == page_space) {
|
||||
/*switch off page if no messages left to read
|
||||
TODO: update buffer end handling to check meassages just after last entry*/
|
||||
if (*scroll_state == WIN_SCROLL_REACHED_BOTTOM) {
|
||||
window->layout->paged = 0;
|
||||
window->layout->unread_msg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -810,6 +815,7 @@ win_clear(ProfWin* window)
|
||||
int* page_start = &(window->layout->y_pos);
|
||||
*page_start = y;
|
||||
window->layout->paged = 1;
|
||||
window->layout->unread_msg = 0;
|
||||
win_update_virtual(window);
|
||||
}
|
||||
|
||||
@@ -914,6 +920,7 @@ void
|
||||
win_move_to_end(ProfWin* window)
|
||||
{
|
||||
window->layout->paged = 0;
|
||||
window->layout->unread_msg = 0;
|
||||
|
||||
int rows = getmaxy(stdscr);
|
||||
int y = getcury(window->layout->win);
|
||||
@@ -1696,6 +1703,13 @@ win_newline(ProfWin* window)
|
||||
static void
|
||||
_win_printf(ProfWin* window, const char* show_char, int pad_indent, GDateTime* timestamp, int flags, theme_item_t theme_item, const char* const display_from, const char* const from_jid, const char* const message_id, const char* const message, ...)
|
||||
{
|
||||
|
||||
/* Prevent printing and buffer update when user is viewing message history [SCROLLING]*/
|
||||
if ((window->layout->paged) && wins_is_current(window)) {
|
||||
window->layout->unread_msg++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (timestamp == NULL) {
|
||||
timestamp = g_date_time_new_now_local();
|
||||
} else {
|
||||
|
||||
@@ -312,7 +312,6 @@ iq_reg2_cb(xmpp_conn_t* xmpp_conn, xmpp_stanza_t* stanza, void* userdata)
|
||||
goto quit;
|
||||
|
||||
quit:
|
||||
log_debug("[CONNDBG] iq_reg2_cb: disconnecting after registration completion");
|
||||
xmpp_disconnect(xmpp_conn);
|
||||
|
||||
return 0;
|
||||
@@ -551,7 +550,6 @@ connection_disconnect(void)
|
||||
// don't disconnect already disconnected connection,
|
||||
// or we get infinite loop otherwise
|
||||
if (conn.conn_last_event == XMPP_CONN_CONNECT) {
|
||||
log_debug("[CONNDBG] connection_disconnect: user-initiated disconnect (status=%d)", (int)conn.conn_status);
|
||||
conn.conn_status = JABBER_DISCONNECTING;
|
||||
xmpp_disconnect(conn.xmpp_conn);
|
||||
|
||||
@@ -559,7 +557,6 @@ connection_disconnect(void)
|
||||
session_process_events();
|
||||
}
|
||||
} else {
|
||||
log_debug("[CONNDBG] connection_disconnect: already disconnected (last_event=%d)", (int)conn.conn_last_event);
|
||||
conn.conn_status = JABBER_DISCONNECTED;
|
||||
}
|
||||
|
||||
@@ -1022,9 +1019,6 @@ _connection_handler(xmpp_conn_t* const xmpp_conn, const xmpp_conn_event_t status
|
||||
// disconnected
|
||||
case XMPP_CONN_DISCONNECT:
|
||||
log_debug("Connection handler: XMPP_CONN_DISCONNECT");
|
||||
log_debug("[CONNDBG] disconnect: previous_status=%d error=%d has_stream_error=%s",
|
||||
(int)conn.conn_status, error,
|
||||
(stream_error && stream_error->stanza) ? "yes" : "no");
|
||||
|
||||
// lost connection for unknown reason
|
||||
if (conn.conn_status == JABBER_CONNECTED || conn.conn_status == JABBER_DISCONNECTING) {
|
||||
|
||||
@@ -218,7 +218,6 @@ session_connect_with_details(const char* const jid, const char* const passwd, co
|
||||
void
|
||||
session_autoping_fail(void)
|
||||
{
|
||||
log_debug("[CONNDBG] session_autoping_fail: autoping timeout, triggering lost connection");
|
||||
session_lost_connection();
|
||||
}
|
||||
|
||||
@@ -265,14 +264,11 @@ session_process_events(void)
|
||||
if ((reconnect_sec != 0) && reconnect_timer) {
|
||||
int elapsed_sec = g_timer_elapsed(reconnect_timer, NULL);
|
||||
if (elapsed_sec > reconnect_sec) {
|
||||
log_debug("[CONNDBG] session_process_events: auto-reconnect triggered after %d seconds (threshold=%d)",
|
||||
elapsed_sec, reconnect_sec);
|
||||
session_reconnect_now();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JABBER_RECONNECT:
|
||||
log_debug("[CONNDBG] session_process_events: JABBER_RECONNECT state, calling session_reconnect_now");
|
||||
session_reconnect_now();
|
||||
break;
|
||||
default:
|
||||
@@ -331,12 +327,12 @@ session_login_success(gboolean secured)
|
||||
|
||||
// logged in with account
|
||||
if (saved_account.name) {
|
||||
log_debug("[CONNDBG] Connection handler: logged in with account name: %s", saved_account.name);
|
||||
log_debug("Connection handler: logged in with account name: %s", saved_account.name);
|
||||
sv_ev_login_account_success(saved_account.name, secured);
|
||||
|
||||
// logged in without account, use details to create new account
|
||||
} else {
|
||||
log_debug("[CONNDBG] Connection handler: logged in with jid: %s", saved_details.name);
|
||||
log_debug("Connection handler: logged in with jid: %s", saved_details.name);
|
||||
accounts_add(saved_details.name, saved_details.altdomain, saved_details.port, saved_details.tls_policy, saved_details.auth_policy);
|
||||
accounts_set_jid(saved_details.name, saved_details.jid);
|
||||
|
||||
@@ -375,11 +371,11 @@ void
|
||||
session_login_failed(void)
|
||||
{
|
||||
if (reconnect_timer == NULL) {
|
||||
log_debug("[CONNDBG] Connection handler: No reconnect timer");
|
||||
log_debug("Connection handler: No reconnect timer");
|
||||
sv_ev_failed_login();
|
||||
_session_free_internals();
|
||||
} else {
|
||||
log_debug("[CONNDBG] Connection handler: Restarting reconnect timer");
|
||||
log_debug("Connection handler: Restarting reconnect timer");
|
||||
if (prefs_get_reconnect() != 0) {
|
||||
g_timer_start(reconnect_timer);
|
||||
}
|
||||
@@ -393,16 +389,12 @@ session_login_failed(void)
|
||||
void
|
||||
session_lost_connection(void)
|
||||
{
|
||||
log_debug("[CONNDBG] session_lost_connection: connection lost, reconnect_interval=%d",
|
||||
prefs_get_reconnect());
|
||||
/* this callback also clears all cached data */
|
||||
sv_ev_lost_connection();
|
||||
if (prefs_get_reconnect() != 0) {
|
||||
assert(reconnect_timer == NULL);
|
||||
reconnect_timer = g_timer_new();
|
||||
log_debug("[CONNDBG] session_lost_connection: reconnect timer started");
|
||||
} else {
|
||||
log_debug("[CONNDBG] session_lost_connection: auto-reconnect disabled, cleaning up");
|
||||
_session_free_internals();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,3 @@
|
||||
/*
|
||||
* functionaltests.c
|
||||
*
|
||||
* Functional tests for CProof XMPP client.
|
||||
* Uses cmocka framework with stabber mock XMPP server.
|
||||
*
|
||||
* Each test is wrapped with PROF_FUNC_TEST macro which sets up
|
||||
* init_prof_test (starts stabber server and profanity client)
|
||||
* and close_prof_test (cleanup) as setup/teardown functions.
|
||||
*
|
||||
* NOTE: We restart client and server for each test to ensure complete
|
||||
* isolation. This prevents state leakage between tests (roster entries,
|
||||
* MUC rooms, presence subscriptions, etc.). While slower, it eliminates
|
||||
* flaky tests caused by leftover state. The overhead is acceptable since
|
||||
* functional tests run less frequently than unit tests.
|
||||
*
|
||||
* Tests are organized into groups for better maintainability:
|
||||
* Group 1: Connection, Ping, Rooms, Presence
|
||||
* Group 2: Messages, Receipts, Roster management
|
||||
* Group 3: MUC (Multi-User Chat) functionality
|
||||
* Group 4: Carbons, Chat sessions, Software version, Disconnect
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@@ -43,41 +20,30 @@
|
||||
#include "test_muc.h"
|
||||
#include "test_disconnect.h"
|
||||
|
||||
/* Macro to wrap each test with setup/teardown functions */
|
||||
#define PROF_FUNC_TEST(test) cmocka_unit_test_setup_teardown(test, init_prof_test, close_prof_test)
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
const struct CMUnitTest all_tests[] = {
|
||||
|
||||
/* ============================================================
|
||||
* GROUP 1: Connect, Ping, Rooms, Presence
|
||||
* Basic XMPP session establishment and presence management
|
||||
* ============================================================ */
|
||||
|
||||
/* Connection tests - verify login, roster, bookmarks */
|
||||
PROF_FUNC_TEST(connect_jid_requests_roster),
|
||||
PROF_FUNC_TEST(connect_jid_sends_presence_after_receiving_roster),
|
||||
PROF_FUNC_TEST(connect_jid_requests_bookmarks),
|
||||
PROF_FUNC_TEST(connect_bad_password),
|
||||
PROF_FUNC_TEST(connect_shows_presence_updates),
|
||||
|
||||
/* Ping tests - XEP-0199 XMPP Ping */
|
||||
PROF_FUNC_TEST(ping_server),
|
||||
PROF_FUNC_TEST(ping_server_not_supported),
|
||||
PROF_FUNC_TEST(ping_responds_to_server_request),
|
||||
PROF_FUNC_TEST(ping_jid),
|
||||
PROF_FUNC_TEST(ping_jid_not_supported),
|
||||
|
||||
/* Room discovery - XEP-0045 */
|
||||
PROF_FUNC_TEST(rooms_query),
|
||||
|
||||
/* Presence tests - online/away/xa/dnd/chat status */
|
||||
PROF_FUNC_TEST(presence_online),
|
||||
PROF_FUNC_TEST(presence_online_with_message),
|
||||
PROF_FUNC_TEST(presence_away),
|
||||
PROF_FUNC_TEST(presence_away_with_message),
|
||||
PROF_FUNC_TEST(presence_online),
|
||||
PROF_FUNC_TEST(presence_online_with_message),
|
||||
PROF_FUNC_TEST(presence_xa),
|
||||
PROF_FUNC_TEST(presence_xa_with_message),
|
||||
PROF_FUNC_TEST(presence_dnd),
|
||||
@@ -90,69 +56,10 @@ main(int argc, char* argv[])
|
||||
PROF_FUNC_TEST(presence_received),
|
||||
PROF_FUNC_TEST(presence_missing_resource_defaults),
|
||||
|
||||
/* ============================================================
|
||||
* GROUP 2: Message, Receipts, Roster
|
||||
* Core messaging and contact management
|
||||
* ============================================================ */
|
||||
|
||||
/* Basic message send/receive */
|
||||
PROF_FUNC_TEST(message_send),
|
||||
PROF_FUNC_TEST(message_receive_console),
|
||||
PROF_FUNC_TEST(message_receive_chatwin),
|
||||
|
||||
/* Message receipts - XEP-0184 */
|
||||
PROF_FUNC_TEST(does_not_send_receipt_request_to_barejid),
|
||||
PROF_FUNC_TEST(send_receipt_request),
|
||||
PROF_FUNC_TEST(send_receipt_on_request),
|
||||
|
||||
/* Roster management - add/remove/rename contacts */
|
||||
PROF_FUNC_TEST(sends_new_item),
|
||||
PROF_FUNC_TEST(sends_new_item_nick),
|
||||
PROF_FUNC_TEST(sends_remove_item),
|
||||
PROF_FUNC_TEST(sends_remove_item_nick),
|
||||
PROF_FUNC_TEST(sends_nick_change),
|
||||
|
||||
/* ============================================================
|
||||
* GROUP 3: MUC (Multi-User Chat)
|
||||
* XEP-0045 conference room functionality
|
||||
* ============================================================ */
|
||||
|
||||
/* Room join with various options */
|
||||
PROF_FUNC_TEST(sends_room_join),
|
||||
PROF_FUNC_TEST(sends_room_join_with_nick),
|
||||
PROF_FUNC_TEST(sends_room_join_with_password),
|
||||
PROF_FUNC_TEST(sends_room_join_with_nick_and_password),
|
||||
|
||||
/* Room information display */
|
||||
PROF_FUNC_TEST(shows_role_and_affiliation_on_join),
|
||||
PROF_FUNC_TEST(shows_subject_on_join),
|
||||
// PROF_FUNC_TEST(shows_history_message), // temporarily disabled due to timing issues in CI
|
||||
PROF_FUNC_TEST(shows_occupant_join),
|
||||
|
||||
/* MUC messaging */
|
||||
PROF_FUNC_TEST(shows_message),
|
||||
PROF_FUNC_TEST(shows_me_message_from_occupant),
|
||||
PROF_FUNC_TEST(shows_me_message_from_self),
|
||||
|
||||
/* Console notification settings for MUC */
|
||||
PROF_FUNC_TEST(shows_all_messages_in_console_when_window_not_focussed),
|
||||
PROF_FUNC_TEST(shows_first_message_in_console_when_window_not_focussed),
|
||||
PROF_FUNC_TEST(shows_no_message_in_console_when_window_not_focussed),
|
||||
|
||||
/* ============================================================
|
||||
* GROUP 4: Carbons, Chat Session, Software, Disconnect
|
||||
* Message synchronization and session management
|
||||
* ============================================================ */
|
||||
|
||||
/* Message Carbons - XEP-0280 (message sync across devices) */
|
||||
PROF_FUNC_TEST(send_enable_carbons),
|
||||
PROF_FUNC_TEST(connect_with_carbons_enabled),
|
||||
PROF_FUNC_TEST(send_disable_carbons),
|
||||
PROF_FUNC_TEST(receive_carbon),
|
||||
PROF_FUNC_TEST(receive_self_carbon),
|
||||
PROF_FUNC_TEST(receive_private_carbon),
|
||||
|
||||
/* Chat session management - bare/full JID routing */
|
||||
PROF_FUNC_TEST(sends_message_to_barejid_when_contact_offline),
|
||||
PROF_FUNC_TEST(sends_message_to_barejid_when_contact_online),
|
||||
PROF_FUNC_TEST(sends_message_to_fulljid_when_received_from_fulljid),
|
||||
@@ -160,7 +67,22 @@ main(int argc, char* argv[])
|
||||
PROF_FUNC_TEST(resets_to_barejid_after_presence_received),
|
||||
PROF_FUNC_TEST(new_session_when_message_received_from_different_fulljid),
|
||||
|
||||
/* Software Version - XEP-0092 */
|
||||
PROF_FUNC_TEST(send_enable_carbons),
|
||||
PROF_FUNC_TEST(connect_with_carbons_enabled),
|
||||
PROF_FUNC_TEST(send_disable_carbons),
|
||||
PROF_FUNC_TEST(receive_carbon),
|
||||
PROF_FUNC_TEST(receive_self_carbon),
|
||||
PROF_FUNC_TEST(receive_private_carbon),
|
||||
|
||||
PROF_FUNC_TEST(send_receipt_request),
|
||||
PROF_FUNC_TEST(send_receipt_on_request),
|
||||
PROF_FUNC_TEST(does_not_send_receipt_request_to_barejid),
|
||||
PROF_FUNC_TEST(sends_new_item),
|
||||
PROF_FUNC_TEST(sends_new_item_nick),
|
||||
PROF_FUNC_TEST(sends_remove_item),
|
||||
PROF_FUNC_TEST(sends_remove_item_nick),
|
||||
PROF_FUNC_TEST(sends_nick_change),
|
||||
|
||||
PROF_FUNC_TEST(send_software_version_request),
|
||||
PROF_FUNC_TEST(display_software_version_result),
|
||||
PROF_FUNC_TEST(shows_message_when_software_version_error),
|
||||
@@ -168,7 +90,21 @@ main(int argc, char* argv[])
|
||||
PROF_FUNC_TEST(show_message_in_chat_window_when_no_resource),
|
||||
PROF_FUNC_TEST(display_software_version_result_in_chat),
|
||||
|
||||
/* Disconnect - clean session termination */
|
||||
PROF_FUNC_TEST(sends_room_join),
|
||||
PROF_FUNC_TEST(sends_room_join_with_nick),
|
||||
PROF_FUNC_TEST(sends_room_join_with_password),
|
||||
PROF_FUNC_TEST(sends_room_join_with_nick_and_password),
|
||||
PROF_FUNC_TEST(shows_role_and_affiliation_on_join),
|
||||
PROF_FUNC_TEST(shows_subject_on_join),
|
||||
PROF_FUNC_TEST(shows_history_message),
|
||||
PROF_FUNC_TEST(shows_occupant_join),
|
||||
PROF_FUNC_TEST(shows_message),
|
||||
PROF_FUNC_TEST(shows_me_message_from_occupant),
|
||||
PROF_FUNC_TEST(shows_me_message_from_self),
|
||||
PROF_FUNC_TEST(shows_all_messages_in_console_when_window_not_focussed),
|
||||
PROF_FUNC_TEST(shows_first_message_in_console_when_window_not_focussed),
|
||||
PROF_FUNC_TEST(shows_no_message_in_console_when_window_not_focussed),
|
||||
|
||||
PROF_FUNC_TEST(disconnect_ends_session),
|
||||
};
|
||||
|
||||
|
||||
@@ -8,12 +8,9 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pty.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/select.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
@@ -21,20 +18,6 @@ char *config_orig;
|
||||
char *data_orig;
|
||||
|
||||
int fd = 0;
|
||||
int stub_port = 5230;
|
||||
pid_t child_pid = 0;
|
||||
|
||||
/*
|
||||
* Buffer for accumulating output from profanity.
|
||||
* 64KB is sufficient for typical test output while keeping memory usage
|
||||
* reasonable. When full, older half is discarded (ring buffer behavior).
|
||||
*/
|
||||
#define OUTPUT_BUF_SIZE 65536
|
||||
static char output_buffer[OUTPUT_BUF_SIZE];
|
||||
static size_t output_len = 0;
|
||||
|
||||
/* Timeout for expect operations in seconds */
|
||||
static int expect_timeout = 30;
|
||||
|
||||
gboolean
|
||||
_create_dir(const char *name)
|
||||
@@ -135,105 +118,31 @@ _cleanup_dirs(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read available data from fd into output_buffer with timeout.
|
||||
* Returns number of bytes read, 0 on timeout, -1 on error.
|
||||
*/
|
||||
static int
|
||||
_read_output(int timeout_ms)
|
||||
{
|
||||
fd_set readfds;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd, &readfds);
|
||||
|
||||
tv.tv_sec = timeout_ms / 1000;
|
||||
tv.tv_usec = (timeout_ms % 1000) * 1000;
|
||||
|
||||
int ret = select(fd + 1, &readfds, NULL, NULL, &tv);
|
||||
if (ret <= 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t space = OUTPUT_BUF_SIZE - output_len - 1;
|
||||
if (space <= 0) {
|
||||
/* Buffer full, shift content */
|
||||
memmove(output_buffer, output_buffer + OUTPUT_BUF_SIZE/2, OUTPUT_BUF_SIZE/2);
|
||||
output_len = OUTPUT_BUF_SIZE/2;
|
||||
space = OUTPUT_BUF_SIZE - output_len - 1;
|
||||
}
|
||||
|
||||
ssize_t n = read(fd, output_buffer + output_len, space);
|
||||
if (n > 0) {
|
||||
output_len += n;
|
||||
output_buffer[output_len] = '\0';
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Custom implementation of exp_spawnl using forkpty.
|
||||
* This avoids the segfault bug in libexpect on Arch Linux.
|
||||
*/
|
||||
void
|
||||
prof_start(void)
|
||||
{
|
||||
struct winsize ws;
|
||||
ws.ws_row = 24;
|
||||
ws.ws_col = 300; /* Match COLUMNS=300 from start_profanity.sh */
|
||||
ws.ws_xpixel = 0;
|
||||
ws.ws_ypixel = 0;
|
||||
|
||||
/* Reset output buffer */
|
||||
output_len = 0;
|
||||
output_buffer[0] = '\0';
|
||||
|
||||
child_pid = forkpty(&fd, NULL, NULL, &ws);
|
||||
|
||||
if (child_pid < 0) {
|
||||
fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (child_pid == 0) {
|
||||
/* Child process */
|
||||
setenv("COLUMNS", "300", 1);
|
||||
setenv("TERM", "xterm", 1);
|
||||
|
||||
execl("./profanity", "./profanity", "-l", "DEBUG", NULL);
|
||||
|
||||
/* If exec fails */
|
||||
fprintf(stderr, "execl failed: %s\n", strerror(errno));
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
/* Parent process */
|
||||
/* Set non-blocking mode for reading */
|
||||
int flags = fcntl(fd, F_GETFL, 0);
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
// 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
|
||||
init_prof_test(void **state)
|
||||
{
|
||||
gboolean started = FALSE;
|
||||
for (int p = 5230; p < 5250; ++p) {
|
||||
int ret = stbbr_start(STBBR_LOGDEBUG, p, 0);
|
||||
if (ret == 0) {
|
||||
stub_port = p;
|
||||
started = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!started) {
|
||||
assert_true(FALSE); // could not start stabber on any port in range
|
||||
if (stbbr_start(STBBR_LOGDEBUG ,5230, 0) != 0) {
|
||||
assert_true(FALSE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Give stabber server thread time to start listening
|
||||
usleep(100000); // 100ms
|
||||
|
||||
config_orig = getenv("XDG_CONFIG_HOME");
|
||||
data_orig = getenv("XDG_DATA_HOME");
|
||||
|
||||
@@ -248,69 +157,50 @@ init_prof_test(void **state)
|
||||
_create_logs_dir();
|
||||
|
||||
prof_start();
|
||||
int prof_started = prof_output_regex("CProof\\. Type /help for help information\\.");
|
||||
assert_true(prof_started);
|
||||
assert_true(prof_output_exact("Profanity"));
|
||||
|
||||
// set UI options to make expect assertions faster and more reliable
|
||||
prof_input("/inpblock timeout 5");
|
||||
assert_true(prof_output_regex("Input blocking set to 5 milliseconds"));
|
||||
assert_true(prof_output_exact("Input blocking set to 5 milliseconds"));
|
||||
prof_input("/inpblock dynamic off");
|
||||
assert_true(prof_output_regex("Dynamic input blocking disabled"));
|
||||
assert_true(prof_output_exact("Dynamic input blocking disabled"));
|
||||
prof_input("/notify chat off");
|
||||
assert_true(prof_output_regex("Chat notifications disabled"));
|
||||
assert_true(prof_output_exact("Chat notifications disabled"));
|
||||
prof_input("/notify room off");
|
||||
assert_true(prof_output_regex("Room notifications disabled"));
|
||||
assert_true(prof_output_exact("Room notifications disabled"));
|
||||
prof_input("/wrap off");
|
||||
assert_true(prof_output_regex("Word wrap disabled"));
|
||||
assert_true(prof_output_exact("Word wrap disabled"));
|
||||
prof_input("/roster hide");
|
||||
assert_true(prof_output_regex("Roster disabled"));
|
||||
assert_true(prof_output_exact("Roster disabled"));
|
||||
prof_input("/occupants default hide");
|
||||
assert_true(prof_output_regex("Occupant list disabled"));
|
||||
assert_true(prof_output_exact("Occupant list disabled"));
|
||||
prof_input("/time console off");
|
||||
prof_input("/time console off");
|
||||
assert_true(prof_output_regex("Console time display disabled\\."));
|
||||
assert_true(prof_output_exact("Console time display disabled."));
|
||||
prof_input("/time chat off");
|
||||
assert_true(prof_output_regex("Chat time display disabled\\."));
|
||||
assert_true(prof_output_exact("Chat time display disabled."));
|
||||
prof_input("/time muc off");
|
||||
assert_true(prof_output_regex("MUC time display disabled\\."));
|
||||
assert_true(prof_output_exact("MUC time display disabled."));
|
||||
prof_input("/time config off");
|
||||
assert_true(prof_output_regex("Config time display disabled\\."));
|
||||
assert_true(prof_output_exact("config time display disabled."));
|
||||
prof_input("/time private off");
|
||||
assert_true(prof_output_regex("Private chat time display disabled\\."));
|
||||
assert_true(prof_output_exact("Private chat time display disabled."));
|
||||
prof_input("/time xml off");
|
||||
assert_true(prof_output_regex("XML Console time display disabled\\."));
|
||||
assert_true(prof_output_exact("XML Console time display disabled."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
close_prof_test(void **state)
|
||||
{
|
||||
if (fd > 0 && child_pid > 0) {
|
||||
prof_input("/quit");
|
||||
// Give profanity time to process quit command
|
||||
sleep(1);
|
||||
waitpid(child_pid, NULL, 0);
|
||||
close(fd);
|
||||
fd = 0;
|
||||
child_pid = 0;
|
||||
}
|
||||
prof_input("/quit");
|
||||
waitpid(exp_pid, NULL, 0);
|
||||
_cleanup_dirs();
|
||||
|
||||
if (config_orig) {
|
||||
setenv("XDG_CONFIG_HOME", config_orig, 1);
|
||||
}
|
||||
if (data_orig) {
|
||||
setenv("XDG_DATA_HOME", data_orig, 1);
|
||||
}
|
||||
setenv("XDG_CONFIG_HOME", config_orig, 1);
|
||||
setenv("XDG_DATA_HOME", data_orig, 1);
|
||||
|
||||
stbbr_stop();
|
||||
/*
|
||||
* TODO: Replace with proper synchronization.
|
||||
* stabber doesn't provide wait_stopped() API yet, so we use delay
|
||||
* to ensure the port is released before the next test starts.
|
||||
* See: https://git.jabber.space/devs/stabber/issues/3
|
||||
*/
|
||||
usleep(100000); // 100ms
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -319,75 +209,20 @@ prof_input(const char *input)
|
||||
{
|
||||
GString *inp_str = g_string_new(input);
|
||||
g_string_append(inp_str, "\r");
|
||||
ssize_t _wn = write(fd, inp_str->str, inp_str->len);
|
||||
(void)_wn;
|
||||
write(fd, inp_str->str, inp_str->len);
|
||||
g_string_free(inp_str, TRUE);
|
||||
|
||||
/* Small delay to let profanity process input */
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for exact text to appear in output.
|
||||
* Returns 1 if found, 0 if timeout.
|
||||
*/
|
||||
int
|
||||
prof_output_exact(const char *text)
|
||||
{
|
||||
time_t start = time(NULL);
|
||||
|
||||
while (time(NULL) - start < expect_timeout) {
|
||||
/* Read any available output */
|
||||
while (_read_output(100) > 0) {
|
||||
/* Keep reading while data available */
|
||||
}
|
||||
|
||||
/* Check if text is in buffer */
|
||||
if (strstr(output_buffer, text) != NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
usleep(50000); /* 50ms */
|
||||
}
|
||||
|
||||
return 0;
|
||||
return (1 == exp_expectl(fd, exp_exact, text, 1, exp_end));
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for regex pattern to match in output.
|
||||
* Returns 1 if found, 0 if timeout.
|
||||
*/
|
||||
int
|
||||
prof_output_regex(const char *pattern)
|
||||
prof_output_regex(const char *text)
|
||||
{
|
||||
regex_t regex;
|
||||
int ret;
|
||||
|
||||
ret = regcomp(®ex, pattern, REG_EXTENDED | REG_NOSUB);
|
||||
if (ret != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t start = time(NULL);
|
||||
|
||||
while (time(NULL) - start < expect_timeout) {
|
||||
/* Read any available output */
|
||||
while (_read_output(100) > 0) {
|
||||
/* Keep reading while data available */
|
||||
}
|
||||
|
||||
/* Check if pattern matches */
|
||||
ret = regexec(®ex, output_buffer, 0, NULL, 0);
|
||||
if (ret == 0) {
|
||||
regfree(®ex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
usleep(50000); /* 50ms */
|
||||
}
|
||||
|
||||
regfree(®ex);
|
||||
return 0;
|
||||
return (1 == exp_expectl(fd, exp_regexp, text, 1, exp_end));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -406,40 +241,33 @@ prof_connect_with_roster(const char *roster)
|
||||
stbbr_for_query("jabber:iq:roster", roster_str->str);
|
||||
g_string_free(roster_str, TRUE);
|
||||
|
||||
stbbr_auth_passwd("password");
|
||||
stbbr_for_id("prof_presence_1",
|
||||
"<presence id='prof_presence_1' 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>"
|
||||
);
|
||||
|
||||
char connect_cmd[128];
|
||||
snprintf(connect_cmd, sizeof(connect_cmd), "/connect stabber@localhost server 127.0.0.1 port %d tls disable auth legacy", stub_port);
|
||||
prof_input(connect_cmd);
|
||||
|
||||
assert_true(prof_output_regex("password:"));
|
||||
prof_input("/connect stabber@localhost server 127.0.0.1 port 5230 tls allow");
|
||||
prof_input("password");
|
||||
|
||||
expect_timeout = 60;
|
||||
assert_true(prof_output_regex("Connecting as stabber@localhost"));
|
||||
assert_true(prof_output_regex("logged in successfully"));
|
||||
assert_true(prof_output_regex(".+online.+ \\(priority 0\\)\\."));
|
||||
|
||||
expect_timeout = 60;
|
||||
// Wait for presence stanza to be sent (content-based, not ID-based)
|
||||
// Match the actual attribute order from stanza_attach_caps
|
||||
assert_true(stbbr_received(
|
||||
"<presence id=\"*\">"
|
||||
"<c xmlns=\"http://jabber.org/protocol/caps\" hash=\"sha-1\" node=\"http://profanity-im.github.io\" ver=\"*\"/>"
|
||||
"</presence>"
|
||||
));
|
||||
// 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_*");
|
||||
}
|
||||
|
||||
void
|
||||
prof_timeout(int timeout)
|
||||
{
|
||||
expect_timeout = timeout;
|
||||
exp_timeout = timeout;
|
||||
}
|
||||
|
||||
void
|
||||
prof_timeout_reset(void)
|
||||
{
|
||||
expect_timeout = 60;
|
||||
exp_timeout = 10;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
#define XDG_CONFIG_HOME "./tests/functionaltests/files/xdg_config_home"
|
||||
#define XDG_DATA_HOME "./tests/functionaltests/files/xdg_data_home"
|
||||
|
||||
extern int stub_port;
|
||||
|
||||
int init_prof_test(void **state);
|
||||
int close_prof_test(void **state);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include <glib.h>
|
||||
#include <unistd.h>
|
||||
#include "prof_cmocka.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
@@ -144,11 +144,7 @@ resets_to_barejid_after_presence_received(void **state)
|
||||
"<show>dnd</show>"
|
||||
"</presence>"
|
||||
);
|
||||
// Wait for presence to be processed before sending next message.
|
||||
// The presence output may appear in console or chat window depending on focus,
|
||||
// so we use a small delay to ensure the session is reset to barejid.
|
||||
// Under Valgrind, processing is slower, so this delay is necessary.
|
||||
g_usleep(500000); // 500ms
|
||||
assert_true(prof_output_exact("Buddy1 (laptop) is dnd"));
|
||||
|
||||
prof_input("/msg buddy1@localhost Outgoing 2");
|
||||
assert_true(stbbr_received(
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
#include "prof_cmocka.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
@@ -47,9 +47,7 @@ connect_jid_requests_bookmarks(void **state)
|
||||
void
|
||||
connect_bad_password(void **state)
|
||||
{
|
||||
char connect_cmd[128];
|
||||
snprintf(connect_cmd, sizeof(connect_cmd), "/connect stabber@localhost server 127.0.0.1 port %d tls allow", stub_port);
|
||||
prof_input(connect_cmd);
|
||||
prof_input("/connect stabber@localhost server 127.0.0.1 port 5230 tls allow");
|
||||
prof_input("badpassword");
|
||||
|
||||
assert_true(prof_output_exact("Login failed."));
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
#include <glib.h>
|
||||
#include <unistd.h>
|
||||
#include "prof_cmocka.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
/*
|
||||
* NOTE: We use prof_output_regex() throughout this file even for seemingly
|
||||
* exact strings because some output may include timestamps, color codes,
|
||||
* or other dynamic content depending on configuration. Using regex provides
|
||||
* more robust matching. For patterns without regex metacharacters, the
|
||||
* performance difference is negligible.
|
||||
*/
|
||||
|
||||
void
|
||||
sends_room_join(void **state)
|
||||
{
|
||||
@@ -23,7 +15,7 @@ sends_room_join(void **state)
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
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'/>"
|
||||
@@ -38,7 +30,7 @@ sends_room_join_with_nick(void **state)
|
||||
|
||||
prof_input("/join testroom@conference.localhost nick testnick");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
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'/>"
|
||||
@@ -53,7 +45,7 @@ sends_room_join_with_password(void **state)
|
||||
|
||||
prof_input("/join testroom@conference.localhost password testpassword");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
assert_true(stbbr_last_received(
|
||||
"<presence id='*' to='testroom@conference.localhost/stabber'>"
|
||||
"<x xmlns='http://jabber.org/protocol/muc'>"
|
||||
"<password>testpassword</password>"
|
||||
@@ -70,7 +62,7 @@ sends_room_join_with_nick_and_password(void **state)
|
||||
|
||||
prof_input("/join testroom@conference.localhost nick testnick password testpassword");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
assert_true(stbbr_last_received(
|
||||
"<presence id='*' to='testroom@conference.localhost/testnick'>"
|
||||
"<x xmlns='http://jabber.org/protocol/muc'>"
|
||||
"<password>testpassword</password>"
|
||||
@@ -85,8 +77,8 @@ shows_role_and_affiliation_on_join(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
stbbr_for_presence_to("testroom@conference.localhost/stabber",
|
||||
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
stbbr_for_id("prof_join_4",
|
||||
"<presence id='prof_join_4' 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'/>"
|
||||
@@ -97,7 +89,7 @@ shows_role_and_affiliation_on_join(void **state)
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
|
||||
assert_true(prof_output_regex("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
assert_true(prof_output_exact("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -105,8 +97,8 @@ shows_subject_on_join(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
stbbr_for_presence_to("testroom@conference.localhost/stabber",
|
||||
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
stbbr_for_id("prof_join_4",
|
||||
"<presence id='prof_join_4' 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'/>"
|
||||
@@ -116,7 +108,7 @@ shows_subject_on_join(void **state)
|
||||
);
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
assert_true(prof_output_regex("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
assert_true(prof_output_exact("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
|
||||
stbbr_send(
|
||||
"<message type='groupchat' to='stabber@localhost/profanity' from='testroom@conference.localhost'>"
|
||||
@@ -133,8 +125,8 @@ shows_history_message(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
stbbr_for_presence_to("testroom@conference.localhost/stabber",
|
||||
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
stbbr_for_id("prof_join_4",
|
||||
"<presence id='prof_join_4' 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'/>"
|
||||
@@ -144,7 +136,7 @@ shows_history_message(void **state)
|
||||
);
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
assert_true(prof_output_regex("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
assert_true(prof_output_exact("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
|
||||
stbbr_send(
|
||||
"<message type='groupchat' to='stabber@localhost/profanity' from='testroom@conference.localhost/testoccupant'>"
|
||||
@@ -154,9 +146,7 @@ shows_history_message(void **state)
|
||||
"</message>"
|
||||
);
|
||||
|
||||
prof_timeout(10);
|
||||
assert_true(prof_output_regex("testoccupant:.*an old message"));
|
||||
prof_timeout_reset();
|
||||
assert_true(prof_output_regex("testoccupant: an old message"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -164,12 +154,8 @@ shows_occupant_join(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
// Enable MUC status messages to see occupant join/leave
|
||||
prof_input("/presence room all");
|
||||
assert_true(prof_output_regex("All presence updates will appear"));
|
||||
|
||||
stbbr_for_presence_to("testroom@conference.localhost/stabber",
|
||||
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
stbbr_for_id("prof_join_4",
|
||||
"<presence id='prof_join_4' 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'/>"
|
||||
@@ -179,7 +165,7 @@ shows_occupant_join(void **state)
|
||||
);
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
assert_true(prof_output_regex("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
assert_true(prof_output_exact("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
|
||||
stbbr_send(
|
||||
"<presence to='stabber@localhost/profanity' from='testroom@conference.localhost/testoccupant'>"
|
||||
@@ -188,9 +174,8 @@ shows_occupant_join(void **state)
|
||||
"</x>"
|
||||
"</presence>"
|
||||
);
|
||||
sleep(1);
|
||||
|
||||
assert_true(prof_output_regex("testoccupant has joined"));
|
||||
assert_true(prof_output_exact("-> testoccupant has joined the room, role: participant, affiliation: none"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -198,8 +183,8 @@ shows_message(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
stbbr_for_presence_to("testroom@conference.localhost/stabber",
|
||||
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
stbbr_for_id("prof_join_4",
|
||||
"<presence id='prof_join_4' 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'/>"
|
||||
@@ -209,7 +194,7 @@ shows_message(void **state)
|
||||
);
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
assert_true(prof_output_regex("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
assert_true(prof_output_exact("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
|
||||
stbbr_send(
|
||||
"<message type='groupchat' to='stabber@localhost/profanity' from='testroom@conference.localhost/testoccupant'>"
|
||||
@@ -225,8 +210,8 @@ shows_me_message_from_occupant(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
stbbr_for_presence_to("testroom@conference.localhost/stabber",
|
||||
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
stbbr_for_id("prof_join_4",
|
||||
"<presence id='prof_join_4' 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'/>"
|
||||
@@ -236,7 +221,7 @@ shows_me_message_from_occupant(void **state)
|
||||
);
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
assert_true(prof_output_regex("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
assert_true(prof_output_exact("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
|
||||
stbbr_send(
|
||||
"<message type='groupchat' to='stabber@localhost/profanity' from='testroom@conference.localhost/testoccupant'>"
|
||||
@@ -244,7 +229,7 @@ shows_me_message_from_occupant(void **state)
|
||||
"</message>"
|
||||
);
|
||||
|
||||
assert_true(prof_output_regex("\\*testoccupant did something"));
|
||||
assert_true(prof_output_exact("*testoccupant did something"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -252,8 +237,8 @@ shows_me_message_from_self(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
stbbr_for_presence_to("testroom@conference.localhost/stabber",
|
||||
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
stbbr_for_id("prof_join_4",
|
||||
"<presence id='prof_join_4' 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'/>"
|
||||
@@ -263,7 +248,7 @@ shows_me_message_from_self(void **state)
|
||||
);
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
assert_true(prof_output_regex("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
assert_true(prof_output_exact("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
|
||||
stbbr_send(
|
||||
"<message type='groupchat' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
@@ -271,7 +256,7 @@ shows_me_message_from_self(void **state)
|
||||
"</message>"
|
||||
);
|
||||
|
||||
assert_true(prof_output_regex("\\*stabber did something"));
|
||||
assert_true(prof_output_exact("*stabber did something"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -279,8 +264,8 @@ shows_all_messages_in_console_when_window_not_focussed(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
stbbr_for_presence_to("testroom@conference.localhost/stabber",
|
||||
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
stbbr_for_id("prof_join_4",
|
||||
"<presence id='prof_join_4' 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'/>"
|
||||
@@ -290,10 +275,10 @@ shows_all_messages_in_console_when_window_not_focussed(void **state)
|
||||
);
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
assert_true(prof_output_regex("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
assert_true(prof_output_exact("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
|
||||
prof_input("/win 1");
|
||||
assert_true(prof_output_regex("CProof\\. Type /help for help information\\."));
|
||||
assert_true(prof_output_exact("CProof. Type /help for help information."));
|
||||
|
||||
stbbr_send(
|
||||
"<message type='groupchat' to='stabber@localhost/profanity' from='testroom@conference.localhost/testoccupant'>"
|
||||
@@ -301,7 +286,7 @@ shows_all_messages_in_console_when_window_not_focussed(void **state)
|
||||
"</message>"
|
||||
);
|
||||
|
||||
assert_true(prof_output_regex("<< room message: testoccupant in testroom@conference\\.localhost \\(win 2\\)"));
|
||||
assert_true(prof_output_exact("<< room message: testoccupant in testroom@conference.localhost (win 2)"));
|
||||
|
||||
stbbr_send(
|
||||
"<message type='groupchat' to='stabber@localhost/profanity' from='testroom@conference.localhost/anotheroccupant'>"
|
||||
@@ -309,7 +294,7 @@ shows_all_messages_in_console_when_window_not_focussed(void **state)
|
||||
"</message>"
|
||||
);
|
||||
|
||||
assert_true(prof_output_regex("<< room message: anotheroccupant in testroom@conference\\.localhost \\(win 2\\)"));
|
||||
assert_true(prof_output_exact("<< room message: anotheroccupant in testroom@conference.localhost (win 2)"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -318,10 +303,10 @@ shows_first_message_in_console_when_window_not_focussed(void **state)
|
||||
prof_connect();
|
||||
|
||||
prof_input("/console muc first");
|
||||
assert_true(prof_output_regex("Console MUC messages set: first"));
|
||||
assert_true(prof_output_exact("Console MUC messages set: first"));
|
||||
|
||||
stbbr_for_presence_to("testroom@conference.localhost/stabber",
|
||||
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
stbbr_for_id("prof_join_4",
|
||||
"<presence id='prof_join_4' 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'/>"
|
||||
@@ -331,22 +316,21 @@ shows_first_message_in_console_when_window_not_focussed(void **state)
|
||||
);
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
assert_true(prof_output_regex("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
assert_true(prof_output_exact("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
|
||||
prof_input("/win 1");
|
||||
assert_true(prof_output_regex("CProof\\. Type /help for help information\\."));
|
||||
assert_true(prof_output_exact("CProof. Type /help for help information."));
|
||||
|
||||
stbbr_send(
|
||||
"<message type='groupchat' to='stabber@localhost/profanity' from='testroom@conference.localhost/testoccupant'>"
|
||||
"<body>a new message</body>"
|
||||
"</message>"
|
||||
);
|
||||
sleep(1);
|
||||
|
||||
assert_true(prof_output_regex("room message.*testroom@conference\\.localhost"));
|
||||
assert_true(prof_output_exact("<< room message: testroom@conference.localhost (win 2)"));
|
||||
prof_input("/clear");
|
||||
prof_input("/about");
|
||||
assert_true(prof_output_regex("Type '/help' to show complete help\\."));
|
||||
assert_true(prof_output_exact("Type '/help' to show complete help."));
|
||||
|
||||
stbbr_send(
|
||||
"<message type='groupchat' to='stabber@localhost/profanity' from='testroom@conference.localhost/anotheroccupant'>"
|
||||
@@ -355,7 +339,7 @@ shows_first_message_in_console_when_window_not_focussed(void **state)
|
||||
);
|
||||
|
||||
prof_timeout(2);
|
||||
assert_false(prof_output_regex("<< room message: testroom@conference\\.localhost \\(win 2\\)"));
|
||||
assert_false(prof_output_exact("<< room message: testroom@conference.localhost (win 2)"));
|
||||
prof_timeout_reset();
|
||||
}
|
||||
|
||||
@@ -365,10 +349,10 @@ shows_no_message_in_console_when_window_not_focussed(void **state)
|
||||
prof_connect();
|
||||
|
||||
prof_input("/console muc none");
|
||||
assert_true(prof_output_regex("Console MUC messages set: none"));
|
||||
assert_true(prof_output_exact("Console MUC messages set: none"));
|
||||
|
||||
stbbr_for_presence_to("testroom@conference.localhost/stabber",
|
||||
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
|
||||
stbbr_for_id("prof_join_4",
|
||||
"<presence id='prof_join_4' 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'/>"
|
||||
@@ -378,10 +362,10 @@ shows_no_message_in_console_when_window_not_focussed(void **state)
|
||||
);
|
||||
|
||||
prof_input("/join testroom@conference.localhost");
|
||||
assert_true(prof_output_regex("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
assert_true(prof_output_exact("-> You have joined the room as stabber, role: participant, affiliation: none"));
|
||||
|
||||
prof_input("/win 1");
|
||||
assert_true(prof_output_regex("CProof\\. Type /help for help information\\."));
|
||||
assert_true(prof_output_exact("CProof. Type /help for help information."));
|
||||
|
||||
stbbr_send(
|
||||
"<message type='groupchat' to='stabber@localhost/profanity' from='testroom@conference.localhost/testoccupant'>"
|
||||
@@ -390,6 +374,6 @@ shows_no_message_in_console_when_window_not_focussed(void **state)
|
||||
);
|
||||
|
||||
prof_timeout(2);
|
||||
assert_false(prof_output_regex("testroom@conference\\.localhost \\(win 2\\)"));
|
||||
assert_false(prof_output_exact("testroom@conference.localhost (win 2)"));
|
||||
prof_timeout_reset();
|
||||
}
|
||||
|
||||
@@ -2,26 +2,17 @@
|
||||
#include "prof_cmocka.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
void
|
||||
ping_server(void **state)
|
||||
{
|
||||
/*
|
||||
* This test verifies that profanity correctly handles the /ping command
|
||||
* when the server supports ping (urn:xmpp:ping feature).
|
||||
*
|
||||
* We register disco#info response with ping support, then verify
|
||||
* profanity sends ping and receives "Pinged server" confirmation.
|
||||
*/
|
||||
|
||||
// Register disco#info response that includes ping support
|
||||
stbbr_for_query("http://jabber.org/protocol/disco#info",
|
||||
"<iq to='stabber@localhost/profanity' type='result' from='localhost'>"
|
||||
stbbr_for_id("prof_disco_info_onconnect_2",
|
||||
"<iq id='prof_disco_info_onconnect_2' 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'/>"
|
||||
@@ -29,33 +20,37 @@ ping_server(void **state)
|
||||
"</iq>"
|
||||
);
|
||||
|
||||
// Register ping response
|
||||
stbbr_for_query("urn:xmpp:ping",
|
||||
"<iq from='localhost' to='stabber@localhost/profanity' type='result'/>"
|
||||
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'/>"
|
||||
);
|
||||
|
||||
prof_connect();
|
||||
|
||||
/*
|
||||
* Wait for disco#info exchange to complete.
|
||||
* TODO: Replace with proper wait mechanism (e.g., wait for capabilities
|
||||
* to be cached). Currently we use sleep to ensure disco#info response
|
||||
* is processed before sending /ping command.
|
||||
*/
|
||||
sleep(3);
|
||||
|
||||
prof_input("/ping");
|
||||
|
||||
prof_timeout(10);
|
||||
assert_true(prof_output_regex("Pinged server"));
|
||||
prof_timeout_reset();
|
||||
assert_true(stbbr_received(
|
||||
"<iq id='prof_ping_4' 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'>"
|
||||
"<ping xmlns='urn:xmpp:ping'/>"
|
||||
"</iq>"
|
||||
));
|
||||
assert_true(prof_output_exact("Ping response from server"));
|
||||
}
|
||||
|
||||
void
|
||||
ping_server_not_supported(void **state)
|
||||
{
|
||||
stbbr_for_query("http://jabber.org/protocol/disco#info",
|
||||
"<iq to='stabber@localhost/profanity' type='result' from='localhost'>"
|
||||
stbbr_for_id("prof_disco_info_onconnect_2",
|
||||
"<iq id='prof_disco_info_onconnect_2' to='stabber@localhost/profanity' type='result' from='localhost'>"
|
||||
"<query xmlns='http://jabber.org/protocol/disco#info'>"
|
||||
"<identity category='server' type='im' name='Stabber'/>"
|
||||
"</query>"
|
||||
@@ -65,7 +60,7 @@ ping_server_not_supported(void **state)
|
||||
prof_connect();
|
||||
|
||||
prof_input("/ping");
|
||||
assert_true(prof_output_regex("Server does not support ping requests"));
|
||||
assert_true(prof_output_exact("Server does not support ping requests."));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -74,21 +69,20 @@ ping_responds_to_server_request(void **state)
|
||||
prof_connect();
|
||||
|
||||
stbbr_send(
|
||||
"<iq id=\"pingtest1\" type=\"get\" to=\"stabber@localhost/profanity\" from=\"localhost\">"
|
||||
"<ping xmlns=\"urn:xmpp:ping\"/>"
|
||||
"<iq id='pingtest1' type='get' to='stabber@localhost/profanity' from='localhost'>"
|
||||
"<ping xmlns='urn:xmpp:ping'/>"
|
||||
"</iq>"
|
||||
);
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<iq id='pingtest1' type='result' from='stabber@localhost/profanity' to='localhost'></iq>"
|
||||
"<iq id='pingtest1' type='result' from='stabber@localhost/profanity' to='localhost'/>"
|
||||
));
|
||||
}
|
||||
|
||||
void ping_jid(void **state)
|
||||
{
|
||||
// Caps/disco info response without relying on a fixed id
|
||||
stbbr_for_query("http://jabber.org/protocol/disco#info",
|
||||
"<iq to='stabber@localhost/profanity' type='result' from='buddy1@localhost/mobile'>"
|
||||
stbbr_for_id("prof_caps_4",
|
||||
"<iq id='prof_caps_4' 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'/>"
|
||||
@@ -115,30 +109,29 @@ void ping_jid(void **state)
|
||||
assert_true(prof_output_exact("Buddy1 (mobile) is online, \"I'm here\""));
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<iq id='*' to='buddy1@localhost/mobile' type='get'>"
|
||||
"<iq id='prof_caps_4' to='buddy1@localhost/mobile' type='get'>"
|
||||
"<query xmlns='http://jabber.org/protocol/disco#info' node='http://profanity-im.github.io#LpT2xs3nun7jC2sq4gg3WRDQFZ4='/>"
|
||||
"</iq>"
|
||||
));
|
||||
|
||||
// Respond to ping result regardless of id
|
||||
stbbr_for_query("urn:xmpp:ping",
|
||||
"<iq from='buddy1@localhost/mobile' to='stabber@localhost' type='result'/>"
|
||||
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='*' type='get' to='buddy1@localhost/mobile'>"
|
||||
"<iq id='prof_ping_5' type='get' to='buddy1@localhost/mobile'>"
|
||||
"<ping xmlns='urn:xmpp:ping'/>"
|
||||
"</iq>"
|
||||
));
|
||||
assert_true(prof_output_regex("Ping response from buddy1@localhost/mobile"));
|
||||
assert_true(prof_output_exact("Ping response from buddy1@localhost/mobile"));
|
||||
}
|
||||
|
||||
void ping_jid_not_supported(void **state)
|
||||
{
|
||||
stbbr_for_query("http://jabber.org/protocol/disco#info",
|
||||
"<iq to='stabber@localhost/profanity' type='result' from='buddy1@localhost/mobile'>"
|
||||
stbbr_for_id("prof_caps_4",
|
||||
"<iq id='prof_caps_4' 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'/>"
|
||||
@@ -164,7 +157,7 @@ void ping_jid_not_supported(void **state)
|
||||
assert_true(prof_output_exact("Buddy1 (mobile) is online, \"I'm here\""));
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<iq id='*' to='buddy1@localhost/mobile' type='get'>"
|
||||
"<iq id='prof_caps_4' to='buddy1@localhost/mobile' type='get'>"
|
||||
"<query xmlns='http://jabber.org/protocol/disco#info' node='http://profanity-im.github.io#LpT2xs3nun7jC2sq4gg3WRDQFZ4='/>"
|
||||
"</iq>"
|
||||
));
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
@@ -12,16 +13,15 @@ presence_online(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set online");
|
||||
|
||||
assert_true(prof_output_exact("Status set to online (priority 0), \"online\"."));
|
||||
prof_input("/online");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<status>online</status>"
|
||||
"<presence id='prof_presence_3'>"
|
||||
"<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)"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -29,16 +29,16 @@ presence_online_with_message(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set online \"Hi there\"");
|
||||
|
||||
assert_true(prof_output_exact("Status set to online (priority 0), \"Hi there\"."));
|
||||
prof_input("/online \"Hi there\"");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<status>Hi there</status>"
|
||||
"<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\"."));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -46,17 +46,16 @@ presence_away(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set away");
|
||||
|
||||
assert_true(prof_output_exact("Status set to away (priority 0), \"away\"."));
|
||||
prof_input("/away");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<show>away</show>"
|
||||
"<status>away</status>"
|
||||
"<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)"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -64,17 +63,17 @@ presence_away_with_message(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set away \"I'm not here for a bit\"");
|
||||
|
||||
assert_true(prof_output_exact("Status set to away (priority 0), \"I'm not here for a bit\"."));
|
||||
prof_input("/away \"I'm not here for a bit\"");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<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'/>"
|
||||
"</presence>"
|
||||
));
|
||||
|
||||
assert_true(prof_output_exact("Status set to away (priority 0), \"I'm not here for a bit\"."));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -82,17 +81,16 @@ presence_xa(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set xa");
|
||||
|
||||
assert_true(prof_output_exact("Status set to xa (priority 0), \"xa\"."));
|
||||
prof_input("/xa");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<show>xa</show>"
|
||||
"<status>xa</status>"
|
||||
"<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)"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -100,17 +98,17 @@ presence_xa_with_message(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set xa \"Gone to the shops\"");
|
||||
|
||||
assert_true(prof_output_exact("Status set to xa (priority 0), \"Gone to the shops\"."));
|
||||
prof_input("/xa \"Gone to the shops\"");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<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'/>"
|
||||
"</presence>"
|
||||
));
|
||||
|
||||
assert_true(prof_output_exact("Status set to xa (priority 0), \"Gone to the shops\"."));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -118,17 +116,16 @@ presence_dnd(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set dnd");
|
||||
|
||||
assert_true(prof_output_exact("Status set to dnd (priority 0), \"dnd\"."));
|
||||
prof_input("/dnd");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<show>dnd</show>"
|
||||
"<status>dnd</status>"
|
||||
"<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)"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -136,17 +133,17 @@ presence_dnd_with_message(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set dnd \"Working\"");
|
||||
|
||||
assert_true(prof_output_exact("Status set to dnd (priority 0), \"Working\"."));
|
||||
prof_input("/dnd \"Working\"");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<show>dnd</show>"
|
||||
"<status>Working</status>"
|
||||
"<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\"."));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -154,17 +151,16 @@ presence_chat(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set chat");
|
||||
|
||||
assert_true(prof_output_exact("Status set to chat (priority 0), \"chat\"."));
|
||||
prof_input("/chat");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<show>chat</show>"
|
||||
"<status>chat</status>"
|
||||
"<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)"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -172,17 +168,17 @@ presence_chat_with_message(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set chat \"Free to talk\"");
|
||||
|
||||
assert_true(prof_output_exact("Status set to chat (priority 0), \"Free to talk\"."));
|
||||
prof_input("/chat \"Free to talk\"");
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<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'/>"
|
||||
"</presence>"
|
||||
));
|
||||
|
||||
assert_true(prof_output_exact("Status set to chat (priority 0), \"Free to talk\"."));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -192,14 +188,14 @@ presence_set_priority(void **state)
|
||||
|
||||
prof_input("/priority 25");
|
||||
|
||||
assert_true(prof_output_exact("Priority set to 25."));
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<priority>25</priority>"
|
||||
"<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."));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -208,24 +204,24 @@ presence_includes_priority(void **state)
|
||||
prof_connect();
|
||||
|
||||
prof_input("/priority 25");
|
||||
assert_true(prof_output_exact("Priority set to 25."));
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<priority>25</priority>"
|
||||
"<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("/status set chat \"Free to talk\"");
|
||||
assert_true(prof_output_exact("Status set to chat (priority 25), \"Free to talk\"."));
|
||||
prof_input("/chat \"Free to talk\"");
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_5'>"
|
||||
"<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'/>"
|
||||
"</presence>"
|
||||
));
|
||||
assert_true(prof_output_exact("Status set to chat (priority 25), \"Free to talk\"."));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -233,26 +229,26 @@ presence_keeps_status(void **state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
prof_input("/status set chat \"Free to talk\"");
|
||||
assert_true(prof_output_exact("Status set to chat (priority 0), \"Free to talk\"."));
|
||||
prof_input("/chat \"Free to talk\"");
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_4'>"
|
||||
"<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'/>"
|
||||
"</presence>"
|
||||
));
|
||||
assert_true(prof_output_exact("Status set to chat (priority 0), \"Free to talk\"."));
|
||||
|
||||
prof_input("/priority 25");
|
||||
assert_true(prof_output_exact("Priority set to 25."));
|
||||
assert_true(stbbr_received(
|
||||
"<presence id='*'>"
|
||||
"<presence id='prof_presence_5'>"
|
||||
"<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'/>"
|
||||
"</presence>"
|
||||
));
|
||||
assert_true(prof_output_exact("Priority set to 25."));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
@@ -30,9 +31,8 @@ send_receipt_request(void **state)
|
||||
|
||||
prof_connect();
|
||||
|
||||
// Register disco#info response for capabilities query (receipts support)
|
||||
stbbr_for_query("http://jabber.org/protocol/disco#info",
|
||||
"<iq from='buddy1@localhost/laptop' to='stabber@localhost' id='*' type='result'>"
|
||||
stbbr_for_id("prof_caps_4",
|
||||
"<iq from='buddy1@localhost/laptop' to='stabber@localhost' id='prof_caps_4' 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'/>"
|
||||
|
||||
@@ -4,14 +4,15 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
void
|
||||
rooms_query(void **state)
|
||||
{
|
||||
stbbr_for_query("http://jabber.org/protocol/disco#items",
|
||||
"<iq id='*' type='result' to='stabber@localhost/profanity' from='conference.localhost'>"
|
||||
stbbr_for_id("prof_confreq_4",
|
||||
"<iq id='prof_confreq_4' 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'/>"
|
||||
@@ -26,8 +27,8 @@ rooms_query(void **state)
|
||||
assert_true(prof_output_exact("chatroom@conference.localhost (A chat room)"));
|
||||
assert_true(prof_output_exact("hangout@conference.localhost (Another chat room)"));
|
||||
|
||||
assert_true(stbbr_received(
|
||||
"<iq id='*' to='conference.localhost' type='get'>"
|
||||
assert_true(stbbr_last_received(
|
||||
"<iq id='prof_confreq_4' to='conference.localhost' type='get'>"
|
||||
"<query xmlns='http://jabber.org/protocol/disco#items'/>"
|
||||
"</iq>"
|
||||
));
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <stabber.h>
|
||||
#include <expect.h>
|
||||
|
||||
#include "proftest.h"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user