diff options
author | iphydf <iphydf@users.noreply.github.com> | 2018-06-24 12:41:26 +0000 |
---|---|---|
committer | iphydf <iphydf@users.noreply.github.com> | 2018-06-24 19:51:34 +0000 |
commit | 5c2600d87bd000b32b2a37c5a74275912ddd5328 (patch) | |
tree | 82ddac9827ff05735bdf7b8a24531333a3c611db /testing | |
parent | 8e00294b3cb9808ce55160240454359638178275 (diff) |
Add new Circle CI configuration.
This one has ASAN enabled, unlike Travis.
Diffstat (limited to 'testing')
-rw-r--r-- | testing/random_testing.cc | 255 |
1 files changed, 128 insertions, 127 deletions
diff --git a/testing/random_testing.cc b/testing/random_testing.cc index 3e5be731..ecad07d3 100644 --- a/testing/random_testing.cc +++ b/testing/random_testing.cc | |||
@@ -47,19 +47,21 @@ struct Tox_Deleter { | |||
47 | using Tox_Ptr = std::unique_ptr<Tox, Tox_Deleter>; | 47 | using Tox_Ptr = std::unique_ptr<Tox, Tox_Deleter>; |
48 | 48 | ||
49 | struct Local_State { | 49 | struct Local_State { |
50 | Tox_Ptr tox; | ||
51 | |||
52 | uint32_t friends_online = 0; | 50 | uint32_t friends_online = 0; |
53 | uint32_t next_invite = 0; | 51 | uint32_t next_invite = 0; |
54 | 52 | ||
55 | explicit Local_State(Tox_Ptr tox, uint32_t id) : tox(std::move(tox)), id_(id) {} | 53 | explicit Local_State(Tox_Ptr tox, uint32_t id) : tox_(std::move(tox)), id_(id) {} |
56 | 54 | ||
55 | Tox *tox() const { return tox_.get(); } | ||
57 | uint32_t id() const { return id_; } | 56 | uint32_t id() const { return id_; } |
58 | 57 | ||
59 | private: | 58 | private: |
59 | Tox_Ptr tox_; | ||
60 | uint32_t id_; | 60 | uint32_t id_; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | struct Action; | ||
64 | |||
63 | struct Random { | 65 | struct Random { |
64 | std::uniform_int_distribution<> tox_selector; | 66 | std::uniform_int_distribution<> tox_selector; |
65 | std::uniform_int_distribution<> friend_selector; | 67 | std::uniform_int_distribution<> friend_selector; |
@@ -70,7 +72,7 @@ struct Random { | |||
70 | std::vector<size_t> action_weights; | 72 | std::vector<size_t> action_weights; |
71 | std::discrete_distribution<size_t> action_selector; | 73 | std::discrete_distribution<size_t> action_selector; |
72 | 74 | ||
73 | Random(); | 75 | explicit Random(std::vector<Action> const &actions); |
74 | }; | 76 | }; |
75 | 77 | ||
76 | struct Action { | 78 | struct Action { |
@@ -80,100 +82,7 @@ struct Action { | |||
80 | void (*run)(Local_State &state, Random &rnd, std::mt19937 &rng); | 82 | void (*run)(Local_State &state, Random &rnd, std::mt19937 &rng); |
81 | }; | 83 | }; |
82 | 84 | ||
83 | Action const actions[] = { | 85 | std::vector<size_t> get_action_weights(std::vector<Action> const &actions) { |
84 | { | ||
85 | 10, | ||
86 | "creates a new conference", | ||
87 | [](Local_State const &state) { | ||
88 | return tox_conference_get_chatlist_size(state.tox.get()) < MAX_CONFERENCES_PER_USER; | ||
89 | }, | ||
90 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
91 | TOX_ERR_CONFERENCE_NEW err; | ||
92 | tox_conference_new(state.tox.get(), &err); | ||
93 | assert(err == TOX_ERR_CONFERENCE_NEW_OK); | ||
94 | }, | ||
95 | }, | ||
96 | { | ||
97 | 10, | ||
98 | "invites a random friend to a conference", | ||
99 | [](Local_State const &state) { | ||
100 | return tox_conference_get_chatlist_size(state.tox.get()) != 0; | ||
101 | }, | ||
102 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
103 | TOX_ERR_CONFERENCE_INVITE err; | ||
104 | tox_conference_invite( | ||
105 | state.tox.get(), rnd.friend_selector(rng), | ||
106 | state.next_invite % tox_conference_get_chatlist_size(state.tox.get()), &err); | ||
107 | state.next_invite++; | ||
108 | assert(err == TOX_ERR_CONFERENCE_INVITE_OK); | ||
109 | }, | ||
110 | }, | ||
111 | { | ||
112 | 10, | ||
113 | "deletes the last conference", | ||
114 | [](Local_State const &state) { | ||
115 | return tox_conference_get_chatlist_size(state.tox.get()) != 0; | ||
116 | }, | ||
117 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
118 | TOX_ERR_CONFERENCE_DELETE err; | ||
119 | tox_conference_delete(state.tox.get(), | ||
120 | tox_conference_get_chatlist_size(state.tox.get()) - 1, &err); | ||
121 | assert(err == TOX_ERR_CONFERENCE_DELETE_OK); | ||
122 | }, | ||
123 | }, | ||
124 | { | ||
125 | 10, | ||
126 | "sends a message to the last conference", | ||
127 | [](Local_State const &state) { | ||
128 | return tox_conference_get_chatlist_size(state.tox.get()) != 0; | ||
129 | }, | ||
130 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
131 | std::vector<uint8_t> message(rnd.message_length_selector(rng)); | ||
132 | for (uint8_t &byte : message) { | ||
133 | byte = rnd.byte_selector(rng); | ||
134 | } | ||
135 | |||
136 | TOX_ERR_CONFERENCE_SEND_MESSAGE err; | ||
137 | tox_conference_send_message( | ||
138 | state.tox.get(), tox_conference_get_chatlist_size(state.tox.get()) - 1, | ||
139 | TOX_MESSAGE_TYPE_NORMAL, message.data(), message.size(), &err); | ||
140 | if (err == TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) { | ||
141 | printf(" (OK, length = %u)", (unsigned)message.size()); | ||
142 | } else { | ||
143 | printf(" (FAILED: %u)", err); | ||
144 | } | ||
145 | }, | ||
146 | }, | ||
147 | { | ||
148 | 10, | ||
149 | "changes their name", | ||
150 | [](Local_State const &state) { return true; }, | ||
151 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
152 | std::vector<uint8_t> name(rnd.name_length_selector(rng)); | ||
153 | for (uint8_t &byte : name) { | ||
154 | byte = rnd.byte_selector(rng); | ||
155 | } | ||
156 | |||
157 | TOX_ERR_SET_INFO err; | ||
158 | tox_self_set_name(state.tox.get(), name.data(), name.size(), &err); | ||
159 | assert(err == TOX_ERR_SET_INFO_OK); | ||
160 | |||
161 | printf(" (length = %u)", (unsigned)name.size()); | ||
162 | }, | ||
163 | }, | ||
164 | { | ||
165 | 10, | ||
166 | "sets their name to empty", | ||
167 | [](Local_State const &state) { return true; }, | ||
168 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
169 | TOX_ERR_SET_INFO err; | ||
170 | tox_self_set_name(state.tox.get(), nullptr, 0, &err); | ||
171 | assert(err == TOX_ERR_SET_INFO_OK); | ||
172 | }, | ||
173 | }, | ||
174 | }; | ||
175 | |||
176 | std::vector<size_t> get_action_weights() { | ||
177 | std::vector<size_t> weights; | 86 | std::vector<size_t> weights; |
178 | for (Action const &action : actions) { | 87 | for (Action const &action : actions) { |
179 | weights.push_back(action.weight); | 88 | weights.push_back(action.weight); |
@@ -181,23 +90,30 @@ std::vector<size_t> get_action_weights() { | |||
181 | return weights; | 90 | return weights; |
182 | } | 91 | } |
183 | 92 | ||
184 | Random::Random() | 93 | Random::Random(std::vector<Action> const &actions) |
185 | : tox_selector(0, NUM_TOXES - 1), | 94 | : tox_selector(0, NUM_TOXES - 1), |
186 | friend_selector(0, NUM_TOXES - 2), | 95 | friend_selector(0, NUM_TOXES - 2), |
187 | name_length_selector(0, TOX_MAX_NAME_LENGTH - 1), | 96 | name_length_selector(0, TOX_MAX_NAME_LENGTH - 1), |
188 | message_length_selector(0, TOX_MAX_MESSAGE_LENGTH - 1), | 97 | message_length_selector(0, TOX_MAX_MESSAGE_LENGTH - 1), |
189 | byte_selector(0, 255), | 98 | byte_selector(0, 255), |
190 | action_weights(get_action_weights()), | 99 | action_weights(get_action_weights(actions)), |
191 | action_selector(action_weights.begin(), action_weights.end()) {} | 100 | action_selector(action_weights.begin(), action_weights.end()) {} |
192 | 101 | ||
193 | struct Global_State : std::vector<Local_State> { | 102 | struct Global_State : std::vector<Local_State> { |
194 | // Non-copyable; | 103 | // Non-copyable; |
195 | Global_State(Global_State const &) = delete; | 104 | Global_State(Global_State const &) = delete; |
196 | Global_State(Global_State &&) = default; | 105 | Global_State(Global_State &&) = default; |
197 | Global_State() : action_counter(rnd.action_weights.size()) {} | 106 | explicit Global_State(std::vector<Action> const &actions) |
107 | : actions_(actions), rnd_(actions), action_counter_(actions.size()) {} | ||
108 | |||
109 | Action const &action(size_t id) const { return actions_.at(id); } | ||
110 | Random &rnd() { return rnd_; } | ||
111 | std::vector<unsigned> &action_counter() { return action_counter_; } | ||
198 | 112 | ||
199 | Random rnd; | 113 | private: |
200 | std::vector<unsigned> action_counter; | 114 | std::vector<Action> const &actions_; |
115 | Random rnd_; | ||
116 | std::vector<unsigned> action_counter_; | ||
201 | }; | 117 | }; |
202 | 118 | ||
203 | void handle_friend_connection_status(Tox *tox, uint32_t friend_number, | 119 | void handle_friend_connection_status(Tox *tox, uint32_t friend_number, |
@@ -256,8 +172,8 @@ void handle_conference_peer_list_changed(Tox *tox, uint32_t conference_number, v | |||
256 | } | 172 | } |
257 | } | 173 | } |
258 | 174 | ||
259 | Global_State make_toxes() { | 175 | Global_State make_toxes(std::vector<Action> const &actions) { |
260 | Global_State toxes; | 176 | Global_State toxes(actions); |
261 | 177 | ||
262 | Tox_Options_Ptr options(tox_options_new(nullptr)); | 178 | Tox_Options_Ptr options(tox_options_new(nullptr)); |
263 | tox_options_set_local_discovery_enabled(options.get(), false); | 179 | tox_options_set_local_discovery_enabled(options.get(), false); |
@@ -266,24 +182,24 @@ Global_State make_toxes() { | |||
266 | TOX_ERR_NEW err; | 182 | TOX_ERR_NEW err; |
267 | toxes.emplace_back(Tox_Ptr(tox_new(options.get(), &err)), i); | 183 | toxes.emplace_back(Tox_Ptr(tox_new(options.get(), &err)), i); |
268 | assert(err == TOX_ERR_NEW_OK); | 184 | assert(err == TOX_ERR_NEW_OK); |
269 | assert(toxes.back().tox != nullptr); | 185 | assert(toxes.back().tox() != nullptr); |
270 | 186 | ||
271 | tox_callback_friend_connection_status(toxes.back().tox.get(), handle_friend_connection_status); | 187 | tox_callback_friend_connection_status(toxes.back().tox(), handle_friend_connection_status); |
272 | tox_callback_conference_invite(toxes.back().tox.get(), handle_conference_invite); | 188 | tox_callback_conference_invite(toxes.back().tox(), handle_conference_invite); |
273 | tox_callback_conference_message(toxes.back().tox.get(), handle_conference_message); | 189 | tox_callback_conference_message(toxes.back().tox(), handle_conference_message); |
274 | tox_callback_conference_peer_list_changed(toxes.back().tox.get(), | 190 | tox_callback_conference_peer_list_changed(toxes.back().tox(), |
275 | handle_conference_peer_list_changed); | 191 | handle_conference_peer_list_changed); |
276 | } | 192 | } |
277 | 193 | ||
278 | std::printf("Bootstrapping %u toxes\n", NUM_TOXES); | 194 | std::printf("Bootstrapping %u toxes\n", NUM_TOXES); |
279 | 195 | ||
280 | uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; | 196 | uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; |
281 | tox_self_get_dht_id(toxes.front().tox.get(), dht_key); | 197 | tox_self_get_dht_id(toxes.front().tox(), dht_key); |
282 | const uint16_t dht_port = tox_self_get_udp_port(toxes.front().tox.get(), nullptr); | 198 | const uint16_t dht_port = tox_self_get_udp_port(toxes.front().tox(), nullptr); |
283 | 199 | ||
284 | for (Local_State const &state : toxes) { | 200 | for (Local_State const &state : toxes) { |
285 | TOX_ERR_BOOTSTRAP err; | 201 | TOX_ERR_BOOTSTRAP err; |
286 | tox_bootstrap(state.tox.get(), "localhost", dht_port, dht_key, &err); | 202 | tox_bootstrap(state.tox(), "localhost", dht_port, dht_key, &err); |
287 | assert(err == TOX_ERR_BOOTSTRAP_OK); | 203 | assert(err == TOX_ERR_BOOTSTRAP_OK); |
288 | } | 204 | } |
289 | 205 | ||
@@ -291,12 +207,12 @@ Global_State make_toxes() { | |||
291 | 207 | ||
292 | for (Local_State const &state1 : toxes) { | 208 | for (Local_State const &state1 : toxes) { |
293 | for (Local_State const &state2 : toxes) { | 209 | for (Local_State const &state2 : toxes) { |
294 | if (state1.tox != state2.tox) { | 210 | if (state1.tox() != state2.tox()) { |
295 | TOX_ERR_FRIEND_ADD err; | 211 | TOX_ERR_FRIEND_ADD err; |
296 | uint8_t key[TOX_PUBLIC_KEY_SIZE]; | 212 | uint8_t key[TOX_PUBLIC_KEY_SIZE]; |
297 | 213 | ||
298 | tox_self_get_public_key(state1.tox.get(), key); | 214 | tox_self_get_public_key(state1.tox(), key); |
299 | tox_friend_add_norequest(state2.tox.get(), key, &err); | 215 | tox_friend_add_norequest(state2.tox(), key, &err); |
300 | assert(err == TOX_ERR_FRIEND_ADD_OK); | 216 | assert(err == TOX_ERR_FRIEND_ADD_OK); |
301 | } | 217 | } |
302 | } | 218 | } |
@@ -316,10 +232,10 @@ bool bootstrap_toxes(Global_State &toxes) { | |||
316 | MAX_BOOTSTRAP_ITERATIONS); | 232 | MAX_BOOTSTRAP_ITERATIONS); |
317 | 233 | ||
318 | for (uint32_t i = 0; i < MAX_BOOTSTRAP_ITERATIONS; i++) { | 234 | for (uint32_t i = 0; i < MAX_BOOTSTRAP_ITERATIONS; i++) { |
319 | c_sleep(tox_iteration_interval(toxes.front().tox.get())); | 235 | c_sleep(tox_iteration_interval(toxes.front().tox())); |
320 | 236 | ||
321 | for (Local_State &state : toxes) { | 237 | for (Local_State &state : toxes) { |
322 | tox_iterate(state.tox.get(), &state); | 238 | tox_iterate(state.tox(), &state); |
323 | } | 239 | } |
324 | 240 | ||
325 | if (all_connected(toxes)) { | 241 | if (all_connected(toxes)) { |
@@ -333,18 +249,18 @@ bool bootstrap_toxes(Global_State &toxes) { | |||
333 | 249 | ||
334 | bool execute_random_action(Global_State &toxes, std::mt19937 &rng) { | 250 | bool execute_random_action(Global_State &toxes, std::mt19937 &rng) { |
335 | // First, choose a random actor. | 251 | // First, choose a random actor. |
336 | Local_State &actor = toxes.at(toxes.rnd.tox_selector(rng)); | 252 | Local_State &actor = toxes.at(toxes.rnd().tox_selector(rng)); |
337 | size_t const action_id = toxes.rnd.action_selector(rng); | 253 | size_t const action_id = toxes.rnd().action_selector(rng); |
338 | Action const &action = actions[action_id]; | 254 | Action const &action = toxes.action(action_id); |
339 | if (!action.can(actor)) { | 255 | if (!action.can(actor)) { |
340 | return false; | 256 | return false; |
341 | } | 257 | } |
342 | 258 | ||
343 | std::printf("Tox #%u %s", actor.id(), action.title); | 259 | std::printf("Tox #%u %s", actor.id(), action.title); |
344 | action.run(actor, toxes.rnd, rng); | 260 | action.run(actor, toxes.rnd(), rng); |
345 | std::printf("\n"); | 261 | std::printf("\n"); |
346 | 262 | ||
347 | toxes.action_counter.at(action_id)++; | 263 | toxes.action_counter().at(action_id)++; |
348 | 264 | ||
349 | return true; | 265 | return true; |
350 | } | 266 | } |
@@ -362,7 +278,92 @@ bool attempt_action(Global_State &toxes, std::mt19937 &rng) { | |||
362 | } // namespace | 278 | } // namespace |
363 | 279 | ||
364 | int main() { | 280 | int main() { |
365 | Global_State toxes = make_toxes(); | 281 | std::vector<Action> const actions = { |
282 | { | ||
283 | 10, "creates a new conference", | ||
284 | [](Local_State const &state) { | ||
285 | return tox_conference_get_chatlist_size(state.tox()) < MAX_CONFERENCES_PER_USER; | ||
286 | }, | ||
287 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
288 | TOX_ERR_CONFERENCE_NEW err; | ||
289 | tox_conference_new(state.tox(), &err); | ||
290 | assert(err == TOX_ERR_CONFERENCE_NEW_OK); | ||
291 | }, | ||
292 | }, | ||
293 | { | ||
294 | 10, "invites a random friend to a conference", | ||
295 | [](Local_State const &state) { | ||
296 | return tox_conference_get_chatlist_size(state.tox()) != 0; | ||
297 | }, | ||
298 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
299 | TOX_ERR_CONFERENCE_INVITE err; | ||
300 | tox_conference_invite(state.tox(), rnd.friend_selector(rng), | ||
301 | state.next_invite % tox_conference_get_chatlist_size(state.tox()), | ||
302 | &err); | ||
303 | state.next_invite++; | ||
304 | assert(err == TOX_ERR_CONFERENCE_INVITE_OK); | ||
305 | }, | ||
306 | }, | ||
307 | { | ||
308 | 10, "deletes the last conference", | ||
309 | [](Local_State const &state) { | ||
310 | return tox_conference_get_chatlist_size(state.tox()) != 0; | ||
311 | }, | ||
312 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
313 | TOX_ERR_CONFERENCE_DELETE err; | ||
314 | tox_conference_delete(state.tox(), tox_conference_get_chatlist_size(state.tox()) - 1, | ||
315 | &err); | ||
316 | assert(err == TOX_ERR_CONFERENCE_DELETE_OK); | ||
317 | }, | ||
318 | }, | ||
319 | { | ||
320 | 10, "sends a message to the last conference", | ||
321 | [](Local_State const &state) { | ||
322 | return tox_conference_get_chatlist_size(state.tox()) != 0; | ||
323 | }, | ||
324 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
325 | std::vector<uint8_t> message(rnd.message_length_selector(rng)); | ||
326 | for (uint8_t &byte : message) { | ||
327 | byte = rnd.byte_selector(rng); | ||
328 | } | ||
329 | |||
330 | TOX_ERR_CONFERENCE_SEND_MESSAGE err; | ||
331 | tox_conference_send_message( | ||
332 | state.tox(), tox_conference_get_chatlist_size(state.tox()) - 1, | ||
333 | TOX_MESSAGE_TYPE_NORMAL, message.data(), message.size(), &err); | ||
334 | if (err == TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) { | ||
335 | printf(" (OK, length = %u)", (unsigned)message.size()); | ||
336 | } else { | ||
337 | printf(" (FAILED: %u)", err); | ||
338 | } | ||
339 | }, | ||
340 | }, | ||
341 | { | ||
342 | 10, "changes their name", [](Local_State const &state) { return true; }, | ||
343 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
344 | std::vector<uint8_t> name(rnd.name_length_selector(rng)); | ||
345 | for (uint8_t &byte : name) { | ||
346 | byte = rnd.byte_selector(rng); | ||
347 | } | ||
348 | |||
349 | TOX_ERR_SET_INFO err; | ||
350 | tox_self_set_name(state.tox(), name.data(), name.size(), &err); | ||
351 | assert(err == TOX_ERR_SET_INFO_OK); | ||
352 | |||
353 | printf(" (length = %u)", (unsigned)name.size()); | ||
354 | }, | ||
355 | }, | ||
356 | { | ||
357 | 10, "sets their name to empty", [](Local_State const &state) { return true; }, | ||
358 | [](Local_State &state, Random &rnd, std::mt19937 &rng) { | ||
359 | TOX_ERR_SET_INFO err; | ||
360 | tox_self_set_name(state.tox(), nullptr, 0, &err); | ||
361 | assert(err == TOX_ERR_SET_INFO_OK); | ||
362 | }, | ||
363 | }, | ||
364 | }; | ||
365 | |||
366 | Global_State toxes = make_toxes(actions); | ||
366 | 367 | ||
367 | std::mt19937 rng; | 368 | std::mt19937 rng; |
368 | uint32_t action_number; | 369 | uint32_t action_number; |
@@ -383,14 +384,14 @@ int main() { | |||
383 | c_sleep(ITERATION_INTERVAL); | 384 | c_sleep(ITERATION_INTERVAL); |
384 | 385 | ||
385 | for (Local_State &state : toxes) { | 386 | for (Local_State &state : toxes) { |
386 | tox_iterate(state.tox.get(), &state); | 387 | tox_iterate(state.tox(), &state); |
387 | } | 388 | } |
388 | } | 389 | } |
389 | } | 390 | } |
390 | 391 | ||
391 | std::printf("Test execution success: %u actions performed\n", action_number); | 392 | std::printf("Test execution success: %u actions performed\n", action_number); |
392 | std::printf("Per-action statistics:\n"); | 393 | std::printf("Per-action statistics:\n"); |
393 | for (uint32_t i = 0; i < toxes.action_counter.size(); i++) { | 394 | for (uint32_t i = 0; i < toxes.action_counter().size(); i++) { |
394 | std::printf("%u x '%s'\n", toxes.action_counter.at(i), actions[i].title); | 395 | std::printf("%u x '%s'\n", toxes.action_counter().at(i), actions[i].title); |
395 | } | 396 | } |
396 | } | 397 | } |