summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rwxr-xr-xother/astyle/format-source16
-rw-r--r--testing/random_testing.cc25
-rw-r--r--toxcore/BUILD.bazel9
-rw-r--r--toxcore/crypto_core_test.cc4
-rw-r--r--toxcore/ping_array.api.h29
-rw-r--r--toxcore/ping_array.c59
-rw-r--r--toxcore/ping_array.h29
-rw-r--r--toxcore/ping_array_test.cc119
9 files changed, 218 insertions, 73 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a867e1dd..95b12ce0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -362,6 +362,7 @@ unit_test(toxav ring_buffer)
362unit_test(toxav rtp) 362unit_test(toxav rtp)
363unit_test(toxcore crypto_core) 363unit_test(toxcore crypto_core)
364unit_test(toxcore mono_time) 364unit_test(toxcore mono_time)
365unit_test(toxcore ping_array)
365unit_test(toxcore util) 366unit_test(toxcore util)
366 367
367################################################################################ 368################################################################################
diff --git a/other/astyle/format-source b/other/astyle/format-source
index 5e139d89..550bcf07 100755
--- a/other/astyle/format-source
+++ b/other/astyle/format-source
@@ -49,15 +49,25 @@ if grep '<unresolved>' */*.h; then
49 exit 1 49 exit 1
50fi 50fi
51 51
52CC_SOURCES=`find . '(' -name '*.cc' ')'`
53CC_SOURCES="$CC_SOURCES toxcore/ping_array.c"
54
55for bin in clang-format-6.0 clang-format-5.0 clang-format; do
56 if which "$bin"; then
57 "$bin" -i -style='{BasedOnStyle: Google, ColumnLimit: 100}' $CC_SOURCES
58 break
59 fi
60done
61
52FIND="find ." 62FIND="find ."
53FIND="$FIND '(' -name '*.[ch]' -or -name '*.cpp' ')'" 63FIND="$FIND '(' -name '*.[ch]' ')'"
54FIND="$FIND -and -not -name '*.api.h'" 64FIND="$FIND -and -not -name '*.api.h'"
55FIND="$FIND -and -not -wholename './super_donators/*'" 65FIND="$FIND -and -not -wholename './super_donators/*'"
56FIND="$FIND -and -not -wholename './third_party/*'" 66FIND="$FIND -and -not -wholename './third_party/*'"
57FIND="$FIND -and -not -wholename './toxencryptsave/crypto_pwhash*'" 67FIND="$FIND -and -not -wholename './toxencryptsave/crypto_pwhash*'"
58 68
59SOURCES=`eval "$FIND"` 69C_SOURCES=`eval "$FIND"`
60 70
61$ASTYLE -n --options=other/astyle/astylerc $SOURCES 71$ASTYLE -n --options=other/astyle/astylerc $C_SOURCES
62 72
63git diff --exit-code 73git diff --exit-code
diff --git a/testing/random_testing.cc b/testing/random_testing.cc
index 5ea0bc9d..6211630e 100644
--- a/testing/random_testing.cc
+++ b/testing/random_testing.cc
@@ -283,7 +283,8 @@ bool attempt_action(Global_State *toxes, std::mt19937 *rng) {
283int main() { 283int main() {
284 std::vector<Action> const actions = { 284 std::vector<Action> const actions = {
285 { 285 {
286 10, "creates a new conference", 286 10,
287 "creates a new conference",
287 [](Local_State const &state) { 288 [](Local_State const &state) {
288 return tox_conference_get_chatlist_size(state.tox()) < MAX_CONFERENCES_PER_USER; 289 return tox_conference_get_chatlist_size(state.tox()) < MAX_CONFERENCES_PER_USER;
289 }, 290 },
@@ -294,7 +295,8 @@ int main() {
294 }, 295 },
295 }, 296 },
296 { 297 {
297 10, "invites a random friend to a conference", 298 10,
299 "invites a random friend to a conference",
298 [](Local_State const &state) { 300 [](Local_State const &state) {
299 return tox_conference_get_chatlist_size(state.tox()) != 0; 301 return tox_conference_get_chatlist_size(state.tox()) != 0;
300 }, 302 },
@@ -302,15 +304,15 @@ int main() {
302 size_t chat_count = tox_conference_get_chatlist_size(state->tox()); 304 size_t chat_count = tox_conference_get_chatlist_size(state->tox());
303 assert(chat_count != 0); // Condition above. 305 assert(chat_count != 0); // Condition above.
304 TOX_ERR_CONFERENCE_INVITE err; 306 TOX_ERR_CONFERENCE_INVITE err;
305 tox_conference_invite( 307 tox_conference_invite(state->tox(), rnd->friend_selector(*rng),
306 state->tox(), rnd->friend_selector(*rng), 308 state->next_invite % chat_count, &err);
307 state->next_invite % chat_count, &err);
308 state->next_invite++; 309 state->next_invite++;
309 assert(err == TOX_ERR_CONFERENCE_INVITE_OK); 310 assert(err == TOX_ERR_CONFERENCE_INVITE_OK);
310 }, 311 },
311 }, 312 },
312 { 313 {
313 10, "deletes the last conference", 314 10,
315 "deletes the last conference",
314 [](Local_State const &state) { 316 [](Local_State const &state) {
315 return tox_conference_get_chatlist_size(state.tox()) != 0; 317 return tox_conference_get_chatlist_size(state.tox()) != 0;
316 }, 318 },
@@ -322,7 +324,8 @@ int main() {
322 }, 324 },
323 }, 325 },
324 { 326 {
325 10, "sends a message to the last conference", 327 10,
328 "sends a message to the last conference",
326 [](Local_State const &state) { 329 [](Local_State const &state) {
327 return tox_conference_get_chatlist_size(state.tox()) != 0; 330 return tox_conference_get_chatlist_size(state.tox()) != 0;
328 }, 331 },
@@ -344,7 +347,9 @@ int main() {
344 }, 347 },
345 }, 348 },
346 { 349 {
347 10, "changes their name", [](Local_State const &state) { return true; }, 350 10,
351 "changes their name",
352 [](Local_State const &state) { return true; },
348 [](Local_State *state, Random *rnd, std::mt19937 *rng) { 353 [](Local_State *state, Random *rnd, std::mt19937 *rng) {
349 std::vector<uint8_t> name(rnd->name_length_selector(*rng)); 354 std::vector<uint8_t> name(rnd->name_length_selector(*rng));
350 for (uint8_t &byte : name) { 355 for (uint8_t &byte : name) {
@@ -359,7 +364,9 @@ int main() {
359 }, 364 },
360 }, 365 },
361 { 366 {
362 10, "sets their name to empty", [](Local_State const &state) { return true; }, 367 10,
368 "sets their name to empty",
369 [](Local_State const &state) { return true; },
363 [](Local_State *state, Random *rnd, std::mt19937 *rng) { 370 [](Local_State *state, Random *rnd, std::mt19937 *rng) {
364 TOX_ERR_SET_INFO err; 371 TOX_ERR_SET_INFO err;
365 tox_self_set_name(state->tox(), nullptr, 0, &err); 372 tox_self_set_name(state->tox(), nullptr, 0, &err);
diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel
index 6fbe016e..a34c328c 100644
--- a/toxcore/BUILD.bazel
+++ b/toxcore/BUILD.bazel
@@ -113,6 +113,15 @@ cc_library(
113 deps = [":network"], 113 deps = [":network"],
114) 114)
115 115
116cc_test(
117 name = "ping_array_test",
118 srcs = ["ping_array_test.cc"],
119 deps = [
120 ":ping_array",
121 "@com_google_googletest//:gtest_main",
122 ],
123)
124
116cc_library( 125cc_library(
117 name = "DHT", 126 name = "DHT",
118 srcs = [ 127 srcs = [
diff --git a/toxcore/crypto_core_test.cc b/toxcore/crypto_core_test.cc
index cdc315b2..d6888b19 100644
--- a/toxcore/crypto_core_test.cc
+++ b/toxcore/crypto_core_test.cc
@@ -10,8 +10,10 @@ enum {
10 /** 10 /**
11 * The size of the arrays to compare. This was chosen to take around 2000 11 * The size of the arrays to compare. This was chosen to take around 2000
12 * CPU clocks on x86_64. 12 * CPU clocks on x86_64.
13 *
14 * This is 1MiB.
13 */ 15 */
14 CRYPTO_TEST_MEMCMP_SIZE = 1024 * 1024, // 1 MiB 16 CRYPTO_TEST_MEMCMP_SIZE = 1024 * 1024,
15 /** 17 /**
16 * The number of times we run memcmp in the test. 18 * The number of times we run memcmp in the test.
17 * 19 *
diff --git a/toxcore/ping_array.api.h b/toxcore/ping_array.api.h
index 61021e24..74e2b002 100644
--- a/toxcore/ping_array.api.h
+++ b/toxcore/ping_array.api.h
@@ -22,10 +22,15 @@
22 * You should have received a copy of the GNU General Public License 22 * You should have received a copy of the GNU General Public License
23 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 23 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */ 24 */
25#ifndef PING_ARRAY_H 25#ifndef C_TOXCORE_TOXCORE_PING_ARRAY_H
26#define PING_ARRAY_H 26#define C_TOXCORE_TOXCORE_PING_ARRAY_H
27 27
28#include "network.h" 28#include <stddef.h>
29#include <stdint.h>
30
31#ifdef __cplusplus
32extern "C" {
33#endif
29%} 34%}
30 35
31class mono_Time { struct this; } 36class mono_Time { struct this; }
@@ -36,11 +41,11 @@ struct this;
36 41
37/** 42/**
38 * Initialize a Ping_Array. 43 * Initialize a Ping_Array.
39 * size represents the total size of the array and should be a power of 2.
40 * timeout represents the maximum timeout in seconds for the entry.
41 * 44 *
42 * return 0 on success. 45 * @param size represents the total size of the array and should be a power of 2.
43 * return -1 on failure. 46 * @param timeout represents the maximum timeout in seconds for the entry.
47 *
48 * @return 0 on success, -1 on failure.
44 */ 49 */
45static this new(uint32_t size, uint32_t timeout); 50static this new(uint32_t size, uint32_t timeout);
46 51
@@ -52,8 +57,7 @@ void kill();
52/** 57/**
53 * Add a data with length to the Ping_Array list and return a ping_id. 58 * Add a data with length to the Ping_Array list and return a ping_id.
54 * 59 *
55 * return ping_id on success. 60 * @return ping_id on success, 0 on failure.
56 * return 0 on failure.
57 */ 61 */
58uint64_t add(const mono_Time::this *mono_time, const uint8_t *data, uint32_t length); 62uint64_t add(const mono_Time::this *mono_time, const uint8_t *data, uint32_t length);
59 63
@@ -62,13 +66,16 @@ uint64_t add(const mono_Time::this *mono_time, const uint8_t *data, uint32_t len
62 * 66 *
63 * On success, copies the data into data of length, 67 * On success, copies the data into data of length,
64 * 68 *
65 * return length of data copied on success. 69 * @return length of data copied on success, -1 on failure.
66 * return -1 on failure.
67 */ 70 */
68int32_t check(const mono_Time::this *mono_time, uint8_t[length] data, uint64_t ping_id); 71int32_t check(const mono_Time::this *mono_time, uint8_t[length] data, uint64_t ping_id);
69 72
70} 73}
71 74
72%{ 75%{
76#ifdef __cplusplus
77} // extern "C"
73#endif 78#endif
79
80#endif // C_TOXCORE_TOXCORE_PING_ARRAY_H
74%} 81%}
diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c
index 9130254e..6669b4bd 100644
--- a/toxcore/ping_array.c
+++ b/toxcore/ping_array.c
@@ -34,7 +34,6 @@
34#include "mono_time.h" 34#include "mono_time.h"
35#include "util.h" 35#include "util.h"
36 36
37
38typedef struct Ping_Array_Entry { 37typedef struct Ping_Array_Entry {
39 void *data; 38 void *data;
40 uint32_t length; 39 uint32_t length;
@@ -46,25 +45,23 @@ struct Ping_Array {
46 Ping_Array_Entry *entries; 45 Ping_Array_Entry *entries;
47 46
48 uint32_t last_deleted; /* number representing the next entry to be deleted. */ 47 uint32_t last_deleted; /* number representing the next entry to be deleted. */
49 uint32_t last_added; /* number representing the last entry to be added. */ 48 uint32_t last_added; /* number representing the last entry to be added. */
50 uint32_t total_size; /* The length of entries */ 49 uint32_t total_size; /* The length of entries */
51 uint32_t timeout; /* The timeout after which entries are cleared. */ 50 uint32_t timeout; /* The timeout after which entries are cleared. */
52}; 51};
53 52
54/* Initialize a Ping_Array.
55 * size represents the total size of the array and should be a power of 2.
56 * timeout represents the maximum timeout in seconds for the entry.
57 *
58 * return 0 on success.
59 * return -1 on failure.
60 */
61Ping_Array *ping_array_new(uint32_t size, uint32_t timeout) 53Ping_Array *ping_array_new(uint32_t size, uint32_t timeout)
62{ 54{
63 if (size == 0 || timeout == 0) { 55 if (size == 0 || timeout == 0) {
64 return nullptr; 56 return nullptr;
65 } 57 }
66 58
67 Ping_Array *empty_array = (Ping_Array *)calloc(1, sizeof(Ping_Array)); 59 if ((size & (size - 1)) != 0) {
60 // Not a power of 2.
61 return nullptr;
62 }
63
64 Ping_Array *const empty_array = (Ping_Array *)calloc(1, sizeof(Ping_Array));
68 65
69 if (empty_array == nullptr) { 66 if (empty_array == nullptr) {
70 return nullptr; 67 return nullptr;
@@ -86,19 +83,15 @@ Ping_Array *ping_array_new(uint32_t size, uint32_t timeout)
86 83
87static void clear_entry(Ping_Array *array, uint32_t index) 84static void clear_entry(Ping_Array *array, uint32_t index)
88{ 85{
86 const Ping_Array_Entry empty = {nullptr};
89 free(array->entries[index].data); 87 free(array->entries[index].data);
90 array->entries[index].data = nullptr; 88 array->entries[index] = empty;
91 array->entries[index].length = 0;
92 array->entries[index].time = 0;
93 array->entries[index].ping_id = 0;
94} 89}
95 90
96/* Free all the allocated memory in a Ping_Array.
97 */
98void ping_array_kill(Ping_Array *array) 91void ping_array_kill(Ping_Array *array)
99{ 92{
100 while (array->last_deleted != array->last_added) { 93 while (array->last_deleted != array->last_added) {
101 uint32_t index = array->last_deleted % array->total_size; 94 const uint32_t index = array->last_deleted % array->total_size;
102 clear_entry(array, index); 95 clear_entry(array, index);
103 ++array->last_deleted; 96 ++array->last_deleted;
104 } 97 }
@@ -112,7 +105,7 @@ void ping_array_kill(Ping_Array *array)
112static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_time) 105static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_time)
113{ 106{
114 while (array->last_deleted != array->last_added) { 107 while (array->last_deleted != array->last_added) {
115 uint32_t index = array->last_deleted % array->total_size; 108 const uint32_t index = array->last_deleted % array->total_size;
116 109
117 if (!mono_time_is_timeout(mono_time, array->entries[index].time, array->timeout)) { 110 if (!mono_time_is_timeout(mono_time, array->entries[index].time, array->timeout)) {
118 break; 111 break;
@@ -123,15 +116,11 @@ static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_t
123 } 116 }
124} 117}
125 118
126/* Add a data with length to the Ping_Array list and return a ping_id. 119uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const uint8_t *data,
127 * 120 uint32_t length)
128 * return ping_id on success.
129 * return 0 on failure.
130 */
131uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const uint8_t *data, uint32_t length)
132{ 121{
133 ping_array_clear_timedout(array, mono_time); 122 ping_array_clear_timedout(array, mono_time);
134 uint32_t index = array->last_added % array->total_size; 123 const uint32_t index = array->last_added % array->total_size;
135 124
136 if (array->entries[index].data != nullptr) { 125 if (array->entries[index].data != nullptr) {
137 array->last_deleted = array->last_added - array->total_size; 126 array->last_deleted = array->last_added - array->total_size;
@@ -161,21 +150,14 @@ uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const uin
161 return ping_id; 150 return ping_id;
162} 151}
163 152
164 153int32_t ping_array_check(Ping_Array *array, const Mono_Time *mono_time, uint8_t *data,
165/* Check if ping_id is valid and not timed out. 154 size_t length, uint64_t ping_id)
166 *
167 * On success, copies the data into data of length,
168 *
169 * return length of data copied on success.
170 * return -1 on failure.
171 */
172int32_t ping_array_check(Ping_Array *array, const Mono_Time *mono_time, uint8_t *data, size_t length, uint64_t ping_id)
173{ 155{
174 if (ping_id == 0) { 156 if (ping_id == 0) {
175 return -1; 157 return -1;
176 } 158 }
177 159
178 uint32_t index = ping_id % array->total_size; 160 const uint32_t index = ping_id % array->total_size;
179 161
180 if (array->entries[index].ping_id != ping_id) { 162 if (array->entries[index].ping_id != ping_id) {
181 return -1; 163 return -1;
@@ -189,12 +171,13 @@ int32_t ping_array_check(Ping_Array *array, const Mono_Time *mono_time, uint8_t
189 return -1; 171 return -1;
190 } 172 }
191 173
174 // TODO(iphydf): This can't happen? If it indeed can't, turn it into an assert.
192 if (array->entries[index].data == nullptr) { 175 if (array->entries[index].data == nullptr) {
193 return -1; 176 return -1;
194 } 177 }
195 178
196 memcpy(data, array->entries[index].data, array->entries[index].length); 179 memcpy(data, array->entries[index].data, array->entries[index].length);
197 uint32_t len = array->entries[index].length; 180 const uint32_t len = array->entries[index].length;
198 clear_entry(array, index); 181 clear_entry(array, index);
199 return len; 182 return len;
200} 183}
diff --git a/toxcore/ping_array.h b/toxcore/ping_array.h
index cfa9bfcc..7bc95a42 100644
--- a/toxcore/ping_array.h
+++ b/toxcore/ping_array.h
@@ -21,10 +21,15 @@
21 * You should have received a copy of the GNU General Public License 21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */ 23 */
24#ifndef PING_ARRAY_H 24#ifndef C_TOXCORE_TOXCORE_PING_ARRAY_H
25#define PING_ARRAY_H 25#define C_TOXCORE_TOXCORE_PING_ARRAY_H
26 26
27#include "network.h" 27#include <stddef.h>
28#include <stdint.h>
29
30#ifdef __cplusplus
31extern "C" {
32#endif
28 33
29#ifndef MONO_TIME_DEFINED 34#ifndef MONO_TIME_DEFINED
30#define MONO_TIME_DEFINED 35#define MONO_TIME_DEFINED
@@ -38,11 +43,11 @@ typedef struct Ping_Array Ping_Array;
38 43
39/** 44/**
40 * Initialize a Ping_Array. 45 * Initialize a Ping_Array.
41 * size represents the total size of the array and should be a power of 2.
42 * timeout represents the maximum timeout in seconds for the entry.
43 * 46 *
44 * return 0 on success. 47 * @param size represents the total size of the array and should be a power of 2.
45 * return -1 on failure. 48 * @param timeout represents the maximum timeout in seconds for the entry.
49 *
50 * @return 0 on success, -1 on failure.
46 */ 51 */
47struct Ping_Array *ping_array_new(uint32_t size, uint32_t timeout); 52struct Ping_Array *ping_array_new(uint32_t size, uint32_t timeout);
48 53
@@ -54,8 +59,7 @@ void ping_array_kill(struct Ping_Array *_array);
54/** 59/**
55 * Add a data with length to the Ping_Array list and return a ping_id. 60 * Add a data with length to the Ping_Array list and return a ping_id.
56 * 61 *
57 * return ping_id on success. 62 * @return ping_id on success, 0 on failure.
58 * return 0 on failure.
59 */ 63 */
60uint64_t ping_array_add(struct Ping_Array *_array, const struct Mono_Time *mono_time, const uint8_t *data, 64uint64_t ping_array_add(struct Ping_Array *_array, const struct Mono_Time *mono_time, const uint8_t *data,
61 uint32_t length); 65 uint32_t length);
@@ -65,10 +69,13 @@ uint64_t ping_array_add(struct Ping_Array *_array, const struct Mono_Time *mono_
65 * 69 *
66 * On success, copies the data into data of length, 70 * On success, copies the data into data of length,
67 * 71 *
68 * return length of data copied on success. 72 * @return length of data copied on success, -1 on failure.
69 * return -1 on failure.
70 */ 73 */
71int32_t ping_array_check(struct Ping_Array *_array, const struct Mono_Time *mono_time, uint8_t *data, size_t length, 74int32_t ping_array_check(struct Ping_Array *_array, const struct Mono_Time *mono_time, uint8_t *data, size_t length,
72 uint64_t ping_id); 75 uint64_t ping_id);
73 76
77#ifdef __cplusplus
78} // extern "C"
74#endif 79#endif
80
81#endif // C_TOXCORE_TOXCORE_PING_ARRAY_H
diff --git a/toxcore/ping_array_test.cc b/toxcore/ping_array_test.cc
new file mode 100644
index 00000000..fca5009a
--- /dev/null
+++ b/toxcore/ping_array_test.cc
@@ -0,0 +1,119 @@
1#include "ping_array.h"
2
3#include <memory>
4
5#include <gtest/gtest.h>
6#include "mono_time.h"
7
8namespace {
9
10struct Ping_Array_Deleter {
11 void operator()(Ping_Array *arr) { ping_array_kill(arr); }
12};
13
14using Ping_Array_Ptr = std::unique_ptr<Ping_Array, Ping_Array_Deleter>;
15
16struct Mono_Time_Deleter {
17 void operator()(Mono_Time *arr) { mono_time_free(arr); }
18};
19
20using Mono_Time_Ptr = std::unique_ptr<Mono_Time, Mono_Time_Deleter>;
21
22TEST(PingArray, MinimumTimeoutIsOne) {
23 EXPECT_EQ(ping_array_new(1, 0), nullptr);
24 EXPECT_NE(Ping_Array_Ptr(ping_array_new(1, 1)), nullptr);
25}
26
27TEST(PingArray, MinimumArraySizeIsOne) {
28 EXPECT_EQ(ping_array_new(0, 1), nullptr);
29 EXPECT_NE(Ping_Array_Ptr(ping_array_new(1, 1)), nullptr);
30}
31
32TEST(PingArray, ArraySizeMustBePowerOfTwo) {
33 Ping_Array_Ptr arr;
34 arr.reset(ping_array_new(2, 1));
35 EXPECT_NE(arr, nullptr);
36 arr.reset(ping_array_new(4, 1));
37 EXPECT_NE(arr, nullptr);
38 arr.reset(ping_array_new(1024, 1));
39 EXPECT_NE(arr, nullptr);
40
41 EXPECT_EQ(ping_array_new(1023, 1), nullptr);
42 EXPECT_EQ(ping_array_new(1234, 1), nullptr);
43}
44
45TEST(PingArray, StoredDataCanBeRetrieved) {
46 Ping_Array_Ptr const arr(ping_array_new(2, 1));
47 Mono_Time_Ptr const mono_time(mono_time_new());
48
49 uint64_t const ping_id =
50 ping_array_add(arr.get(), mono_time.get(), std::vector<uint8_t>{1, 2, 3, 4}.data(), 4);
51 EXPECT_NE(ping_id, 0);
52
53 std::vector<uint8_t> data(4);
54 EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), data.size(), ping_id), 4);
55 EXPECT_EQ(data, std::vector<uint8_t>({1, 2, 3, 4}));
56}
57
58TEST(PingArray, RetrievingDataWithTooSmallOutputBufferHasNoEffect) {
59 Ping_Array_Ptr const arr(ping_array_new(2, 1));
60 Mono_Time_Ptr const mono_time(mono_time_new());
61
62 uint64_t const ping_id =
63 ping_array_add(arr.get(), mono_time.get(), (std::vector<uint8_t>{1, 2, 3, 4}).data(), 4);
64 EXPECT_NE(ping_id, 0);
65
66 std::vector<uint8_t> data(4);
67 EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), 3, ping_id), -1);
68 // It doesn't write anything to the data array.
69 EXPECT_EQ(data, std::vector<uint8_t>({0, 0, 0, 0}));
70 // Afterwards, we can still read it.
71 EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), 4, ping_id), 4);
72 EXPECT_EQ(data, std::vector<uint8_t>({1, 2, 3, 4}));
73}
74
75TEST(PingArray, ZeroLengthDataCanBeAdded) {
76 Ping_Array_Ptr const arr(ping_array_new(2, 1));
77 Mono_Time_Ptr const mono_time(mono_time_new());
78
79 uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), nullptr, 0);
80 EXPECT_NE(ping_id, 0);
81
82 EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, ping_id), 0);
83}
84
85TEST(PingArray, PingId0IsInvalid) {
86 Ping_Array_Ptr const arr(ping_array_new(2, 1));
87 Mono_Time_Ptr const mono_time(mono_time_new());
88
89 EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, 0), -1);
90}
91
92// Protection against replay attacks.
93TEST(PingArray, DataCanOnlyBeRetrievedOnce) {
94 Ping_Array_Ptr const arr(ping_array_new(2, 1));
95 Mono_Time_Ptr const mono_time(mono_time_new());
96
97 uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), nullptr, 0);
98 EXPECT_NE(ping_id, 0);
99
100 EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, ping_id), 0);
101 EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, ping_id), -1);
102}
103
104TEST(PingArray, PingIdMustMatchOnCheck) {
105 Ping_Array_Ptr const arr(ping_array_new(1, 1));
106 Mono_Time_Ptr const mono_time(mono_time_new());
107
108 uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), nullptr, 0);
109 EXPECT_NE(ping_id, 0);
110
111 uint64_t const bad_ping_id = ping_id == 1 ? 2 : 1;
112
113 // bad_ping_id will also be pointing at the same element, but won't match the
114 // actual ping_id.
115 EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, bad_ping_id), -1);
116 EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, ping_id), 0);
117}
118
119} // namespace