Coverage Report

Created: 2024-01-26 01:52

/work/auto_tests/group_general_test.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Tests that we can connect to a public group chat through the DHT and make basic queries
3
 * about the group, other peers, and ourselves. We also make sure we can disconnect and
4
 * reconnect to a group while retaining our credentials.
5
 */
6
7
#include <stdbool.h>
8
#include <stdint.h>
9
#include <string.h>
10
11
#include "auto_test_support.h"
12
#include "../toxcore/tox_private.h"
13
14
typedef struct State {
15
    size_t   peer_joined_count;
16
    size_t   self_joined_count;
17
    size_t   peer_exit_count;
18
    bool     peer_nick;
19
    bool     peer_status;
20
    uint32_t peer_id;
21
    bool     is_founder;
22
} State;
23
24
841
#define NUM_GROUP_TOXES 2
25
26
4
#define GROUP_NAME "NASA Headquarters"
27
3
#define GROUP_NAME_LEN (sizeof(GROUP_NAME) - 1)
28
29
2
#define TOPIC "Funny topic here"
30
1
#define TOPIC_LEN (sizeof(TOPIC) - 1)
31
32
2
#define PEER0_NICK "Lois"
33
1
#define PEER0_NICK_LEN (sizeof(PEER0_NICK) - 1)
34
35
2
#define PEER0_NICK2 "Terry Davis"
36
1
#define PEER0_NICK2_LEN (sizeof(PEER0_NICK2) - 1)
37
38
2
#define PEER1_NICK "Bran"
39
1
#define PEER1_NICK_LEN (sizeof(PEER1_NICK) - 1)
40
41
2
#define EXIT_MESSAGE "Goodbye world"
42
1
#define EXIT_MESSAGE_LEN (sizeof(EXIT_MESSAGE) - 1)
43
44
5
#define PEER_LIMIT 20
45
46
static void print_ip(const Tox *tox, uint32_t groupnumber, uint32_t peer_id)
47
6
{
48
6
    Tox_Err_Group_Peer_Query err;
49
6
    size_t length = tox_group_peer_get_ip_address_size(tox, groupnumber, peer_id, &err);
50
51
6
    ck_assert_msg(err == TOX_ERR_GROUP_PEER_QUERY_OK, "failed to get ip address size: error %d", err);
52
53
6
    uint8_t ip_str[TOX_GROUP_PEER_IP_STRING_MAX_LENGTH];
54
6
    tox_group_peer_get_ip_address(tox, groupnumber, peer_id, ip_str, &err);
55
6
    ip_str[length] = '\0';
56
57
6
    ck_assert_msg(err == TOX_ERR_GROUP_PEER_QUERY_OK, "failed to get ip address: error %d", err);
58
59
6
    fprintf(stderr, "%s\n", ip_str);
60
6
}
61
62
static bool all_group_peers_connected(AutoTox *autotoxes, uint32_t tox_count, uint32_t groupnumber, size_t name_length)
63
2
{
64
6
    for (size_t i = 0; i < tox_count; ++i) {
65
        // make sure we got an invite response
66
4
        if (tox_group_get_name_size(autotoxes[i].tox, groupnumber, nullptr) != name_length) {
67
0
            return false;
68
0
        }
69
70
        // make sure we got a sync response
71
4
        if (tox_group_get_peer_limit(autotoxes[i].tox, groupnumber, nullptr) != PEER_LIMIT) {
72
0
            return false;
73
0
        }
74
75
        // make sure we're actually connected
76
4
        if (!tox_group_is_connected(autotoxes[i].tox, groupnumber, nullptr)) {
77
0
            return false;
78
0
        }
79
4
    }
80
81
2
    return true;
82
2
}
83
84
static void group_peer_join_handler(Tox *tox, const Tox_Event_Group_Peer_Join *event, void *user_data)
85
4
{
86
4
    AutoTox *autotox = (AutoTox *)user_data;
87
4
    ck_assert(autotox != nullptr);
88
89
4
    State *state = (State *)autotox->state;
90
91
4
    const uint32_t groupnumber = tox_event_group_peer_join_get_group_number(event);
92
4
    const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
93
94
    // we do a connection test here for fun
95
4
    Tox_Err_Group_Peer_Query pq_err;
96
4
    Tox_Connection connection_status = tox_group_peer_get_connection_status(tox, groupnumber, peer_id, &pq_err);
97
4
    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
98
4
    ck_assert(connection_status != TOX_CONNECTION_NONE);
99
100
4
    Tox_Group_Role role = tox_group_peer_get_role(tox, groupnumber, peer_id, &pq_err);
101
4
    ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err);
