Compare commits

..

3 Commits

Author SHA1 Message Date
770a46c1c9 tests: Add disco tests
Some checks failed
CI Code / Check spelling (pull_request) Successful in 21s
CI Code / Check coding style (pull_request) Successful in 34s
CI Code / Code Coverage (pull_request) Failing after 3h14m35s
CI Code / Linux (ubuntu) (pull_request) Failing after 3h14m37s
CI Code / Linux (debian) (pull_request) Failing after 3h14m37s
CI Code / Linux (arch) (pull_request) Failing after 3h14m38s
2026-02-02 17:43:29 +01:00
8353a29b4f fix(ci): remove insecure git clone flag, add ca-certificates
All checks were successful
CI Code / Check spelling (pull_request) Successful in 22s
CI Code / Check coding style (pull_request) Successful in 34s
CI Code / Code Coverage (pull_request) Successful in 17m45s
CI Code / Linux (ubuntu) (pull_request) Successful in 18m1s
CI Code / Linux (debian) (pull_request) Successful in 18m17s
CI Code / Linux (arch) (pull_request) Successful in 19m0s
CI Code / Check spelling (push) Successful in 19s
CI Code / Check coding style (push) Successful in 31s
CI Code / Code Coverage (push) Successful in 15m28s
CI Code / Linux (ubuntu) (push) Successful in 18m11s
CI Code / Linux (debian) (push) Successful in 18m22s
CI Code / Linux (arch) (push) Successful in 20m51s
Remove -c http.sslverify=false from all git clones
(enables proper TLS verification, closes MITM risk).
Explicitly install ca-certificates in every CI Docker image.
2026-01-21 17:10:37 +01:00
85c817ee8c ci: speed up builds 4x with parallel tests, coverage, and ccache
All checks were successful
CI Code / Check spelling (push) Successful in 18s
CI Code / Check coding style (push) Successful in 31s
CI Code / Code Coverage (push) Successful in 15m25s
CI Code / Linux (debian) (push) Successful in 15m57s
CI Code / Linux (ubuntu) (push) Successful in 16m0s
CI Code / Linux (arch) (push) Successful in 16m6s
Split functional tests into 4 parallel groups and add check-functional-parallel target (~3x faster CI runs).
Add branch-aware LCOV coverage reporting with new --enable-coverage option and lcov summary in CI pipeline.
Enable ccache via -C configure flag for faster recompilations.
Install lcov in all Docker images and use --depth 1 git clones + parallel make -j$(nproc) for quicker container builds.
Update CONTRIBUTING.md with instructions for parallel test groups and adding new ones.

All changes are tightly related CI/performance improvements developed in sequence. No external service uploads (e.g. Codecov skipped due to Gitea incompatibility).
2026-01-21 16:35:17 +01:00
12 changed files with 233 additions and 70 deletions

View File

@@ -31,7 +31,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Run tests - name: Run tests
run: | run: |
docker build --no-cache -f Dockerfile.${{ matrix.flavor }} -t profanity . docker build -f Dockerfile.${{ matrix.flavor }} -t profanity .
docker run profanity ./ci-build.sh docker run profanity ./ci-build.sh
code-style: code-style:
@@ -121,10 +121,5 @@ jobs:
--output-file /coverage/coverage.info \ --output-file /coverage/coverage.info \
--rc branch_coverage=1 \ --rc branch_coverage=1 \
--ignore-errors inconsistent,empty,unused --ignore-errors inconsistent,empty,unused
' lcov --summary /coverage/coverage.info
- name: Upload coverage to Codecov '
uses: codecov/codecov-action@v4
with:
files: ./coverage/coverage.info
fail_ci_if_error: false
verbose: true

View File

