Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Test Suite

Functional and integration tests that verify correctness of every layer — from raw io_uring events up to full GObj protocol stacks. All tests are registered as ctest targets and run automatically with yunetas test.

Source: tests/c/

# Run the full suite
yunetas test

# Run a single test by name
ctest -R test_c_timer --output-on-failure --test-dir build

# Run ctest in a loop until first failure (flaky-test detection)
./ctest-loop.sh

Event loop (yev_loop)

Low-level tests for the io_uring event loop, without the GObj layer.

BinaryDescription
test_yevent_listen1–4Server creates a listen socket and accepts one client connection.
test_yevent_connect1–2Client connects to a listening server, then makes sure that the connection succeeds.
test_yevent_traffic1–6Client ↔ server message echo over plain TCP (multiple variants).
test_yevent_udp_traffic1UDP message echo.
test_yevent_traffic_secure1TLS-encrypted TCP message echo.
test_yevent_timer_once1–2One-shot timer expiration.
test_yevent_timer_periodic1Periodic (recurring) timer.

Source: tests/c/yev_loop/yev_events/, tests/c/yev_loop/yev_events_tls/

Timers

BinaryDescription
test_c_timerC_TIMER GClass — periodic timeout operations.
test_c_timer0C_TIMER0 GClass — basic (low-level) timer.

Source: tests/c/c_timer/, tests/c/c_timer0/

TCP networking

Plain and TLS TCP through the full GObj protocol stack.

BinaryDescription
test_c_tcp test1–4Plain TCP: connect, disconnect, echo, and rapid multi-message burst.
test_c_tcp2 test1–4Same scenarios using the newer C_TCP_S method (no child_tree_filter).
test_c_tcps test1–4TLS TCP: connect, disconnect, echo, and multi-message burst.
test_c_tcps2 test1–4TLS TCP with the newer method.

Source: tests/c/c_tcp/, tests/c/c_tcp2/, tests/c/c_tcps/, tests/c/c_tcps2/

TLS certificate hot-reload

Protects the cert-reload feature — validates that ytls_reload_certificates() swaps certificates atomically without dropping live sessions and rolls back cleanly on invalid material.

BinaryDescription
test_cert_reloadSwap cert A → B and make sure that view-cert shows the new subject and not_after. Then feed an invalid cert and make sure that the previous context stays intact (rollback).
test_cert_infoytls_get_cert_info() edge cases: short / long validity, self-signed invariant, serial shape, client-side NULL, already-expired cert.
test_cert_reload_mem1000 reloads without any live session and asserts get_cur_system_memory() == 0 (leak gate, run under valgrind for exhaustive checking).
test_yevent_reload_liveOne reload while a TCP session is live. The session keeps working end-to-end.
test_yevent_reload_stress50 reloads with a live session, one echo message per iteration.

Source: tests/c/ytls/, tests/c/yev_loop/yev_events_tls/

HTTP parser (llhttp wrapper)

BinaryDescription
test_c_llhttp_parserSanity test for the vendored llhttp library and the ghttp_parser wrapper: request/response parse, keep-alive pipelining, HPE_PAUSED_UPGRADE tail bytes, EOF completion via ghttp_parser_finish().

Source: tests/c/c_llhttp_parser/

OAuth2 / BFF (c_auth_bff)

Self-contained yunos that spin up a mock Keycloak (signed HS256 JWTs, scriptable latency / response status / body override) alongside C_AUTH_BFF and drive /auth/login, /auth/callback, /auth/refresh, /auth/logout through happy paths and failure modes. Each test is its own binary so a crash or leak cannot mask neighbours.