102
103
4
    Tox_User_Status status = tox_group_peer_get_status(tox, groupnumber, peer_id, &pq_err);
104
4
    ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err);
105
106
4
    size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &pq_err);
107
4
    char peer_name[TOX_MAX_NAME_LENGTH + 1];
108
109
4
    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
110
4
    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
111
112
4
    tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &pq_err);
113
4
    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
114
115
4
    peer_name[peer_name_len] = 0;
116
117
    // make sure we see the correct peer state on join
118
4
    if (!state->is_founder) {
119
2
        ck_assert_msg(role == TOX_GROUP_ROLE_FOUNDER, "wrong role: %d", role);
120
121
2
        if (state->peer_joined_count == 0) {
122
1
            ck_assert_msg(status == TOX_USER_STATUS_NONE, "wrong status: %d", status);
123
1
            ck_assert_msg(peer_name_len == PEER0_NICK_LEN, "wrong nick: %s", peer_name);
124
1
            ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
125
1
        } else {
126
1
            ck_assert_msg(status == TOX_USER_STATUS_BUSY, "wrong status: %d", status);
127
1
            ck_assert(peer_name_len == PEER0_NICK2_LEN);
128
1
            ck_assert(memcmp(peer_name, PEER0_NICK2, peer_name_len) == 0);
129
1
        }
130
2
    } else {
131
2
        ck_assert_msg(role == TOX_GROUP_ROLE_USER, "wrong role: %d", role);
132
2
        ck_assert(peer_name_len == PEER1_NICK_LEN);
133
2
        ck_assert(memcmp(peer_name, PEER1_NICK, peer_name_len) == 0);
134
135
2
        if (state->peer_joined_count == 0) {
136
1
            ck_assert_msg(status == TOX_USER_STATUS_NONE, "wrong status: %d", status);
137
1
        } else {
138
1
            ck_assert_msg(status == TOX_USER_STATUS_AWAY, "wrong status: %d", status);
139
1
        }
140
2
    }
141
142
4
    fprintf(stderr, "%s joined with IP: ", peer_name);
143
4
    print_ip(tox, groupnumber, peer_id);
144
145
4
    state->peer_id = peer_id;
146
4
    ++state->peer_joined_count;