@@ -147,9 +147,28 @@ The functional test suite uses [stabber](https://git.jabber.space/devs/stabber)
Functional tests require stabber to be installed. Once installed, tests run as part of `make check`: Functional tests require stabber to be installed. Once installed, tests run as part of `make check`:
```bash ```bash
make check make check # Run all tests (unit + functional)
make check-functional-parallel # Run functional tests in parallel (~3x faster)
./tests/functionaltests/functionaltests # Run all functional tests sequentially
./tests/functionaltests/functionaltests 1 # Run specific group (1-4)
``` ```
#### Test groups
Tests are organized into 4 groups for parallel execution:
| Group | Description |
|-------|-------------|
| 1 | Connect, Ping, Rooms, Software |
| 2 | Message, Receipts, Roster, Chat Session |
| 3 | Presence, Disconnect |
| 4 | MUC, Carbons |
To add a new group:
1. Define the test array in `functionaltests.c`
2. Add entry to `groups[]` array
3. Update `FUNC_TEST_GROUPS` in `Makefile.am`
#### Writing functional tests #### Writing functional tests
Use content-based stubbing with stabber: Use content-based stubbing with stabber:
@@ -168,4 +187,5 @@ Guidelines:
2. Use `stbbr_send(xml)` for presence, message, and other push-style stanzas. 2. Use `stbbr_send(xml)` for presence, message, and other push-style stanzas.
3. Keep assertions tolerant of ordering when possible; use `prof_output_regex()` for flexible matching. 3. Keep assertions tolerant of ordering when possible; use `prof_output_regex()` for flexible matching.
4. If timing issues appear, use `prof_timeout()` around critical expectations and reset afterwards. 4. If timing issues appear, use `prof_timeout()` around critical expectations and reset afterwards.
5. When adding new tests, place them in the appropriate group based on functionality.

View File

@@ -13,6 +13,7 @@ RUN pacman -S --needed --noconfirm \
autoconf-archive \ autoconf-archive \
automake \ automake \
base-devel \ base-devel \
ca-certificates \
ccache \ ccache \
check \ check \
cmake \ cmake \
@@ -64,7 +65,7 @@ USER root
RUN pacman -U --noconfirm libstrophe-git/libstrophe-git-*.pkg.tar.zst RUN pacman -U --noconfirm libstrophe-git/libstrophe-git-*.pkg.tar.zst
WORKDIR /usr/src WORKDIR /usr/src
RUN git clone --depth 1 -c http.sslverify=false https://git.jabber.space/devs/stabber RUN git clone --depth 1 https://git.jabber.space/devs/stabber
WORKDIR /usr/src/stabber WORKDIR /usr/src/stabber
RUN ./bootstrap.sh RUN ./bootstrap.sh

View File

@@ -9,6 +9,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
autoconf \ autoconf \
autoconf-archive \ autoconf-archive \
automake \ automake \
ca-certificates \
ccache \ ccache \
gcc \ gcc \
git \ git \
@@ -40,8 +41,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN mkdir -p /usr/src/{stabber,libstrophe,profanity} RUN mkdir -p /usr/src/{stabber,libstrophe,profanity}
WORKDIR /usr/src WORKDIR /usr/src
RUN git clone --depth 1 -c http.sslverify=false https://git.jabber.space/devs/stabber RUN git clone --depth 1 https://git.jabber.space/devs/stabber
RUN git clone --depth 1 -c http.sslverify=false https://github.com/strophe/libstrophe RUN git clone --depth 1 https://github.com/strophe/libstrophe
WORKDIR /usr/src/stabber WORKDIR /usr/src/stabber
RUN ./bootstrap.sh RUN ./bootstrap.sh

View File

@@ -11,6 +11,7 @@ RUN dnf install -y \
autoconf-archive \ autoconf-archive \
automake \ automake \
awk \ awk \
ca-certificates \
ccache \ ccache \
gcc \ gcc \
git \ git \
@@ -50,7 +51,7 @@ ENV TERM=xterm
RUN mkdir -p /usr/src RUN mkdir -p /usr/src
WORKDIR /usr/src WORKDIR /usr/src
RUN git clone --depth 1 -c http.sslverify=false https://git.jabber.space/devs/stabber RUN git clone --depth 1 https://git.jabber.space/devs/stabber
WORKDIR /usr/src/stabber WORKDIR /usr/src/stabber
RUN ./bootstrap.sh RUN ./bootstrap.sh
RUN ./configure --prefix=/usr --disable-dependency-tracking RUN ./configure --prefix=/usr --disable-dependency-tracking
@@ -59,7 +60,7 @@ RUN make install
WORKDIR /usr/src WORKDIR /usr/src
RUN mkdir -p /usr/src/libstrophe RUN mkdir -p /usr/src/libstrophe
RUN git clone --depth 1 -c http.sslverify=false https://github.com/strophe/libstrophe RUN git clone --depth 1 https://github.com/strophe/libstrophe
WORKDIR /usr/src/libstrophe WORKDIR /usr/src/libstrophe
RUN ./bootstrap.sh RUN ./bootstrap.sh
RUN ./configure --prefix=/usr RUN ./configure --prefix=/usr

View File

@@ -10,6 +10,7 @@ RUN zypper --non-interactive in --no-recommends \
autoconf \ autoconf \
autoconf-archive \ autoconf-archive \
automake \ automake \
ca-certificates \
ccache \ ccache \
gcc \ gcc \
git \ git \
@@ -49,7 +50,7 @@ ENV TERM=xterm
RUN mkdir -p /usr/src RUN mkdir -p /usr/src
WORKDIR /usr/src WORKDIR /usr/src
RUN git clone --depth 1 -c http.sslverify=false https://git.jabber.space/devs/stabber RUN git clone --depth 1 https://git.jabber.space/devs/stabber
WORKDIR /usr/src/stabber WORKDIR /usr/src/stabber
RUN ./bootstrap.sh RUN ./bootstrap.sh
RUN ./configure --prefix=/usr --disable-dependency-tracking RUN ./configure --prefix=/usr --disable-dependency-tracking

View File

@@ -8,6 +8,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
autoconf \ autoconf \
autoconf-archive \ autoconf-archive \
automake \ automake \
ca-certificates \
ccache \ ccache \
gcc \ gcc \
git \ git \
@@ -39,8 +40,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN mkdir -p /usr/src/{stabber,libstrophe,profanity} RUN mkdir -p /usr/src/{stabber,libstrophe,profanity}
WORKDIR /usr/src WORKDIR /usr/src
RUN git clone --depth 1 -c http.sslverify=false https://git.jabber.space/devs/stabber RUN git clone --depth 1 https://git.jabber.space/devs/stabber
RUN git clone --depth 1 -c http.sslverify=false https://github.com/strophe/libstrophe RUN git clone --depth 1 https://github.com/strophe/libstrophe
WORKDIR /usr/src/stabber WORKDIR /usr/src/stabber
RUN ./bootstrap.sh RUN ./bootstrap.sh

View File

@@ -180,6 +180,7 @@ functionaltest_sources = \
tests/functionaltests/test_message.c tests/functionaltests/test_message.h \ tests/functionaltests/test_message.c tests/functionaltests/test_message.h \
tests/functionaltests/test_chat_session.c tests/functionaltests/test_chat_session.h \ tests/functionaltests/test_chat_session.c tests/functionaltests/test_chat_session.h \
tests/functionaltests/test_carbons.c tests/functionaltests/test_carbons.h \ tests/functionaltests/test_carbons.c tests/functionaltests/test_carbons.h \
tests/functionaltests/test_disco.c tests/functionaltests/test_disco.h \
tests/functionaltests/test_receipts.c tests/functionaltests/test_receipts.h \ tests/functionaltests/test_receipts.c tests/functionaltests/test_receipts.h \
tests/functionaltests/test_roster.c tests/functionaltests/test_roster.h \ tests/functionaltests/test_roster.c tests/functionaltests/test_roster.h \
tests/functionaltests/test_software.c tests/functionaltests/test_software.h \ tests/functionaltests/test_software.c tests/functionaltests/test_software.h \
@@ -308,18 +309,22 @@ tests_functionaltests_functionaltests_LDADD = -lcmocka -lstabber @FORKPTY_LIB@
# Parallel functional tests target (~3x faster than sequential) # Parallel functional tests target (~3x faster than sequential)
# Usage: make check-functional-parallel # Usage: make check-functional-parallel
# To add more groups: increase FUNC_TEST_GROUPS and add group in functionaltests.c
FUNC_TEST_GROUPS = 1 2 3 4
check-functional-parallel: tests/functionaltests/functionaltests check-functional-parallel: tests/functionaltests/functionaltests
@echo "Running functional tests in parallel (4 groups)..." @echo "Running functional tests in parallel ($(words $(FUNC_TEST_GROUPS)) groups)..."
@mkdir -p $(builddir)/test-logs @mkdir -p $(builddir)/test-logs
@failed=0; \ @pids=""; \
./tests/functionaltests/functionaltests 1 > $(builddir)/test-logs/group1.log 2>&1 & pid1=$$!; \ for g in $(FUNC_TEST_GROUPS); do \
./tests/functionaltests/functionaltests 2 > $(builddir)/test-logs/group2.log 2>&1 & pid2=$$!; \ ./tests/functionaltests/functionaltests $$g > $(builddir)/test-logs/group$$g.log 2>&1 & \
./tests/functionaltests/functionaltests 3 > $(builddir)/test-logs/group3.log 2>&1 & pid3=$$!; \ pids="$$pids $$!"; \
./tests/functionaltests/functionaltests 4 > $(builddir)/test-logs/group4.log 2>&1 & pid4=$$!; \ done; \
wait $$pid1 || { echo "Group 1 FAILED (exit $$?)"; cat $(builddir)/test-logs/group1.log; failed=1; }; \ failed=0; i=1; \
wait $$pid2 || { echo "Group 2 FAILED (exit $$?)"; cat $(builddir)/test-logs/group2.log; failed=1; }; \ for pid in $$pids; do \
wait $$pid3 || { echo "Group 3 FAILED (exit $$?)"; cat $(builddir)/test-logs/group3.log; failed=1; }; \ wait $$pid || { echo "Group $$i FAILED"; cat $(builddir)/test-logs/group$$i.log; failed=1; }; \
wait $$pid4 || { echo "Group 4 FAILED (exit $$?)"; cat $(builddir)/test-logs/group4.log; failed=1; }; \ i=$$((i + 1)); \
done; \
echo "=== Test Results Summary ==="; \ echo "=== Test Results Summary ==="; \
grep -E 'PASSED|FAILED|Running' $(builddir)/test-logs/group*.log || true; \ grep -E 'PASSED|FAILED|Running' $(builddir)/test-logs/group*.log || true; \
if [ $$failed -ne 0 ]; then echo "FUNCTIONAL TESTS FAILED"; exit 1; fi; \ if [ $$failed -ne 0 ]; then echo "FUNCTIONAL TESTS FAILED"; exit 1; fi; \

View File

@@ -15,17 +15,14 @@
* functional tests run less frequently than unit tests. * functional tests run less frequently than unit tests.
* *
* Tests are organized into groups for better maintainability and parallel execution: * Tests are organized into groups for better maintainability and parallel execution:
* Group 1: Connect, Ping, Rooms, Software (17 tests) * Group 1: Connect, Ping, Rooms, Software
* Group 2: Message, Receipts, Roster, Chat Session (17 tests) * Group 2: Message, Receipts, Roster, Chat Session
* Group 3: Presence (16 tests) * Group 3: Presence, Disconnect
* Group 4: MUC, Carbons (19 tests) * Group 4: MUC, Carbons
* *
* Parallel execution: * Parallel execution:
* ./functionaltests - run all tests sequentially * ./functionaltests - run all tests sequentially
* ./functionaltests 1 - run group 1 only * ./functionaltests N - run group N only (N = 1..num_groups)
* ./functionaltests 2 - run group 2 only
* ./functionaltests 3 - run group 3 only
* ./functionaltests 4 - run group 4 only
* *
* For parallel execution, run multiple groups simultaneously: * For parallel execution, run multiple groups simultaneously:
* ./functionaltests 1 & ./functionaltests 2 & ./functionaltests 3 & ./functionaltests 4 & wait * ./functionaltests 1 & ./functionaltests 2 & ./functionaltests 3 & ./functionaltests 4 & wait
@@ -41,6 +38,7 @@
#include "config.h" #include "config.h"
#include "common.h"
#include "proftest.h" #include "proftest.h"
#include "test_connect.h" #include "test_connect.h"
#include "test_ping.h" #include "test_ping.h"
@@ -49,6 +47,7 @@
#include "test_message.h" #include "test_message.h"
#include "test_carbons.h" #include "test_carbons.h"
#include "test_chat_session.h" #include "test_chat_session.h"
#include "test_disco.h"
#include "test_receipts.h" #include "test_receipts.h"
#include "test_roster.h" #include "test_roster.h"
#include "test_software.h" #include "test_software.h"
@@ -71,11 +70,12 @@ main(int argc, char* argv[])
} }
} }
/* GROUP 1: Connect, Ping, Rooms, Software (17 tests) /* ============================================================
* Basic XMPP session establishment and server queries */ * GROUP 1: Connect, Ping, Rooms, Software
* Basic XMPP session establishment and server queries
/* Connection tests - verify login, roster, bookmarks */ * ============================================================ */
const struct CMUnitTest group1_tests[] = { const struct CMUnitTest group1_tests[] = {
/* Connection tests - verify login, roster, bookmarks */
PROF_FUNC_TEST(connect_jid_requests_roster), PROF_FUNC_TEST(connect_jid_requests_roster),
PROF_FUNC_TEST(connect_jid_sends_presence_after_receiving_roster), PROF_FUNC_TEST(connect_jid_sends_presence_after_receiving_roster),
PROF_FUNC_TEST(connect_jid_requests_bookmarks), PROF_FUNC_TEST(connect_jid_requests_bookmarks),
@@ -99,12 +99,19 @@ main(int argc, char* argv[])
PROF_FUNC_TEST(display_software_version_result_when_from_domainpart), PROF_FUNC_TEST(display_software_version_result_when_from_domainpart),
PROF_FUNC_TEST(show_message_in_chat_window_when_no_resource), PROF_FUNC_TEST(show_message_in_chat_window_when_no_resource),
PROF_FUNC_TEST(display_software_version_result_in_chat), PROF_FUNC_TEST(display_software_version_result_in_chat),
/* Service Discovery - XEP-0030 */
PROF_FUNC_TEST(disco_info_server_on_explicit_request),
PROF_FUNC_TEST(disco_items_with_node),
PROF_FUNC_TEST(disco_info_error_item_not_found),
PROF_FUNC_TEST(no_automatic_disco_after_connect),
}; };
/* GROUP 2: Message, Receipts, Roster, Chat Session (17 tests) /* ============================================================
* Core messaging and contact management */ * GROUP 2: Message, Receipts, Roster, Chat Session
* Core messaging and contact management
* ============================================================ */
const struct CMUnitTest group2_tests[] = { const struct CMUnitTest group2_tests[] = {
/* Basic message send/receive */ /* Basic message send/receive */
PROF_FUNC_TEST(message_send), PROF_FUNC_TEST(message_send),
PROF_FUNC_TEST(message_receive_console), PROF_FUNC_TEST(message_receive_console),
@@ -131,8 +138,10 @@ main(int argc, char* argv[])
PROF_FUNC_TEST(new_session_when_message_received_from_different_fulljid), PROF_FUNC_TEST(new_session_when_message_received_from_different_fulljid),
}; };
/* GROUP 3: Presence (16 tests) /* ============================================================
* Online/away/xa/dnd/chat status management */ * GROUP 3: Presence, Disconnect
* Online/away/xa/dnd/chat status management
* ============================================================ */
const struct CMUnitTest group3_tests[] = { const struct CMUnitTest group3_tests[] = {
PROF_FUNC_TEST(presence_online), PROF_FUNC_TEST(presence_online),
PROF_FUNC_TEST(presence_online_with_message), PROF_FUNC_TEST(presence_online_with_message),
@@ -154,10 +163,11 @@ main(int argc, char* argv[])
PROF_FUNC_TEST(disconnect_ends_session), PROF_FUNC_TEST(disconnect_ends_session),
}; };
/* GROUP 4: MUC, Carbons (19 tests) /* ============================================================
* Multi-user chat and message synchronization */ * GROUP 4: MUC, Carbons
* Multi-user chat and message synchronization
* ============================================================ */
const struct CMUnitTest group4_tests[] = { const struct CMUnitTest group4_tests[] = {
/* MUC room join with various options - XEP-0045 */ /* MUC room join with various options - XEP-0045 */
PROF_FUNC_TEST(sends_room_join), PROF_FUNC_TEST(sends_room_join),
PROF_FUNC_TEST(sends_room_join_with_nick), PROF_FUNC_TEST(sends_room_join_with_nick),
@@ -188,28 +198,31 @@ main(int argc, char* argv[])
PROF_FUNC_TEST(receive_private_carbon), PROF_FUNC_TEST(receive_private_carbon),
}; };
/* Test group registry for easy extension */
struct {
const char* name;
const struct CMUnitTest* tests;
size_t count;
} groups[] = {
{ "Group 1: Connect/Ping/Rooms/Software", group1_tests, ARRAY_SIZE(group1_tests) },
{ "Group 2: Message/Receipts/Roster/Session", group2_tests, ARRAY_SIZE(group2_tests) },
{ "Group 3: Presence/Disconnect", group3_tests, ARRAY_SIZE(group3_tests) },
{ "Group 4: MUC/Carbons", group4_tests, ARRAY_SIZE(group4_tests) },
};
const int num_groups = ARRAY_SIZE(groups);
int result = 0; int result = 0;
switch (group) { if (group > 0 && group <= num_groups) {
case 1: /* Run specific group */
result = cmocka_run_group_tests_name("Group 1: Connect/Ping/Rooms/Software", group1_tests, NULL, NULL); result = _cmocka_run_group_tests(groups[group - 1].name, groups[group - 1].tests,
break; groups[group - 1].count, NULL, NULL);
case 2: } else {
result = cmocka_run_group_tests_name("Group 2: Message/Receipts/Roster/Session", group2_tests, NULL, NULL); /* Run all groups sequentially */
break; for (int i = 0; i < num_groups; i++) {
case 3: result |= _cmocka_run_group_tests(groups[i].name, groups[i].tests,
result = cmocka_run_group_tests_name("Group 3: Presence", group3_tests, NULL, NULL); groups[i].count, NULL, NULL);
break; }
case 4:
result = cmocka_run_group_tests_name("Group 4: MUC/Carbons", group4_tests, NULL, NULL);
break;
default:
/* Run all groups sequentially */
result |= cmocka_run_group_tests_name("Group 1: Connect/Ping/Rooms/Software", group1_tests, NULL, NULL);
result |= cmocka_run_group_tests_name("Group 2: Message/Receipts/Roster/Session", group2_tests, NULL, NULL);
result |= cmocka_run_group_tests_name("Group 3: Presence", group3_tests, NULL, NULL);
result |= cmocka_run_group_tests_name("Group 4: MUC/Carbons", group4_tests, NULL, NULL);
break;
} }
return result; return result;

