From a09929c26535abc512883979189d16d25b5a3f7f Mon Sep 17 00:00:00 2001 From: Dominik Loidolt <dominik.loidolt@univie.ac.at> Date: Tue, 20 Aug 2024 11:32:05 +0200 Subject: [PATCH] Refactor: chunk_round_trip() test --- lib/common/cmp_max_used_bits.h | 1 + test/cmp_decmp/test_cmp_decmp.c | 634 +++++++++++++++------------- test/fuzz/fuzz_compression.c | 7 +- test/fuzz/fuzz_data_producer.c | 3 +- test/fuzz/fuzz_helpers.c | 49 --- test/fuzz/fuzz_helpers.h | 36 -- test/fuzz/fuzz_round_trip.c | 102 +---- test/fuzz/meson.build | 4 +- test/meson.build | 5 +- test/test_common/chunk_round_trip.c | 133 ++++++ test/test_common/chunk_round_trip.h | 34 ++ test/test_common/meson.build | 1 + test/test_common/test_common.c | 14 +- test/test_common/test_common.h | 2 +- 14 files changed, 541 insertions(+), 484 deletions(-) delete mode 100644 test/fuzz/fuzz_helpers.c create mode 100644 test/test_common/chunk_round_trip.c create mode 100644 test/test_common/chunk_round_trip.h diff --git a/lib/common/cmp_max_used_bits.h b/lib/common/cmp_max_used_bits.h index 21e7dd4..c13a6d6 100644 --- a/lib/common/cmp_max_used_bits.h +++ b/lib/common/cmp_max_used_bits.h @@ -29,6 +29,7 @@ /* predefined maximum used bits registry constants */ extern const struct cmp_max_used_bits MAX_USED_BITS_SAFE; extern const struct cmp_max_used_bits MAX_USED_BITS_V1; +#define MAX_USED_BITS MAX_USED_BITS_SAFE /** diff --git a/test/cmp_decmp/test_cmp_decmp.c b/test/cmp_decmp/test_cmp_decmp.c index be5da6e..915a8cf 100644 --- a/test/cmp_decmp/test_cmp_decmp.c +++ b/test/cmp_decmp/test_cmp_decmp.c @@ -26,6 +26,7 @@ #include <unity.h> #include "../test_common/test_common.h" +#include "../test_common/chunk_round_trip.h" #include <cmp_icu.h> #include <cmp_chunk.h> @@ -58,7 +59,6 @@ void setUp(void) #ifdef HAS_TIME_H seed = (uint64_t)(time(NULL) ^ getpid() ^ (intptr_t)&setUp); - seed = 0; #else seed = 1; #endif @@ -73,8 +73,71 @@ void setUp(void) } +/** + * @brief generate a geometric distribution (bernoulli trial with probability p) + * + * prob(k) = p (1 - p)^k for k = 0, 1, 2, 3, ... + * + * @param p probability of geometric distribution (0 < p <= 1) + * + * @returns random number following a geometric distribution + */ + +static uint32_t cmp_rand_geometric(double p) +{ + double u = ldexp(cmp_rand32(), -32); /*see: https://www.pcg-random.org/using-pcg-c-basic.html */ + + if (p >= 1.0) + return 0; + + return (uint32_t)(log(u) / log(1 - p)); +} + + +/** + * @brief generate geometric distribution data with a specified number of bits + * + * @param n_bits number of bits for the output (1 <= n_bits <= 32) + * @param extra pointer to a double containing the probability of + * geometric distribution (0 < p <= 1) + * + * @returns random number following a geometric distribution, masked with n_bits + */ + +static uint32_t gen_geometric_data(uint32_t n_bits, void *extra) +{ + double *p = (double *)extra; + uint32_t mask; + + TEST_ASSERT(n_bits > 0); + TEST_ASSERT(n_bits <= 32); + TEST_ASSERT_NOT_NULL(p); + TEST_ASSERT(*p > 0); + TEST_ASSERT(*p <= 1.0); + + mask = ~0U >> (32 - n_bits); + return cmp_rand_geometric(*p) & mask; +} + + +/** + * @brief Generate uniform distribution data with a specified number of bits + * + * @param n_bits number of bits for the output (1 <= n_bits <= 32) + * @param unused unused parameter + * + * @returns random number following a uniform distribution, masked with n_bits + */ + +static uint32_t gen_uniform_data(uint32_t n_bits, void* unused UNUSED) +{ + return cmp_rand_nbits(n_bits); +} + + static size_t gen_ima_data(uint16_t *data, enum cmp_data_type data_type, - uint32_t samples, const struct cmp_max_used_bits *max_used_bits) + uint32_t samples, uint32_t (*gen_data_f)(uint32_t, void*), + void *extra) { uint32_t i; @@ -84,35 +147,35 @@ static size_t gen_ima_data(uint16_t *data, enum cmp_data_type data_type, switch (data_type) { case DATA_TYPE_IMAGETTE: case DATA_TYPE_IMAGETTE_ADAPTIVE: - max_data_bits = max_used_bits->nc_imagette; + max_data_bits = MAX_USED_BITS.nc_imagette; break; case DATA_TYPE_SAT_IMAGETTE: case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: - max_data_bits = max_used_bits->saturated_imagette; + max_data_bits = MAX_USED_BITS.saturated_imagette; break; case DATA_TYPE_F_CAM_IMAGETTE: case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - max_data_bits = max_used_bits->fc_imagette; + max_data_bits = MAX_USED_BITS.fc_imagette; break; default: TEST_FAIL(); } for (i = 0; i < samples; i++) - data[i] = (uint16_t)cmp_rand_nbits(max_data_bits); + data[i] = (uint16_t)gen_data_f(max_data_bits, extra); } return sizeof(*data) * samples; } static size_t gen_nc_offset_data(struct offset *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].mean = cmp_rand_nbits(max_used_bits->nc_offset_mean); - data[i].variance = cmp_rand_nbits(max_used_bits->nc_offset_variance); + data[i].mean = gen_data_f(MAX_USED_BITS.nc_offset_mean, extra); + data[i].variance = gen_data_f(MAX_USED_BITS.nc_offset_variance, extra); } } return sizeof(*data) * samples; @@ -120,14 +183,14 @@ static size_t gen_nc_offset_data(struct offset *data, uint32_t samples, static size_t gen_fc_offset_data(struct offset *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].mean = cmp_rand_nbits(max_used_bits->fc_offset_mean); - data[i].variance = cmp_rand_nbits(max_used_bits->fc_offset_variance); + data[i].mean = gen_data_f(MAX_USED_BITS.fc_offset_mean, extra); + data[i].variance = gen_data_f(MAX_USED_BITS.fc_offset_variance, extra); } } return sizeof(*data) * samples; @@ -135,15 +198,16 @@ static size_t gen_fc_offset_data(struct offset *data, uint32_t samples, static size_t gen_nc_background_data(struct background *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].mean = cmp_rand_nbits(max_used_bits->nc_background_mean); - data[i].variance = cmp_rand_nbits(max_used_bits->nc_background_variance); - data[i].outlier_pixels = (__typeof__(data[i].outlier_pixels))cmp_rand_nbits(max_used_bits->nc_background_outlier_pixels); + data[i].mean = gen_data_f(MAX_USED_BITS.nc_background_mean, extra); + data[i].variance = gen_data_f(MAX_USED_BITS.nc_background_variance, extra); + data[i].outlier_pixels = + (__typeof__(data[i].outlier_pixels))gen_data_f(MAX_USED_BITS.nc_background_outlier_pixels, extra); } } return sizeof(*data) * samples; @@ -151,15 +215,16 @@ static size_t gen_nc_background_data(struct background *data, uint32_t samples, static size_t gen_fc_background_data(struct background *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].mean = cmp_rand_nbits(max_used_bits->fc_background_mean); - data[i].variance = cmp_rand_nbits(max_used_bits->fc_background_variance); - data[i].outlier_pixels = (__typeof__(data[i].outlier_pixels))cmp_rand_nbits(max_used_bits->fc_background_outlier_pixels); + data[i].mean = gen_data_f(MAX_USED_BITS.fc_background_mean, extra); + data[i].variance = gen_data_f(MAX_USED_BITS.fc_background_variance, extra); + data[i].outlier_pixels = + (__typeof__(data[i].outlier_pixels))gen_data_f(MAX_USED_BITS.fc_background_outlier_pixels, extra); } } return sizeof(*data) * samples; @@ -167,15 +232,17 @@ static size_t gen_fc_background_data(struct background *data, uint32_t samples, static size_t gen_smearing_data(struct smearing *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].mean = cmp_rand_nbits(max_used_bits->smearing_mean); - data[i].variance_mean = (__typeof__(data[i].variance_mean))cmp_rand_nbits(max_used_bits->smearing_variance_mean); - data[i].outlier_pixels = (__typeof__(data[i].outlier_pixels))cmp_rand_nbits(max_used_bits->smearing_outlier_pixels); + data[i].mean = gen_data_f(MAX_USED_BITS.smearing_mean, extra); + data[i].variance_mean = + (__typeof__(data[i].variance_mean))gen_data_f(MAX_USED_BITS.smearing_variance_mean, extra); + data[i].outlier_pixels = + (__typeof__(data[i].outlier_pixels))gen_data_f(MAX_USED_BITS.smearing_outlier_pixels, extra); } } return sizeof(*data) * samples; @@ -183,14 +250,15 @@ static size_t gen_smearing_data(struct smearing *data, uint32_t samples, static size_t gen_s_fx_data(struct s_fx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].exp_flags = (__typeof__(data[i].exp_flags))cmp_rand_nbits(max_used_bits->s_exp_flags); - data[i].fx = cmp_rand_nbits(max_used_bits->s_fx); + data[i].exp_flags = + (__typeof__(data[i].exp_flags))gen_data_f(MAX_USED_BITS.s_exp_flags, extra); + data[i].fx = gen_data_f(MAX_USED_BITS.s_fx, extra); } } return sizeof(*data) * samples; @@ -198,15 +266,16 @@ static size_t gen_s_fx_data(struct s_fx *data, uint32_t samples, static size_t gen_s_fx_efx_data(struct s_fx_efx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].exp_flags = (__typeof__(data[i].exp_flags))cmp_rand_nbits(max_used_bits->s_exp_flags); - data[i].fx = cmp_rand_nbits(max_used_bits->s_fx); - data[i].efx = cmp_rand_nbits(max_used_bits->s_efx); + data[i].exp_flags = + (__typeof__(data[i].exp_flags))gen_data_f(MAX_USED_BITS.s_exp_flags, extra); + data[i].fx = gen_data_f(MAX_USED_BITS.s_fx, extra); + data[i].efx = gen_data_f(MAX_USED_BITS.s_efx, extra); } } return sizeof(*data) * samples; @@ -214,16 +283,17 @@ static size_t gen_s_fx_efx_data(struct s_fx_efx *data, uint32_t samples, static size_t gen_s_fx_ncob_data(struct s_fx_ncob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].exp_flags = (__typeof__(data[i].exp_flags))cmp_rand_nbits(max_used_bits->s_exp_flags); - data[i].fx = cmp_rand_nbits(max_used_bits->s_fx); - data[i].ncob_x = cmp_rand_nbits(max_used_bits->s_ncob); - data[i].ncob_y = cmp_rand_nbits(max_used_bits->s_ncob); + data[i].exp_flags = + (__typeof__(data[i].exp_flags))gen_data_f(MAX_USED_BITS.s_exp_flags, extra); + data[i].fx = gen_data_f(MAX_USED_BITS.s_fx, extra); + data[i].ncob_x = gen_data_f(MAX_USED_BITS.s_ncob, extra); + data[i].ncob_y = gen_data_f(MAX_USED_BITS.s_ncob, extra); } } return sizeof(*data) * samples; @@ -231,19 +301,20 @@ static size_t gen_s_fx_ncob_data(struct s_fx_ncob *data, uint32_t samples, static size_t gen_s_fx_efx_ncob_ecob_data(struct s_fx_efx_ncob_ecob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].exp_flags = (__typeof__(data[i].exp_flags))cmp_rand_nbits(max_used_bits->s_exp_flags); - data[i].fx = cmp_rand_nbits(max_used_bits->s_fx); - data[i].ncob_x = cmp_rand_nbits(max_used_bits->s_ncob); - data[i].ncob_y = cmp_rand_nbits(max_used_bits->s_ncob); - data[i].efx = cmp_rand_nbits(max_used_bits->s_efx); - data[i].ecob_x = cmp_rand_nbits(max_used_bits->s_ecob); - data[i].ecob_y = cmp_rand_nbits(max_used_bits->s_ecob); + data[i].exp_flags = + (__typeof__(data[i].exp_flags))gen_data_f(MAX_USED_BITS.s_exp_flags, extra); + data[i].fx = gen_data_f(MAX_USED_BITS.s_fx, extra); + data[i].ncob_x = gen_data_f(MAX_USED_BITS.s_ncob, extra); + data[i].ncob_y = gen_data_f(MAX_USED_BITS.s_ncob, extra); + data[i].efx = gen_data_f(MAX_USED_BITS.s_efx, extra); + data[i].ecob_x = gen_data_f(MAX_USED_BITS.s_ecob, extra); + data[i].ecob_y = gen_data_f(MAX_USED_BITS.s_ecob, extra); } } return sizeof(*data) * samples; @@ -251,26 +322,26 @@ static size_t gen_s_fx_efx_ncob_ecob_data(struct s_fx_efx_ncob_ecob *data, uint3 static size_t gen_f_fx_data(struct f_fx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) for (i = 0; i < samples; i++) - data[i].fx = cmp_rand_nbits(max_used_bits->f_fx); + data[i].fx = gen_data_f(MAX_USED_BITS.f_fx, extra); return sizeof(*data) * samples; } static size_t gen_f_fx_efx_data(struct f_fx_efx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].fx = cmp_rand_nbits(max_used_bits->f_fx); - data[i].efx = cmp_rand_nbits(max_used_bits->f_efx); + data[i].fx = gen_data_f(MAX_USED_BITS.f_fx, extra); + data[i].efx = gen_data_f(MAX_USED_BITS.f_efx, extra); } } return sizeof(*data) * samples; @@ -278,15 +349,15 @@ static size_t gen_f_fx_efx_data(struct f_fx_efx *data, uint32_t samples, static size_t gen_f_fx_ncob_data(struct f_fx_ncob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].fx = cmp_rand_nbits(max_used_bits->f_fx); - data[i].ncob_x = cmp_rand_nbits(max_used_bits->f_ncob); - data[i].ncob_y = cmp_rand_nbits(max_used_bits->f_ncob); + data[i].fx = gen_data_f(MAX_USED_BITS.f_fx, extra); + data[i].ncob_x = gen_data_f(MAX_USED_BITS.f_ncob, extra); + data[i].ncob_y = gen_data_f(MAX_USED_BITS.f_ncob, extra); } } return sizeof(*data) * samples; @@ -294,18 +365,18 @@ static size_t gen_f_fx_ncob_data(struct f_fx_ncob *data, uint32_t samples, static size_t gen_f_fx_efx_ncob_ecob_data(struct f_fx_efx_ncob_ecob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].fx = cmp_rand_nbits(max_used_bits->f_fx); - data[i].ncob_x = cmp_rand_nbits(max_used_bits->f_ncob); - data[i].ncob_y = cmp_rand_nbits(max_used_bits->f_ncob); - data[i].efx = cmp_rand_nbits(max_used_bits->f_efx); - data[i].ecob_x = cmp_rand_nbits(max_used_bits->f_ecob); - data[i].ecob_y = cmp_rand_nbits(max_used_bits->f_ecob); + data[i].fx = gen_data_f(MAX_USED_BITS.f_fx, extra); + data[i].ncob_x = gen_data_f(MAX_USED_BITS.f_ncob, extra); + data[i].ncob_y = gen_data_f(MAX_USED_BITS.f_ncob, extra); + data[i].efx = gen_data_f(MAX_USED_BITS.f_efx, extra); + data[i].ecob_x = gen_data_f(MAX_USED_BITS.f_ecob, extra); + data[i].ecob_y = gen_data_f(MAX_USED_BITS.f_ecob, extra); } } return sizeof(*data) * samples; @@ -313,15 +384,15 @@ static size_t gen_f_fx_efx_ncob_ecob_data(struct f_fx_efx_ncob_ecob *data, uint3 static size_t gen_l_fx_data(struct l_fx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].exp_flags = cmp_rand_nbits(max_used_bits->l_exp_flags); - data[i].fx = cmp_rand_nbits(max_used_bits->l_fx); - data[i].fx_variance = cmp_rand_nbits(max_used_bits->l_fx_variance); + data[i].exp_flags = gen_data_f(MAX_USED_BITS.l_exp_flags, extra); + data[i].fx = gen_data_f(MAX_USED_BITS.l_fx, extra); + data[i].fx_variance = gen_data_f(MAX_USED_BITS.l_fx_variance, extra); } } return sizeof(*data) * samples; @@ -329,16 +400,16 @@ static size_t gen_l_fx_data(struct l_fx *data, uint32_t samples, static size_t gen_l_fx_efx_data(struct l_fx_efx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { uint32_t i; if (data) { for (i = 0; i < samples; i++) { - data[i].exp_flags = cmp_rand_nbits(max_used_bits->l_exp_flags); - data[i].fx = cmp_rand_nbits(max_used_bits->l_fx); - data[i].efx = cmp_rand_nbits(max_used_bits->l_efx); - data[i].fx_variance = cmp_rand_nbits(max_used_bits->l_fx_variance); + data[i].exp_flags = gen_data_f(MAX_USED_BITS.l_exp_flags, extra); + data[i].fx = gen_data_f(MAX_USED_BITS.l_fx, extra); + data[i].efx = gen_data_f(MAX_USED_BITS.l_efx, extra); + data[i].fx_variance = gen_data_f(MAX_USED_BITS.l_fx_variance, extra); } } return sizeof(*data) * samples; @@ -346,19 +417,19 @@ static size_t gen_l_fx_efx_data(struct l_fx_efx *data, uint32_t samples, static size_t gen_l_fx_ncob_data(struct l_fx_ncob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { if (data) { uint32_t i; for (i = 0; i < samples; i++) { - data[i].exp_flags = cmp_rand_nbits(max_used_bits->l_exp_flags); - data[i].fx = cmp_rand_nbits(max_used_bits->l_fx); - data[i].ncob_x = cmp_rand_nbits(max_used_bits->l_ncob); - data[i].ncob_y = cmp_rand_nbits(max_used_bits->l_ncob); - data[i].fx_variance = cmp_rand_nbits(max_used_bits->l_fx_variance); - data[i].cob_x_variance = cmp_rand_nbits(max_used_bits->l_cob_variance); - data[i].cob_y_variance = cmp_rand_nbits(max_used_bits->l_cob_variance); + data[i].exp_flags = gen_data_f(MAX_USED_BITS.l_exp_flags, extra); + data[i].fx = gen_data_f(MAX_USED_BITS.l_fx, extra); + data[i].ncob_x = gen_data_f(MAX_USED_BITS.l_ncob, extra); + data[i].ncob_y = gen_data_f(MAX_USED_BITS.l_ncob, extra); + data[i].fx_variance = gen_data_f(MAX_USED_BITS.l_fx_variance, extra); + data[i].cob_x_variance = gen_data_f(MAX_USED_BITS.l_cob_variance, extra); + data[i].cob_y_variance = gen_data_f(MAX_USED_BITS.l_cob_variance, extra); } } return sizeof(*data) * samples; @@ -366,22 +437,22 @@ static size_t gen_l_fx_ncob_data(struct l_fx_ncob *data, uint32_t samples, static size_t gen_l_fx_efx_ncob_ecob_data(struct l_fx_efx_ncob_ecob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { if (data) { uint32_t i; for (i = 0; i < samples; i++) { - data[i].exp_flags = cmp_rand_nbits(max_used_bits->l_exp_flags); - data[i].fx = cmp_rand_nbits(max_used_bits->l_fx); - data[i].ncob_x = cmp_rand_nbits(max_used_bits->l_ncob); - data[i].ncob_y = cmp_rand_nbits(max_used_bits->l_ncob); - data[i].efx = cmp_rand_nbits(max_used_bits->l_efx); - data[i].ecob_x = cmp_rand_nbits(max_used_bits->l_ecob); - data[i].ecob_y = cmp_rand_nbits(max_used_bits->l_ecob); - data[i].fx_variance = cmp_rand_nbits(max_used_bits->l_fx_variance); - data[i].cob_x_variance = cmp_rand_nbits(max_used_bits->l_cob_variance); - data[i].cob_y_variance = cmp_rand_nbits(max_used_bits->l_cob_variance); + data[i].exp_flags = gen_data_f(MAX_USED_BITS.l_exp_flags, extra); + data[i].fx = gen_data_f(MAX_USED_BITS.l_fx, extra); + data[i].ncob_x = gen_data_f(MAX_USED_BITS.l_ncob, extra); + data[i].ncob_y = gen_data_f(MAX_USED_BITS.l_ncob, extra); + data[i].efx = gen_data_f(MAX_USED_BITS.l_efx, extra); + data[i].ecob_x = gen_data_f(MAX_USED_BITS.l_ecob, extra); + data[i].ecob_y = gen_data_f(MAX_USED_BITS.l_ecob, extra); + data[i].fx_variance = gen_data_f(MAX_USED_BITS.l_fx_variance, extra); + data[i].cob_x_variance = gen_data_f(MAX_USED_BITS.l_cob_variance, extra); + data[i].cob_y_variance = gen_data_f(MAX_USED_BITS.l_cob_variance, extra); } } return sizeof(*data) * samples; @@ -423,14 +494,16 @@ uint32_t generate_random_collection_hdr(struct collection_hdr *col, enum cmp_dat * random collection * @param data_type specifies the compression data type of the test data * @param samples the number of random test data samples to generate - * @param max_used_bits pointer to a structure that tracks the maximum number of - * bits used + * @param gen_data_f function pointer to a data generation function + * @param extra pointer to additional data required by the data + * generation function * * @return the size of the generated random collection in bytes */ size_t generate_random_collection(struct collection_hdr *col, enum cmp_data_type data_type, - uint32_t samples, const struct cmp_max_used_bits *max_used_bits) + uint32_t samples, uint32_t (*gen_data_f)(uint32_t, void *), + void *extra) { size_t size; void *science_data = NULL; @@ -439,16 +512,6 @@ size_t generate_random_collection(struct collection_hdr *col, enum cmp_data_type science_data = col->entry; size = generate_random_collection_hdr(col, data_type, samples); -#if 0 - { int i; - - for (i = 0; i < size_of_a_sample(data_type)*samples; i++) { - if (col) - col->entry[i] = i; - } - return size+i; - } -#endif switch (data_type) { case DATA_TYPE_IMAGETTE: @@ -457,58 +520,64 @@ size_t generate_random_collection(struct collection_hdr *col, enum cmp_data_type case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: case DATA_TYPE_F_CAM_IMAGETTE: case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - size += gen_ima_data(science_data, data_type, samples, max_used_bits); + size += gen_ima_data(science_data, data_type, samples, + gen_data_f, extra); break; case DATA_TYPE_OFFSET: - size += gen_nc_offset_data(science_data, samples, max_used_bits); + size += gen_nc_offset_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_BACKGROUND: - size += gen_nc_background_data(science_data, samples, max_used_bits); + size += gen_nc_background_data(science_data, samples, + gen_data_f, extra); break; case DATA_TYPE_SMEARING: - size += gen_smearing_data(science_data, samples, max_used_bits); + size += gen_smearing_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_S_FX: - size += gen_s_fx_data(science_data, samples, max_used_bits); + size += gen_s_fx_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_S_FX_EFX: - size += gen_s_fx_efx_data(science_data, samples, max_used_bits); + size += gen_s_fx_efx_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_S_FX_NCOB: - size += gen_s_fx_ncob_data(science_data, samples, max_used_bits); + size += gen_s_fx_ncob_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_S_FX_EFX_NCOB_ECOB: - size += gen_s_fx_efx_ncob_ecob_data(science_data, samples, max_used_bits); + size += gen_s_fx_efx_ncob_ecob_data(science_data, samples, + gen_data_f, extra); break; case DATA_TYPE_L_FX: - size += gen_l_fx_data(science_data, samples, max_used_bits); + size += gen_l_fx_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_L_FX_EFX: - size += gen_l_fx_efx_data(science_data, samples, max_used_bits); + size += gen_l_fx_efx_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_L_FX_NCOB: - size += gen_l_fx_ncob_data(science_data, samples, max_used_bits); + size += gen_l_fx_ncob_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_L_FX_EFX_NCOB_ECOB: - size += gen_l_fx_efx_ncob_ecob_data(science_data, samples, max_used_bits); + size += gen_l_fx_efx_ncob_ecob_data(science_data, samples, + gen_data_f, extra); break; case DATA_TYPE_F_FX: - size += gen_f_fx_data(science_data, samples, max_used_bits); + size += gen_f_fx_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_F_FX_EFX: - size += gen_f_fx_efx_data(science_data, samples, max_used_bits); + size += gen_f_fx_efx_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_F_FX_NCOB: - size += gen_f_fx_ncob_data(science_data, samples, max_used_bits); + size += gen_f_fx_ncob_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_F_FX_EFX_NCOB_ECOB: - size += gen_f_fx_efx_ncob_ecob_data(science_data, samples, max_used_bits); + size += gen_f_fx_efx_ncob_ecob_data(science_data, samples, + gen_data_f, extra); break; case DATA_TYPE_F_CAM_OFFSET: - size += gen_fc_offset_data(science_data, samples, max_used_bits); + size += gen_fc_offset_data(science_data, samples, gen_data_f, extra); break; case DATA_TYPE_F_CAM_BACKGROUND: - size += gen_fc_background_data(science_data, samples, max_used_bits); + size += gen_fc_background_data(science_data, samples, + gen_data_f, extra); break; default: TEST_FAIL(); @@ -534,14 +603,16 @@ struct chunk_def { * random chunk * @param col_array specifies which collections are contained in the chunk * @param array_elements number of elements in the col_array - * @param max_used_bits pointer to a structure that tracks the maximum number of - * bits used + * @param gen_data_f function pointer to a data generation function + * @param extra pointer to additional data required by the data + * generation function * * @return the size of the generated random chunk in bytes */ -static uint32_t generate_random_chunk(void *chunk, struct chunk_def col_array[], size_t array_elements, - const struct cmp_max_used_bits *max_used_bits) +static uint32_t generate_random_chunk(void *chunk, struct chunk_def col_array[], + size_t array_elements, + uint32_t (*gen_data_f)(uint32_t, void*), void *extra) { size_t i; uint32_t chunk_size = 0; @@ -552,7 +623,8 @@ static uint32_t generate_random_chunk(void *chunk, struct chunk_def col_array[], col = (struct collection_hdr *)((uint8_t *)chunk + chunk_size); chunk_size += generate_random_collection(col, col_array[i].data_type, - col_array[i].samples, max_used_bits); + col_array[i].samples, gen_data_f, + extra); } return chunk_size; } @@ -583,45 +655,47 @@ void generate_random_rdcu_cfg(struct rdcu_cfg *rcfg) void generate_random_cmp_par(struct cmp_par *par) { - if (par) { - par->cmp_mode = cmp_rand_between(0, MAX_RDCU_CMP_MODE); - par->model_value = cmp_rand_between(0, MAX_MODEL_VALUE); - par->lossy_par = cmp_rand_between(0, MAX_ICU_ROUND); - - par->nc_imagette = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - - par->s_exp_flags = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->s_fx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->s_ncob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->s_efx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->s_ecob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - - par->l_exp_flags = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->l_fx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->l_ncob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->l_efx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->l_ecob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->l_fx_cob_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - - par->saturated_imagette = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - - par->nc_offset_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->nc_offset_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->nc_background_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->nc_background_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->nc_background_outlier_pixels = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - - par->smearing_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->smearing_variance_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->smearing_outlier_pixels = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - - par->fc_imagette = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->fc_offset_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->fc_offset_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->fc_background_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->fc_background_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - par->fc_background_outlier_pixels = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - } + if (!par) + return; + + par->cmp_mode = cmp_rand_between(0, MAX_RDCU_CMP_MODE); + par->model_value = cmp_rand_between(0, MAX_MODEL_VALUE); + par->lossy_par = cmp_rand_between(0, MAX_ICU_ROUND); + + par->nc_imagette = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->s_exp_flags = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->s_fx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->s_ncob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->s_efx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->s_ecob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->l_exp_flags = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->l_fx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->l_ncob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->l_efx = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->l_ecob = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->l_fx_cob_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->saturated_imagette = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->nc_offset_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->nc_offset_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->nc_background_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->nc_background_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->nc_background_outlier_pixels = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->smearing_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->smearing_variance_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->smearing_outlier_pixels = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + + par->fc_imagette = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->fc_offset_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->fc_offset_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->fc_background_mean = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->fc_background_variance = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + par->fc_background_outlier_pixels = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + } @@ -726,7 +800,7 @@ void compression_decompression_like_rdcu(struct rdcu_cfg *rcfg) void test_random_round_trip_like_rdcu_compression(void) { - enum cmp_data_type data_type; + enum cmp_data_type data_type = DATA_TYPE_IMAGETTE; enum cmp_mode cmp_mode; struct rdcu_cfg rcfg; enum { @@ -736,22 +810,39 @@ void test_random_round_trip_like_rdcu_compression(void) void *data_to_compress1 = malloc(MAX_DATA_TO_COMPRESS_SIZE); void *data_to_compress2 = malloc(MAX_DATA_TO_COMPRESS_SIZE); void *updated_model = calloc(1, MAX_DATA_TO_COMPRESS_SIZE); + int run; - for (data_type = 1; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { - /* printf("%s\n", data_type2string(data_type)); */ - /* generate random data*/ + for (run = 0; run < 2; run++) { + uint32_t (*gen_data_f)(uint32_t, void*); + void *extra; + double p = 0.01; size_t size; - uint32_t samples = cmp_rand_between(1, UINT16_MAX/size_of_a_sample(data_type)); - uint32_t model_value = cmp_rand_between(0, MAX_MODEL_VALUE); + uint32_t samples, model_value; + + /* generate random data*/ + switch (run) { + case 0: + gen_data_f = gen_uniform_data; + extra = NULL; + break; + case 1: + gen_data_f = gen_geometric_data; + extra = &p; + break; + default: + TEST_FAIL(); + } + samples = cmp_rand_between(1, UINT16_MAX/size_of_a_sample(data_type)); + model_value = cmp_rand_between(0, MAX_MODEL_VALUE); if (!rdcu_supported_data_type_is_used(data_type)) continue; - size = gen_ima_data(NULL, data_type, samples, &MAX_USED_BITS_V1); + size = gen_ima_data(NULL, data_type, samples, gen_data_f, extra); TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); - size = gen_ima_data(data_to_compress1, data_type, samples, &MAX_USED_BITS_V1); + size = gen_ima_data(data_to_compress1, data_type, samples, gen_data_f, extra); TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); - size = gen_ima_data(data_to_compress2, data_type, samples, &MAX_USED_BITS_V1); + size = gen_ima_data(data_to_compress2, data_type, samples, gen_data_f, extra); TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); /* for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_STUFF; cmp_mode++) { */ for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_DIFF_MULTI; cmp_mode++) { @@ -832,91 +923,6 @@ void test_random_compression_decompress_rdcu_data(void) } -static uint32_t chunk_round_trip(void *data, uint32_t data_size, - void *model, void *up_model, - uint32_t *cmp_data, uint32_t cmp_data_capacity, - struct cmp_par *cmp_par, int use_decmp_buf, int use_decmp_up_model) -{ - uint32_t cmp_size; - void *model_cpy = NULL; - - /* if in-place model update is used (up_model == model), the model - * needed for decompression is destroyed; therefore we make a copy - */ - if (model) { - if (up_model == model) { - model_cpy = TEST_malloc(data_size); - memcpy(model_cpy, model, data_size); - } else { - model_cpy = model; - } - } - - cmp_size = compress_chunk(data, data_size, model, up_model, - cmp_data, cmp_data_capacity, cmp_par); - -#if 0 - { /* Compress a second time and check for determinism */ - int32_t cSize2; - void *compressed2 = NULL; - void *up_model2 = NULL; - - if (compressed) - compressed2 = FUZZ_malloc(compressedCapacity); - - if (up_model) - up_model2 = FUZZ_malloc(srcSize); - cSize2 = compress_chunk((void *)src, srcSize, (void *)model, up_model2, - compressed2, compressedCapacity, cmp_par); - FUZZ_ASSERT(cSize == cSize2); - FUZZ_ASSERT_MSG(!FUZZ_memcmp(compressed, compressed2, cSize), "Not deterministic!"); - FUZZ_ASSERT_MSG(!FUZZ_memcmp(up_model, compressed2, cSize), "NO deterministic!"); - free(compressed2); - free(up_model2); - } -#endif - if (!cmp_is_error(cmp_size) && cmp_data) { - void *decmp_data = NULL; - void *up_model_decmp = NULL; - int decmp_size; - - decmp_size = decompress_cmp_entiy((struct cmp_entity *)cmp_data, model_cpy, NULL, NULL); - TEST_ASSERT(decmp_size >= 0); - TEST_ASSERT_EQUAL((uint32_t)decmp_size, data_size); - - if (use_decmp_buf) - decmp_data = TEST_malloc(data_size); - if (use_decmp_up_model) - up_model_decmp = TEST_malloc(data_size); - - decmp_size = decompress_cmp_entiy((struct cmp_entity *)cmp_data, model_cpy, - up_model_decmp, decmp_data); - TEST_ASSERT(decmp_size >= 0); - TEST_ASSERT((uint32_t)decmp_size == data_size); - - if (use_decmp_buf) { - TEST_ASSERT_EQUAL_HEX8_ARRAY(data, decmp_data, data_size); - TEST_ASSERT(!memcmp(data, decmp_data, data_size)); - - /* - * the model is only updated when the decompressed_data - * buffer is set - */ - if (up_model && up_model_decmp) - TEST_ASSERT(!memcmp(up_model, up_model_decmp, data_size)); - } - - free(decmp_data); - free(up_model_decmp); - } - - if (up_model == model) - free(model_cpy); - - return cmp_size; -} - - /** * @brief random compression decompression round trip test * @@ -934,6 +940,7 @@ void test_random_collection_round_trip(void) enum cmp_mode cmp_mode; enum { MAX_DATA_TO_COMPRESS_SIZE = UINT16_MAX}; uint32_t cmp_data_capacity = COMPRESS_CHUNK_BOUND(MAX_DATA_TO_COMPRESS_SIZE, 1); + int run; #ifdef __sparc__ void *data = (void *)0x63000000; void *model = (void *)0x64000000; @@ -951,36 +958,85 @@ void test_random_collection_round_trip(void) TEST_ASSERT_NOT_NULL(updated_model); TEST_ASSERT_NOT_NULL(cmp_data); - for (data_type = 1; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { - /* printf("%s\n", data_type2string(data_type)); */ - /* generate random data*/ - size_t size; - uint32_t samples = cmp_rand_between(1, UINT16_MAX/size_of_a_sample(data_type)); + for (run = 0; run < 2; run++) { + uint32_t (*gen_data_f)(uint32_t, void*); + void *extra; + double p = 0.01; - size = generate_random_collection(NULL, data_type, samples, &MAX_USED_BITS_SAFE); - TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); - size = generate_random_collection(data, data_type, samples, &MAX_USED_BITS_SAFE); - TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); - size = generate_random_collection(model, data_type, samples, &MAX_USED_BITS_SAFE); - TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); + switch (run) { + case 0: + gen_data_f = gen_uniform_data; + extra = NULL; + break; + case 1: + gen_data_f = gen_geometric_data; + extra = &p; + break; + default: + TEST_FAIL(); + } - for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_DIFF_MULTI; cmp_mode++) { - struct cmp_par par; - uint32_t cmp_size; - - generate_random_cmp_par(&par); - par.cmp_mode = cmp_mode; - par.lossy_par = CMP_LOSSLESS; - - cmp_size = chunk_round_trip(data, (uint32_t)size, model, updated_model, - cmp_data, cmp_data_capacity, - &par, 1, model_mode_is_used(par.cmp_mode)); - /* No chunk is defined for fast cadence subservices */ - if (data_type == DATA_TYPE_F_FX || data_type == DATA_TYPE_F_FX_EFX || - data_type == DATA_TYPE_F_FX_NCOB || data_type == DATA_TYPE_F_FX_EFX_NCOB_ECOB) - TEST_ASSERT_EQUAL_INT(CMP_ERROR_COL_SUBSERVICE_UNSUPPORTED, cmp_get_error_code(cmp_size)); - else - TEST_ASSERT_FALSE(cmp_is_error(cmp_size)); + for (data_type = 1; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { + /* printf("%s\n", data_type2string(data_type)); */ + /* generate random data*/ + size_t size; + uint32_t samples = cmp_rand_between(1, UINT16_MAX/size_of_a_sample(data_type) - COLLECTION_HDR_SIZE); + + size = generate_random_collection(NULL, data_type, samples, gen_data_f, extra); + TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); + size = generate_random_collection(data, data_type, samples, gen_data_f, extra); + TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); + size = generate_random_collection(model, data_type, samples, gen_data_f, extra); + TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); + + for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_DIFF_MULTI; cmp_mode++) { + struct cmp_par par; + uint32_t cmp_size, cmp_size2; + + cmp_data_capacity = COMPRESS_CHUNK_BOUND(MAX_DATA_TO_COMPRESS_SIZE, 1); + + generate_random_cmp_par(&par); + par.cmp_mode = cmp_mode; + par.lossy_par = CMP_LOSSLESS; + + cmp_size = chunk_round_trip(data, (uint32_t)size, model, updated_model, + cmp_data, cmp_data_capacity, + &par, 1, model_mode_is_used(par.cmp_mode)); + /* No chunk is defined for fast cadence subservices */ + if (data_type == DATA_TYPE_F_FX || data_type == DATA_TYPE_F_FX_EFX || + data_type == DATA_TYPE_F_FX_NCOB || data_type == DATA_TYPE_F_FX_EFX_NCOB_ECOB) { + TEST_ASSERT_EQUAL_INT(CMP_ERROR_COL_SUBSERVICE_UNSUPPORTED, cmp_get_error_code(cmp_size)); + continue; + } else { + TEST_ASSERT_EQUAL_INT(CMP_ERROR_NO_ERROR, cmp_get_error_code(cmp_size)); + } + + + /* test with minimum compressed data capacity */ + cmp_data_capacity = ROUND_UP_TO_MULTIPLE_OF_4(cmp_size); + cmp_size2 = chunk_round_trip(data, (uint32_t)size, model, updated_model, + cmp_data, cmp_data_capacity, + &par, 1, model_mode_is_used(par.cmp_mode)); + + TEST_ASSERT_EQUAL_UINT(cmp_size, cmp_size2); + TEST_ASSERT_FALSE(cmp_is_error(cmp_size2)); + + /* error: the capacity for the compressed data is to small */ + for (cmp_data_capacity = cmp_size2 - 1; + cmp_data_capacity <= cmp_size - 32 && cmp_data_capacity > 1; + cmp_data_capacity--) { + cmp_size = chunk_round_trip(data, (uint32_t)size, model, updated_model, + cmp_data, cmp_data_capacity, + &par, 1, model_mode_is_used(par.cmp_mode)); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF_, cmp_get_error_code(cmp_size)); + } + + cmp_data_capacity = cmp_size2 - cmp_rand_between(1, cmp_size2); + cmp_size = chunk_round_trip(data, (uint32_t)size, model, updated_model, + cmp_data, cmp_data_capacity, + &par, 1, model_mode_is_used(par.cmp_mode)); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF_, cmp_get_error_code(cmp_size)); + } } } #ifndef __sparc__ @@ -1335,11 +1391,11 @@ void test_cmp_decmp_chunk_raw(void) uint32_t dst_capacity = 0; /* generate test data */ - chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); + chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), gen_uniform_data, NULL); TEST_ASSERT_EQUAL_size_t(chunk_size_exp, chunk_size); chunk = calloc(1, chunk_size); TEST_ASSERT_NOT_NULL(chunk); - chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); + chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), gen_uniform_data, NULL); TEST_ASSERT_EQUAL_size_t(chunk_size_exp, chunk_size); /* "compress" data */ @@ -1548,11 +1604,11 @@ void test_cmp_decmp_diff(void) struct collection_hdr *col; size_t chunk_size_exp = 2*sizeof(struct s_fx) + 3*sizeof(struct s_fx_efx_ncob_ecob) + 2*COLLECTION_HDR_SIZE; - chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); + chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), gen_uniform_data, NULL); TEST_ASSERT_EQUAL_size_t(chunk_size_exp, chunk_size); chunk = calloc(1, chunk_size); TEST_ASSERT_NOT_NULL(chunk); - chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); + chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), gen_uniform_data, NULL); TEST_ASSERT_EQUAL_size_t(chunk_size_exp, chunk_size); col = (struct collection_hdr *)chunk; diff --git a/test/fuzz/fuzz_compression.c b/test/fuzz/fuzz_compression.c index 9962dee..daff743 100644 --- a/test/fuzz/fuzz_compression.c +++ b/test/fuzz/fuzz_compression.c @@ -26,6 +26,7 @@ #include "fuzz_helpers.h" #include "fuzz_data_producer.h" +#include "../test_common/test_common.h" #include "../../lib/cmp_chunk.h" @@ -61,7 +62,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) if (cmp_is_error(cmp_size_bound)) cmp_size_bound = 0; cmp_data_capacity = FUZZ_dataProducer_uint32Range(producer, 0, cmp_size_bound+(uint32_t)size); - cmp_data = (uint32_t *)FUZZ_malloc(cmp_data_capacity); + cmp_data = (uint32_t *)TEST_malloc(cmp_data_capacity); FUZZ_dataProducer_cmp_par(producer, &cmp_par); cmp_par.lossy_par = 0; /*TODO: implement lossy */ @@ -74,10 +75,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) up_model = NULL; break; case 1: - up_model = FUZZ_malloc(size); + up_model = TEST_malloc(size); break; case 2: - up_model = FUZZ_malloc(size); + up_model = TEST_malloc(size); if (model && up_model) { memcpy(up_model, model, size); model = up_model; /* in-place update */ diff --git a/test/fuzz/fuzz_data_producer.c b/test/fuzz/fuzz_data_producer.c index 1ee5994..9f03a94 100644 --- a/test/fuzz/fuzz_data_producer.c +++ b/test/fuzz/fuzz_data_producer.c @@ -23,6 +23,7 @@ #include "fuzz_helpers.h" #include "fuzz_data_producer.h" +#include "../test_common/test_common.h" #include <cmp_chunk.h> struct FUZZ_dataProducer_s{ @@ -31,7 +32,7 @@ struct FUZZ_dataProducer_s{ }; FUZZ_dataProducer_t *FUZZ_dataProducer_create(const uint8_t *data, size_t size) { - FUZZ_dataProducer_t *producer = FUZZ_malloc(sizeof(FUZZ_dataProducer_t)); + FUZZ_dataProducer_t *producer = TEST_malloc(sizeof(FUZZ_dataProducer_t)); producer->data = data; producer->size = size; diff --git a/test/fuzz/fuzz_helpers.c b/test/fuzz/fuzz_helpers.c deleted file mode 100644 index 27f1076..0000000 --- a/test/fuzz/fuzz_helpers.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE.BSD-3.Zstandard file in the 3rdparty_licenses directory) and the GPLv2 - * (found in the LICENSE.GPL-2 file in the 3rdparty_licenses directory). - * You may select, at your option, one of the above-listed licenses. - */ - -#include "fuzz_helpers.h" - -#include <stddef.h> -#include <stdlib.h> -#include <string.h> - -void* FUZZ_malloc(size_t size) -{ - if (size > 0) { - void* const mem = malloc(size); - FUZZ_ASSERT(mem); - return mem; - } - return NULL; -} - -void* FUZZ_malloc_rand(size_t size, FUZZ_dataProducer_t *producer) -{ - if (size > 0) { - void* const mem = malloc(size); - FUZZ_ASSERT(mem); - return mem; - } else { - uintptr_t ptr = 0; - /* Add +- 1M 50% of the time */ - if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) - FUZZ_dataProducer_int32Range(producer, -1000000, 1000000); - return (void*)ptr; - } - -} - -int FUZZ_memcmp(void const* lhs, void const* rhs, int32_t size) -{ - if (size <= 0) { - return 0; - } - return memcmp(lhs, rhs, (size_t)size); -} diff --git a/test/fuzz/fuzz_helpers.h b/test/fuzz/fuzz_helpers.h index 70fb3fb..0f95b74 100644 --- a/test/fuzz/fuzz_helpers.h +++ b/test/fuzz/fuzz_helpers.h @@ -15,18 +15,12 @@ #ifndef FUZZ_HELPERS_H #define FUZZ_HELPERS_H -#include "fuzz.h" -#include "fuzz_data_producer.h" -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #ifdef __cplusplus extern "C" { #endif -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define FUZZ_QUOTE_IMPL(str) #str #define FUZZ_QUOTE(str) FUZZ_QUOTE_IMPL(str) @@ -40,36 +34,6 @@ extern "C" { __LINE__, FUZZ_QUOTE(cond), (msg)), \ abort())) #define FUZZ_ASSERT(cond) FUZZ_ASSERT_MSG((cond), ""); -#define FUZZ_ZASSERT(code) \ - FUZZ_ASSERT_MSG(!ZSTD_isError(code), ZSTD_getErrorName(code)) - -#if defined(__GNUC__) -#define FUZZ_STATIC static __inline __attribute__((unused)) -#elif defined(__cplusplus) || \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -#define FUZZ_STATIC static inline -#elif defined(_MSC_VER) -#define FUZZ_STATIC static __inline -#else -#define FUZZ_STATIC static -#endif - -/** - * malloc except return NULL for zero sized data and FUZZ_ASSERT - * that malloc doesn't fail. - */ -void* FUZZ_malloc(size_t size); - -/** - * malloc except returns random pointer for zero sized data and FUZZ_ASSERT - * that malloc doesn't fail. - */ -void* FUZZ_malloc_rand(size_t size, FUZZ_dataProducer_t *producer); - -/** - * memcmp but accepts NULL. Ignore negative sizes - */ -int FUZZ_memcmp(void const* lhs, void const* rhs, int32_t size); #ifdef __cplusplus } diff --git a/test/fuzz/fuzz_round_trip.c b/test/fuzz/fuzz_round_trip.c index 1aec745..cef6591 100644 --- a/test/fuzz/fuzz_round_trip.c +++ b/test/fuzz/fuzz_round_trip.c @@ -22,104 +22,12 @@ */ #include <string.h> +#include <stdlib.h> #include "fuzz_helpers.h" #include "fuzz_data_producer.h" - -#include "../../lib/cmp_chunk.h" -#include "../../lib/decmp.h" - - -#define TEST_malloc(size) FUZZ_malloc(size) -#define TEST_ASSERT(cond) FUZZ_ASSERT(cond) - - -static uint32_t chunk_round_trip(void *data, uint32_t data_size, - void *model, void *up_model, - uint32_t *cmp_data, uint32_t cmp_data_capacity, - struct cmp_par *cmp_par, int use_decmp_buf, - int use_decmp_up_model) -{ - uint32_t cmp_size; - void *model_cpy = NULL; - - /* if in-place model update is used (up_model == model), the model - * needed for decompression is destroyed; therefore we make a copy - */ - if (model) { - if (up_model == model) { - model_cpy = TEST_malloc(data_size); - memcpy(model_cpy, model, data_size); - } else { - model_cpy = model; - } - } - - cmp_size = compress_chunk(data, data_size, model, up_model, - cmp_data, cmp_data_capacity, cmp_par); - -#if 0 - { /* Compress a second time and check for determinism */ - int32_t cSize2; - void *compressed2 = NULL; - void *up_model2 = NULL; - - if (compressed) - compressed2 = FUZZ_malloc(compressedCapacity); - - if (up_model) - up_model2 = FUZZ_malloc(srcSize); - cSize2 = compress_chunk((void *)src, srcSize, (void *)model, up_model2, - compressed2, compressedCapacity, cmp_par); - FUZZ_ASSERT(cSize == cSize2); - FUZZ_ASSERT_MSG(!FUZZ_memcmp(compressed, compressed2, cSize), "Not deterministic!"); - FUZZ_ASSERT_MSG(!FUZZ_memcmp(up_model, compressed2, cSize), "NO deterministic!"); - free(compressed2); - free(up_model2); - } -#endif - if (!cmp_is_error(cmp_size) && cmp_data) { - void *decmp_data = NULL; - void *up_model_decmp = NULL; - int decmp_size; - - decmp_size = decompress_cmp_entiy((struct cmp_entity *)cmp_data, model_cpy, NULL, NULL); - TEST_ASSERT(decmp_size >= 0); - TEST_ASSERT((uint32_t)decmp_size == data_size); - - if (use_decmp_buf) - decmp_data = TEST_malloc(data_size); - if (use_decmp_up_model) { - up_model_decmp = TEST_malloc(data_size); - if (!model_mode_is_used(cmp_par->cmp_mode)) - memset(up_model_decmp, 0, data_size); /* up_model is not used */ - } - - decmp_size = decompress_cmp_entiy((struct cmp_entity *)cmp_data, model_cpy, - up_model_decmp, decmp_data); - TEST_ASSERT(decmp_size >= 0); - TEST_ASSERT((uint32_t)decmp_size == data_size); - - if (use_decmp_buf) { - TEST_ASSERT(!memcmp(data, decmp_data, data_size)); - - /* - * the model is only updated when the decompressed_data - * buffer is set - */ - if (up_model && up_model_decmp) - TEST_ASSERT(!memcmp(up_model, up_model_decmp, data_size)); - } - - free(decmp_data); - free(up_model_decmp); - } - - if (up_model == model) - free(model_cpy); - - return cmp_size; -} +#include "../test_common/chunk_round_trip.h" +#include "../test_common/test_common.h" int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) @@ -155,7 +63,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) /* 1/2 of the cases we use a updated model buffer */ if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) { - up_model = FUZZ_malloc(size); + up_model = TEST_malloc(size); if (!model_mode_is_used(cmp_par.cmp_mode)) memset(up_model, 0, size); /* up_model is not used */ } @@ -164,7 +72,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) if (cmp_is_error(cmp_size_bound)) cmp_size_bound = 0; cmp_data_capacity = FUZZ_dataProducer_uint32Range(producer, 0, cmp_size_bound+(uint32_t)size); - cmp_data = (uint32_t *)FUZZ_malloc(cmp_data_capacity); + cmp_data = (uint32_t *)TEST_malloc(cmp_data_capacity); use_decmp_buf = FUZZ_dataProducer_int32Range(producer, 0, 1); use_decmp_up_model = FUZZ_dataProducer_int32Range(producer, 0, 1); diff --git a/test/fuzz/meson.build b/test/fuzz/meson.build index f7da779..3815fcf 100644 --- a/test/fuzz/meson.build +++ b/test/fuzz/meson.build @@ -2,7 +2,7 @@ if get_option('fuzzer').disabled() subdir_done() endif -fuzz_common = files('fuzz_helpers.c', 'fuzz_data_producer.c') +fuzz_common = files('fuzz_data_producer.c') fuzz_targets = ['fuzz_compression.c', 'fuzz_round_trip.c'] add_languages('cpp', native: false) # libFuzzingEngine needs c++ @@ -14,7 +14,7 @@ foreach target : fuzz_targets fuzz_exe = executable(target_name, fuzz_common, file_name, include_directories : incdir, - link_with : cmp_lib, + link_with : [cmp_lib, test_common_lib], link_args : get_option('fuzzer_ldflags'), link_language : 'cpp' # libFuzzingEngine needs c++ ) diff --git a/test/meson.build b/test/meson.build index 0fdcfc7..7878b91 100644 --- a/test/meson.build +++ b/test/meson.build @@ -53,7 +53,7 @@ if cc.has_argument('-fsanitize=leak') and not (host_machine.system() == 'darwin' endif test_env.set('UBSAN_OPTIONS', - 'abort_on_error=1', + 'halt_on_error=1', 'print_stacktrace=1', 'print_summary=1', 'symbolize=1', @@ -71,6 +71,7 @@ subdir('tools') subdir('cmp_tool') unity_dep = dependency('unity', fallback : ['unity', 'unity_dep']) +m_dep = cc.find_library('m', required : false) subdir('test_common') subdir('fuzz') @@ -104,7 +105,7 @@ if ruby.found() test_src, test_runner, include_directories : incdir, link_with : test_libs, - dependencies : unity_dep, + dependencies : [unity_dep, m_dep], c_args : test_args, build_by_default : false ) diff --git a/test/test_common/chunk_round_trip.c b/test/test_common/chunk_round_trip.c new file mode 100644 index 0000000..4819ffd --- /dev/null +++ b/test/test_common/chunk_round_trip.c @@ -0,0 +1,133 @@ +/** + * @file chunk_round_trip.c + * @date 2024 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief chunk compression/decompression test + * + */ + +#include <string.h> +#include <stdlib.h> + +#include "../test_common/test_common.h" +#include "../../lib/cmp_chunk.h" +#include "../../lib/decmp.h" +#include "chunk_round_trip.h" + +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +# include "../fuzz/fuzz_helpers.h" +# define TEST_ASSERT(cond) FUZZ_ASSERT(cond) +#else +# include <unity.h> +#endif + + +/** + * @brief performs chunk compression and checks if a decompression is possible + * + * @param chunk pointer to the chunk to be compressed + * @param chunk_size byte size of the chunk + * @param chunk_model pointer to a model of a chunk; has the same size + * as the chunk (can be NULL if no model compression + * mode is used) + * @param updated_chunk_model pointer to store the updated model for the next + * model mode compression; has the same size as the + * chunk (can be the same as the model_of_data + * buffer for in-place update or NULL if updated + * model is not needed) + * @param dst destination pointer to the compressed data + * buffer; has to be 4-byte aligned; can be NULL to + * only get the compressed data size + * @param dst_capacity capacity of the dst buffer; it's recommended to + * provide a dst_capacity >= + * compress_chunk_cmp_size_bound(chunk, chunk_size) + * as it eliminates one potential failure scenario: + * not enough space in the dst buffer to write the + * compressed data; size is internally rounded down + * to a multiple of 4 + * @param use_decmp_buf if non-zero, a buffer is allocated for the + * decompressed data + * @param use_decmp_up_model if non-zero, a buffer for the updated model is + * allocated during the decompression + * + * @returns the return value of the compress_chunk() function + */ + +uint32_t chunk_round_trip(void *chunk, uint32_t chunk_size, + void *chunk_model, void *updated_chunk_model, + uint32_t *dst, uint32_t dst_capacity, + struct cmp_par *cmp_par, + int use_decmp_buf, int use_decmp_up_model) +{ + uint32_t cmp_size; + void *model_cpy = NULL; + + /* if in-place model update is used (up_model == model), the model + * needed for decompression is destroyed; therefore we make a copy + */ + if (chunk_model) { + if (updated_chunk_model == chunk_model) { + model_cpy = TEST_malloc(chunk_size); + memcpy(model_cpy, chunk_model, chunk_size); + } else { + model_cpy = chunk_model; + } + } + + cmp_size = compress_chunk(chunk, chunk_size, chunk_model, updated_chunk_model, + dst, dst_capacity, cmp_par); + + + /* decompress the data if the compression was successful */ + if (!cmp_is_error(cmp_size) && dst) { + void *decmp_data = NULL; + void *up_model_decmp = NULL; + int decmp_size; + + decmp_size = decompress_cmp_entiy((struct cmp_entity *)dst, model_cpy, NULL, NULL); + TEST_ASSERT(decmp_size >= 0); + TEST_ASSERT((uint32_t)decmp_size == chunk_size); + + if (use_decmp_buf) + decmp_data = TEST_malloc(chunk_size); + if (use_decmp_up_model) { + up_model_decmp = TEST_malloc(chunk_size); + if (!model_mode_is_used(cmp_par->cmp_mode)) + memset(up_model_decmp, 0, chunk_size); /* up_model is not used */ + } + + decmp_size = decompress_cmp_entiy((struct cmp_entity *)dst, model_cpy, + up_model_decmp, decmp_data); + TEST_ASSERT(decmp_size >= 0); + TEST_ASSERT((uint32_t)decmp_size == chunk_size); + + if (use_decmp_buf) { + TEST_ASSERT(!memcmp(chunk, decmp_data, chunk_size)); + + /* + * the model is only updated when the decompressed_data + * buffer is set + */ + if (use_decmp_up_model && updated_chunk_model) + TEST_ASSERT(!memcmp(updated_chunk_model, up_model_decmp, chunk_size)); + } + + free(decmp_data); + free(up_model_decmp); + } + + if (updated_chunk_model == chunk_model) + free(model_cpy); + + return cmp_size; +} diff --git a/test/test_common/chunk_round_trip.h b/test/test_common/chunk_round_trip.h new file mode 100644 index 0000000..96e9df8 --- /dev/null +++ b/test/test_common/chunk_round_trip.h @@ -0,0 +1,34 @@ +/** + * @file chunk_round_trip.h + * @date 2024 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief chunk compression/decompression + */ + + +#ifndef CHUNK_ROUND_TRIP_H +#define CHUNK_ROUND_TRIP_H + +#include <stdint.h> +#include "../../lib/cmp_chunk.h" + + +uint32_t chunk_round_trip(void *data, uint32_t data_size, + void *model, void *up_model, + uint32_t *cmp_data, uint32_t cmp_data_capacity, + struct cmp_par *cmp_par, int use_decmp_buf, int + use_decmp_up_model); + + +#endif /* CHUNK_ROUND_TRIP_H */ + diff --git a/test/test_common/meson.build b/test/test_common/meson.build index 082ac4c..ab030dc 100644 --- a/test/test_common/meson.build +++ b/test/test_common/meson.build @@ -4,5 +4,6 @@ pcb_dep = pcg_proj.get_variable('libpcg_basic_dep') test_common_lib = static_library( 'test_common', 'test_common.c', + 'chunk_round_trip.c', dependencies: [pcb_dep, unity_dep] ) diff --git a/test/test_common/test_common.c b/test/test_common/test_common.c index 7a1b25f..0cdd826 100644 --- a/test/test_common/test_common.c +++ b/test/test_common/test_common.c @@ -6,7 +6,12 @@ #include "pcg_basic.h" #include "test_common.h" -#include <unity.h> +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +# include "../fuzz/fuzz_helpers.h" +# define TEST_ASSERT(cond) FUZZ_ASSERT(cond) +#else +# include <unity.h> +#endif void cmp_rand_seed(uint64_t seed) { @@ -38,11 +43,12 @@ uint32_t cmp_rand_between(uint32_t min, uint32_t max) } -uint32_t cmp_rand_nbits(unsigned int nbits) +uint32_t cmp_rand_nbits(unsigned int n_bits) { - TEST_ASSERT(nbits > 0); + TEST_ASSERT(n_bits > 0); + TEST_ASSERT(n_bits <= 32); - return cmp_rand32() >> (32 - nbits); + return cmp_rand32() >> (32 - n_bits); } diff --git a/test/test_common/test_common.h b/test/test_common/test_common.h index e27d68a..a5e72f9 100644 --- a/test/test_common/test_common.h +++ b/test/test_common/test_common.h @@ -10,7 +10,7 @@ uint32_t cmp_rand32(void); uint32_t cmp_rand_between(uint32_t min, uint32_t max); -uint32_t cmp_rand_nbits(unsigned int nbits); +uint32_t cmp_rand_nbits(unsigned int n_bits); void* TEST_malloc(size_t size); -- GitLab