diff options
| -rw-r--r-- | tests/t_random.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/tests/t_random.c b/tests/t_random.c new file mode 100644 index 0000000..67dedf6 --- /dev/null +++ b/tests/t_random.c | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> | ||
| 2 | It is considered beerware. Prost. Skol. Cheers or whatever. | ||
| 3 | |||
| 4 | $id$ */ | ||
| 5 | |||
| 6 | /* System */ | ||
| 7 | #include <stdint.h> | ||
| 8 | #include <string.h> | ||
| 9 | |||
| 10 | /* Opentracker */ | ||
| 11 | #include "ot_random.h" | ||
| 12 | #include "test.h" | ||
| 13 | |||
| 14 | /* Nothing here can test that the bytes are unpredictable, which is a property | ||
| 15 | of the generator the build selected. What these cases do pin is that the | ||
| 16 | wrapper hands the whole buffer to it, writes nothing beyond the length it | ||
| 17 | was given, and is actually wired to something that varies. The first of | ||
| 18 | those matters: the fallback this module replaced filled only the first | ||
| 19 | sixteen bytes of the sixty-four byte key buffer in ot_udp.c. */ | ||
| 20 | |||
| 21 | #define DRAWS 32 | ||
| 22 | #define BUFLEN 64 | ||
| 23 | |||
| 24 | static void case_every_byte_varies(void) { | ||
| 25 | unsigned char first[BUFLEN], draw[BUFLEN]; | ||
| 26 | unsigned char varied[BUFLEN]; | ||
| 27 | size_t i, n; | ||
| 28 | |||
| 29 | test_case("every byte of the buffer comes from the generator"); | ||
| 30 | memset(varied, 0, sizeof(varied)); | ||
| 31 | random_bytes(first, sizeof(first)); | ||
| 32 | |||
| 33 | for (n = 0; n < DRAWS; ++n) { | ||
| 34 | random_bytes(draw, sizeof(draw)); | ||
| 35 | for (i = 0; i < BUFLEN; ++i) | ||
| 36 | if (draw[i] != first[i]) | ||
| 37 | varied[i] = 1; | ||
| 38 | } | ||
| 39 | |||
| 40 | /* A byte position that never moved across 32 draws is not being written. | ||
| 41 | A false alarm needs all 32 draws to agree by chance, around 256^-31. */ | ||
| 42 | for (i = 0; i < BUFLEN; ++i) | ||
| 43 | if (!varied[i]) { | ||
| 44 | test_failf(__FILE__, __LINE__, "byte %zu never changed over %d draws", i, DRAWS); | ||
| 45 | return; | ||
| 46 | } | ||
| 47 | ++test_checks; | ||
| 48 | } | ||
| 49 | |||
| 50 | static void case_respects_length(void) { | ||
| 51 | unsigned char buf[32]; | ||
| 52 | size_t i; | ||
| 53 | |||
| 54 | test_case("nothing is written past the requested length"); | ||
| 55 | memset(buf, 0xA5, sizeof(buf)); | ||
| 56 | random_bytes(buf, 8); | ||
| 57 | for (i = 8; i < sizeof(buf); ++i) | ||
| 58 | if (buf[i] != 0xA5) { | ||
| 59 | test_failf(__FILE__, __LINE__, "byte %zu past the end was overwritten", i); | ||
| 60 | return; | ||
| 61 | } | ||
| 62 | ++test_checks; | ||
| 63 | } | ||
| 64 | |||
| 65 | static void case_zero_length(void) { | ||
| 66 | unsigned char buf[4]; | ||
| 67 | |||
| 68 | test_case("a zero length request writes nothing"); | ||
| 69 | memset(buf, 0x5A, sizeof(buf)); | ||
| 70 | random_bytes(buf, 0); | ||
| 71 | CHECK_MEM(buf, "\x5a\x5a\x5a\x5a", 4); | ||
| 72 | } | ||
| 73 | |||
| 74 | static void case_successive_draws_differ(void) { | ||
| 75 | unsigned char a[32], b[32]; | ||
| 76 | |||
| 77 | test_case("two draws differ"); | ||
| 78 | random_bytes(a, sizeof(a)); | ||
| 79 | random_bytes(b, sizeof(b)); | ||
| 80 | CHECK(memcmp(a, b, sizeof(a)) != 0); | ||
| 81 | } | ||
| 82 | |||
| 83 | static void case_uint32_varies(void) { | ||
| 84 | uint32_t first = random_uint32(); | ||
| 85 | int differs = 0; | ||
| 86 | size_t n; | ||
| 87 | |||
| 88 | test_case("random_uint32 does not return a constant"); | ||
| 89 | for (n = 0; n < DRAWS; ++n) | ||
| 90 | if (random_uint32() != first) | ||
| 91 | differs = 1; | ||
| 92 | CHECK(differs); | ||
| 93 | } | ||
| 94 | |||
| 95 | static void case_uint32_uses_the_top_bit(void) { | ||
| 96 | uint32_t seen = 0; | ||
| 97 | size_t n; | ||
| 98 | |||
| 99 | test_case("random_uint32 spans the full 32 bits"); | ||
| 100 | /* random() never sets bit 31, so a build that returned it unmixed would | ||
| 101 | fail this. Over 64 draws the chance of a false alarm is 2^-64. */ | ||
| 102 | for (n = 0; n < 64; ++n) | ||
| 103 | seen |= random_uint32(); | ||
| 104 | CHECK_INT(seen & 0x80000000u, 0x80000000u); | ||
| 105 | } | ||
| 106 | |||
| 107 | void test_random(void) { | ||
| 108 | case_every_byte_varies(); | ||
| 109 | case_respects_length(); | ||
| 110 | case_zero_length(); | ||
| 111 | case_successive_draws_differ(); | ||
| 112 | case_uint32_varies(); | ||
| 113 | case_uint32_uses_the_top_bit(); | ||
| 114 | } | ||
