nlib
testing/param_value/param_value.cpp
Sample test that uses parameterized values. Describes how to use the TEST_P macro and INSTANCE_TEST_CASE_P( ) macro.
The tests use the Miller-Rabin primality test code and a prime number data array. Prime number data is not explicitly written in the test code. Known prime numbers are written in the sample as array data.
Data is made into parameters to make the test code more compact and to make it easier to add test data.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// define NLIB_USE_GTEST to use googletest
// #define NLIB_USE_GTEST
static uint64_t MyPow(uint64_t base, int power, int mod) {
int result = 1;
while (power > 0) {
if ((power & 1) == 1) result = static_cast<int>((result * base) % mod);
base = (base * base) % mod;
power >>= 1;
}
return result;
}
static bool MillerRabinIsPrime(int n) {
// Miller-Rabin primality test
if (n < 0) n = -n;
if (n == 2) return true;
if (n == 1 || (n & 1) == 0) return false;
int d = n - 1;
while ((d & 1) == 0) d >>= 1;
for (int i = 0; i < 20; ++i) {
double tmp = rand(); // NOLINT
tmp = tmp * (n - 2) / (RAND_MAX);
int a = static_cast<int>(tmp) + 1;
int t = d;
uint64_t y = MyPow(a, t, n);
while (t != n - 1 && y != 1U && y != static_cast<uint64_t>(n - 1)) {
y = (y * y) % n;
t <<= 1;
}
if (y != static_cast<uint64_t>(n - 1) && (t & 1) == 0) return false;
}
return true;
}
class IsPrimeTest : public ::testing::TestWithParam<int> {};
TEST_P(IsPrimeTest, MillerRabinTrue) {
int v = GetParam();
EXPECT_TRUE(MillerRabinIsPrime(v)) << v;
}
TEST_P(IsPrimeTest, MillerRabinFalse) {
int v = GetParam();
if (v < 10000000) {
v = v * 11;
} else {
// too big values will result in overflow....
return;
}
// MillerRabinIsPrime(v) may return true if v is not prime
// because Miller-Rabin primality test is probabilistic algorithm.
EXPECT_FALSE(MillerRabinIsPrime(v)) << v;
}
INSTANTIATE_TEST_CASE_P(Inst, IsPrimeTest,
::testing::Values(11, 13, 661, 1193, 118633, 999961, 24036583));
int lucky_primes[] = {3, 7, 13, 31, 37, 43, 67, 73, 79, 127, 151, 163, 193, 211, 223,
241, 283, 307, 331, 349, 367, 409, 421, 433, 463, 487, 541, 577, 601, 613,
619, 631, 643, 673, 727, 739, 769, 787, 823, 883, 937, 991, 997};
INSTANTIATE_TEST_CASE_P(LuckyPrimes, IsPrimeTest, ::testing::ValuesIn(lucky_primes));
int markov_primes[] = {2, 5, 13, 29, 89, 233,
433, 1597, 2897, 5741, 7561, 28657,
33461, 43261, 96557, 426389, 514229, 1686049,
2922509, 3276509, 94418953, 321534781, 433494437, 780291637};
INSTANTIATE_TEST_CASE_P(MarkovPrimes, IsPrimeTest, ::testing::ValuesIn(markov_primes));
int mersenne_prime_exponents[] = {2, 3, 5, 7, 13, 17, 19,
31, 61, 89, 107, 127, 521, 607,
1279, 2203, 2281, 3217, 4253, 4423, 9689,
9941, 11213, 19937, 21701, 23209, 44497, 86243,
110503, 132049, 216091, 756839, 859433, 1257787, 1398269,
2976221, 3021377, 6972593, 13466917, 20996011, 24036583};
INSTANTIATE_TEST_CASE_P(MersennePrimeExponents, IsPrimeTest,
::testing::ValuesIn(mersenne_prime_exponents));
NLIB_PATHMAPPER_FORSAMPLE
bool SampleMain(int argc, char** argv) {
srand(0);
InitPathMapperForSample();
char path[512];
char buf[512];
size_t count;
g_PathMapper.ResolvePath(&count, path, "nlibpath:///readwrite/param_value.xml");
nlib_snprintf(&count, buf, "xml:%s", path);
::testing::GTEST_FLAG(output) = buf;
// RUN_ALL_TESTS returns 0 if all the tests are successful.
// You can use the return value of main() function.
return RUN_ALL_TESTS() == 0;
}
NLIB_MAINFUNC