nlib
testing/param_type/param_type.cpp
The sample for the typing test. Describes how to use the TYPED_TEST_CASE( ) macro and the TYPED_TEST( ) macro.
The sample test code tests whether the target class fulfills the group definition. This means that the following are valid for all objects a,b,c that are part of a class.
  • a + (b + c) == (a + b) + c (Associative Law)
  • 0 + a == a + 0 (Identity Element)
  • 0 + a == a + 0 (Inverse Element)
These operations correspond to the following test codes.
Integer 4 modulo(Z4), quaternion(Q4), and integer 256 modulo(unsigned char) are provided as the test target class (type).
/*--------------------------------------------------------------------------------*
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.
*--------------------------------------------------------------------------------*/
// define NLIB_USE_GTEST to use googletest
// #define NLIB_USE_GTEST
// Z4: factor group of 'x mod 4'
class Z4 {
public:
Z4() : value_(0) {}
explicit Z4(int x) : value_(x > 0 ? (x & 3) : ((-x) & 3)) {}
bool operator==(const Z4& rhs) const { return value_ == rhs.value_; }
bool operator!=(const Z4& rhs) const { return value_ != rhs.value_; }
Z4& operator+=(const Z4& rhs) {
value_ = (value_ + rhs.value_) & 3;
return *this;
}
int value() const { return value_; }
Z4& operator++() {
value_ = (value_ + 1) & 3;
return *this;
}
private:
int value_;
};
NLIB_TESTING_OSTREAM& operator<<(NLIB_TESTING_OSTREAM& str, const Z4& data) {
str << "Z4(" << data.value() << ")";
return str;
}
Z4 operator+(const Z4& lhs, const Z4& rhs) {
Z4 result(lhs);
result += rhs;
return result;
}
// quaternion group
class Q4 {
public:
enum ValueType {
kOne = 0,
kI = 1,
kJ = 2,
kK = 3,
kMinusOne = 4,
kMinusI = 5,
kMinusJ = 6,
kMinusK = 7
};
Q4() : value_(kOne) {}
explicit Q4(int x) : value_(static_cast<ValueType>(x > 0 ? x % 8 : -x % 8)) {}
bool operator==(const Q4& rhs) const { return value_ == rhs.value_; }
bool operator!=(const Q4& rhs) const { return value_ != rhs.value_; }
Q4& operator+=(const Q4& rhs);
ValueType value() const { return value_; }
Q4& operator++() {
value_ = static_cast<ValueType>((value_ + 1) % 8);
return *this;
}
private:
ValueType value_;
};
Q4& Q4::operator+=(const Q4& rhs) {
// ii = jj == kk = ijk = -1
// ij = -ij = k
// jk = -kj = i
// ki = -ik = j
// This sample uses operator+=() for binary operation.
static const ValueType table[8][8] = {{kOne, kI, kJ, kK, kMinusOne, kMinusI, kMinusJ, kMinusK},
{kI, kMinusOne, kK, kMinusJ, kMinusI, kOne, kMinusK, kJ},
{kJ, kMinusK, kMinusOne, kI, kMinusJ, kK, kOne, kMinusI},
{kK, kJ, kMinusI, kMinusOne, kMinusK, kMinusJ, kI, kOne},
{kMinusOne, kMinusI, kMinusJ, kMinusK, kOne, kI, kJ, kK},
{kMinusI, kOne, kMinusK, kJ, kI, kMinusOne, kK, kMinusJ},
{kMinusJ, kK, kOne, kMinusI, kJ, kMinusK, kMinusOne, kI},
{kMinusK, kMinusJ, kI, kOne, kK, kJ, kMinusI, kMinusOne}};
value_ = table[value_][rhs.value_];
return *this;
}
NLIB_TESTING_OSTREAM& operator<<(NLIB_TESTING_OSTREAM& str, const Q4& data) {
switch (data.value()) {
case Q4::kOne:
str << "1";
break;
case Q4::kI:
str << "i";
break;
case Q4::kJ:
str << "j";
break;
case Q4::kK:
str << "k";
break;
case Q4::kMinusOne:
str << "-1";
break;
case Q4::kMinusI:
str << "-i";
break;
case Q4::kMinusJ:
str << "-j";
break;
case Q4::kMinusK:
str << "-k";
break;
default:
str << "ERROR";
break;
}
return str;
}
Q4 operator+(const Q4& lhs, const Q4& rhs) {
Q4 result(lhs);
result += rhs;
return result;
}
template <class T>
class GroupTest : public ::testing::Test {
public:
// you can define text fixtures here
};
// check if Z4, Q4, and unsigned char satisfy the definition of group
typedef ::testing::Types<Z4, Q4, unsigned char> MyTypes;
TYPED_TEST_CASE(GroupTest, MyTypes);
TYPED_TEST(GroupTest, BasicInterface) {
TypeParam x = TypeParam(); // check if TypeParam has a default constructor
TypeParam y = TypeParam(x); // check if TypeParam has a copy constructor
x = y; // check if TypeParam has an assignment operator
TypeParam z = x;
++z; // check if operator++() is defined.
// it is used for convenience, to get the next element.
EXPECT_EQ(x, y); // check if operator==() is defined, and x == y
EXPECT_EQ(TypeParam(), TypeParam(0)); // default value is equal to an identity element
}
TYPED_TEST(GroupTest, AssociativeLaw) {
// Associative law:
// a + (b + c) == (a + b) + c
// for all elements
TypeParam e = TypeParam();
TypeParam a = TypeParam();
TypeParam b = TypeParam();
TypeParam c = TypeParam();
do {
do {
do {
ASSERT_EQ(a + (b + c), (a + b) + c) << "a = " << a << ", "
<< "b = " << b << ", "
<< "c = " << c;
++c;
} while (e != c);
++b;
} while (e != b);
++a;
} while (e != a);
}
TYPED_TEST(GroupTest, IdentityElement) {
// existence of an identity element:
// 0 + a == a + 0
// for all elements
TypeParam e = TypeParam();
TypeParam a = TypeParam();
ASSERT_EQ(e, TypeParam());
do {
ASSERT_EQ(e + a, a + e) << a;
++a;
} while (e != a);
}
TYPED_TEST(GroupTest, InverseElement) {
// existence of inverse elements:
// there is an inverse element 'b' for all 'a' such that
// 0 == a + b
TypeParam e = TypeParam();
TypeParam a = TypeParam();
do {
bool success = false;
TypeParam b = TypeParam();
do {
if (e == a + b) {
success = true;
break;
}
} while (e != b);
ASSERT_TRUE(success) << a;
} while (e != a);
}
NLIB_PATHMAPPER_FORSAMPLE
bool SampleMain(int argc, char** argv) {
InitPathMapperForSample();
char path[512];
char buf[512];
size_t count;
g_pathmapper.ResolvePath(&count, path, "nlibpath:///readwrite/param_type.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