Coverage Report

Created: 2026-10-24 08:16

/work/auto_tests/scenarios/scenario_group_save_test.c
Line
Count
Source (jump to first uncovered line)
1
#include "framework/framework.h"
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <string.h>
5
6
2
#define GROUP_NAME "The Test Chamber"
7
1
#define GROUP_NAME_LEN (sizeof(GROUP_NAME) - 1)
8
2
#define TOPIC "They're waiting for you Gordon..."
9
1
#define TOPIC_LEN (sizeof(TOPIC) - 1)
10
1
#define NEW_PRIV_STATE TOX_GROUP_PRIVACY_STATE_PRIVATE
11
2
#define PASSWORD "password123"
12
1
#define PASS_LEN (sizeof(PASSWORD) - 1)
13
1
#define PEER_LIMIT 69
14
2
#define PEER0_NICK "Mike"
15
1
#define PEER0_NICK_LEN (sizeof(PEER0_NICK) - 1)
16
1
#define NEW_USER_STATUS TOX_USER_STATUS_BUSY
17
18
typedef struct {
19
    bool peer_joined;
20
} State;
21
22
static void on_group_invite(const Tox_Event_Group_Invite *event, void *user_data)
23
2
{
24
2
    ToxNode *self = (ToxNode *)user_data;
25
2
    uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
26
2
    const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
27
2
    size_t length = tox_event_group_invite_get_invite_data_length(event);
28
29
2
    tox_group_invite_accept(tox_node_get_tox(self), friend_number, invite_data, length, (const uint8_t *)"Bob", 3, nullptr, 0, nullptr);
30
2
}
31
32
static void on_group_peer_join(const Tox_Event_Group_Peer_Join *event, void *user_data)
33
25
{
34
25
    ToxNode *self = (ToxNode *)user_data;
35
25
    State *state = (State *)tox_node_get_script_ctx(self);
36
25
    state->peer_joined = true;
37
25
}
38
39
static void check_founder_state(ToxNode *self, uint32_t group_number, const uint8_t *expected_chat_id, const uint8_t *expected_self_pk)
40
1
{
41
1
    Tox *tox = tox_node_get_tox(self);
42
1
    Tox_Err_Group_State_Query query_err;
43
44
    // Group state
45
1
    ck_assert(tox_group_get_privacy_state(tox, group_number, &query_err) == NEW_PRIV_STATE);
46
1
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
47
48
1
    uint8_t password[TOX_GROUP_MAX_PASSWORD_SIZE];
49
1
    size_t pass_len = tox_group_get_password_size(tox, group_number, &query_err);
50
1
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
51
1
    tox_group_get_password(tox, group_number, password, &query_err);
52
1
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
53
1
    ck_assert(pass_len == PASS_LEN && memcmp(password, PASSWORD, pass_len) == 0);
54
55
1
    uint8_t gname[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
56
1
    size_t gname_len = tox_group_get_name_size(tox, group_number, &query_err);
57
1
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
58
1
    tox_group_get_name(tox, group_number, gname, &query_err);
59
1
    ck_assert(gname_len == GROUP_NAME_LEN && memcmp(gname, GROUP_NAME, gname_len) == 0);
60
61
1
    ck_assert(tox_group_get_peer_limit(tox, group_number, nullptr) == PEER_LIMIT);
62
1
    ck_assert(tox_group_get_topic_lock(tox, group_number, nullptr) == TOX_GROUP_TOPIC_LOCK_DISABLED);
63
64
1
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
65
1
    tox_group_get_chat_id(tox, group_number, chat_id, nullptr);
66
1
    ck_assert(memcmp(chat_id, expected_chat_id, TOX_GROUP_CHAT_ID_SIZE) == 0);
67
68
    // Self state
69
1
    Tox_Err_Group_Self_Query sq_err;
70
1
    uint8_t self_name[TOX_MAX_NAME_LENGTH];
71
1
    size_t self_len = tox_group_self_get_name_size(tox, group_number, &sq_err);
72
1
    tox_group_self_get_name(tox, group_number, self_name, nullptr);
73
1
    ck_assert(self_len == PEER0_NICK_LEN && memcmp(self_name, PEER0_NICK, self_len) == 0);
74
75
1
    ck_assert(tox_group_self_get_status(tox, group_number, nullptr) == NEW_USER_STATUS);
76
1
    ck_assert(tox_group_self_get_role(tox, group_number, nullptr) == TOX_GROUP_ROLE_FOUNDER);
77
78
1
    uint8_t self_pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
79
1
    tox_group_self_get_public_key(tox, group_number, self_pk, nullptr);
80
1
    ck_assert(memcmp(self_pk, expected_self_pk, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) == 0);
81
1
}
82
83
static void founder_script(ToxNode *self, void *ctx)
84
1
{
85
1
    const State *state = (const State *)ctx;
86
1
    Tox *tox = tox_node_get_tox(self);
87
1
    tox_events_callback_group_peer_join(tox_node_get_dispatch(self), on_group_peer_join);
88
89
1
    tox_node_wait_for_self_connected(self);
90
1
    tox_node_wait_for_friend_connected(self, 0);
91
92
1
    Tox_Err_Group_New err_new;
93
1
    uint32_t group_number = tox_group_new(tox, TOX_GROUP_PRIVACY_STATE_PRIVATE, (const uint8_t *)GROUP_NAME, GROUP_NAME_LEN, (const uint8_t *)"test", 4, &err_new);
94
1
    ck_assert(err_new == TOX_ERR_GROUP_NEW_OK);
95
96
1
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
97
1
    tox_group_get_chat_id(tox, group_number, chat_id, nullptr);
98
99
1
    uint8_t founder_pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
100
1
    tox_group_self_get_public_key(tox, group_number, founder_pk, nullptr);
101
102
1
    tox_group_invite_friend(tox, group_number, 0, nullptr);
103
1
    WAIT_UNTIL(state->peer_joined);
104
105
1
    tox_node_log(self, "Bob joined. Changing group state...");
106
1
    tox_group_set_topic(tox, group_number, (const uint8_t *)TOPIC, TOPIC_LEN, nullptr);
107
1
    tox_group_set_topic_lock(tox, group_number, TOX_GROUP_TOPIC_LOCK_DISABLED, nullptr);
108
1
    tox_group_set_privacy_state(tox, group_number, NEW_PRIV_STATE, nullptr);
109
1
    tox_group_set_password(tox, group_number, (const uint8_t *)PASSWORD, PASS_LEN, nullptr);
110
1
    tox_group_set_peer_limit(tox, group_number, PEER_LIMIT, nullptr);
111
1
    tox_group_self_set_name(tox, group_number, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN, nullptr);
112
1
    tox_group_self_set_status(tox, group_number, NEW_USER_STATUS, nullptr);
113
114
1
    tox_scenario_yield(self);
115
116
1
    tox_node_log(self, "Saving and reloading...");
117
1
    tox_node_reload(self);
118
1
    tox_node_log(self, "Reloaded.");
119
120
1
    tox_node_wait_for_self_connected(self);
121
1
    check_founder_state(self, group_number, chat_id, founder_pk);
122
1
    tox_node_log(self, "State verified after reload.");
123
1
}
124
125
static void bob_script(ToxNode *self, void *ctx)
126
6
{
127
6
    tox_events_callback_group_invite(tox_node_get_dispatch(self), on_group_invite);
128
6
    tox_node_wait_for_self_connected(self);
129
6
    tox_node_wait_for_friend_connected(self, 0);
130
131
6
    ToxNode *founder = tox_scenario_get_node(tox_node_get_scenario(self), 0);
132
6
    tox_node_log(self, "Waiting for founder to finish...");
133
6
    WAIT_UNTIL(tox_node_is_finished(founder));
134
6
    tox_node_log(self, "Founder finished, Bob exiting.");
135
6
}
136
137
int main(int argc, char *argv[])
138
31
{
139
31
    ToxScenario *s = tox_scenario_new(argc, argv, 60000);
140
31
    State states[2] = {{0}};
141
142
31
    Tox_Options *opts = tox_options_new(nullptr);
143
31
    tox_options_set_experimental_groups_persistence(opts, true);
144
31
    tox_options_set_ipv6_enabled(opts, false);
145
31
    tox_options_set_local_discovery_enabled(opts, false);
146
147
31
    ToxNode *alice = tox_scenario_add_node_ex(s, "Alice", founder_script, &states[0], sizeof(State), opts);
148
31
    ToxNode *bob = tox_scenario_add_node(s, "Bob", bob_script, &states[1], sizeof(State));
149
31
    tox_options_free(opts);
150
151
31
    tox_node_bootstrap(bob, alice);
152
31
    tox_node_friend_add(alice, bob);
153
31
    tox_node_friend_add(bob, alice);
154
155
31
    ToxScenarioStatus res = tox_scenario_run(s);
156
31
    if (res != TOX_SCENARIO_DONE) {
157
0
        return 1;
158
0
    }
159
160
31
    tox_scenario_free(s);
161
31
    return 0;
162
31
}
163
164
#undef PASSWORD
165
#undef PASS_LEN
166
#undef PEER_LIMIT
167
#undef GROUP_NAME
168
#undef GROUP_NAME_LEN
169
#undef TOPIC
170
#undef TOPIC_LEN
171
#undef PEER0_NICK
172
#undef PEER0_NICK_LEN