Coverage Report

Created: 2024-01-26 01:52

/work/auto_tests/group_save_test.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Tests that we can save a groupchat and load a groupchat with the saved data.
3
 */
4
5
#include <string.h>
6
#include <stdio.h>
7
#include <stdint.h>
8
#include <stdbool.h>
9
10
#include "auto_test_support.h"
11
12
typedef struct State {
13
    bool     peer_joined;
14
} State;
15
16
2.14k
#define NUM_GROUP_TOXES 2
17
230
#define GROUP_NAME "The Test Chamber"
18
124
#define GROUP_NAME_LEN (sizeof(GROUP_NAME) - 1)
19
196
#define TOPIC "They're waiting for you Gordon..."
20
98
#define TOPIC_LEN (sizeof(TOPIC) - 1)
21
95
#define NEW_PRIV_STATE TOX_GROUP_PRIVACY_STATE_PRIVATE
22
190
#define PASSWORD "password123"
23
104
#define PASS_LEN (sizeof(PASSWORD) - 1)
24
90
#define PEER_LIMIT 69
25
170
#define PEER0_NICK "Mike"
26
94
#define PEER0_NICK_LEN (sizeof(PEER0_NICK) -1)
27
79
#define NEW_USER_STATUS TOX_USER_STATUS_BUSY
28
29
static void group_invite_handler(Tox *tox, const Tox_Event_Group_Invite *event, void *user_data)
30
95
{
31
95
    const uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
32
95
    const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
33
95
    const size_t length = tox_event_group_invite_get_invite_data_length(event);
34
35
95
    Tox_Err_Group_Invite_Accept err_accept;
36
95
    tox_group_invite_accept(tox, friend_number, invite_data, length, (const uint8_t *)"test2", 5,
37
95
                            nullptr, 0, &err_accept);
38
95
    ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
39
40
95
}
41
42
static void group_peer_join_handler(Tox *tox, const Tox_Event_Group_Peer_Join *event, void *user_data)
43
151
{
44
151
    AutoTox *autotox = (AutoTox *)user_data;
45
151
    ck_assert(autotox != nullptr);
46
47
151
    State *state = (State *)autotox->state;
48
151
    state->peer_joined = true;
49
151
}
50
51
/* Checks that group has the same state according to the above defines
52
 *
53
 * Returns 0 if state is correct.
54
 * Returns a value < 0 if state is incorrect.
55
 */