BinaryDescription
test1_loginHappy-path login round-trip through the BFF.
test2_kc_401IdP returns 401. BFF must give a stable error_code, and it must not corrupt its kc_ok counter.
test3_callback/auth/callback code-for-token exchange.
test4_refreshProactive refresh-token round-trip.
test5_logoutLogout clears cookies and drives the IdP revoke endpoint.
test6_invalid_bodyMalformed JSON body → 4xx with error_code mapped for the GUI.
test7_slow_loginIdP replies slowly. The BFF makes the browser wait, and it does not time out early.
test8_queue_fullPipeline 4 POSTs + overflow: dl_list pending queue drops the overflow in order and reports the configured pending_queue_size.
test9_browser_cancelBrowser disconnects in the middle of the round-trip. The BFF drops the stale IdP reply (responses_dropped counter) and does not forward it.
test10_kc_silenceIdP gives no answer. The kc_timeout_ms watchdog fires, answers 504 to the browser, and drains the task (kc_timeouts counter).
test11_cancel_retryCancel-then-retry: state cleanup between two back-to-back logins on the same browser.
test12_stale_replyPer-task browser generation blocks cross-user token leak races.
test13_refresh_expiredExpired refresh token → mapped error, no silent kc_error.
test14_method_not_allowedNon-POST on an auth endpoint → 405.
test15_missing_bodyMissing body → 4xx with mapped error.
test16_unknown_endpointUnknown /auth/* path → 404, not 5xx.

Source: tests/c/c_auth_bff/ (includes c_mock_keycloak, test_helpers).

MQTT

BinaryDescription
test_c_mqtt test1Self-contained broker + client: subscribe, publish QoS 0, verify reception, disconnect.

Source: tests/c/c_mqtt/

BinaryDescription
test_subscriptions test1–2GObj event subscribe / unsubscribe lifecycle.
test_c_node_link_eventsEV_TREEDB_NODE_LINKED / UNLINKED events at the C_NODE GClass level.
test_tr_treedb_link_eventsLow-level link/unlink callback mechanism in tr_treedb.

Source: tests/c/c_subscriptions/, tests/c/c_node_link_events/, tests/c/tr_treedb_link_events/

Timeranger2 persistence

BinaryDescription
test_tranger_startupDatabase initialization and startup.
test_topic_pkey_integerOpen topic as master, manage runtime lists, append records with integer keys.
test_topic_pkey_integer_iteratorIterator without callbacks over integer-key data.
test_topic_pkey_integer_iterator2Iterator with per-key callbacks and time-based matching.
test_topic_pkey_integer_iterator3Absolute-position searches.
test_topic_pkey_integer_iterator4Relative-position searches.
test_topic_pkey_integer_iterator5Paginated searches.
test_topic_pkey_integer_iterator6Master/client iterator mode with realtime record additions.
test_testingTesting utilities (event counters, assertions).

Source: tests/c/timeranger2/

TR_MSG & TR_QUEUE

BinaryDescription
test_tr_msg1Message topics: iteration, key matching, instance retrieval.
test_tr_msg2Stress variant: 1 000 devices × 100 traces.
test_tr_queue1Queue topic: enqueue / dequeue with time-based keys over a multi-day period.

Source: tests/c/tr_msg/, tests/c/tr_queue/

TreeDB

BinaryDescription
test_tr_treedbSchema creation, user/department/compound structures, node CRUD, and state snapshots (foto files).

Source: tests/c/tr_treedb/

Keyword matching

BinaryDescription
test_kw1kw_match_simple() with strings, booleans, integers, and floats.

Source: tests/c/kw/

Generic message interchange

A JSON-driven test runner that executes scripted test sequences and validates event traces and error logs.

Test scenarioDescription
test_mqtt_qos0MQTT QoS 0 publish/subscribe interchange.
test_tcp_connectTCP connection establishment.
test_tcp_reconnectTCP reconnection and recovery.

Source: tests/c/msg_interchange/

Debugging a test that corrupts the heap

A test that dies with “corrupted double-linked list” or “free(): chunks in smallbin corrupted” is reporting heap corruption that happened earlier: the abort lands at the next malloc/free, not at the write that caused it. The backtrace at that point names the detector, not the culprit.

AddressSanitizer finds it, but not by simply building with it. The test tree links the installed libraries from outputs/lib, not the ones in the build tree, so configuring a build with -fsanitize=address instruments the test’s own .c files and nothing else — and ASan reports nothing while the plain build keeps aborting, which reads as “it is not a real bug” and is only “you did not look at it”.

What actually works, and what it costs:

# 1. a non-static build, because -static and -fsanitize=address are exclusive
cp .config .config.bak && sed -i 's/^CONFIG_FULLY_STATIC=y/CONFIG_FULLY_STATIC=n/' .config

# 2. configure a separate tree WITH the sanitiser
cmake -S . -B build_asan -DCMAKE_BUILD_TYPE=Debug \
    -DCMAKE_C_FLAGS="-fsanitize=address -g -fno-omit-frame-pointer" \
    -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address"

# 3. build the LIBRARIES too, not only the test
cmake --build build_asan --target yunetas-gobj timeranger2 yev_loop ytls \
    yunetas-core-linux <the test> -j8

# 4. relink the test by hand against those libraries: take its link.txt and
#    replace every /outputs/lib/lib*.a with the build_asan path

And instrument jansson as well when the corruption is around json: it lives in outputs_ext/lib and is not part of the build. Compile kernel/c/linux-ext-libs/build/jansson/src/*.c with the sanitiser and with its own generated headers-DHAVE_CONFIG_H -I<jansson>/build/private_include -I<jansson>/build/include —, or it builds but parses nothing and every test fails with “Cannot load json file, bad json”, which looks like a different bug entirely.

With all of it instrumented, ASan names the two lines that matter — where the memory was freed and where it was used afterwards — and a hunt that had taken hours takes a minute.

Restore .config afterwards.

The mistake it usually is

Three bench tests died this way on 2026-08-28, and all three were the same thing: a borrowed pointer handed to a function that owns what it is given.

json_array_get(), kw_get_dict(), treedb_get_node() and friends answer a pointer they still own; test_json() frees what it receives. Passing one to the other spends a reference that was never given, and the next json_decref() of the container frees the same block twice. Incref it at the call:

result += test_json(json_incref(record));   // record is borrowed

Build flag

Tests are enabled by default via .config (CONFIG_MODULE_TEST=y). Toggle with menuconfig or pass -DENABLE_TESTS=OFF to CMake.