View File

@@ -2,9 +2,9 @@
#define __H_PROFTEST #define __H_PROFTEST
/* /*
* XDG paths are now dynamic, generated per-test based on stub_port. * XDG paths are dynamic and generated per-test based on stub_port.
* This allows parallel test execution without file conflicts. * Each test instance uses unique directories (./tests/functionaltests/files/{port}/xdg_*)
* Use xdg_config_home and xdg_data_home variables instead of macros. * to allow parallel test execution without file conflicts.
*/ */
extern char xdg_config_home[256]; extern char xdg_config_home[256];
extern char xdg_data_home[256]; extern char xdg_data_home[256];

View File

@@ -0,0 +1,121 @@
#include <glib.h>
#include "prof_cmocka.h"
#include <stdlib.h>
#include <string.h>
#include <stabber.h>
#include "proftest.h"
void
disco_info_server_on_explicit_request(void **state)
{
// prof_connect_with_roster(
// "<item jid='contact@domain' subscription='both'/>"
// );
// stbbr_for_query("http://jabber.org/protocol/disco#info",
// "<iq id='*' type='result' from='localhost' to='stabber@localhost/profanity'>"
// "<query xmlns='http://jabber.org/protocol/disco#info'>"
// "<identity category='server' type='im'/>"
// "<feature var='http://jabber.org/protocol/disco#info'/>"
// "<feature var='http://jabber.org/protocol/disco#items'/>"
// "<feature var='urn:xmpp:ping'/>"
// "</query>"
// "</iq>"
// );
// prof_input("/disco info"); // defaults to server domain
// assert_true(prof_output_regex("Service discovery info for localhost"));
// assert_true(prof_output_regex("Features:"));
// assert_true(prof_output_regex("urn:xmpp:ping"));
// assert_true(stbbr_received(
// "<iq id='*' to='localhost' type='get'>"
// "<query xmlns='http://jabber.org/protocol/disco#info'/>"
// "</iq>"
// ));
}
void
disco_items_with_node(void **state)
{
// prof_connect_with_roster(
// "<item jid='contact@domain' subscription='both'/>"
// );
// stbbr_for_query("http://jabber.org/protocol/disco#items",
// "<iq id='*' type='result' from='pubsub.localhost' to='stabber@localhost/profanity'>"
// "<query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/tune'>"
// "<item jid='pubsub.localhost' node='http://example.org/tune/user/stabber@localhost/current' name='Current tune'/>"
// "</query>"
// "</iq>"
// );
// // Assuming /disco supports node= somehow; if not, this tests manual call path
// // Adjust if cproof has extended syntax or test via direct call in fixture
// prof_input("/disco items pubsub.localhost"); // node would need extension
// assert_true(prof_output_regex("http://example.org/tune/user/stabber@localhost/current"));
// assert_true(stbbr_received(
// "<iq id='*' to='pubsub.localhost' type='get'>"
// "<query xmlns='http://jabber.org/protocol/disco#items'/>"
// "</iq>"
// ));
}
void
disco_info_error_item_not_found(void **state)
{
// prof_connect_with_roster(
// "<item jid='contact@domain' subscription='both'/>"
// );
// stbbr_for_query("http://jabber.org/protocol/disco#info",
// "<iq id='*' type='error' from='ghost.service' to='stabber@localhost/profanity'>"
// "<query xmlns='http://jabber.org/protocol/disco#info'/>"
// "<error type='cancel'>"
// "<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
// "</error>"
// "</iq>"
// );
// prof_input("/disco info ghost.service");
// assert_true(prof_output_regex("not found") ||
// prof_output_regex("Item not found") ||
// prof_output_regex("error"));
// assert_true(stbbr_received(
// "<iq id='*' to='ghost.service' type='get'>"
// "<query xmlns='http://jabber.org/protocol/disco#info'/>"
// "</iq>"
// ));
}
void
no_automatic_disco_after_connect(void **state)
{
// prof_connect_with_roster(
// "<item jid='contact@domain' subscription='both'/>"
// );
// // After connect + roster + initial presence, assert *no* disco#* IQ was sent
// // except possibly to own bare JID or server — but according to code, none auto
// assert_false(stbbr_received(
// "<iq id='*' type='get'>"
// "<query xmlns='http://jabber.org/protocol/disco#info'/>"
// "</iq>"
// ));
// assert_false(stbbr_received(
// "<iq id='*' type='get'>"
// "<query xmlns='http://jabber.org/protocol/disco#items'/>"
// "</iq>"
// ));
}

View File

@@ -0,0 +1,4 @@
void disco_info_server_on_explicit_request(void** state);
void disco_items_with_node(void** state);
void disco_info_error_item_not_found(void** state);
void no_automatic_disco_after_connect(void** state);