56
static int has_correct_group_state(const Tox *tox, uint32_t group_number, const uint8_t *expected_chat_id)
57
10
{
58
10
    Tox_Err_Group_State_Queries query_err;
59
60
10
    Tox_Group_Privacy_State priv_state = tox_group_get_privacy_state(tox, group_number, &query_err);
61
10
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
62
63
9
    if (priv_state != NEW_PRIV_STATE) {
64
0
        return -1;
65
0
    }
66
67
9
    size_t pass_len = tox_group_get_password_size(tox, group_number, &query_err);
68
9
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
69
70
9
    uint8_t password[TOX_GROUP_MAX_PASSWORD_SIZE];
71
9
    tox_group_get_password(tox, group_number, password, &query_err);
72
9
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
73
74
9
    if (pass_len != PASS_LEN || memcmp(password, PASSWORD, pass_len) != 0) {
75
0
        return -2;
76
0
    }
77
78
9
    size_t gname_len = tox_group_get_name_size(tox, group_number, &query_err);
79
9
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
80
81
9
    uint8_t group_name[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
82
9
    tox_group_get_name(tox, group_number, group_name, &query_err);
83
84
9
    if (gname_len != GROUP_NAME_LEN || memcmp(group_name, GROUP_NAME, gname_len) != 0) {
85
0
        return -3;
86
0
    }
87
88
9
    if (tox_group_get_peer_limit(tox, group_number, nullptr) != PEER_LIMIT) {
89
0
        return -4;
90
0
    }
91
92
9
    Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(tox, group_number, &query_err);
93
9
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
94
95
9
    if (topic_lock != TOX_GROUP_TOPIC_LOCK_DISABLED) {
96
0
        return -5;
97
0
    }
98
99
9
    Tox_Err_Group_State_Queries id_err;
100
9
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
101
9
    tox_group_get_chat_id(tox, group_number, chat_id, &id_err);
102
103
9
    ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
104
105
9
    if (memcmp(chat_id, expected_chat_id, TOX_GROUP_CHAT_ID_SIZE) != 0) {
106
0
        return -6;
107
0
    }
108
109
9
    return 0;
110
9
}
111
112
static int has_correct_self_state(const Tox *tox, uint32_t group_number, const uint8_t *expected_self_pk)
113
9
{
114
9
    Tox_Err_Group_Self_Query sq_err;
115
9
    size_t self_length = tox_group_self_get_name_size(tox, group_number, &sq_err);
116
9
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
117
118
9
    uint8_t self_name[TOX_MAX_NAME_LENGTH];
119
9
    tox_group_self_get_name(tox, group_number, self_name, &sq_err);
120
9
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
121
122
9
    if (self_length != PEER0_NICK_LEN || memcmp(self_name, PEER0_NICK, self_length) != 0) {
123
0
        return -1;
124
0
    }
125
126
9
    Tox_User_Status self_status = tox_group_self_get_status(tox, group_number, &sq_err);
127
9
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
128
129
9
    if (self_status != NEW_USER_STATUS) {
130
0
        return -2;
131
0
    }
132
133
9
    Tox_Group_Role self_role = tox_group_self_get_role(tox, group_number, &sq_err);
134
9
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
135
136
9
    if (self_role != TOX_GROUP_ROLE_FOUNDER) {
137
0
        return -3;
138
0
    }
139
140
9
    uint8_t self_pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
141
142
9
    tox_group_self_get_public_key(tox, group_number, self_pk, &sq_err);
143
9
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
144
145
9
    if (memcmp(self_pk, expected_self_pk, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) != 0) {
146
0
        return -4;
147
0
    }
148
149
9
    return 0;
150
9
}
151
152
static void group_save_test(AutoTox *autotoxes)
153
106
{
154
106
    ck_assert_msg(NUM_GROUP_TOXES > 1, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
155
156
318
    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
157
212
        tox_events_callback_group_invite(autotoxes[i].dispatch, group_invite_handler);
158
212
        tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
159
212
    }
160
161
106
    Tox *tox0 = autotoxes[0].tox;
162
163
106
    const State *state0 = (State *)autotoxes[0].state;
164
106
    const State *state1 = (State *)autotoxes[1].state;
165
166
106
    Tox_Err_Group_New err_new;
167
106
    const uint32_t group_number = tox_group_new(tox0, TOX_GROUP_PRIVACY_STATE_PRIVATE, (const uint8_t *)GROUP_NAME,
168
106
                                  GROUP_NAME_LEN, (const uint8_t *)"test", 4, &err_new);
169
170
106
    ck_assert(err_new == TOX_ERR_GROUP_NEW_OK);
171
172
100
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
173
174
100
    Tox_Err_Group_State_Queries id_err;
175
100
    tox_group_get_chat_id(tox0, group_number, chat_id, &id_err);
176
100
    ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
177
178
100
    uint8_t founder_pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
179
180
100
    Tox_Err_Group_Self_Query sq_err;
181
100
    tox_group_self_get_public_key(tox0, group_number, founder_pk, &sq_err);
182
100
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
183
184
185
100
    Tox_Err_Group_Invite_Friend err_invite;
186
100
    tox_group_invite_friend(tox0, group_number, 0, &err_invite);
187
188
100
    ck_assert(err_invite == TOX_ERR_GROUP_INVITE_FRIEND_OK);
189
190
959
    while (!state0->peer_joined && !state1->peer_joined) {
191
861
        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
192
861
    }
193
194
98
    printf("tox0 invites tox1 to group\n");
195
196
    // change group state
197
98
    Tox_Err_Group_Topic_Set top_err;
198
98
    tox_group_set_topic(tox0, group_number, (const uint8_t *)TOPIC, TOPIC_LEN, &top_err);
199
98
    ck_assert(top_err == TOX_ERR_GROUP_TOPIC_SET_OK);
200
201
91
    Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err;
202
91
    tox_group_founder_set_topic_lock(tox0, group_number, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
203
91
    ck_assert(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK);
204
205
86
    Tox_Err_Group_Founder_Set_Privacy_State priv_err;
206
86
    tox_group_founder_set_privacy_state(tox0, group_number, NEW_PRIV_STATE, &priv_err);
207
86
    ck_assert(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK);
208
209
86
    Tox_Err_Group_Founder_Set_Password pass_set_err;
210
86
    tox_group_founder_set_password(tox0, group_number, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
211
86
    ck_assert(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK);
212
213
81
    Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err;
214
81
    tox_group_founder_set_peer_limit(tox0, group_number, PEER_LIMIT, &limit_set_err);
215
81
    ck_assert(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK);
216
217
    // change self state
218
76
    Tox_Err_Group_Self_Name_Set n_err;
219
76
    tox_group_self_set_name(tox0, group_number, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN, &n_err);
220
76
    ck_assert(n_err == TOX_ERR_GROUP_SELF_NAME_SET_OK);
221
222
70
    Tox_Err_Group_Self_Status_Set s_err;
223
70
    tox_group_self_set_status(tox0, group_number, NEW_USER_STATUS, &s_err);
224
70
    ck_assert(s_err == TOX_ERR_GROUP_SELF_STATUS_SET_OK);
225
226
64
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
227
228
64
    printf("tox0 changes group state\n");
229
230
64
    const size_t save_length = tox_get_savedata_size(tox0);
231
232
64
    uint8_t *save = (uint8_t *)malloc(save_length);
233
234
64
    ck_assert(save != nullptr);
235
236
63
    tox_get_savedata(tox0, save);
237
238
143
    for (size_t i = 0; i < NUM_GROUP_TOXES; i++) {
239
80
        tox_group_leave(autotoxes[i].tox, group_number, nullptr, 0, nullptr);
240
80
    }
241
242
63
    struct Tox_Options *const options = tox_options_new(nullptr);
243
244
63
    ck_assert(options != nullptr);
245
246
62
    tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
247
248
62
    tox_options_set_savedata_data(options, save, save_length);
249
250
62
    Tox *new_tox = tox_new_log(options, nullptr, nullptr);
251
252
62
    ck_assert(new_tox != nullptr);
253
254
33
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
255
256
33
    printf("tox0 saves group and reloads client\n");
257
258
33
    const int group_ret = has_correct_group_state(new_tox, group_number, chat_id);
259
260
33
    ck_assert_msg(group_ret == 0, "incorrect group state: %d", group_ret);
261
262
33
    const int self_ret = has_correct_self_state(new_tox, group_number, founder_pk);
263
264
33
    ck_assert_msg(self_ret == 0, "incorrect self state: %d", self_ret);
265
266
33
    tox_group_leave(new_tox, group_number, nullptr, 0, nullptr);
267
268
33
    free(save);
269
270
33
    tox_options_free(options);
271
272
33
    tox_kill(new_tox);
273
274
33
    printf("All tests passed!\n");
275
33
}
276
277
int main(void)
278
721
{
279
721
    setvbuf(stdout, nullptr, _IONBF, 0);
280
281
721
    Run_Auto_Options autotest_opts = default_run_auto_options();
282
721
    autotest_opts.graph = GRAPH_COMPLETE;
283
284
721
    run_auto_test(nullptr, NUM_GROUP_TOXES, group_save_test, sizeof(State), &autotest_opts);
285
286
721
    return 0;
287
721
}
288
289
#undef NUM_GROUP_TOXES
290
#undef GROUP_NAME
291
#undef GROUP_NAME_LEN
292
#undef TOPIC
293
#undef TOPIC_LEN
294
#undef NEW_PRIV_STATE
295
#undef PASSWORD
296
#undef PASS_LEN
297
#undef PEER_LIMIT
298
#undef PEER0_NICK
299
#undef PEER0_NICK_LEN
300
#undef NEW_USER_STATUS