/work/auto_tests/scenarios/scenario_group_message_test.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "framework/framework.h" |
2 | | #include <stdio.h> |
3 | | #include <string.h> |
4 | | #include <stdlib.h> |
5 | | |
6 | 2 | #define PEER0_NICK "Thomas" |
7 | 1 | #define PEER0_NICK_LEN (sizeof(PEER0_NICK) - 1) |
8 | 4 | #define PEER1_NICK "Winslow" |
9 | 2 | #define PEER1_NICK_LEN (sizeof(PEER1_NICK) - 1) |
10 | 2 | #define TEST_GROUP_NAME "Utah Data Center" |
11 | 1 | #define TEST_GROUP_NAME_LEN (sizeof(TEST_GROUP_NAME) - 1) |
12 | 107 | #define TEST_MESSAGE "Where is it I've read that someone condemned to death says or thinks..." |
13 | 205 | #define TEST_MESSAGE_LEN (sizeof(TEST_MESSAGE) - 1) |
14 | 6 | #define TEST_PRIVATE_MESSAGE "Don't spill yer beans" |
15 | 5 | #define TEST_PRIVATE_MESSAGE_LEN (sizeof(TEST_PRIVATE_MESSAGE) - 1) |
16 | 4 | #define TEST_CUSTOM_PACKET "Why'd ya spill yer beans?" |
17 | 2 | #define TEST_CUSTOM_PACKET_LEN (sizeof(TEST_CUSTOM_PACKET) - 1) |
18 | 4 | #define TEST_CUSTOM_PRIVATE_PACKET "This is a custom private packet. Enjoy." |
19 | 2 | #define TEST_CUSTOM_PRIVATE_PACKET_LEN (sizeof(TEST_CUSTOM_PRIVATE_PACKET) - 1) |
20 | 203 | #define MAX_NUM_MESSAGES_LOSSLESS_TEST 100 |
21 | | |
22 | | typedef struct { |
23 | | uint32_t group_number; |
24 | | uint32_t peer_id; |
25 | | bool peer_joined; |
26 | | bool message_received; |
27 | | bool private_message_received; |
28 | | size_t custom_packets_received; |
29 | | size_t custom_private_packets_received; |
30 | | int32_t last_msg_recv; |
31 | | bool lossless_done; |
32 | | } GroupState; |
33 | | |
34 | | static uint16_t get_message_checksum(const uint8_t *message, uint16_t length) |
35 | 202 | { |
36 | 202 | uint16_t sum = 0; |
37 | 10.5k | for (size_t i = 0; i < length; ++i) { |
38 | 10.3k | sum += message[i]; |
39 | 10.3k | } |
40 | 202 | return sum; |
41 | 202 | } |
42 | | |
43 | | static void on_group_invite(const Tox_Event_Group_Invite *event, void *user_data) |
44 | 2 | { |
45 | 2 | ToxNode *self = (ToxNode *)user_data; |
46 | 2 | GroupState *state = (GroupState *)tox_node_get_script_ctx(self); |
47 | 2 | Tox_Err_Group_Invite_Accept err; |
48 | 2 | state->group_number = tox_group_invite_accept(tox_node_get_tox(self), |
49 | 2 | tox_event_group_invite_get_friend_number(event), |
50 | 2 | tox_event_group_invite_get_invite_data(event), |
51 | 2 | tox_event_group_invite_get_invite_data_length(event), |
52 | 2 | (const uint8_t *)PEER1_NICK, PEER1_NICK_LEN, nullptr, 0, &err); |
53 | 2 | tox_node_log(self, "Accepted group invite, group %u", state->group_number); |
54 | 2 | } |
55 | | |
56 | | static void on_group_peer_join(const Tox_Event_Group_Peer_Join *event, void *user_data) |
57 | 25 | { |
58 | 25 | ToxNode *self = (ToxNode *)user_data; |
59 | 25 | GroupState *state = (GroupState *)tox_node_get_script_ctx(self); |
60 | 25 | state->peer_joined = true; |
61 | 25 | state->peer_id = tox_event_group_peer_join_get_peer_id(event); |
62 | 25 | tox_node_log(self, "Peer %u joined group", state->peer_id); |
63 | 25 | } |
64 | | |
65 | | static void on_group_message(const Tox_Event_Group_Message *event, void *user_data) |
66 | 102 | { |
67 | 102 | ToxNode *self = (ToxNode *)user_data; |
68 | 102 | GroupState *state = (GroupState *)tox_node_get_script_ctx(self); |
69 | 102 | const uint8_t *msg = tox_event_group_message_get_message(event); |
70 | 102 | size_t len = tox_event_group_message_get_message_length(event); |
71 | | |
72 | 102 | if (len == TEST_MESSAGE_LEN && memcmp(msg, TEST_MESSAGE, len) == 0) { |
73 | 1 | state->message_received = true; |
74 | 1 | tox_node_log(self, "Received group message"); |
75 | 101 | } else if (len >= 4) { |
76 | 101 | uint16_t start, checksum; |
77 | 101 | memcpy(&start, msg, 2); |
78 | 101 | memcpy(&checksum, msg + 2, 2); |
79 | 101 | if (checksum == get_message_checksum(msg + 4, len - 4)) { |
80 | 101 | state->last_msg_recv = start; |
81 | 101 | if (start == MAX_NUM_MESSAGES_LOSSLESS_TEST) { |
82 | 1 | state->lossless_done = true; |
83 | 1 | } |
84 | 101 | } |
85 | 101 | } |
86 | 102 | } |
87 | | |
88 | | static void on_group_private_message(const Tox_Event_Group_Private_Message *event, void *user_data) |
89 | 2 | { |
90 | 2 | ToxNode *self = (ToxNode *)user_data; |
91 | 2 | GroupState *state = (GroupState *)tox_node_get_script_ctx(self); |
92 | 2 | const uint8_t *msg = tox_event_group_private_message_get_message(event); |
93 | 2 | size_t len = tox_event_group_private_message_get_message_length(event); |
94 | | |
95 | 2 | if (len == TEST_PRIVATE_MESSAGE_LEN && memcmp(msg, TEST_PRIVATE_MESSAGE, len) == 0) { |
96 | 2 | state->private_message_received = true; |
97 | 2 | tox_node_log(self, "Received private group message"); |
98 | 2 | } |
99 | 2 | } |
100 | | |
101 | | static void on_group_custom_packet(const Tox_Event_Group_Custom_Packet *event, void *user_data) |
102 | 2 | { |
103 | 2 | ToxNode *self = (ToxNode *)user_data; |
104 | 2 | GroupState *state = (GroupState *)tox_node_get_script_ctx(self); |
105 | 2 | state->custom_packets_received++; |
106 | 2 | tox_node_log(self, "Received custom packet %zu", state->custom_packets_received); |
107 | 2 | } |
108 | | |
109 | | static void on_group_custom_private_packet(const Tox_Event_Group_Custom_Private_Packet *event, void *user_data) |
110 | 2 | { |
111 | 2 | ToxNode *self = (ToxNode *)user_data; |
112 | 2 | GroupState *state = (GroupState *)tox_node_get_script_ctx(self); |
113 | 2 | state->custom_private_packets_received++; |
114 | 2 | tox_node_log(self, "Received custom private packet %zu", state->custom_private_packets_received); |
115 | 2 | } |
116 | | |
117 | | static void peer0_script(ToxNode *self, void *ctx) |
118 | 1 | { |
119 | 1 | GroupState *state = (GroupState *)ctx; |
120 | 1 | Tox *tox = tox_node_get_tox(self); |
121 | 1 | Tox_Dispatch *dispatch = tox_node_get_dispatch(self); |
122 | | |
123 | 1 | tox_events_callback_group_peer_join(dispatch, on_group_peer_join); |
124 | 1 | tox_events_callback_group_message(dispatch, on_group_message); |
125 | 1 | tox_events_callback_group_private_message(dispatch, on_group_private_message); |
126 | 1 | tox_events_callback_group_custom_packet(dispatch, on_group_custom_packet); |
127 | 1 | tox_events_callback_group_custom_private_packet(dispatch, on_group_custom_private_packet); |
128 | | |
129 | 1 | WAIT_UNTIL(tox_node_is_self_connected(self)); |
130 | 1 | WAIT_UNTIL(tox_node_is_friend_connected(self, 0)); |
131 | | |
132 | 1 | state->group_number = tox_group_new(tox, TOX_GROUP_PRIVACY_STATE_PRIVATE, (const uint8_t *)TEST_GROUP_NAME, TEST_GROUP_NAME_LEN, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN, nullptr); |
133 | 1 | tox_group_invite_friend(tox, state->group_number, 0, nullptr); |
134 | 1 | tox_node_log(self, "Created group and invited friend"); |
135 | | |
136 | 1 | WAIT_UNTIL(state->peer_joined); |
137 | 1 | WAIT_UNTIL(state->message_received); |
138 | 1 | WAIT_UNTIL(state->private_message_received); |
139 | 1 | WAIT_UNTIL(state->custom_packets_received >= 2); |
140 | 1 | WAIT_UNTIL(state->custom_private_packets_received >= 2); |
141 | | |
142 | | // Lossless test |
143 | 1 | uint8_t m[TOX_GROUP_MAX_MESSAGE_LENGTH]; |
144 | 102 | for (uint16_t i = 0; i <= MAX_NUM_MESSAGES_LOSSLESS_TEST; ++i) { |
145 | 101 | uint32_t size = 4 + (rand() % 100); |
146 | 101 | memcpy(m, &i, 2); |
147 | 5.29k | for (size_t j = 4; j < size; ++j) { |
148 | 5.18k | uint32_t val = rand() % 256; |
149 | 5.18k | m[j] = (uint8_t)val; |
150 | 5.18k | } |
151 | 101 | uint16_t checksum = get_message_checksum(m + 4, (uint16_t)(size - 4)); |
152 | 101 | memcpy(m + 2, &checksum, 2); |
153 | 101 | tox_group_send_message(tox, state->group_number, TOX_MESSAGE_TYPE_NORMAL, m, size, nullptr); |
154 | 101 | if (i % 10 == 0) { |
155 | 11 | tox_scenario_yield(self); |
156 | 11 | } |
157 | 101 | } |
158 | | |
159 | 1 | tox_node_log(self, "Done"); |
160 | 1 | } |
161 | | |
162 | | static void peer1_script(ToxNode *self, void *ctx) |
163 | 1 | { |
164 | 1 | const GroupState *state = (const GroupState *)ctx; |
165 | 1 | const Tox *tox = tox_node_get_tox(self); |
166 | 1 | Tox_Dispatch *dispatch = tox_node_get_dispatch(self); |
167 | | |
168 | 1 | tox_events_callback_group_invite(dispatch, on_group_invite); |
169 | 1 | tox_events_callback_group_peer_join(dispatch, on_group_peer_join); |
170 | 1 | tox_events_callback_group_message(dispatch, on_group_message); |
171 | | |
172 | 1 | WAIT_UNTIL(tox_node_is_self_connected(self)); |
173 | 1 | WAIT_UNTIL(state->peer_joined); |
174 | | |
175 | 1 | tox_group_send_message(tox, state->group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)TEST_MESSAGE, TEST_MESSAGE_LEN, nullptr); |
176 | 1 | tox_group_send_private_message(tox, state->group_number, state->peer_id, TOX_MESSAGE_TYPE_ACTION, (const uint8_t *)TEST_PRIVATE_MESSAGE, TEST_PRIVATE_MESSAGE_LEN, nullptr); |
177 | | |
178 | 1 | tox_group_send_custom_packet(tox, state->group_number, true, (const uint8_t *)TEST_CUSTOM_PACKET, TEST_CUSTOM_PACKET_LEN, nullptr); |
179 | 1 | tox_group_send_custom_packet(tox, state->group_number, false, (const uint8_t *)TEST_CUSTOM_PACKET, TEST_CUSTOM_PACKET_LEN, nullptr); |
180 | | |
181 | 1 | tox_group_send_custom_private_packet(tox, state->group_number, state->peer_id, true, (const uint8_t *)TEST_CUSTOM_PRIVATE_PACKET, TEST_CUSTOM_PRIVATE_PACKET_LEN, nullptr); |
182 | 1 | tox_group_send_custom_private_packet(tox, state->group_number, state->peer_id, false, (const uint8_t *)TEST_CUSTOM_PRIVATE_PACKET, TEST_CUSTOM_PRIVATE_PACKET_LEN, nullptr); |
183 | | |
184 | 1 | WAIT_UNTIL(state->lossless_done); |
185 | 1 | tox_node_log(self, "Done"); |
186 | 1 | } |
187 | | |
188 | | int main(int argc, char *argv[]) |
189 | 31 | { |
190 | 31 | ToxScenario *s = tox_scenario_new(argc, argv, 300000); |
191 | 31 | GroupState s0 = { .last_msg_recv = -1 }, s1 = { .last_msg_recv = -1 }; |
192 | | |
193 | 31 | ToxNode *n0 = tox_scenario_add_node(s, "Peer0", peer0_script, &s0, sizeof(GroupState)); |
194 | 31 | ToxNode *n1 = tox_scenario_add_node(s, "Peer1", peer1_script, &s1, sizeof(GroupState)); |
195 | | |
196 | 31 | tox_node_friend_add(n0, n1); |
197 | 31 | tox_node_friend_add(n1, n0); |
198 | 31 | tox_node_bootstrap(n0, n1); |
199 | 31 | tox_node_bootstrap(n1, n0); |
200 | | |
201 | 31 | ToxScenarioStatus res = tox_scenario_run(s); |
202 | 31 | if (res != TOX_SCENARIO_DONE) { |
203 | 0 | tox_scenario_log(s, "Test failed with status %u", res); |
204 | 0 | return 1; |
205 | 0 | } |
206 | | |
207 | 31 | tox_scenario_free(s); |
208 | 31 | return 0; |
209 | 31 | } |
210 | | |
211 | | #undef PEER0_NICK |
212 | | #undef PEER0_NICK_LEN |
213 | | #undef PEER1_NICK |
214 | | #undef PEER1_NICK_LEN |