diff --git a/UnitTest1/unittest1.cpp b/UnitTest1/unittest1.cpp index 2a8cec84c8ccf54b43e49a8c58085ecd8a9f972c..3bc25927f1811df56f362b51f27b2250ab235918 100644 --- a/UnitTest1/unittest1.cpp +++ b/UnitTest1/unittest1.cpp @@ -37,6 +37,13 @@ namespace UnitTest1 Assert::AreEqual(ret, 0); } + TEST_METHOD(random_tester) + { + int ret = random_tester_test(); + + Assert::AreEqual(ret, 0); + } + TEST_METHOD(splay) { int ret = splay_test(); diff --git a/picoquic/sender.c b/picoquic/sender.c index 7c8e26a1da47c112a4eeb77fe0a08fa8f0d714d9..7eae161637d7613d1804c01598475c99ad1603a8 100644 --- a/picoquic/sender.c +++ b/picoquic/sender.c @@ -1344,7 +1344,7 @@ int picoquic_prepare_packet_0rtt(picoquic_cnx_t* cnx, picoquic_path_t * path_x, picoquic_finalize_and_protect_packet(cnx, packet, ret, length, header_length, checksum_overhead, - send_length, send_buffer, send_buffer_max, path_x, current_time); + send_length, send_buffer, (uint32_t)send_buffer_max, path_x, current_time); if (length > 0) { /* Accounting of zero rtt packets sent */ @@ -1640,7 +1640,7 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p } else { picoquic_finalize_and_protect_packet(cnx, packet, ret, length, header_length, checksum_overhead, - send_length, send_buffer, send_buffer_max, path_x, current_time); + send_length, send_buffer, (uint32_t)send_buffer_max, path_x, current_time); if (cnx->cnx_state != picoquic_state_draining) { picoquic_cnx_set_next_wake_time(cnx, current_time); @@ -1797,7 +1797,7 @@ int picoquic_prepare_packet_server_init(picoquic_cnx_t* cnx, picoquic_path_t * p picoquic_finalize_and_protect_packet(cnx, packet, ret, length, header_length, checksum_overhead, - send_length, send_buffer, send_buffer_max, path_x, current_time); + send_length, send_buffer, (uint32_t)send_buffer_max, path_x, current_time); picoquic_cnx_set_next_wake_time(cnx, current_time); @@ -2009,7 +2009,7 @@ int picoquic_prepare_packet_closing(picoquic_cnx_t* cnx, picoquic_path_t * path_ picoquic_finalize_and_protect_packet(cnx, packet, ret, length, header_length, checksum_overhead, - send_length, send_buffer, send_buffer_max, path_x, current_time); + send_length, send_buffer, (uint32_t)send_buffer_max, path_x, current_time); return ret; } diff --git a/picoquic_t/picoquic_t.c b/picoquic_t/picoquic_t.c index 3e7499ed123e6c17d7ba04a46f9f4b218c4e82ea..86133946a4343ea826270b393a73c10dbc956129 100644 --- a/picoquic_t/picoquic_t.c +++ b/picoquic_t/picoquic_t.c @@ -126,6 +126,7 @@ static const picoquic_test_def_t test_table[] = { { "pn_vector", cleartext_pn_vector_test }, { "zero_rtt_spurious", zero_rtt_spurious_test }, { "zero_rtt_retry", zero_rtt_retry_test }, + { "random_tester", random_tester_test}, { "stress", stress_test }, { "fuzz", fuzz_test } }; diff --git a/picoquictest/picoquictest.h b/picoquictest/picoquictest.h index b2b6008fabf7ee434df6c1b2bdb2098bc206c560..4e5774fa4595442847bd8182b52126c2ed22ae0c 100644 --- a/picoquictest/picoquictest.h +++ b/picoquictest/picoquictest.h @@ -120,6 +120,7 @@ int splay_test(); int TlsStreamFrameTest(); int draft13_vector_test(); int fuzz_test(); +int random_tester_test(); #ifdef __cplusplus } diff --git a/picoquictest/skip_frame_test.c b/picoquictest/skip_frame_test.c index 9181e8994e3e176c396da71ee40e7c71d125ad54..fa8f72ff3593a8e77dbfb2d60f9c15e06aa1959f 100644 --- a/picoquictest/skip_frame_test.c +++ b/picoquictest/skip_frame_test.c @@ -223,7 +223,7 @@ uint64_t picoquic_test_uniform_random(uint64_t * random_context, uint64_t rnd_ma uint64_t rnd_min = ((uint64_t)((int64_t)-1)) % rnd_max; do { - rnd = picoquic_public_random_64(); + rnd = picoquic_test_random(random_context); } while (rnd < rnd_min); return rnd % rnd_max; diff --git a/picoquictest/stresstest.c b/picoquictest/stresstest.c index edc46331b8b06aef4d50e5315023e88601c5b98d..9924de33c76b61acf32af9b349c9a555931ed5ee 100644 --- a/picoquictest/stresstest.c +++ b/picoquictest/stresstest.c @@ -1018,9 +1018,9 @@ static uint32_t basic_fuzzer(void * fuzz_ctx, picoquic_cnx_t* cnx, if (should_fuzz) { /* Once in 16, fuzz by changing the length */ if ((fuzz_pilot & 0xF) == 0xD) { - uint32_t fuzz_length_max = length + 16; + uint32_t fuzz_length_max = (uint32_t)(length + 16); if (fuzz_length_max > bytes_max) { - fuzz_length_max = bytes_max; + fuzz_length_max = (uint32_t)bytes_max; } fuzz_pilot >>= 4; length = 16 + (uint32_t)((fuzz_pilot&0xFFFF) % length); @@ -1041,7 +1041,7 @@ static uint32_t basic_fuzzer(void * fuzz_ctx, picoquic_cnx_t* cnx, } } - return length; + return (uint32_t)length; } int fuzz_test() @@ -1063,5 +1063,116 @@ int fuzz_test() DBG_PRINTF("Fuzzed %d packets out of %d, changed %d lengths, ret = %d\n", fuzz_ctx.nb_fuzzed, fuzz_ctx.nb_packets, fuzz_ctx.nb_fuzzed_length, ret); + return ret; +} + +/* +* Test that the random generation works the same on every platform. This is meant to +* give us assurance that the stress and fuzz tests behave identically on all platforms. +* +* A test sequence is defined by: +* - A test seed value; +* - The result to three successive calls to "picoquic_test_random" +* - The result of 4 tests to "picoquic_test_uniform_random" with ranges 31, 32, 100, 1000. +* We run several such sequences, and check that the results match expectation +*/ + +typedef struct st_test_random_tester_t { + uint64_t seed; + uint64_t trials[3]; + int uniform[4]; +} test_random_tester_t; + +static int uniform_test[4] = { 31, 32, 100, 1000 }; + +static test_random_tester_t random_cases[] = { +#if 1 + { 0xdeadbeefbabac001ull, + { 0x5e15223d01b20defull, 0x9ede0d895c9bd2a6ull, 0xe3a0ed91f612c17full }, + { 0, 0, 70, 197 } }, + { 0x56df77dd5d6000efull, + { 0xdfccc8d428187e18ull, 0x7d7552fd225a16d7ull, 0x32dabe642e7390cull }, + { 30, 5, 34, 751 } }, + { 0x6fbbeeaeb00077abull, + { 0x43131e190d5c97full, 0x42fb1ccc58b906dull, 0x610a3b5abef97be4ull }, + { 26, 16, 12, 939 } }, + { 0xddf75758003bd5b7ull, + { 0x3a8d9a1a727aba2dull, 0xe9279c9bb67c725cull, 0x1acf0953978b79e8ull }, + { 3, 11, 41, 82 } }, + { 0xfbabac001deadbeeull, + { 0x5112b0a7de31f1b7ull, 0xd691b591d3598619ull, 0xf1b42dc66cf4f215ull }, + { 17, 10, 44, 527 } }, + { 0xd5d6000ef56df77dull, + { 0xb699f9cadcb2a474ull, 0xc2213dfa4ec1c973ull, 0x843f0e6573dda32eull }, + { 9, 30, 52, 680 } }, + { 0xeb00077ab6fbbeeaull, + { 0x6dd0c0b399bae357ull, 0xa5a6b1ec22fa894bull, 0x85f25e84ba0843a0ull }, + { 16, 5, 5, 899 } }, + { 0x8003bd5b7ddf7575ull, + { 0xf7745169aa75f266ull, 0x551964d08e2c25e0ull, 0x17b86c9be72f96bbull }, + { 4, 24, 48, 21 } }, + { 0x1deadbeefbabac0ull, + { 0xc51696cc9c124ff9ull, 0x1b9d1372c2f72058ull, 0xe539681abb702c48ull }, + { 20, 21, 96, 865 } }, + { 0xef56df77dd5d6000ull, + { 0xf40b816f8efc0ec8ull, 0xd8a949c49d03c01cull, 0x170902fde977c269ull }, + { 2, 30, 55, 720 } } +#else + /* Dummy value used when computing the table */ + { 0, { 0, 0, 0}, { 0, 0, 0, 0}} +#endif +}; + +static size_t nb_random_cases = sizeof(random_cases) / sizeof(test_random_tester_t); + +int random_tester_test() +{ + /* This is the initial run, so we merely write the expected value */ + uint64_t t_seed = 0xDEADBEEFBABAC001ull; + int ret = 0; + + if (nb_random_cases < 2) { + /* This code was used to generate the table of random cases */ + for (int i = 0; i < 10; i++) + { + /* Rotate the seed */ + uint64_t ctx = t_seed; + /* Generate the values */ + printf("{ 0x%llxull, \n{ ", t_seed); + for (int j = 0; j < 3; j++) { + printf("0x%llxull%s", picoquic_test_random(&ctx), (j < 2) ? ", " : "},\n{ "); + } + for (int j = 0; j < 4; j++) { + printf("%d%s", (int)picoquic_test_uniform_random(&ctx, uniform_test[j]), + (j < 3) ? ", " : "}},\n"); + } + t_seed = (t_seed << 7) | (t_seed >> 57); + } + } + else { + for (int i = 0; ret == 0 && i < (int)nb_random_cases; i++) + { + uint64_t ctx = random_cases[i].seed; + for (int j = 0; ret == 0 && j < 3; j++) { + uint64_t r = picoquic_test_random(&ctx); + if (r != random_cases[i].trials[j]) { + DBG_PRINTF("Case %d, seed %llx, trial[%d] = %llx, expected %llx\n", + i, (unsigned long long)random_cases[i].seed, j, + (unsigned long long)r, (unsigned long long)random_cases[i].trials[j]); + ret = -1; + } + } + for (int j = 0; ret == 0 && j < 4; j++) { + int r = (int)picoquic_test_uniform_random(&ctx, uniform_test[j]); + if (r != random_cases[i].uniform[j]) { + DBG_PRINTF("Case %d, seed %llx, uniform(%d) = %d, expected %d\n", + i, (unsigned long long)random_cases[i].seed, uniform_test[j], + (unsigned long long)r, (unsigned long long)random_cases[i].uniform[j]); + ret = -1; + } + } + } + } + return ret; } \ No newline at end of file