147
4
}
148
149
static void group_peer_self_join_handler(Tox *tox, const Tox_Event_Group_Self_Join *event, void *user_data)
150
2
{
151
2
    AutoTox *autotox = (AutoTox *)user_data;
152
2
    ck_assert(autotox != nullptr);
153
154
2
    State *state = (State *)autotox->state;
155
156
2
    const uint32_t groupnumber = tox_event_group_self_join_get_group_number(event);
157
158
    // make sure we see our own correct peer state on join callback
159
160
2
    Tox_Err_Group_Self_Query sq_err;
161
2
    size_t self_length = tox_group_self_get_name_size(tox, groupnumber, &sq_err);
162
163
2
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
164
165
2
    uint8_t self_name[TOX_MAX_NAME_LENGTH];
166
2
    tox_group_self_get_name(tox, groupnumber, self_name, &sq_err);
167
168
2
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
169
170
2
    Tox_User_Status self_status = tox_group_self_get_status(tox, groupnumber, &sq_err);
171
2
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
172
173
2
    Tox_Group_Role self_role = tox_group_self_get_role(tox, groupnumber, &sq_err);
174
2
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
175
176
2
    if (state->is_founder) {
177
        // founder doesn't get a self join callback on initial creation of group
178
1
        ck_assert(self_length == PEER0_NICK2_LEN);
179
1
        ck_assert(memcmp(self_name, PEER0_NICK2, self_length) == 0);
180
1
        ck_assert(self_status == TOX_USER_STATUS_BUSY);
181
1
        ck_assert(self_role == TOX_GROUP_ROLE_FOUNDER);
182
1
    } else {
183
1
        ck_assert(self_length == PEER1_NICK_LEN);
184
1
        ck_assert(memcmp(self_name, PEER1_NICK, self_length) == 0);
185
1
        ck_assert(self_role == TOX_GROUP_ROLE_USER);
186
1
        ck_assert(self_status == TOX_USER_STATUS_NONE);
187
1
    }
188
189
    // make sure we see correct group state on join callback
190
2
    uint8_t group_name[GROUP_NAME_LEN];
191
2
    uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
192
193
2
    ck_assert(tox_group_get_peer_limit(tox, groupnumber, nullptr) == PEER_LIMIT);
194
2
    ck_assert(tox_group_get_name_size(tox, groupnumber, nullptr) == GROUP_NAME_LEN);
195
2
    ck_assert(tox_group_get_topic_size(tox, groupnumber, nullptr) == TOPIC_LEN);
196
197
2
    Tox_Err_Group_State_Queries query_err;
198
2
    tox_group_get_name(tox, groupnumber, group_name, &query_err);
199
2
    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", query_err);
200
2
    ck_assert(memcmp(group_name, GROUP_NAME, GROUP_NAME_LEN) == 0);
201
202
2
    tox_group_get_topic(tox, groupnumber, topic, &query_err);
203
2
    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", query_err);
204
2
    ck_assert(memcmp(topic, TOPIC, TOPIC_LEN) == 0);
205
206
2
    uint32_t peer_id = tox_group_self_get_peer_id(tox, groupnumber, nullptr);
207
208
2
    fprintf(stderr, "self joined with IP: ");
209
2
    print_ip(tox, groupnumber, peer_id);
210
211
2
    ++state->self_joined_count;
212
2
}
213
214
static void group_peer_exit_handler(Tox *tox, const Tox_Event_Group_Peer_Exit *event, void *user_data)
215
2
{
216
2
    AutoTox *autotox = (AutoTox *)user_data;
217
2
    ck_assert(autotox != nullptr);
218
219
2
    State *state = (State *)autotox->state;
220
221
2
    const uint8_t *part_message = tox_event_group_peer_exit_get_part_message(event);
222
2
    const size_t length = tox_event_group_peer_exit_get_part_message_length(event);
223
224
2
    ++state->peer_exit_count;
225
226
    // first exit is a disconnect. second is a real exit with a part message
227
2
    if (state->peer_exit_count == 2) {
228
1
        ck_assert(length == EXIT_MESSAGE_LEN);
229
1
        ck_assert(memcmp(part_message, EXIT_MESSAGE, length) == 0);
230
1
    }
231
2
}
232
233
static void group_peer_name_handler(Tox *tox, const Tox_Event_Group_Peer_Name *event, void *user_data)
234
1
{
235
1
    AutoTox *autotox = (AutoTox *)user_data;
236
1
    ck_assert(autotox != nullptr);
237
238
1
    State *state = (State *)autotox->state;
239
240
1
    const uint8_t *name = tox_event_group_peer_name_get_name(event);
241
1
    const size_t length = tox_event_group_peer_name_get_name_length(event);
242
243
    // note: we already test the name_get api call elsewhere
244
245
1
    ck_assert(length == PEER0_NICK2_LEN);
246
1
    ck_assert(memcmp(name, PEER0_NICK2, length) == 0);
247
248
1
    state->peer_nick = true;
249
1
}
250
251
static void group_peer_status_handler(Tox *tox, const Tox_Event_Group_Peer_Status *event,
252
                                      void *user_data)
253
1
{
254
1
    AutoTox *autotox = (AutoTox *)user_data;
255
1
    ck_assert(autotox != nullptr);
256
257
1
    State *state = (State *)autotox->state;
258
259
1
    const uint32_t groupnumber = tox_event_group_peer_status_get_group_number(event);
260
1
    const uint32_t peer_id = tox_event_group_peer_status_get_peer_id(event);
261
1
    const Tox_User_Status status = tox_event_group_peer_status_get_status(event);
262
263
1
    Tox_Err_Group_Peer_Query err;
264
1
    Tox_User_Status cur_status = tox_group_peer_get_status(tox, groupnumber, peer_id, &err);
265
266
1
    ck_assert_msg(cur_status == status, "%d, %d", cur_status, status);
267
1
    ck_assert(status == TOX_USER_STATUS_BUSY);
268
269
1
    state->peer_status = true;
270
1
}
271
272
static void group_announce_test(AutoTox *autotoxes)
273
1
{
274
1
    ck_assert_msg(NUM_GROUP_TOXES == 2, "NUM_GROUP_TOXES needs to be 2");
275
276
1
    Tox *tox0 = autotoxes[0].tox;
277
1
    Tox *tox1 = autotoxes[1].tox;
278
1
    State *state0 = (State *)autotoxes[0].state;
279
1
    const State *state1 = (const State *)autotoxes[1].state;
280
281
1
    tox_events_callback_group_peer_join(autotoxes[0].dispatch, group_peer_join_handler);
282
1
    tox_events_callback_group_peer_join(autotoxes[1].dispatch, group_peer_join_handler);
283
1
    tox_events_callback_group_self_join(autotoxes[0].dispatch, group_peer_self_join_handler);
284
1
    tox_events_callback_group_self_join(autotoxes[1].dispatch, group_peer_self_join_handler);
285
1
    tox_events_callback_group_peer_name(autotoxes[1].dispatch, group_peer_name_handler);
286
1
    tox_events_callback_group_peer_status(autotoxes[1].dispatch, group_peer_status_handler);
287
1
    tox_events_callback_group_peer_exit(autotoxes[1].dispatch, group_peer_exit_handler);
288
289
    // tox0 makes new group.
290
1
    Tox_Err_Group_New err_new;
291
1
    uint32_t groupnumber = tox_group_new(tox0, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *) GROUP_NAME,
292
1
                                         GROUP_NAME_LEN, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN,
293
1
                                         &err_new);
