nlib
testing/param_value/param_value.cpp
値をパラメータ化したテストのサンプルです。 TEST_PマクロとINSTANCE_TEST_CASE_P()マクロの利用法を解説しています。
ミラー-ラビン素数判定法のコードを素数のデータ列を用いてテストしています。 素数データはテストコード内には明示的に記述されておらず、素数であることが既に知られている数値がサンプル内に配列データとして記述されています。
このようにデータをパラメータ化することで、テストコードをコンパクトにでき、テストデータの追加も容易に行うことができるようになります。
/*--------------------------------------------------------------------------------*
Project: CrossRoad
Copyright (C)Nintendo All rights reserved.
These coded instructions, statements, and computer programs contain proprietary
information of Nintendo and/or its licensed developers and are protected by
national and international copyright laws. They may not be disclosed to third
parties or copied or duplicated in any form, in whole or in part, without the
prior written consent of Nintendo.
The content herein is highly confidential and should be handled accordingly.
*--------------------------------------------------------------------------------*/
#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