libprio/ptest/rand_test.c

200 строки
3.5 KiB
C

/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mpi.h>
#include "mutest.h"
#include "prio/rand.h"
#include "prio/util.h"
void
mu_test__util_msb_mast(void)
{
mu_check(msb_mask(0x01) == 0x01);
mu_check(msb_mask(0x02) == 0x03);
mu_check(msb_mask(0x0C) == 0x0F);
mu_check(msb_mask(0x1C) == 0x1F);
mu_check(msb_mask(0xFF) == 0xFF);
}
void
test_rand_once(int limit)
{
mp_int max;
mp_int out;
mu_check(mp_init(&max) == MP_OKAY);
mu_check(mp_init(&out) == MP_OKAY);
mp_set(&max, limit);
mu_check(rand_int(&out, &max) == MP_OKAY);
mu_check(mp_cmp_d(&out, limit) == -1);
mu_check(mp_cmp_z(&out) > -1);
mp_clear(&max);
mp_clear(&out);
}
void
mu_test_rand__multiple_of_8(void)
{
test_rand_once(256);
test_rand_once(256 * 256);
}
void
mu_test_rand__near_multiple_of_8(void)
{
test_rand_once(256 + 1);
test_rand_once(256 * 256 + 1);
}
void
mu_test_rand__odd(void)
{
test_rand_once(39);
test_rand_once(123);
test_rand_once(993123);
}
void
mu_test_rand__large(void)
{
test_rand_once(1231239933);
}
void
mu_test_rand__bit(void)
{
test_rand_once(1);
for (int i = 0; i < 100; i++)
test_rand_once(2);
}
void
test_rand_distribution(int limit)
{
SECStatus rv = SECSuccess;
int* bins = NULL;
mp_int max;
mp_int out;
MP_DIGITS(&max) = NULL;
MP_DIGITS(&out) = NULL;
P_CHECKA(bins = calloc(limit, sizeof(int)));
MP_CHECKC(mp_init(&max));
MP_CHECKC(mp_init(&out));
mp_set(&max, limit);
for (int i = 0; i < limit; i++) {
bins[i] = 0;
}
for (int i = 0; i < limit * limit; i++) {
mu_check(rand_int(&out, &max) == MP_OKAY);
mu_check(mp_cmp_d(&out, limit) == -1);
mu_check(mp_cmp_z(&out) > -1);
unsigned char ival[2] = { 0x00, 0x00 };
MP_CHECKC(mp_to_fixlen_octets(&out, ival, 2));
if (ival[1] + 256 * ival[0] < limit) {
bins[ival[1] + 256 * ival[0]] += 1;
} else {
mu_check(false);
}
}
for (int i = 0; i < limit; i++) {
mu_check(bins[i] > limit / 2);
}
cleanup:
mu_check(rv == SECSuccess);
if (bins)
free(bins);
mp_clear(&max);
mp_clear(&out);
}
void
mu_test__rand_distribution123(void)
{
test_rand_distribution(123);
}
void
mu_test__rand_distribution257(void)
{
test_rand_distribution(257);
}
void
mu_test__rand_distribution259(void)
{
test_rand_distribution(259);
}
void
test_rand_distribution_large(mp_int* max)
{
SECStatus rv = SECSuccess;
int limit = 16;
int* bins = NULL;
mp_int out;
MP_DIGITS(&out) = NULL;
MP_CHECKC(mp_init(&out));
P_CHECKA(bins = calloc(limit, sizeof(int)));
for (int i = 0; i < limit; i++) {
bins[i] = 0;
}
for (int i = 0; i < 100 * limit * limit; i++) {
MP_CHECKC(rand_int(&out, max));
mu_check(mp_cmp(&out, max) == -1);
mu_check(mp_cmp_z(&out) > -1);
unsigned long res;
MP_CHECKC(mp_mod_d(&out, limit, &res));
bins[res] += 1;
}
for (int i = 0; i < limit; i++) {
mu_check(bins[i] > limit / 2);
}
cleanup:
mu_check(rv == SECSuccess);
if (bins)
free(bins);
mp_clear(&out);
}
void
mu_test__rand_distribution_large(void)
{
SECStatus rv = SECSuccess;
mp_int max;
MP_DIGITS(&max) = NULL;
MP_CHECKC(mp_init(&max));
char bytes[] = "FF1230985198451798EDC8123";
MP_CHECKC(mp_read_radix(&max, bytes, 16));
test_rand_distribution_large(&max);
cleanup:
mu_check(rv == SECSuccess);
mp_clear(&max);
}