294
1
    ck_assert(err_new == TOX_ERR_GROUP_NEW_OK);
295
296
1
    state0->is_founder = true;
297
298
1
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
299
300
    // changes the state (for sync check purposes)
301
1
    Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err;
302
1
    tox_group_founder_set_peer_limit(tox0, groupnumber, PEER_LIMIT, &limit_set_err);
303
1
    ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
304
305
1
    Tox_Err_Group_Topic_Set tp_err;
306
1
    tox_group_set_topic(tox0, groupnumber, (const uint8_t *)TOPIC, TOPIC_LEN, &tp_err);
307
1
    ck_assert(tp_err == TOX_ERR_GROUP_TOPIC_SET_OK);
308
309
    // get the chat id of the new group.
310
1
    Tox_Err_Group_State_Queries err_id;
311
1
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
312
1
    tox_group_get_chat_id(tox0, groupnumber, chat_id, &err_id);
313
1
    ck_assert(err_id == TOX_ERR_GROUP_STATE_QUERIES_OK);
314
315
    // tox1 joins it.
316
1
    Tox_Err_Group_Join err_join;
317
1
    tox_group_join(tox1, chat_id, (const uint8_t *)PEER1_NICK, PEER1_NICK_LEN, nullptr, 0, &err_join);
318
1
    ck_assert(err_join == TOX_ERR_GROUP_JOIN_OK);
319
320
    // peers see each other and themselves join
321
12
    while (!state1->peer_joined_count || !state1->self_joined_count || !state0->peer_joined_count) {
322
11
        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
323
11
    }
324
325
    // wait for group syncing to finish
326
1
    while (!all_group_peers_connected(autotoxes, NUM_GROUP_TOXES, groupnumber, GROUP_NAME_LEN)) {
327
0
        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
328
0
    }
329
330
1
    fprintf(stderr, "Peers connected to group\n");
331
332
    // tox 0 changes name
333
1
    Tox_Err_Group_Self_Name_Set n_err;
334
1
    tox_group_self_set_name(tox0, groupnumber, (const uint8_t *)PEER0_NICK2, PEER0_NICK2_LEN, &n_err);
335
1
    ck_assert(n_err == TOX_ERR_GROUP_SELF_NAME_SET_OK);
336
337
1
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
338
339
1
    Tox_Err_Group_Self_Query sq_err;
340
1
    size_t self_length = tox_group_self_get_name_size(tox0, groupnumber, &sq_err);
341
1
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
342
1
    ck_assert(self_length == PEER0_NICK2_LEN);
343
344
1
    uint8_t self_name[TOX_MAX_NAME_LENGTH];
345
1
    tox_group_self_get_name(tox0, groupnumber, self_name, &sq_err);
346
1
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
347
1
    ck_assert(memcmp(self_name, PEER0_NICK2, self_length) == 0);
348
349
1
    fprintf(stderr, "Peer 0 successfully changed nick\n");
350
351
    // tox 0 changes status
352
1
    Tox_Err_Group_Self_Status_Set s_err;
353
1
    tox_group_self_set_status(tox0, groupnumber, TOX_USER_STATUS_BUSY, &s_err);
354
1
    ck_assert(s_err == TOX_ERR_GROUP_SELF_STATUS_SET_OK);
355
356
1
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
357
358
1
    Tox_User_Status self_status = tox_group_self_get_status(tox0, groupnumber, &sq_err);
359
1
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
360
1
    ck_assert(self_status == TOX_USER_STATUS_BUSY);
361
362
1
    fprintf(stderr, "Peer 0 successfully changed status to %d\n", self_status);
363
364
1
    while (!state1->peer_nick && !state1->peer_status) {
365
0
        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
366
0
    }
367
368
    // tox 0 and tox 1 should see the same public key for tox 0
369
1
    uint8_t tox0_self_pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
370
1
    tox_group_self_get_public_key(tox0, groupnumber, tox0_self_pk, &sq_err);
371
1
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
372
373
1
    Tox_Err_Group_Peer_Query pq_err;
