blob: 5c56a40b0ff179007fc2b18ae7dedcab1f66f65c [file] [log] [blame]
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef JSONTEST_H_INCLUDED
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05007#define JSONTEST_H_INCLUDED
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04008
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05009#include <json/config.h>
10#include <json/value.h>
11#include <json/writer.h>
12#include <stdio.h>
13#include <deque>
14#include <sstream>
15#include <string>
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040016
17// //////////////////////////////////////////////////////////////////
18// //////////////////////////////////////////////////////////////////
19// Mini Unit Testing framework
20// //////////////////////////////////////////////////////////////////
21// //////////////////////////////////////////////////////////////////
22
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040023/** \brief Unit testing framework.
24 * \warning: all assertions are non-aborting, test case execution will continue
25 * even if an assertion namespace.
26 * This constraint is for portability: the framework needs to compile
27 * on Visual Studio 6 and must not require exception usage.
28 */
29namespace JsonTest {
30
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050031class Failure {
32public:
33 const char* file_;
34 unsigned int line_;
35 std::string expr_;
36 std::string message_;
37 unsigned int nestingLevel_;
38};
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040039
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050040/// Context used to create the assertion callstack on failure.
41/// Must be a POD to allow inline initialisation without stepping
42/// into the debugger.
43struct PredicateContext {
44 typedef unsigned int Id;
45 Id id_;
46 const char* file_;
47 unsigned int line_;
48 const char* expr_;
49 PredicateContext* next_;
50 /// Related Failure, set when the PredicateContext is converted
51 /// into a Failure.
52 Failure* failure_;
53};
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040054
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050055class TestResult {
56public:
57 TestResult();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040058
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050059 /// \internal Implementation detail for assertion macros
60 /// Not encapsulated to prevent step into when debugging failed assertions
61 /// Incremented by one on assertion predicate entry, decreased by one
62 /// by addPredicateContext().
63 PredicateContext::Id predicateId_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040064
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050065 /// \internal Implementation detail for predicate macros
66 PredicateContext* predicateStackTail_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040067
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050068 void setTestName(const std::string& name);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040069
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050070 /// Adds an assertion failure.
71 TestResult&
72 addFailure(const char* file, unsigned int line, const char* expr = 0);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040073
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050074 /// Removes the last PredicateContext added to the predicate stack
75 /// chained list.
76 /// Next messages will be targed at the PredicateContext that was removed.
77 TestResult& popPredicateContext();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040078
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050079 bool failed() const;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040080
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050081 void printFailure(bool printTestName) const;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040082
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050083 // Generic operator that will work with anything ostream can deal with.
84 template <typename T> TestResult& operator<<(const T& value) {
85 std::ostringstream oss;
86 oss.precision(16);
87 oss.setf(std::ios_base::floatfield);
88 oss << value;
89 return addToLastFailure(oss.str());
90 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040091
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050092 // Specialized versions.
93 TestResult& operator<<(bool value);
94 // std:ostream does not support 64bits integers on all STL implementation
95 TestResult& operator<<(Json::Int64 value);
96 TestResult& operator<<(Json::UInt64 value);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040097
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050098private:
99 TestResult& addToLastFailure(const std::string& message);
100 unsigned int getAssertionNestingLevel() const;
101 /// Adds a failure or a predicate context
102 void addFailureInfo(const char* file,
103 unsigned int line,
104 const char* expr,
105 unsigned int nestingLevel);
106 static std::string indentText(const std::string& text,
107 const std::string& indent);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400108
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500109 typedef std::deque<Failure> Failures;
110 Failures failures_;
111 std::string name_;
112 PredicateContext rootPredicateNode_;
113 PredicateContext::Id lastUsedPredicateId_;
114 /// Failure which is the target of the messages added using operator <<
115 Failure* messageTarget_;
116};
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400117
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500118class TestCase {
119public:
120 TestCase();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400121
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500122 virtual ~TestCase();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400123
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500124 void run(TestResult& result);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400125
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500126 virtual const char* testName() const = 0;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400127
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500128protected:
129 TestResult* result_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400130
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500131private:
132 virtual void runTestCase() = 0;
133};
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400134
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500135/// Function pointer type for TestCase factory
136typedef TestCase* (*TestCaseFactory)();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400137
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500138class Runner {
139public:
140 Runner();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400141
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500142 /// Adds a test to the suite
143 Runner& add(TestCaseFactory factory);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400144
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500145 /// Runs test as specified on the command-line
146 /// If no command-line arguments are provided, run all tests.
147 /// If --list-tests is provided, then print the list of all test cases
148 /// If --test <testname> is provided, then run test testname.
149 int runCommandLine(int argc, const char* argv[]) const;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400150
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500151 /// Runs all the test cases
152 bool runAllTest(bool printSummary) const;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400153
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500154 /// Returns the number of test case in the suite
155 unsigned int testCount() const;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400156
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500157 /// Returns the name of the test case at the specified index
158 std::string testNameAt(unsigned int index) const;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400159
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500160 /// Runs the test case at the specified index using the specified TestResult
161 void runTestAt(unsigned int index, TestResult& result) const;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400162
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500163 static void printUsage(const char* appName);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400164
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500165private: // prevents copy construction and assignment
166 Runner(const Runner& other);
167 Runner& operator=(const Runner& other);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400168
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500169private:
170 void listTests() const;
171 bool testIndex(const std::string& testName, unsigned int& index) const;
172 static void preventDialogOnCrash();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400173
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500174private:
175 typedef std::deque<TestCaseFactory> Factories;
176 Factories tests_;
177};
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400178
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500179template <typename T, typename U>
180TestResult& checkEqual(TestResult& result,
181 const T& expected,
182 const U& actual,
183 const char* file,
184 unsigned int line,
185 const char* expr) {
186 if (static_cast<U>(expected) != actual) {
187 result.addFailure(file, line, expr);
188 result << "Expected: " << static_cast<U>(expected) << "\n";
189 result << "Actual : " << actual;
190 }
191 return result;
192}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400193
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500194TestResult& checkStringEqual(TestResult& result,
195 const std::string& expected,
196 const std::string& actual,
197 const char* file,
198 unsigned int line,
199 const char* expr);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400200
201} // namespace JsonTest
202
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400203/// \brief Asserts that the given expression is true.
204/// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y;
205/// JSONTEST_ASSERT( x == y );
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500206#define JSONTEST_ASSERT(expr) \
207 if (expr) { \
208 } else \
209 result_->addFailure(__FILE__, __LINE__, #expr)
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400210
211/// \brief Asserts that the given predicate is true.
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500212/// The predicate may do other assertions and be a member function of the
213/// fixture.
214#define JSONTEST_ASSERT_PRED(expr) \
215 { \
216 JsonTest::PredicateContext _minitest_Context = { \
217 result_->predicateId_, __FILE__, __LINE__, #expr \
218 }; \
219 result_->predicateStackTail_->next_ = &_minitest_Context; \
220 result_->predicateId_ += 1; \
221 result_->predicateStackTail_ = &_minitest_Context; \
222 (expr); \
223 result_->popPredicateContext(); \
224 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400225
226/// \brief Asserts that two values are equals.
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500227#define JSONTEST_ASSERT_EQUAL(expected, actual) \
228 JsonTest::checkEqual(*result_, \
229 expected, \
230 actual, \
231 __FILE__, \
232 __LINE__, \
233 #expected " == " #actual)
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400234
235/// \brief Asserts that two values are equals.
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500236#define JSONTEST_ASSERT_STRING_EQUAL(expected, actual) \
237 JsonTest::checkStringEqual(*result_, \
238 std::string(expected), \
239 std::string(actual), \
240 __FILE__, \
241 __LINE__, \
242 #expected " == " #actual)
243
244/// \brief Asserts that a given expression throws an exception
245#define JSONTEST_ASSERT_THROWS(expr) \
246 { \
247 bool _threw = false; \
248 try { \
249 expr; \
250 } \
251 catch (...) { \
252 _threw = true; \
253 } \
254 if (!_threw) \
255 result_->addFailure( \
256 __FILE__, __LINE__, "expected exception thrown: " #expr); \
257 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400258
259/// \brief Begin a fixture test case.
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500260#define JSONTEST_FIXTURE(FixtureType, name) \
261 class Test##FixtureType##name : public FixtureType { \
262 public: \
263 static JsonTest::TestCase* factory() { \
264 return new Test##FixtureType##name(); \
265 } \
266 \
267 public: /* overidden from TestCase */ \
268 virtual const char* testName() const { return #FixtureType "/" #name; } \
269 virtual void runTestCase(); \
270 }; \
271 \
272 void Test##FixtureType##name::runTestCase()
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400273
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500274#define JSONTEST_FIXTURE_FACTORY(FixtureType, name) \
275 &Test##FixtureType##name::factory
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400276
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500277#define JSONTEST_REGISTER_FIXTURE(runner, FixtureType, name) \
278 (runner).add(JSONTEST_FIXTURE_FACTORY(FixtureType, name))
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400279
280#endif // ifndef JSONTEST_H_INCLUDED