Compare commits
15 Commits
tests/disc
...
feat/paral
| Author | SHA1 | Date | |
|---|---|---|---|
|
01c3205f5d
|
|||
|
4789ada834
|
|||
|
f6b621ad40
|
|||
|
d80092821b
|
|||
|
ca5835c58e
|
|||
|
1d113c4d64
|
|||
|
e40b89ad92
|
|||
|
f41888b7a5
|
|||
|
c125746f6e
|
|||
|
16d4efbccc
|
|||
|
e1a9f55a32
|
|||
|
7765f65be1
|
|||
|
5153e04f96
|
|||
|
bed046e7ed
|
|||
|
fa17173e5c
|
32
.github/workflows/ci-code.yml
vendored
32
.github/workflows/ci-code.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: |
|
run: |
|
||||||
docker build -f Dockerfile.${{ matrix.flavor }} -t profanity .
|
docker build --no-cache -f Dockerfile.${{ matrix.flavor }} -t profanity .
|
||||||
docker run profanity ./ci-build.sh
|
docker run profanity ./ci-build.sh
|
||||||
|
|
||||||
code-style:
|
code-style:
|
||||||
@@ -98,3 +98,33 @@ jobs:
|
|||||||
- name: Check spelling
|
- name: Check spelling
|
||||||
run: |
|
run: |
|
||||||
codespell
|
codespell
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Code Coverage
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Build and run coverage
|
||||||
|
run: |
|
||||||
|
docker build -f Dockerfile.debian -t profanity-cov .
|
||||||
|
docker run -v ${{ github.workspace }}/coverage:/coverage profanity-cov bash -c '
|
||||||
|
./bootstrap.sh
|
||||||
|
./configure --enable-coverage --enable-otr --enable-pgp --enable-omemo --enable-plugins
|
||||||
|
make -j$(nproc)
|
||||||
|
make check || true
|
||||||
|
make check-functional-parallel || true
|
||||||
|
lcov --capture --directory . --output-file /coverage/coverage.info \
|
||||||
|
--rc branch_coverage=1 \
|
||||||
|
--ignore-errors inconsistent
|
||||||
|
lcov --remove /coverage/coverage.info \
|
||||||
|
"/usr/include/*" "*/tests/*" \
|
||||||
|
--output-file /coverage/coverage.info \
|
||||||
|
--rc branch_coverage=1 \
|
||||||
|
--ignore-errors inconsistent,empty,unused
|
||||||
|
'
|
||||||
|
- name: Upload coverage to Codecov
|
||||||
|
uses: codecov/codecov-action@v4
|
||||||
|
with:
|
||||||
|
files: ./coverage/coverage.info
|
||||||
|
fail_ci_if_error: false
|
||||||
|
verbose: true
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -107,3 +107,4 @@ breaks
|
|||||||
*.tar.*
|
*.tar.*
|
||||||
*.zip
|
*.zip
|
||||||
*.log*
|
*.log*
|
||||||
|
coverage/
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
FROM archlinux
|
FROM archlinux
|
||||||
|
|
||||||
ENV TERM=xterm
|
ENV TERM=xterm
|
||||||
|
ENV CC="ccache gcc"
|
||||||
|
|
||||||
RUN pacman -Syu --noconfirm
|
RUN pacman -Syu --noconfirm
|
||||||
# reflector is optional - if it fails due to network issues, continue with default mirrorlist
|
# reflector is optional - if it fails due to network issues, continue with default mirrorlist
|
||||||
@@ -12,9 +13,11 @@ RUN pacman -S --needed --noconfirm \
|
|||||||
autoconf-archive \
|
autoconf-archive \
|
||||||
automake \
|
automake \
|
||||||
base-devel \
|
base-devel \
|
||||||
|
ccache \
|
||||||
check \
|
check \
|
||||||
cmake \
|
cmake \
|
||||||
cmocka \
|
cmocka \
|
||||||
|
lcov \
|
||||||
curl \
|
curl \
|
||||||
debuginfod \
|
debuginfod \
|
||||||
doxygen \
|
doxygen \
|
||||||
@@ -61,12 +64,12 @@ 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 -c http.sslverify=false https://git.jabber.space/devs/stabber
|
RUN git clone --depth 1 -c http.sslverify=false 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
|
||||||
RUN make
|
RUN make -j$(nproc)
|
||||||
RUN make install
|
RUN make install
|
||||||
|
|
||||||
WORKDIR /usr/src/profanity
|
WORKDIR /usr/src/profanity
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ FROM debian:testing
|
|||||||
|
|
||||||
ENV DEBIAN_FRONTEND="noninteractive"
|
ENV DEBIAN_FRONTEND="noninteractive"
|
||||||
ENV TERM=xterm
|
ENV TERM=xterm
|
||||||
|
ENV CC="ccache gcc"
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
autoconf \
|
autoconf \
|
||||||
autoconf-archive \
|
autoconf-archive \
|
||||||
automake \
|
automake \
|
||||||
|
ccache \
|
||||||
gcc \
|
gcc \
|
||||||
git \
|
git \
|
||||||
|
lcov \
|
||||||
libcmocka-dev \
|
libcmocka-dev \
|
||||||
libcurl3-dev \
|
libcurl3-dev \
|
||||||
libgcrypt-dev \
|
libgcrypt-dev \
|
||||||
@@ -37,19 +40,19 @@ 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 -c http.sslverify=false https://git.jabber.space/devs/stabber
|
RUN git clone --depth 1 -c http.sslverify=false https://git.jabber.space/devs/stabber
|
||||||
RUN git clone -c http.sslverify=false https://github.com/strophe/libstrophe
|
RUN git clone --depth 1 -c http.sslverify=false https://github.com/strophe/libstrophe
|
||||||
|
|
||||||
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
|
||||||
RUN make
|
RUN make -j$(nproc)
|
||||||
RUN make install
|
RUN make install
|
||||||
|
|
||||||
WORKDIR /usr/src/libstrophe
|
WORKDIR /usr/src/libstrophe
|
||||||
RUN ./bootstrap.sh
|
RUN ./bootstrap.sh
|
||||||
RUN ./configure --prefix=/usr
|
RUN ./configure --prefix=/usr
|
||||||
RUN make
|
RUN make -j$(nproc)
|
||||||
RUN make install
|
RUN make install
|
||||||
|
|
||||||
WORKDIR /usr/src/profanity
|
WORKDIR /usr/src/profanity
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
# Build the latest Fedora image
|
# Build the latest Fedora image
|
||||||
FROM fedora:latest
|
FROM fedora:latest
|
||||||
|
|
||||||
|
ENV TERM=xterm
|
||||||
|
ENV CC="ccache gcc"
|
||||||
|
|
||||||
# libmicrohttpd - for stabber
|
# libmicrohttpd - for stabber
|
||||||
# glibc-locale - to have en_US locale
|
# glibc-locale - to have en_US locale
|
||||||
RUN dnf install -y \
|
RUN dnf install -y \
|
||||||
@@ -8,8 +11,10 @@ RUN dnf install -y \
|
|||||||
autoconf-archive \
|
autoconf-archive \
|
||||||
automake \
|
automake \
|
||||||
awk \
|
awk \
|
||||||
|
ccache \
|
||||||
gcc \
|
gcc \
|
||||||
git \
|
git \
|
||||||
|
lcov \
|
||||||
glib2-devel \
|
glib2-devel \
|
||||||
glibc-all-langpacks \
|
glibc-all-langpacks \
|
||||||
gtk2-devel \
|
gtk2-devel \
|
||||||
@@ -45,20 +50,20 @@ ENV TERM=xterm
|
|||||||
RUN mkdir -p /usr/src
|
RUN mkdir -p /usr/src
|
||||||
WORKDIR /usr/src
|
WORKDIR /usr/src
|
||||||
|
|
||||||
RUN git clone -c http.sslverify=false https://git.jabber.space/devs/stabber
|
RUN git clone --depth 1 -c http.sslverify=false 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
|
||||||
RUN make
|
RUN make -j$(nproc)
|
||||||
RUN make install
|
RUN make install
|
||||||
|
|
||||||
WORKDIR /usr/src
|
WORKDIR /usr/src
|
||||||
RUN mkdir -p /usr/src/libstrophe
|
RUN mkdir -p /usr/src/libstrophe
|
||||||
RUN git clone -c http.sslverify=false https://github.com/strophe/libstrophe
|
RUN git clone --depth 1 -c http.sslverify=false 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
|
||||||
RUN make
|
RUN make -j$(nproc)
|
||||||
RUN make install
|
RUN make install
|
||||||
|
|
||||||
RUN mkdir -p /usr/src/profanity
|
RUN mkdir -p /usr/src/profanity
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
# Build the latest openSUSE Tumbleweed image
|
# Build the latest openSUSE Tumbleweed image
|
||||||
FROM opensuse/tumbleweed
|
FROM opensuse/tumbleweed
|
||||||
|
|
||||||
|
ENV TERM=xterm
|
||||||
|
ENV CC="ccache gcc"
|
||||||
|
|
||||||
# libmicrohttpd - for stabber
|
# libmicrohttpd - for stabber
|
||||||
# glibc-locale - to have en_US locale
|
# glibc-locale - to have en_US locale
|
||||||
RUN zypper --non-interactive in --no-recommends \
|
RUN zypper --non-interactive in --no-recommends \
|
||||||
autoconf \
|
autoconf \
|
||||||
autoconf-archive \
|
autoconf-archive \
|
||||||
automake \
|
automake \
|
||||||
|
ccache \
|
||||||
gcc \
|
gcc \
|
||||||
git \
|
git \
|
||||||
|
lcov \
|
||||||
glib2-devel \
|
glib2-devel \
|
||||||
glibc-locale \
|
glibc-locale \
|
||||||
gtk2-devel \
|
gtk2-devel \
|
||||||
@@ -44,11 +49,11 @@ ENV TERM=xterm
|
|||||||
RUN mkdir -p /usr/src
|
RUN mkdir -p /usr/src
|
||||||
WORKDIR /usr/src
|
WORKDIR /usr/src
|
||||||
|
|
||||||
RUN git clone -c http.sslverify=false https://git.jabber.space/devs/stabber
|
RUN git clone --depth 1 -c http.sslverify=false 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
|
||||||
RUN make
|
RUN make -j$(nproc)
|
||||||
RUN make install
|
RUN make install
|
||||||
|
|
||||||
RUN mkdir -p /usr/src/profanity
|
RUN mkdir -p /usr/src/profanity
|
||||||
|
|||||||
@@ -2,13 +2,16 @@ FROM ubuntu:latest
|
|||||||
|
|
||||||
ENV DEBIAN_FRONTEND="noninteractive"
|
ENV DEBIAN_FRONTEND="noninteractive"
|
||||||
ENV TERM=xterm
|
ENV TERM=xterm
|
||||||
|
ENV CC="ccache gcc"
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
autoconf \
|
autoconf \
|
||||||
autoconf-archive \
|
autoconf-archive \
|
||||||
automake \
|
automake \
|
||||||
|
ccache \
|
||||||
gcc \
|
gcc \
|
||||||
git \
|
git \
|
||||||
|
lcov \
|
||||||
libcmocka-dev \
|
libcmocka-dev \
|
||||||
libcurl3-dev \
|
libcurl3-dev \
|
||||||
libgcrypt-dev \
|
libgcrypt-dev \
|
||||||
@@ -36,19 +39,19 @@ 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 -c http.sslverify=false https://git.jabber.space/devs/stabber
|
RUN git clone --depth 1 -c http.sslverify=false https://git.jabber.space/devs/stabber
|
||||||
RUN git clone -c http.sslverify=false https://github.com/strophe/libstrophe
|
RUN git clone --depth 1 -c http.sslverify=false https://github.com/strophe/libstrophe
|
||||||
|
|
||||||
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
|
||||||
RUN make
|
RUN make -j$(nproc)
|
||||||
RUN make install
|
RUN make install
|
||||||
|
|
||||||
WORKDIR /usr/src/libstrophe
|
WORKDIR /usr/src/libstrophe
|
||||||
RUN ./bootstrap.sh
|
RUN ./bootstrap.sh
|
||||||
RUN ./configure --prefix=/usr
|
RUN ./configure --prefix=/usr
|
||||||
RUN make
|
RUN make -j$(nproc)
|
||||||
RUN make install
|
RUN make install
|
||||||
|
|
||||||
WORKDIR /usr/src/profanity
|
WORKDIR /usr/src/profanity
|
||||||
|
|||||||
37
Makefile.am
37
Makefile.am
@@ -286,7 +286,7 @@ endif
|
|||||||
|
|
||||||
TESTS = tests/unittests/unittests
|
TESTS = tests/unittests/unittests
|
||||||
check_PROGRAMS = tests/unittests/unittests
|
check_PROGRAMS = tests/unittests/unittests
|
||||||
tests_unittests_unittests_CPPFLAGS = -Itests/
|
tests_unittests_unittests_CPPFLAGS = -I$(srcdir)/tests
|
||||||
tests_unittests_unittests_SOURCES = $(unittest_sources)
|
tests_unittests_unittests_SOURCES = $(unittest_sources)
|
||||||
tests_unittests_unittests_LDADD = -lcmocka
|
tests_unittests_unittests_LDADD = -lcmocka
|
||||||
|
|
||||||
@@ -302,9 +302,28 @@ if HAVE_FORKPTY
|
|||||||
TESTS += tests/functionaltests/functionaltests
|
TESTS += tests/functionaltests/functionaltests
|
||||||
check_PROGRAMS += tests/functionaltests/functionaltests
|
check_PROGRAMS += tests/functionaltests/functionaltests
|
||||||
tests_functionaltests_functionaltests_SOURCES = $(functionaltest_sources)
|
tests_functionaltests_functionaltests_SOURCES = $(functionaltest_sources)
|
||||||
tests_functionaltests_functionaltests_CPPFLAGS = -Itests/
|
tests_functionaltests_functionaltests_CPPFLAGS = -I$(srcdir)/tests
|
||||||
tests_functionaltests_functionaltests_CFLAGS = $(AM_CFLAGS)
|
tests_functionaltests_functionaltests_CFLAGS = $(AM_CFLAGS)
|
||||||
tests_functionaltests_functionaltests_LDADD = -lcmocka -lstabber @FORKPTY_LIB@
|
tests_functionaltests_functionaltests_LDADD = -lcmocka -lstabber @FORKPTY_LIB@
|
||||||
|
|
||||||
|
# Parallel functional tests target (~3x faster than sequential)
|
||||||
|
# Usage: make check-functional-parallel
|
||||||
|
check-functional-parallel: tests/functionaltests/functionaltests
|
||||||
|
@echo "Running functional tests in parallel (4 groups)..."
|
||||||
|
@mkdir -p $(builddir)/test-logs
|
||||||
|
@failed=0; \
|
||||||
|
./tests/functionaltests/functionaltests 1 > $(builddir)/test-logs/group1.log 2>&1 & pid1=$$!; \
|
||||||
|
./tests/functionaltests/functionaltests 2 > $(builddir)/test-logs/group2.log 2>&1 & pid2=$$!; \
|
||||||
|
./tests/functionaltests/functionaltests 3 > $(builddir)/test-logs/group3.log 2>&1 & pid3=$$!; \
|
||||||
|
./tests/functionaltests/functionaltests 4 > $(builddir)/test-logs/group4.log 2>&1 & pid4=$$!; \
|
||||||
|
wait $$pid1 || { echo "Group 1 FAILED (exit $$?)"; cat $(builddir)/test-logs/group1.log; failed=1; }; \
|
||||||
|
wait $$pid2 || { echo "Group 2 FAILED (exit $$?)"; cat $(builddir)/test-logs/group2.log; failed=1; }; \
|
||||||
|
wait $$pid3 || { echo "Group 3 FAILED (exit $$?)"; cat $(builddir)/test-logs/group3.log; failed=1; }; \
|
||||||
|
wait $$pid4 || { echo "Group 4 FAILED (exit $$?)"; cat $(builddir)/test-logs/group4.log; failed=1; }; \
|
||||||
|
echo "=== Test Results Summary ==="; \
|
||||||
|
grep -E 'PASSED|FAILED|Running' $(builddir)/test-logs/group*.log || true; \
|
||||||
|
if [ $$failed -ne 0 ]; then echo "FUNCTIONAL TESTS FAILED"; exit 1; fi; \
|
||||||
|
echo "All functional test groups passed!"
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -367,6 +386,20 @@ check-unit: tests/unittests/unittests
|
|||||||
@VALGRIND_CHECK_RULES@
|
@VALGRIND_CHECK_RULES@
|
||||||
VALGRIND_SUPPRESSIONS_FILES=prof.supp
|
VALGRIND_SUPPRESSIONS_FILES=prof.supp
|
||||||
|
|
||||||
|
# Code coverage targets (requires --enable-coverage)
|
||||||
|
coverage-clean:
|
||||||
|
find . -name '*.gcda' -delete
|
||||||
|
find . -name '*.gcno' -delete
|
||||||
|
rm -rf coverage-html coverage.info
|
||||||
|
|
||||||
|
coverage-report: check
|
||||||
|
lcov --capture --directory . --output-file coverage.info --ignore-errors inconsistent
|
||||||
|
lcov --remove coverage.info '/usr/*' '*/tests/*' --output-file coverage.info --ignore-errors inconsistent
|
||||||
|
genhtml coverage.info --output-directory coverage-html
|
||||||
|
@echo "Coverage report generated in coverage-html/index.html"
|
||||||
|
|
||||||
|
.PHONY: coverage-clean coverage-report
|
||||||
|
|
||||||
format: $(all_c_sources)
|
format: $(all_c_sources)
|
||||||
clang-format -i $(all_c_sources)
|
clang-format -i $(all_c_sources)
|
||||||
|
|
||||||
|
|||||||
175
ci-build.sh
175
ci-build.sh
@@ -23,6 +23,79 @@ error_handler()
|
|||||||
|
|
||||||
trap error_handler ERR
|
trap error_handler ERR
|
||||||
|
|
||||||
|
# Verify that test failures are properly detected
|
||||||
|
# This is a meta-test: it runs a deliberately failing test
|
||||||
|
# and checks that the test framework reports the failure correctly
|
||||||
|
verify_test_failure_detection()
|
||||||
|
{
|
||||||
|
echo
|
||||||
|
echo "==> Verifying test failure detection..."
|
||||||
|
|
||||||
|
# Create a simple failing test
|
||||||
|
cat > /tmp/test_must_fail.c << 'EOF'
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <cmocka.h>
|
||||||
|
|
||||||
|
static void test_that_must_fail(void **state) {
|
||||||
|
(void)state;
|
||||||
|
assert_true(0); // This MUST fail
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
const struct CMUnitTest tests[] = {
|
||||||
|
cmocka_unit_test(test_that_must_fail),
|
||||||
|
};
|
||||||
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Compile the failing test
|
||||||
|
if ! gcc -o /tmp/test_must_fail /tmp/test_must_fail.c -lcmocka 2>/dev/null; then
|
||||||
|
echo "Warning: Could not compile test failure verification (cmocka not available?)"
|
||||||
|
echo "Skipping test failure detection verification"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test 1: Single failing test detection
|
||||||
|
echo " Testing single test failure detection..."
|
||||||
|
if /tmp/test_must_fail > /tmp/test_must_fail.log 2>&1; then
|
||||||
|
echo "ERROR: Test that should fail returned success (exit code 0)"
|
||||||
|
echo "This means the test framework is NOT detecting failures correctly!"
|
||||||
|
echo "--- Test output ---"
|
||||||
|
cat /tmp/test_must_fail.log
|
||||||
|
echo "--- End output ---"
|
||||||
|
rm -f /tmp/test_must_fail /tmp/test_must_fail.c /tmp/test_must_fail.log
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " ✓ Single test failure correctly detected"
|
||||||
|
|
||||||
|
# Test 2: Parallel failure detection (simulates check-functional-parallel)
|
||||||
|
echo " Testing parallel test failure detection..."
|
||||||
|
failed=0
|
||||||
|
/tmp/test_must_fail > /tmp/p1.log 2>&1 & pid1=$!
|
||||||
|
true > /tmp/p2.log 2>&1 & pid2=$! # This passes
|
||||||
|
/tmp/test_must_fail > /tmp/p3.log 2>&1 & pid3=$!
|
||||||
|
true > /tmp/p4.log 2>&1 & pid4=$! # This passes
|
||||||
|
|
||||||
|
wait $pid1 || failed=$((failed + 1))
|
||||||
|
wait $pid2 || failed=$((failed + 1))
|
||||||
|
wait $pid3 || failed=$((failed + 1))
|
||||||
|
wait $pid4 || failed=$((failed + 1))
|
||||||
|
|
||||||
|
if [ $failed -ne 2 ]; then
|
||||||
|
echo "ERROR: Expected 2 failures in parallel tests, got $failed"
|
||||||
|
echo "Parallel failure detection is broken!"
|
||||||
|
rm -f /tmp/test_must_fail /tmp/test_must_fail.c /tmp/test_must_fail.log /tmp/p?.log
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " ✓ Parallel test failures correctly detected (2 of 4 failed as expected)"
|
||||||
|
|
||||||
|
rm -f /tmp/test_must_fail /tmp/test_must_fail.c /tmp/test_must_fail.log /tmp/p?.log
|
||||||
|
echo "✓ Test failure detection verified"
|
||||||
|
}
|
||||||
|
|
||||||
num_cores()
|
num_cores()
|
||||||
{
|
{
|
||||||
# Check for cores, for systems with:
|
# Check for cores, for systems with:
|
||||||
@@ -34,6 +107,9 @@ num_cores()
|
|||||||
|| getconf _NPROCESSORS_ONLN 2>/dev/null
|
|| getconf _NPROCESSORS_ONLN 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Run test failure detection verification first
|
||||||
|
verify_test_failure_detection
|
||||||
|
|
||||||
./bootstrap.sh
|
./bootstrap.sh
|
||||||
|
|
||||||
tests=()
|
tests=()
|
||||||
@@ -44,7 +120,7 @@ ARCH="$(uname | tr '[:upper:]' '[:lower:]')"
|
|||||||
|
|
||||||
case "$ARCH" in
|
case "$ARCH" in
|
||||||
linux*)
|
linux*)
|
||||||
# Reduced set of configurations for faster CI
|
# 4 configurations for parallel CI
|
||||||
tests=(
|
tests=(
|
||||||
# 1. Full build (all features enabled)
|
# 1. Full build (all features enabled)
|
||||||
"--enable-notifications --enable-icons-and-clipboard --enable-otr --enable-pgp
|
"--enable-notifications --enable-icons-and-clipboard --enable-otr --enable-pgp
|
||||||
@@ -56,15 +132,13 @@ case "$ARCH" in
|
|||||||
--disable-python-plugins --without-xscreensaver --disable-omemo-qrcode --disable-gdk-pixbuf"
|
--disable-python-plugins --without-xscreensaver --disable-omemo-qrcode --disable-gdk-pixbuf"
|
||||||
# 3. No encryption (disable otr, pgp, omemo)
|
# 3. No encryption (disable otr, pgp, omemo)
|
||||||
"--disable-pgp --disable-otr --disable-omemo --disable-omemo-qrcode"
|
"--disable-pgp --disable-otr --disable-omemo --disable-omemo-qrcode"
|
||||||
# 4. No plugins
|
# 4. Default configuration
|
||||||
"--disable-plugins --disable-c-plugins --disable-python-plugins"
|
|
||||||
# 5. Default configuration
|
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
source /etc/profile.d/debuginfod.sh 2>/dev/null || true
|
source /etc/profile.d/debuginfod.sh 2>/dev/null || true
|
||||||
;;
|
;;
|
||||||
darwin*)
|
darwin*)
|
||||||
# Reduced set of configurations for faster CI
|
# 4 configurations for parallel CI
|
||||||
tests=(
|
tests=(
|
||||||
# 1. Full build (all features enabled)
|
# 1. Full build (all features enabled)
|
||||||
"--enable-notifications --enable-icons-and-clipboard --enable-otr --enable-pgp
|
"--enable-notifications --enable-icons-and-clipboard --enable-otr --enable-pgp
|
||||||
@@ -76,9 +150,7 @@ case "$ARCH" in
|
|||||||
--disable-python-plugins"
|
--disable-python-plugins"
|
||||||
# 3. No encryption (disable otr, pgp, omemo)
|
# 3. No encryption (disable otr, pgp, omemo)
|
||||||
"--disable-pgp --disable-otr --disable-omemo"
|
"--disable-pgp --disable-otr --disable-omemo"
|
||||||
# 4. No plugins
|
# 4. Default configuration
|
||||||
"--disable-plugins --disable-c-plugins --disable-python-plugins"
|
|
||||||
# 5. Default configuration
|
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
;;
|
;;
|
||||||
@@ -90,7 +162,7 @@ case "$ARCH" in
|
|||||||
# src/event/server_events.c:1454:19: error: universal character names are only valid in C++ and C99
|
# 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"
|
CC="egcc -std=gnu99 -fexec-charset=UTF-8"
|
||||||
|
|
||||||
# Reduced set of configurations for faster CI
|
# 4 configurations for parallel CI
|
||||||
tests=(
|
tests=(
|
||||||
# 1. Full build (all features enabled)
|
# 1. Full build (all features enabled)
|
||||||
"--enable-notifications --enable-icons-and-clipboard --enable-otr --enable-pgp
|
"--enable-notifications --enable-icons-and-clipboard --enable-otr --enable-pgp
|
||||||
@@ -102,9 +174,7 @@ case "$ARCH" in
|
|||||||
--disable-python-plugins"
|
--disable-python-plugins"
|
||||||
# 3. No encryption (disable otr, pgp, omemo)
|
# 3. No encryption (disable otr, pgp, omemo)
|
||||||
"--disable-pgp --disable-otr --disable-omemo"
|
"--disable-pgp --disable-otr --disable-omemo"
|
||||||
# 4. No plugins
|
# 4. Default configuration
|
||||||
"--disable-plugins --disable-c-plugins --disable-python-plugins"
|
|
||||||
# 5. Default configuration
|
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
;;
|
;;
|
||||||
@@ -113,11 +183,11 @@ esac
|
|||||||
case "$ARCH" in
|
case "$ARCH" in
|
||||||
linux*)
|
linux*)
|
||||||
echo
|
echo
|
||||||
echo "--> Building with ./configure ${tests[0]} --enable-valgrind $*"
|
echo "--> Building with ./configure -C ${tests[0]} --enable-valgrind $*"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
./configure ${tests[0]} --enable-valgrind $*
|
./configure -C ${tests[0]} --enable-valgrind $*
|
||||||
|
|
||||||
$MAKE CC="${CC}"
|
$MAKE CC="${CC}"
|
||||||
if grep '^ID=' /etc/os-release | grep -q -e debian; then
|
if grep '^ID=' /etc/os-release | grep -q -e debian; then
|
||||||
@@ -129,18 +199,73 @@ case "$ARCH" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
for features in "${tests[@]}"
|
# Function to build and test a single configuration
|
||||||
do
|
build_and_test() {
|
||||||
echo
|
local features="$1"
|
||||||
echo "--> Building with ./configure ${features} $*"
|
local extra_args="$2"
|
||||||
echo
|
local idx="$3"
|
||||||
|
local build_dir="build-$idx"
|
||||||
|
local log_file="build-$idx.log"
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
{
|
||||||
./configure $features $*
|
echo "=== Build $idx started at $(date) ==="
|
||||||
|
echo "--> Building in $build_dir with ./configure -C $features $extra_args"
|
||||||
|
|
||||||
$MAKE CC="${CC}"
|
mkdir -p "$build_dir"
|
||||||
$MAKE check
|
cd "$build_dir"
|
||||||
|
|
||||||
./profanity -v
|
# shellcheck disable=SC2086
|
||||||
$MAKE clean
|
../configure -C $features $extra_args
|
||||||
|
|
||||||
|
$MAKE CC="${CC}"
|
||||||
|
$MAKE check-functional-parallel
|
||||||
|
|
||||||
|
./profanity -v
|
||||||
|
$MAKE clean
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
rm -rf "$build_dir"
|
||||||
|
|
||||||
|
echo "=== Build $idx completed at $(date) ==="
|
||||||
|
} > "$log_file" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run all 4 configurations in parallel
|
||||||
|
echo "Starting parallel builds..."
|
||||||
|
pids=()
|
||||||
|
for idx in 1 2 3 4; do
|
||||||
|
if [ $idx -le ${#tests[@]} ]; then
|
||||||
|
build_and_test "${tests[$((idx-1))]}" "$*" "$idx" &
|
||||||
|
pids+=("$!")
|
||||||
|
echo "Started build $idx (PID: $!)"
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Wait for all builds and check exit codes
|
||||||
|
failed=0
|
||||||
|
for i in "${!pids[@]}"; do
|
||||||
|
idx=$((i + 1))
|
||||||
|
if wait "${pids[$i]}"; then
|
||||||
|
echo "✓ Build $idx passed"
|
||||||
|
else
|
||||||
|
echo "✗ Build $idx failed"
|
||||||
|
echo "--- Log for build $idx ---"
|
||||||
|
cat "build-$idx.log"
|
||||||
|
echo "--- End log ---"
|
||||||
|
failed=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Show all logs on success too
|
||||||
|
if [ $failed -eq 0 ]; then
|
||||||
|
echo
|
||||||
|
echo "All builds passed!"
|
||||||
|
for idx in 1 2 3 4; do
|
||||||
|
if [ -f "build-$idx.log" ]; then
|
||||||
|
echo "--- Log for build $idx ---"
|
||||||
|
cat "build-$idx.log"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ AC_ARG_ENABLE([gdk-pixbuf],
|
|||||||
[AS_HELP_STRING([--enable-gdk-pixbuf], [enable GDK Pixbuf support to scale avatars before uploading])])
|
[AS_HELP_STRING([--enable-gdk-pixbuf], [enable GDK Pixbuf support to scale avatars before uploading])])
|
||||||
AC_ARG_ENABLE([omemo-qrcode],
|
AC_ARG_ENABLE([omemo-qrcode],
|
||||||
[AS_HELP_STRING([--enable-omemo-qrcode], [enable ability to display omemo qr code])])
|
[AS_HELP_STRING([--enable-omemo-qrcode], [enable ability to display omemo qr code])])
|
||||||
|
AC_ARG_ENABLE([coverage],
|
||||||
|
[AS_HELP_STRING([--enable-coverage], [enable code coverage analysis])])
|
||||||
|
|
||||||
m4_include([m4/ax_valgrind_check.m4])
|
m4_include([m4/ax_valgrind_check.m4])
|
||||||
AX_VALGRIND_DFLT([drd], [off])
|
AX_VALGRIND_DFLT([drd], [off])
|
||||||
@@ -386,6 +388,11 @@ AC_SUBST([FORKPTY_LIB])
|
|||||||
AM_CFLAGS="$AM_CFLAGS -Wall -Wno-deprecated-declarations -std=gnu99 -ggdb3"
|
AM_CFLAGS="$AM_CFLAGS -Wall -Wno-deprecated-declarations -std=gnu99 -ggdb3"
|
||||||
AM_LDFLAGS="$AM_LDFLAGS -export-dynamic"
|
AM_LDFLAGS="$AM_LDFLAGS -export-dynamic"
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_coverage" = xyes],
|
||||||
|
[AM_CFLAGS="$AM_CFLAGS --coverage -O0"
|
||||||
|
AM_LDFLAGS="$AM_LDFLAGS --coverage"
|
||||||
|
AC_MSG_NOTICE([Code coverage analysis enabled])])
|
||||||
|
|
||||||
AS_IF([test "x$PACKAGE_STATUS" = xdevelopment],
|
AS_IF([test "x$PACKAGE_STATUS" = xdevelopment],
|
||||||
[AM_CFLAGS="$AM_CFLAGS -Wunused -Werror"])
|
[AM_CFLAGS="$AM_CFLAGS -Wunused -Werror"])
|
||||||
AS_IF([test "x$PLATFORM" = xosx],
|
AS_IF([test "x$PLATFORM" = xosx],
|
||||||
|
|||||||
@@ -14,16 +14,28 @@
|
|||||||
* flaky tests caused by leftover state. The overhead is acceptable since
|
* flaky tests caused by leftover state. The overhead is acceptable since
|
||||||
* functional tests run less frequently than unit tests.
|
* functional tests run less frequently than unit tests.
|
||||||
*
|
*
|
||||||
* Tests are organized into groups for better maintainability:
|
* Tests are organized into groups for better maintainability and parallel execution:
|
||||||
* Group 1: Connection, Ping, Rooms, Presence
|
* Group 1: Connect, Ping, Rooms, Software (17 tests)
|
||||||
* Group 2: Messages, Receipts, Roster management
|
* Group 2: Message, Receipts, Roster, Chat Session (17 tests)
|
||||||
* Group 3: MUC (Multi-User Chat) functionality
|
* Group 3: Presence (16 tests)
|
||||||
* Group 4: Carbons, Chat sessions, Software version, Disconnect
|
* Group 4: MUC, Carbons (19 tests)
|
||||||
|
*
|
||||||
|
* Parallel execution:
|
||||||
|
* ./functionaltests - run all tests sequentially
|
||||||
|
* ./functionaltests 1 - run group 1 only
|
||||||
|
* ./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:
|
||||||
|
* ./functionaltests 1 & ./functionaltests 2 & ./functionaltests 3 & ./functionaltests 4 & wait
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
#include "prof_cmocka.h"
|
#include "prof_cmocka.h"
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
@@ -49,14 +61,21 @@
|
|||||||
int
|
int
|
||||||
main(int argc, char* argv[])
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
const struct CMUnitTest all_tests[] = {
|
int group = 0; /* 0 = all groups */
|
||||||
|
if (argc > 1) {
|
||||||
|
group = atoi(argv[1]);
|
||||||
|
if (group < 1 || group > 4) {
|
||||||
|
fprintf(stderr, "Usage: %s [group]\n", argv[0]);
|
||||||
|
fprintf(stderr, " group: 1-4 to run specific group, or omit for all\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* GROUP 1: Connect, Ping, Rooms, Software (17 tests)
|
||||||
* GROUP 1: Connect, Ping, Rooms, Presence
|
* Basic XMPP session establishment and server queries */
|
||||||
* Basic XMPP session establishment and presence management
|
|
||||||
* ============================================================ */
|
|
||||||
|
|
||||||
/* Connection tests - verify login, roster, bookmarks */
|
/* Connection tests - verify login, roster, bookmarks */
|
||||||
|
const struct CMUnitTest group1_tests[] = {
|
||||||
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),
|
||||||
@@ -73,27 +92,18 @@ main(int argc, char* argv[])
|
|||||||
/* Room discovery - XEP-0045 */
|
/* Room discovery - XEP-0045 */
|
||||||
PROF_FUNC_TEST(rooms_query),
|
PROF_FUNC_TEST(rooms_query),
|
||||||
|
|
||||||
/* Presence tests - online/away/xa/dnd/chat status */
|
/* Software Version - XEP-0092 */
|
||||||
PROF_FUNC_TEST(presence_online),
|
PROF_FUNC_TEST(send_software_version_request),
|
||||||
PROF_FUNC_TEST(presence_online_with_message),
|
PROF_FUNC_TEST(display_software_version_result),
|
||||||
PROF_FUNC_TEST(presence_away),
|
PROF_FUNC_TEST(shows_message_when_software_version_error),
|
||||||
PROF_FUNC_TEST(presence_away_with_message),
|
PROF_FUNC_TEST(display_software_version_result_when_from_domainpart),
|
||||||
PROF_FUNC_TEST(presence_xa),
|
PROF_FUNC_TEST(show_message_in_chat_window_when_no_resource),
|
||||||
PROF_FUNC_TEST(presence_xa_with_message),
|
PROF_FUNC_TEST(display_software_version_result_in_chat),
|
||||||
PROF_FUNC_TEST(presence_dnd),
|
};
|
||||||
PROF_FUNC_TEST(presence_dnd_with_message),
|
|
||||||
PROF_FUNC_TEST(presence_chat),
|
|
||||||
PROF_FUNC_TEST(presence_chat_with_message),
|
|
||||||
PROF_FUNC_TEST(presence_set_priority),
|
|
||||||
PROF_FUNC_TEST(presence_includes_priority),
|
|
||||||
PROF_FUNC_TEST(presence_keeps_status),
|
|
||||||
PROF_FUNC_TEST(presence_received),
|
|
||||||
PROF_FUNC_TEST(presence_missing_resource_defaults),
|
|
||||||
|
|
||||||
/* ============================================================
|
/* GROUP 2: Message, Receipts, Roster, Chat Session (17 tests)
|
||||||
* GROUP 2: Message, Receipts, Roster
|
* Core messaging and contact management */
|
||||||
* Core messaging and contact management
|
const struct CMUnitTest group2_tests[] = {
|
||||||
* ============================================================ */
|
|
||||||
|
|
||||||
/* Basic message send/receive */
|
/* Basic message send/receive */
|
||||||
PROF_FUNC_TEST(message_send),
|
PROF_FUNC_TEST(message_send),
|
||||||
@@ -112,21 +122,51 @@ main(int argc, char* argv[])
|
|||||||
PROF_FUNC_TEST(sends_remove_item_nick),
|
PROF_FUNC_TEST(sends_remove_item_nick),
|
||||||
PROF_FUNC_TEST(sends_nick_change),
|
PROF_FUNC_TEST(sends_nick_change),
|
||||||
|
|
||||||
/* ============================================================
|
/* Chat session management - bare/full JID routing */
|
||||||
* GROUP 3: MUC (Multi-User Chat)
|
PROF_FUNC_TEST(sends_message_to_barejid_when_contact_offline),
|
||||||
* XEP-0045 conference room functionality
|
PROF_FUNC_TEST(sends_message_to_barejid_when_contact_online),
|
||||||
* ============================================================ */
|
PROF_FUNC_TEST(sends_message_to_fulljid_when_received_from_fulljid),
|
||||||
|
PROF_FUNC_TEST(sends_subsequent_messages_to_fulljid),
|
||||||
|
PROF_FUNC_TEST(resets_to_barejid_after_presence_received),
|
||||||
|
PROF_FUNC_TEST(new_session_when_message_received_from_different_fulljid),
|
||||||
|
};
|
||||||
|
|
||||||
/* Room join with various options */
|
/* GROUP 3: Presence (16 tests)
|
||||||
|
* Online/away/xa/dnd/chat status management */
|
||||||
|
const struct CMUnitTest group3_tests[] = {
|
||||||
|
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_xa),
|
||||||
|
PROF_FUNC_TEST(presence_xa_with_message),
|
||||||
|
PROF_FUNC_TEST(presence_dnd),
|
||||||
|
PROF_FUNC_TEST(presence_dnd_with_message),
|
||||||
|
PROF_FUNC_TEST(presence_chat),
|
||||||
|
PROF_FUNC_TEST(presence_chat_with_message),
|
||||||
|
PROF_FUNC_TEST(presence_set_priority),
|
||||||
|
PROF_FUNC_TEST(presence_includes_priority),
|
||||||
|
PROF_FUNC_TEST(presence_keeps_status),
|
||||||
|
PROF_FUNC_TEST(presence_received),
|
||||||
|
PROF_FUNC_TEST(presence_missing_resource_defaults),
|
||||||
|
|
||||||
|
/* Disconnect - clean session termination */
|
||||||
|
PROF_FUNC_TEST(disconnect_ends_session),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* GROUP 4: MUC, Carbons (19 tests)
|
||||||
|
* Multi-user chat and message synchronization */
|
||||||
|
const struct CMUnitTest group4_tests[] = {
|
||||||
|
|
||||||
|
/* 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),
|
||||||
PROF_FUNC_TEST(sends_room_join_with_password),
|
PROF_FUNC_TEST(sends_room_join_with_password),
|
||||||
PROF_FUNC_TEST(sends_room_join_with_nick_and_password),
|
PROF_FUNC_TEST(sends_room_join_with_nick_and_password),
|
||||||
|
|
||||||
/* Room information display */
|
/* MUC room information display */
|
||||||
PROF_FUNC_TEST(shows_role_and_affiliation_on_join),
|
PROF_FUNC_TEST(shows_role_and_affiliation_on_join),
|
||||||
PROF_FUNC_TEST(shows_subject_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),
|
PROF_FUNC_TEST(shows_occupant_join),
|
||||||
|
|
||||||
/* MUC messaging */
|
/* MUC messaging */
|
||||||
@@ -134,16 +174,11 @@ main(int argc, char* argv[])
|
|||||||
PROF_FUNC_TEST(shows_me_message_from_occupant),
|
PROF_FUNC_TEST(shows_me_message_from_occupant),
|
||||||
PROF_FUNC_TEST(shows_me_message_from_self),
|
PROF_FUNC_TEST(shows_me_message_from_self),
|
||||||
|
|
||||||
/* Console notification settings for MUC */
|
/* MUC console notification settings */
|
||||||
PROF_FUNC_TEST(shows_all_messages_in_console_when_window_not_focussed),
|
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_first_message_in_console_when_window_not_focussed),
|
||||||
PROF_FUNC_TEST(shows_no_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) */
|
/* Message Carbons - XEP-0280 (message sync across devices) */
|
||||||
PROF_FUNC_TEST(send_enable_carbons),
|
PROF_FUNC_TEST(send_enable_carbons),
|
||||||
PROF_FUNC_TEST(connect_with_carbons_enabled),
|
PROF_FUNC_TEST(connect_with_carbons_enabled),
|
||||||
@@ -151,26 +186,31 @@ main(int argc, char* argv[])
|
|||||||
PROF_FUNC_TEST(receive_carbon),
|
PROF_FUNC_TEST(receive_carbon),
|
||||||
PROF_FUNC_TEST(receive_self_carbon),
|
PROF_FUNC_TEST(receive_self_carbon),
|
||||||
PROF_FUNC_TEST(receive_private_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),
|
|
||||||
PROF_FUNC_TEST(sends_subsequent_messages_to_fulljid),
|
|
||||||
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_software_version_request),
|
|
||||||
PROF_FUNC_TEST(display_software_version_result),
|
|
||||||
PROF_FUNC_TEST(shows_message_when_software_version_error),
|
|
||||||
PROF_FUNC_TEST(display_software_version_result_when_from_domainpart),
|
|
||||||
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(disconnect_ends_session),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return cmocka_run_group_tests(all_tests, NULL, NULL);
|
int result = 0;
|
||||||
|
|
||||||
|
switch (group) {
|
||||||
|
case 1:
|
||||||
|
result = cmocka_run_group_tests_name("Group 1: Connect/Ping/Rooms/Software", group1_tests, NULL, NULL);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
result = cmocka_run_group_tests_name("Group 2: Message/Receipts/Roster/Session", group2_tests, NULL, NULL);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
result = cmocka_run_group_tests_name("Group 3: Presence", group3_tests, 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,13 @@ int fd = 0;
|
|||||||
int stub_port = 5230;
|
int stub_port = 5230;
|
||||||
pid_t child_pid = 0;
|
pid_t child_pid = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dynamic XDG paths based on stub_port for parallel test execution.
|
||||||
|
* Each test instance gets unique directories to avoid file conflicts.
|
||||||
|
*/
|
||||||
|
char xdg_config_home[256];
|
||||||
|
char xdg_data_home[256];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Buffer for accumulating output from profanity.
|
* Buffer for accumulating output from profanity.
|
||||||
* 64KB is sufficient for typical test output while keeping memory usage
|
* 64KB is sufficient for typical test output while keeping memory usage
|
||||||
@@ -77,7 +84,7 @@ _mkdir_recursive(const char *dir)
|
|||||||
void
|
void
|
||||||
_create_config_dir(void)
|
_create_config_dir(void)
|
||||||
{
|
{
|
||||||
GString *profanity_dir = g_string_new(XDG_CONFIG_HOME);
|
GString *profanity_dir = g_string_new(xdg_config_home);
|
||||||
g_string_append(profanity_dir, "/profanity");
|
g_string_append(profanity_dir, "/profanity");
|
||||||
|
|
||||||
if (!_mkdir_recursive(profanity_dir->str)) {
|
if (!_mkdir_recursive(profanity_dir->str)) {
|
||||||
@@ -90,7 +97,7 @@ _create_config_dir(void)
|
|||||||
void
|
void
|
||||||
_create_data_dir(void)
|
_create_data_dir(void)
|
||||||
{
|
{
|
||||||
GString *profanity_dir = g_string_new(XDG_DATA_HOME);
|
GString *profanity_dir = g_string_new(xdg_data_home);
|
||||||
g_string_append(profanity_dir, "/profanity");
|
g_string_append(profanity_dir, "/profanity");
|
||||||
|
|
||||||
if (!_mkdir_recursive(profanity_dir->str)) {
|
if (!_mkdir_recursive(profanity_dir->str)) {
|
||||||
@@ -103,7 +110,7 @@ _create_data_dir(void)
|
|||||||
void
|
void
|
||||||
_create_chatlogs_dir(void)
|
_create_chatlogs_dir(void)
|
||||||
{
|
{
|
||||||
GString *chatlogs_dir = g_string_new(XDG_DATA_HOME);
|
GString *chatlogs_dir = g_string_new(xdg_data_home);
|
||||||
g_string_append(chatlogs_dir, "/profanity/chatlogs");
|
g_string_append(chatlogs_dir, "/profanity/chatlogs");
|
||||||
|
|
||||||
if (!_mkdir_recursive(chatlogs_dir->str)) {
|
if (!_mkdir_recursive(chatlogs_dir->str)) {
|
||||||
@@ -116,7 +123,7 @@ _create_chatlogs_dir(void)
|
|||||||
void
|
void
|
||||||
_create_logs_dir(void)
|
_create_logs_dir(void)
|
||||||
{
|
{
|
||||||
GString *logs_dir = g_string_new(XDG_DATA_HOME);
|
GString *logs_dir = g_string_new(xdg_data_home);
|
||||||
g_string_append(logs_dir, "/profanity/logs");
|
g_string_append(logs_dir, "/profanity/logs");
|
||||||
|
|
||||||
if (!_mkdir_recursive(logs_dir->str)) {
|
if (!_mkdir_recursive(logs_dir->str)) {
|
||||||
@@ -129,7 +136,9 @@ _create_logs_dir(void)
|
|||||||
void
|
void
|
||||||
_cleanup_dirs(void)
|
_cleanup_dirs(void)
|
||||||
{
|
{
|
||||||
int res = system("rm -rf ./tests/functionaltests/files");
|
char cmd[512];
|
||||||
|
snprintf(cmd, sizeof(cmd), "rm -rf ./tests/functionaltests/files/%d", stub_port);
|
||||||
|
int res = system(cmd);
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
assert_true(FALSE);
|
assert_true(FALSE);
|
||||||
}
|
}
|
||||||
@@ -231,14 +240,20 @@ init_prof_test(void **state)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate unique XDG paths based on stub_port for parallel execution
|
||||||
|
snprintf(xdg_config_home, sizeof(xdg_config_home),
|
||||||
|
"./tests/functionaltests/files/%d/xdg_config_home", stub_port);
|
||||||
|
snprintf(xdg_data_home, sizeof(xdg_data_home),
|
||||||
|
"./tests/functionaltests/files/%d/xdg_data_home", stub_port);
|
||||||
|
|
||||||
// Give stabber server thread time to start listening
|
// Give stabber server thread time to start listening
|
||||||
usleep(100000); // 100ms
|
usleep(100000); // 100ms
|
||||||
|
|
||||||
config_orig = getenv("XDG_CONFIG_HOME");
|
config_orig = getenv("XDG_CONFIG_HOME");
|
||||||
data_orig = getenv("XDG_DATA_HOME");
|
data_orig = getenv("XDG_DATA_HOME");
|
||||||
|
|
||||||
setenv("XDG_CONFIG_HOME", XDG_CONFIG_HOME, 1);
|
setenv("XDG_CONFIG_HOME", xdg_config_home, 1);
|
||||||
setenv("XDG_DATA_HOME", XDG_DATA_HOME, 1);
|
setenv("XDG_DATA_HOME", xdg_data_home, 1);
|
||||||
|
|
||||||
_cleanup_dirs();
|
_cleanup_dirs();
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
#ifndef __H_PROFTEST
|
#ifndef __H_PROFTEST
|
||||||
#define __H_PROFTEST
|
#define __H_PROFTEST
|
||||||
|
|
||||||
#define XDG_CONFIG_HOME "./tests/functionaltests/files/xdg_config_home"
|
/*
|
||||||
#define XDG_DATA_HOME "./tests/functionaltests/files/xdg_data_home"
|
* XDG paths are now dynamic, generated per-test based on stub_port.
|
||||||
|
* This allows parallel test execution without file conflicts.
|
||||||
|
* Use xdg_config_home and xdg_data_home variables instead of macros.
|
||||||
|
*/
|
||||||
|
extern char xdg_config_home[256];
|
||||||
|
extern char xdg_data_home[256];
|
||||||
|
|
||||||
extern int stub_port;
|
extern int stub_port;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user