Skip to content

Commit b09b4ae

Browse files
committed
added unittest framework
The unittests can be run with the `make test` build target. They currently fail on a single test for pystring::translate as a demonstration of the unit-tests fail behavior. (This error is a known issue, documented as imageworks#3)
1 parent af3cdaa commit b09b4ae

File tree

4 files changed

+209
-0
lines changed

4 files changed

+209
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
test
2+
.libs
3+
libpystring.la
4+
pystring.lo
5+
pystring.o

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,9 @@ install: libpystring.la
1616

1717
clean:
1818
$(RM) -fr pystring.lo pystring.o libpystring.la .libs
19+
20+
.PHONY: test
21+
test:
22+
$(RM) -fr test
23+
$(CXX) pystring.cpp test.cpp -o test
24+
./test

test.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <iostream>
2+
3+
#include "pystring.h"
4+
#include "unittest.h"
5+
6+
PYSTRING_TEST_APP(PyStringUnitTests)
7+
8+
9+
PYSTRING_ADD_TEST(pystring, endswith)
10+
{
11+
PYSTRING_CHECK_EQUAL(pystring::endswith("", ".mesh"), false);
12+
PYSTRING_CHECK_EQUAL(pystring::endswith("help", ".mesh"), false);
13+
PYSTRING_CHECK_EQUAL(pystring::endswith(".mesh", ".mesh"), true);
14+
PYSTRING_CHECK_EQUAL(pystring::endswith("a.mesh", ".mesh"), true);
15+
PYSTRING_CHECK_EQUAL(pystring::endswith("a.", "."), true);
16+
}
17+
18+
PYSTRING_ADD_TEST(pystring, strip)
19+
{
20+
PYSTRING_CHECK_EQUAL(pystring::strip(""), "");
21+
PYSTRING_CHECK_EQUAL(pystring::strip("a"), "a");
22+
PYSTRING_CHECK_EQUAL(pystring::strip("a "), "a");
23+
PYSTRING_CHECK_EQUAL(pystring::strip(" a"), "a");
24+
PYSTRING_CHECK_EQUAL(pystring::strip("\n a "), "a");
25+
PYSTRING_CHECK_EQUAL(pystring::strip("\r\n a \r\n"), "a");
26+
PYSTRING_CHECK_EQUAL(pystring::strip("\r\n a \r\n\t"), "a");
27+
}
28+
29+
PYSTRING_ADD_TEST(pystring, translate)
30+
{
31+
char t1data[256];
32+
for(int i=0; i<256; ++i) t1data[i] = (char)i;
33+
std::string t1(t1data, 256);
34+
PYSTRING_CHECK_EQUAL(pystring::translate("", t1), "");
35+
PYSTRING_CHECK_EQUAL(pystring::translate("cheese", t1), "cheese");
36+
PYSTRING_CHECK_EQUAL(pystring::translate("cheese", t1, "e"), "chs");
37+
38+
char t2data[256];
39+
for(int i=0; i<256; ++i) t2data[i] = (char)i;
40+
t2data[101] = 111; // Map e -> o
41+
std::string t2(t2data, 256);
42+
PYSTRING_CHECK_EQUAL(pystring::translate("", t2), "");
43+
PYSTRING_CHECK_EQUAL(pystring::translate("cheese", t2), "chooso");
44+
}

unittest.h

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
///////////////////////////////////////////////////////////////////////////////
2+
// Copyright (c) 2008-2010, Sony Pictures Imageworks Inc
3+
// All rights reserved.
4+
//
5+
// Redistribution and use in source and binary forms, with or without
6+
// modification, are permitted provided that the following conditions are
7+
// met:
8+
//
9+
// Redistributions of source code must retain the above copyright notice,
10+
// this list of conditions and the following disclaimer.
11+
// Redistributions in binary form must reproduce the above copyright
12+
// notice, this list of conditions and the following disclaimer in the
13+
// documentation and/or other materials provided with the distribution.
14+
// Neither the name of the organization Sony Pictures Imageworks nor the
15+
// names of its contributors
16+
// may be used to endorse or promote products derived from this software
17+
// without specific prior written permission.
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
// "AS
20+
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21+
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22+
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23+
// OWNER
24+
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+
// SPECIAL,
26+
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27+
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28+
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29+
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30+
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31+
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
///////////////////////////////////////////////////////////////////////////////
33+
34+
#ifndef INCLUDED_PYSTRING_UNITTEST_H
35+
#define INCLUDED_PYSTRING_UNITTEST_H
36+
37+
#include <iostream>
38+
#include <cmath>
39+
#include <vector>
40+
41+
extern int unit_test_failures;
42+
43+
void unittest_fail();
44+
45+
typedef void (*PYSTRINGTestFunc)();
46+
47+
struct PYSTRINGTest
48+
{
49+
PYSTRINGTest(std::string testgroup, std::string testname, PYSTRINGTestFunc test) :
50+
group(testgroup), name(testname), function(test) { };
51+
std::string group, name;
52+
PYSTRINGTestFunc function;
53+
};
54+
55+
typedef std::vector<PYSTRINGTest*> UnitTests;
56+
57+
UnitTests& GetUnitTests();
58+
59+
struct AddTest { AddTest(PYSTRINGTest* test); };
60+
61+
/// PYSTRING_CHECK_* macros checks if the conditions is met, and if not,
62+
/// prints an error message indicating the module and line where the
63+
/// error occurred, but does NOT abort. This is helpful for unit tests
64+
/// where we do not want one failure.
65+
#define PYSTRING_CHECK_ASSERT(x) \
66+
((x) ? ((void)0) \
67+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
68+
<< "FAILED: " << #x << "\n"), \
69+
(void)++unit_test_failures))
70+
71+
#define PYSTRING_CHECK_EQUAL(x,y) \
72+
(((x) == (y)) ? ((void)0) \
73+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
74+
<< "FAILED: " << #x << " == " << #y << "\n" \
75+
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
76+
(void)++unit_test_failures))
77+
78+
#define PYSTRING_CHECK_NE(x,y) \
79+
(((x) != (y)) ? ((void)0) \
80+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
81+
<< "FAILED: " << #x << " != " << #y << "\n" \
82+
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
83+
(void)++unit_test_failures))
84+
85+
#define PYSTRING_CHECK_LT(x,y) \
86+
(((x) < (y)) ? ((void)0) \
87+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
88+
<< "FAILED: " << #x << " < " << #y << "\n" \
89+
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
90+
(void)++unit_test_failures))
91+
92+
#define PYSTRING_CHECK_GT(x,y) \
93+
(((x) > (y)) ? ((void)0) \
94+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
95+
<< "FAILED: " << #x << " > " << #y << "\n" \
96+
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
97+
(void)++unit_test_failures))
98+
99+
#define PYSTRING_CHECK_LE(x,y) \
100+
(((x) <= (y)) ? ((void)0) \
101+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
102+
<< "FAILED: " << #x << " <= " << #y << "\n" \
103+
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
104+
(void)++unit_test_failures))
105+
106+
#define PYSTRING_CHECK_GE(x,y) \
107+
(((x) >= (y)) ? ((void)0) \
108+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
109+
<< "FAILED: " << #x << " >= " << #y << "\n" \
110+
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
111+
(void)++unit_test_failures))
112+
113+
#define PYSTRING_CHECK_CLOSE(x,y,tol) \
114+
((std::abs((x) - (y)) < tol) ? ((void)0) \
115+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
116+
<< "FAILED: abs(" << #x << " - " << #y << ") < " << #tol << "\n" \
117+
<< "\tvalues were '" << (x) << "', '" << (y) << "' and '" << (tol) << "'\n"), \
118+
(void)++unit_test_failures))
119+
120+
#define PYSTRING_CHECK_THOW(S, E) \
121+
try { S; throw "throwanything"; } catch( E const& ex ) { } catch (...) { \
122+
std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
123+
<< "FAILED: " << #E << " is expected to be thrown\n"; \
124+
++unit_test_failures; }
125+
126+
#define PYSTRING_CHECK_NO_THOW(S) \
127+
try { S; } catch (...) { \
128+
std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
129+
<< "FAILED: exception thrown from " << #S <<"\n"; \
130+
++unit_test_failures; }
131+
132+
#define PYSTRING_ADD_TEST(group, name) \
133+
static void pystringtest_##group##_##name(); \
134+
AddTest pystringaddtest_##group##_##name(new PYSTRINGTest(#group, #name, pystringtest_##group##_##name)); \
135+
static void pystringtest_##group##_##name()
136+
137+
#define PYSTRING_TEST_SETUP() \
138+
int unit_test_failures = 0
139+
140+
#define PYSTRING_TEST_APP(app) \
141+
std::vector<PYSTRINGTest*>& GetUnitTests() { \
142+
static std::vector<PYSTRINGTest*> pystring_unit_tests; \
143+
return pystring_unit_tests; } \
144+
AddTest::AddTest(PYSTRINGTest* test){GetUnitTests().push_back(test);}; \
145+
PYSTRING_TEST_SETUP(); \
146+
int main(int, char **) { std::cerr << "\n" << #app <<"\n\n"; \
147+
for(size_t i = 0; i < GetUnitTests().size(); ++i) { \
148+
int _tmp = unit_test_failures; GetUnitTests()[i]->function(); \
149+
std::cerr << "Test [" << GetUnitTests()[i]->group << "] [" << GetUnitTests()[i]->name << "] - "; \
150+
std::cerr << (_tmp == unit_test_failures ? "PASSED" : "FAILED") << "\n"; } \
151+
std::cerr << "\n" << unit_test_failures << " tests failed\n\n"; \
152+
return unit_test_failures; }
153+
154+
#endif

0 commit comments

Comments
 (0)