374
1
    uint8_t tox0_pk_query[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
375
1
    tox_group_peer_get_public_key(tox1, groupnumber, state1->peer_id, tox0_pk_query, &pq_err);
376
1
    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
377
1
    ck_assert(memcmp(tox0_pk_query, tox0_self_pk, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) == 0);
378
379
1
    fprintf(stderr, "Peer 0 disconnecting...\n");
380
381
    // tox 0 disconnects then reconnects
382
1
    Tox_Err_Group_Disconnect d_err;
383
1
    tox_group_disconnect(tox0, groupnumber, &d_err);
384
1
    ck_assert(d_err == TOX_ERR_GROUP_DISCONNECT_OK);
385
386
3
    while (state1->peer_exit_count != 1) {
387
2
        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
388
2
    }
389
390
    // tox 1 changes status while alone in the group
391
1
    tox_group_self_set_status(tox1, groupnumber, TOX_USER_STATUS_AWAY, &s_err);
392
1
    ck_assert(s_err == TOX_ERR_GROUP_SELF_STATUS_SET_OK);
393
394
1
    fprintf(stderr, "Peer 0 reconnecting...\n");
395
1
    Tox_Err_Group_Reconnect r_err;
396
1
    tox_group_reconnect(tox0, groupnumber, &r_err);
397
1
    ck_assert(r_err == TOX_ERR_GROUP_RECONNECT_OK);
398
399
1
    while (state1->peer_joined_count != 2 && state0->self_joined_count == 2) {
400
0
        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
401
0
    }
402
403
101
    for (size_t i = 0; i < 100; ++i) {  // if we don't do this the exit packet never arrives
404
100
        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
405
100
    }
406
407
1
    while (!all_group_peers_connected(autotoxes, NUM_GROUP_TOXES, groupnumber, GROUP_NAME_LEN))  {
408
0
        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
409
0
    }
410
411
    // tox 0 should have the same public key and still be founder
412
1
    uint8_t tox0_self_pk2[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
413
1
    tox_group_self_get_public_key(tox0, groupnumber, tox0_self_pk2, &sq_err);
414
415
1
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
416
1
    ck_assert(memcmp(tox0_self_pk2, tox0_self_pk, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) == 0);
417
418
1
    Tox_Group_Role self_role = tox_group_self_get_role(tox0, groupnumber, &sq_err);
419
1
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
420
421
1
    Tox_Group_Role other_role = tox_group_peer_get_role(tox1, groupnumber, state1->peer_id, &pq_err);
422
1
    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
423
424
1
    ck_assert(self_role == other_role && self_role == TOX_GROUP_ROLE_FOUNDER);
425
426
1
    uint32_t num_groups1 = tox_group_get_number_groups(tox0);
427
1
    uint32_t num_groups2 = tox_group_get_number_groups(tox1);
428
429
1
    ck_assert(num_groups1 == num_groups2 && num_groups2 == 1);
430
431
1
    fprintf(stderr, "Both peers exiting group...\n");
432
433
1
    Tox_Err_Group_Leave err_exit;
434
1
    tox_group_leave(tox0, groupnumber, (const uint8_t *)EXIT_MESSAGE, EXIT_MESSAGE_LEN, &err_exit);
435
1
    ck_assert(err_exit == TOX_ERR_GROUP_LEAVE_OK);
436
437
3
    while (state1->peer_exit_count != 2) {
438
2
        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
439
2
    }
440
441
1
    tox_group_leave(tox1, groupnumber, nullptr, 0, &err_exit);
442
1
    ck_assert(err_exit == TOX_ERR_GROUP_LEAVE_OK);
443
444
1
    num_groups1 = tox_group_get_number_groups(tox0);
445
1
    num_groups2 = tox_group_get_number_groups(tox1);
446
447
1
    ck_assert(num_groups1 == num_groups2 && num_groups2 == 0);
448
449
1
    printf("All tests passed!\n");
450
1
}
451
452
int main(void)
453
721
{
454
721
    setvbuf(stdout, nullptr, _IONBF, 0);
455
456
721
    Run_Auto_Options options = default_run_auto_options();
457
721
    options.graph = GRAPH_LINEAR;
458
459
721
    run_auto_test(nullptr, NUM_GROUP_TOXES, group_announce_test, sizeof(State), &options);
460
461
721
    return 0;
462
721
}
463
464
#undef NUM_GROUP_TOXES
465
#undef PEER1_NICK
466
#undef PEER0_NICK
467
#undef PEER0_NICK_LEN
468
#undef PEER1_NICK_LEN
469
#undef GROUP_NAME
470
#undef GROUP_NAME_LEN
471
#undef PEER_LIMIT
472
#undef TOPIC
473
#undef TOPIC_LEN