summaryrefslogtreecommitdiff
path: root/testing
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2018-06-24 12:41:26 +0000
committeriphydf <iphydf@users.noreply.github.com>2018-06-24 19:51:34 +0000
commit5c2600d87bd000b32b2a37c5a74275912ddd5328 (patch)
tree82ddac9827ff05735bdf7b8a24531333a3c611db /testing
parent8e00294b3cb9808ce55160240454359638178275 (diff)
Add new Circle CI configuration.
This one has ASAN enabled, unlike Travis.
Diffstat (limited to 'testing')
-rw-r--r--testing/random_testing.cc255
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 {
47using Tox_Ptr = std::unique_ptr<Tox, Tox_Deleter>; 47using Tox_Ptr = std::unique_ptr<Tox, Tox_Deleter>;
48 48
49struct Local_State { 49struct 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
63struct Action;
64
63struct Random { 65struct 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
76struct Action { 78struct 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
83Action const actions[] = { 85std::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
176std::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
184Random::Random() 93Random::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
193struct Global_State : std::vector<Local_State> { 102struct 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
203void handle_friend_connection_status(Tox *tox, uint32_t friend_number, 119void 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
259Global_State make_toxes() { 175Global_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
334bool execute_random_action(Global_State &toxes, std::mt19937 &rng) { 250bool 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
364int main() { 280int 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}