All checks were successful
CI Code / Check spelling (push) Successful in 16s
CI Code / Check coding style (push) Successful in 30s
CI Code / Linux (debian) (push) Successful in 5m25s
CI Code / Linux (ubuntu) (push) Successful in 5m33s
CI Code / Code Coverage (push) Successful in 7m54s
CI Code / Linux (arch) (push) Successful in 12m7s
## Introduced change A new warning that notifies users when the connected XMPP server advertises XEP-0199 (urn:xmpp:ping) support but the autoping feature is disabled in settings. The warning can be toggled with `/autoping warning on|off`. The warning fires during the on-connect disco#info exchange, only for responses from the server's own domain — responses from user JIDs or subdomain services (e.g., conference servers) are excluded. ### Capabilities - **On-connect detection**: Warning is emitted automatically when the server's disco#info response indicates `urn:xmpp:ping` support while autoping is disabled and the preference is enabled (default: on) - **`/autoping warning on|off`**: Toggle the warning via the existing autoping command - **Domain-scoped**: Only triggers for disco#info from the bound server domain; user JIDs and subdomain service JIDs are skipped - **Case-insensitive domain matching**: Uses `g_ascii_strcasecmp` instead of `g_strcmp0` to handle case differences between the stanza `from` field and the bound domain - **Display in settings**: Shown in both `/notify` and `/autoping` settings dumps, with consistent alignment and `(/autoping warning)` reference in each line - **Autocomplete**: Dedicated `_autoping_autocomplete` function handles the `warning` subcommand with `on|off` completion ## Reasoning behind the change Users connecting to servers that support XEP-0199 ping but have autoping disabled may experience poorer connection stability. The warning draws attention to this configuration mismatch without requiring users to read documentation or dig into settings. The warning is scoped to the server domain (not user JIDs or subdomain services) because autoping is a connection-level feature — it only makes sense in the context of the server's keepalive capabilities. The warning preference defaults to `on` so users are informed by default, but can be disabled with `/autoping warning off` if they prefer not to see it. ## Implementation details ### Warning logic (`src/xmpp/iq.c`) `_disco_autoping_warning_message()` is called from the on-connect disco#info handler when the `from` field matches the bound domain. It checks three conditions: 1. Server features contain `urn:xmpp:ping` 2. Autoping interval is 0 (disabled) 3. `PREF_AUTOPING_WARNING` is true All three must be true for the warning to display. ### Domain matching `g_ascii_strcasecmp(from, connection_get_domain())` is used instead of `g_strcmp0` to handle case differences. This prevents the warning from silently skipping if a server echoes the `from` field in a different case than the bound domain. ### Command integration (`src/command/cmd_*.c`) - `cmd_defs.c`: Added `/autoping warning on|off` syntax and argument description - `cmd_funcs.c`: Added `warning` subcommand handler that calls `_cmd_set_boolean_preference` with `PREF_AUTOPING_WARNING` - `cmd_ac.c`: Registered dedicated `_autoping_autocomplete` that handles the `warning` subcommand with `on|off` boolean completion ### Preference storage (`src/config/preferences.c`) - Group: `PREF_GROUP_NOTIFICATIONS` - Key: `autoping.warning` - Default: `TRUE` ### Settings display (`src/ui/console.c`) The autoping warning preference is shown in both `cons_notify_setting()` and `cons_autoping_setting()` with consistent column alignment and a `(/autoping warning)` reference in each line. ### Tests (`tests/functionaltests/test_autoping.c`) Six functional tests cover all condition combinations: | Test | Server ping | Autoping | Warning pref | Expected | |---|---|---|---|---| | `autoping_warning_shown_when_disabled` | yes | off | on | warning shown | | `autoping_warning_not_shown_when_server_unsupported` | no | off | on | no warning | | `autoping_warning_not_shown_when_autoping_enabled` | yes | on | on | no warning | | `autoping_warning_not_shown_when_user_disabled` | yes | off | off | no warning | | `autoping_warning_not_shown_for_user_jid` | yes (from user JID) | off | on | no warning | | `autoping_warning_not_shown_for_subdomain_service` | yes (from subdomain) | off | on | no warning | Co-authored-by: Jabber Developer2 <jabber.developer2@jabber.space>
387 lines
16 KiB
C
387 lines
16 KiB
C
/*
|
|
* 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 balanced for parallel execution:
|
|
* Group 1: Connect, Ping, Rooms, Software, Last Activity, Autoping, Disco, Roster
|
|
* Group 2: Export/Import (core + bidirectional), Receipts
|
|
* Group 3: Presence, Disconnect, DB History, Message, MUC Database
|
|
* Group 4: Chat Session, MUC, Carbons, Migration Stress
|
|
*
|
|
* Parallel execution:
|
|
* ./functionaltests - run all tests sequentially
|
|
* ./functionaltests N - run group N only (N = 1..num_groups)
|
|
*
|
|
* For parallel execution, run multiple groups simultaneously:
|
|
* ./functionaltests 1 & ./functionaltests 2 & ./functionaltests 3 & ./functionaltests 4 & wait
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include "prof_cmocka.h"
|
|
#include <sys/stat.h>
|
|
|
|
#include "config.h"
|
|
|
|
#include "common.h"
|
|
#include "proftest.h"
|
|
#include "test_connect.h"
|
|
#include "test_ping.h"
|
|
#include "test_rooms.h"
|
|
#include "test_presence.h"
|
|
#include "test_message.h"
|
|
#include "test_carbons.h"
|
|
#include "test_chat_session.h"
|
|
#include "test_receipts.h"
|
|
#include "test_roster.h"
|
|
#include "test_software.h"
|
|
#include "test_muc.h"
|
|
#include "test_disconnect.h"
|
|
#include "test_lastactivity.h"
|
|
#include "test_autoping.h"
|
|
#include "test_disco.h"
|
|
#include "test_history.h"
|
|
#ifdef HAVE_SQLITE
|
|
#include "test_export_import.h"
|
|
#endif
|
|
#include "test_ai.h"
|
|
|
|
/* Macro to wrap each test with setup/teardown functions */
|
|
#define PROF_FUNC_TEST(test) \
|
|
{ \
|
|
#test, test, init_prof_test, close_prof_test, #test \
|
|
}
|
|
|
|
/* AI tests use a custom init that primes stabber via prof_connect so
|
|
* stbbr_stop() in close_prof_test() doesn't hang on a never-connected
|
|
* server thread. See ai_init_test() in test_ai.c. */
|
|
#define PROF_FUNC_TEST_AI(test) \
|
|
{ \
|
|
#test, test, ai_init_test, close_prof_test, #test \
|
|
}
|
|
|
|
#ifdef HAVE_SQLITE
|
|
/* Custom init that sets a non-UTC timezone (POSIX TST-3 = UTC+3) */
|
|
static int
|
|
init_tz_plus3_test(void** state)
|
|
{
|
|
prof_test_tz = "TST-3";
|
|
int ret = init_prof_test(state);
|
|
prof_test_tz = "UTC";
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
int
|
|
main(int argc, char* argv[])
|
|
{
|
|
int group = 0; /* 0 = all groups */
|
|
if (argc > 1) {
|
|
group = atoi(argv[1]);
|
|
if (group < 1 || group > 5) {
|
|
fprintf(stderr, "Usage: %s [group]\n", argv[0]);
|
|
fprintf(stderr, " group: 1-5 to run specific group, or omit for all\n");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
char group_env[16];
|
|
snprintf(group_env, sizeof(group_env), "%d", group);
|
|
setenv("PROF_TEST_GROUP", group_env, 1);
|
|
|
|
fprintf(stderr, "[PROF_TEST] Starting functional tests, group=%d\n", group);
|
|
|
|
/* ============================================================
|
|
* GROUP 1: Connect, Ping, Rooms, Software, Last Activity, Disco, Roster
|
|
* Basic XMPP session establishment, server queries, contact mgmt
|
|
* ============================================================ */
|
|
const struct CMUnitTest group1_tests[] = {
|
|
/* 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),
|
|
|
|
/* 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),
|
|
|
|
/* Last Activity - XEP-0012 */
|
|
PROF_FUNC_TEST(responds_to_last_activity_request),
|
|
PROF_FUNC_TEST(last_activity_request_to_contact),
|
|
|
|
/* Autoping command tests - fast, no waiting */
|
|
PROF_FUNC_TEST(autoping_set_interval),
|
|
PROF_FUNC_TEST(autoping_set_zero_disables),
|
|
PROF_FUNC_TEST(autoping_timeout_set),
|
|
PROF_FUNC_TEST(autoping_timeout_zero_disables),
|
|
|
|
/* Autoping slow tests - require sleep for timer triggers (~2s each) */
|
|
PROF_FUNC_TEST(autoping_sends_ping_after_interval),
|
|
PROF_FUNC_TEST(autoping_server_not_supporting_ping),
|
|
|
|
/* Autoping availability warning - negative cases wait ~3s */
|
|
PROF_FUNC_TEST(autoping_warning_shown_when_disabled),
|
|
PROF_FUNC_TEST(autoping_warning_not_shown_when_server_unsupported),
|
|
PROF_FUNC_TEST(autoping_warning_not_shown_when_autoping_enabled),
|
|
PROF_FUNC_TEST(autoping_warning_not_shown_when_user_disabled),
|
|
PROF_FUNC_TEST(autoping_warning_not_shown_for_user_jid),
|
|
PROF_FUNC_TEST(autoping_warning_not_shown_for_subdomain_service),
|
|
|
|
/* Service Discovery - XEP-0030 */
|
|
PROF_FUNC_TEST(disco_info_shows_identity),
|
|
PROF_FUNC_TEST(disco_info_shows_features),
|
|
PROF_FUNC_TEST(disco_info_to_server),
|
|
PROF_FUNC_TEST(disco_info_to_jid),
|
|
PROF_FUNC_TEST(disco_info_not_found),
|
|
PROF_FUNC_TEST(disco_items_shows_items),
|
|
PROF_FUNC_TEST(disco_items_empty_result),
|
|
PROF_FUNC_TEST(disco_requires_connection),
|
|
PROF_FUNC_TEST(disco_items_to_jid),
|
|
PROF_FUNC_TEST(disco_info_empty_result),
|
|
PROF_FUNC_TEST(disco_info_multiple_identities),
|
|
PROF_FUNC_TEST(disco_info_without_name),
|
|
PROF_FUNC_TEST(disco_items_without_name),
|
|
PROF_FUNC_TEST(disco_info_service_unavailable),
|
|
|
|
/* 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 2: Export/Import (core + bidirectional), Receipts
|
|
* Cross-backend migration, message timestamp round-trip
|
|
* ============================================================ */
|
|
const struct CMUnitTest group2_tests[] = {
|
|
#ifdef HAVE_SQLITE
|
|
/* Export/Import — cross-backend migration (SQLite ↔ flat-file) */
|
|
PROF_FUNC_TEST(export_sqlite_to_flatfile),
|
|
PROF_FUNC_TEST(import_flatfile_to_sqlite),
|
|
PROF_FUNC_TEST(export_idempotent_no_duplicates),
|
|
PROF_FUNC_TEST(export_lmc_correction_survives),
|
|
PROF_FUNC_TEST(switch_preserves_old_backend_data),
|
|
PROF_FUNC_TEST(export_all_contacts),
|
|
PROF_FUNC_TEST(import_double_dedup),
|
|
PROF_FUNC_TEST(verify_after_export),
|
|
PROF_FUNC_TEST(switch_backends_independent_messages),
|
|
PROF_FUNC_TEST(export_empty_contact),
|
|
|
|
/* Bidirectional migration — split timelines merged across backends */
|
|
PROF_FUNC_TEST(bidirectional_merge_to_flatfile),
|
|
PROF_FUNC_TEST(bidirectional_merge_to_sqlite),
|
|
PROF_FUNC_TEST(migration_incremental_accumulation),
|
|
PROF_FUNC_TEST(roundtrip_full_cycle),
|
|
PROF_FUNC_TEST(export_timestamps_preserved),
|
|
PROF_FUNC_TEST(import_timestamps_preserved),
|
|
{ "export_timestamps_non_utc", export_timestamps_non_utc, init_tz_plus3_test, close_prof_test, "export_timestamps_non_utc" },
|
|
#endif
|
|
|
|
/* 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),
|
|
};
|
|
|
|
/* ============================================================
|
|
* GROUP 3: Presence, Disconnect, DB History, Message, MUC Database
|
|
* Status management, message persistence, MUC storage
|
|
* ============================================================ */
|
|
const struct CMUnitTest group3_tests[] = {
|
|
/* Presence - online/away/xa/dnd/chat status management */
|
|
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),
|
|
|
|
/* Database persistence - message write+read round-trip */
|
|
PROF_FUNC_TEST(message_db_history_on_reopen),
|
|
PROF_FUNC_TEST(message_db_history_multiple),
|
|
PROF_FUNC_TEST(message_db_history_contact_isolation),
|
|
PROF_FUNC_TEST(message_db_history_special_chars),
|
|
PROF_FUNC_TEST(message_db_history_outgoing),
|
|
PROF_FUNC_TEST(message_db_history_dialog),
|
|
PROF_FUNC_TEST(message_db_history_empty),
|
|
PROF_FUNC_TEST(message_db_history_long_message),
|
|
PROF_FUNC_TEST(message_db_history_newline),
|
|
PROF_FUNC_TEST(message_db_history_service_chars),
|
|
PROF_FUNC_TEST(message_db_history_verify),
|
|
PROF_FUNC_TEST(message_db_history_lmc),
|
|
PROF_FUNC_TEST(message_db_history_multi_resource),
|
|
|
|
/* Basic message send/receive */
|
|
PROF_FUNC_TEST(message_send),
|
|
PROF_FUNC_TEST(message_receive_console),
|
|
PROF_FUNC_TEST(message_receive_chatwin),
|
|
|
|
/* XEP-0359 disco gate for stanza-id trust */
|
|
PROF_FUNC_TEST(stanza_id_dedup_fires_when_server_announces_sid0),
|
|
PROF_FUNC_TEST(stanza_id_not_trusted_when_server_does_not_announce_sid0),
|
|
|
|
#ifdef HAVE_SQLITE
|
|
/* MUC (groupchat) database — export/import of type="muc" messages */
|
|
PROF_FUNC_TEST(muc_export_sqlite_to_flatfile),
|
|
PROF_FUNC_TEST(muc_import_flatfile_to_sqlite),
|
|
PROF_FUNC_TEST(muc_export_timestamps_preserved),
|
|
PROF_FUNC_TEST(muc_export_multiple_rooms),
|
|
#endif
|
|
};
|
|
|
|
/* ============================================================
|
|
* GROUP 4: Chat Session, MUC, Carbons, Migration Stress
|
|
* Session routing, multi-user chat, message sync, stress tests
|
|
* ============================================================ */
|
|
const struct CMUnitTest group4_tests[] = {
|
|
/* 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),
|
|
|
|
/* MUC room join with various options - XEP-0045 */
|
|
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),
|
|
|
|
/* MUC room information display */
|
|
PROF_FUNC_TEST(shows_role_and_affiliation_on_join),
|
|
PROF_FUNC_TEST(shows_subject_on_join),
|
|
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),
|
|
|
|
/* MUC console notification settings */
|
|
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),
|
|
|
|
/* MUC moderation - XEP-0045 room admin */
|
|
PROF_FUNC_TEST(sends_affiliation_list_request),
|
|
PROF_FUNC_TEST(sends_kick_request),
|
|
|
|
/* 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),
|
|
|
|
#ifdef HAVE_SQLITE
|
|
/* Migration stress — pool accumulation, LMC chains, large bodies */
|
|
PROF_FUNC_TEST(export_message_pool_dated),
|
|
PROF_FUNC_TEST(export_lmc_pool_multiple),
|
|
PROF_FUNC_TEST(export_large_body_survives),
|
|
#endif
|
|
};
|
|
|
|
/* ============================================================
|
|
* GROUP 5: AI command surface (console + HTTP stub)
|
|
* Standalone because AI tests don't use stabber's XMPP path; mixing
|
|
* them with XMPP-bound tests in the same group poisons stabber state
|
|
* between fixture init/teardown cycles and hangs subsequent
|
|
* prof_connect() calls.
|
|
* ============================================================ */
|
|
const struct CMUnitTest group5_tests[] = {
|
|
/* Console-only — no network calls */
|
|
PROF_FUNC_TEST_AI(ai_no_args_shows_help),
|
|
PROF_FUNC_TEST_AI(ai_providers_lists_defaults),
|
|
PROF_FUNC_TEST_AI(ai_providers_list_shows_key_status),
|
|
PROF_FUNC_TEST_AI(ai_set_provider_adds_custom),
|
|
PROF_FUNC_TEST_AI(ai_set_token_marks_key_set),
|
|
PROF_FUNC_TEST_AI(ai_start_unknown_provider_errors),
|
|
PROF_FUNC_TEST_AI(ai_start_without_key_errors),
|
|
PROF_FUNC_TEST_AI(ai_start_with_key_opens_window),
|
|
PROF_FUNC_TEST_AI(ai_clear_without_window_errors),
|
|
PROF_FUNC_TEST_AI(ai_remove_provider_works),
|
|
PROF_FUNC_TEST_AI(ai_remove_provider_unknown_errors),
|
|
PROF_FUNC_TEST_AI(ai_set_default_model_updates_provider),
|
|
PROF_FUNC_TEST_AI(ai_switch_without_window_errors),
|
|
PROF_FUNC_TEST_AI(ai_bad_subcommand_shows_usage),
|
|
};
|
|
|
|
/* Test group registry for easy extension */
|
|
struct
|
|
{
|
|
const char* name;
|
|
const struct CMUnitTest* tests;
|
|
size_t count;
|
|
} groups[] = {
|
|
{ "Group 1: Connect/Ping/Disco/Roster", group1_tests, ARRAY_SIZE(group1_tests) },
|
|
{ "Group 2: ExportImport/Receipts", group2_tests, ARRAY_SIZE(group2_tests) },
|
|
{ "Group 3: Presence/Disconnect/DBHistory/Message/MUC-DB", group3_tests, ARRAY_SIZE(group3_tests) },
|
|
{ "Group 4: Session/MUC/Carbons/MigrationStress", group4_tests, ARRAY_SIZE(group4_tests) },
|
|
{ "Group 5: AI command surface (console only)", group5_tests, ARRAY_SIZE(group5_tests) },
|
|
};
|
|
const int num_groups = ARRAY_SIZE(groups);
|
|
|
|
int result = 0;
|
|
|
|
if (group > 0 && group <= num_groups) {
|
|
/* Run specific group */
|
|
result = _cmocka_run_group_tests(groups[group - 1].name, groups[group - 1].tests,
|
|
groups[group - 1].count, NULL, NULL);
|
|
} else {
|
|
/* Run all groups sequentially */
|
|
for (int i = 0; i < num_groups; i++) {
|
|
result |= _cmocka_run_group_tests(groups[i].name, groups[i].tests,
|
|
groups[i].count, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|