xref: /aosp_15_r20/external/jsoncpp/src/test_lib_json/jsontest.h (revision 4484440890e2bc6e07362b4feaf15601abfe0071)
1*44844408SAndroid Build Coastguard Worker // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
2*44844408SAndroid Build Coastguard Worker // Distributed under MIT license, or public domain if desired and
3*44844408SAndroid Build Coastguard Worker // recognized in your jurisdiction.
4*44844408SAndroid Build Coastguard Worker // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5*44844408SAndroid Build Coastguard Worker 
6*44844408SAndroid Build Coastguard Worker #ifndef JSONTEST_H_INCLUDED
7*44844408SAndroid Build Coastguard Worker #define JSONTEST_H_INCLUDED
8*44844408SAndroid Build Coastguard Worker 
9*44844408SAndroid Build Coastguard Worker #include <cstdio>
10*44844408SAndroid Build Coastguard Worker #include <deque>
11*44844408SAndroid Build Coastguard Worker #include <iomanip>
12*44844408SAndroid Build Coastguard Worker #include <json/config.h>
13*44844408SAndroid Build Coastguard Worker #include <json/value.h>
14*44844408SAndroid Build Coastguard Worker #include <json/writer.h>
15*44844408SAndroid Build Coastguard Worker #include <sstream>
16*44844408SAndroid Build Coastguard Worker #include <string>
17*44844408SAndroid Build Coastguard Worker 
18*44844408SAndroid Build Coastguard Worker // //////////////////////////////////////////////////////////////////
19*44844408SAndroid Build Coastguard Worker // //////////////////////////////////////////////////////////////////
20*44844408SAndroid Build Coastguard Worker // Mini Unit Testing framework
21*44844408SAndroid Build Coastguard Worker // //////////////////////////////////////////////////////////////////
22*44844408SAndroid Build Coastguard Worker // //////////////////////////////////////////////////////////////////
23*44844408SAndroid Build Coastguard Worker 
24*44844408SAndroid Build Coastguard Worker /** \brief Unit testing framework.
25*44844408SAndroid Build Coastguard Worker  * \warning: all assertions are non-aborting, test case execution will continue
26*44844408SAndroid Build Coastguard Worker  *           even if an assertion namespace.
27*44844408SAndroid Build Coastguard Worker  *           This constraint is for portability: the framework needs to compile
28*44844408SAndroid Build Coastguard Worker  *           on Visual Studio 6 and must not require exception usage.
29*44844408SAndroid Build Coastguard Worker  */
30*44844408SAndroid Build Coastguard Worker namespace JsonTest {
31*44844408SAndroid Build Coastguard Worker 
32*44844408SAndroid Build Coastguard Worker class Failure {
33*44844408SAndroid Build Coastguard Worker public:
34*44844408SAndroid Build Coastguard Worker   const char* file_;
35*44844408SAndroid Build Coastguard Worker   unsigned int line_;
36*44844408SAndroid Build Coastguard Worker   Json::String expr_;
37*44844408SAndroid Build Coastguard Worker   Json::String message_;
38*44844408SAndroid Build Coastguard Worker   unsigned int nestingLevel_;
39*44844408SAndroid Build Coastguard Worker };
40*44844408SAndroid Build Coastguard Worker 
41*44844408SAndroid Build Coastguard Worker /// Context used to create the assertion callstack on failure.
42*44844408SAndroid Build Coastguard Worker /// Must be a POD to allow inline initialisation without stepping
43*44844408SAndroid Build Coastguard Worker /// into the debugger.
44*44844408SAndroid Build Coastguard Worker struct PredicateContext {
45*44844408SAndroid Build Coastguard Worker   using Id = unsigned int;
46*44844408SAndroid Build Coastguard Worker   Id id_;
47*44844408SAndroid Build Coastguard Worker   const char* file_;
48*44844408SAndroid Build Coastguard Worker   unsigned int line_;
49*44844408SAndroid Build Coastguard Worker   const char* expr_;
50*44844408SAndroid Build Coastguard Worker   PredicateContext* next_;
51*44844408SAndroid Build Coastguard Worker   /// Related Failure, set when the PredicateContext is converted
52*44844408SAndroid Build Coastguard Worker   /// into a Failure.
53*44844408SAndroid Build Coastguard Worker   Failure* failure_;
54*44844408SAndroid Build Coastguard Worker };
55*44844408SAndroid Build Coastguard Worker 
56*44844408SAndroid Build Coastguard Worker class TestResult {
57*44844408SAndroid Build Coastguard Worker public:
58*44844408SAndroid Build Coastguard Worker   TestResult();
59*44844408SAndroid Build Coastguard Worker 
60*44844408SAndroid Build Coastguard Worker   /// \internal Implementation detail for assertion macros
61*44844408SAndroid Build Coastguard Worker   /// Not encapsulated to prevent step into when debugging failed assertions
62*44844408SAndroid Build Coastguard Worker   /// Incremented by one on assertion predicate entry, decreased by one
63*44844408SAndroid Build Coastguard Worker   /// by addPredicateContext().
64*44844408SAndroid Build Coastguard Worker   PredicateContext::Id predicateId_{1};
65*44844408SAndroid Build Coastguard Worker 
66*44844408SAndroid Build Coastguard Worker   /// \internal Implementation detail for predicate macros
67*44844408SAndroid Build Coastguard Worker   PredicateContext* predicateStackTail_;
68*44844408SAndroid Build Coastguard Worker 
69*44844408SAndroid Build Coastguard Worker   void setTestName(const Json::String& name);
70*44844408SAndroid Build Coastguard Worker 
71*44844408SAndroid Build Coastguard Worker   /// Adds an assertion failure.
72*44844408SAndroid Build Coastguard Worker   TestResult& addFailure(const char* file, unsigned int line,
73*44844408SAndroid Build Coastguard Worker                          const char* expr = nullptr);
74*44844408SAndroid Build Coastguard Worker 
75*44844408SAndroid Build Coastguard Worker   /// Removes the last PredicateContext added to the predicate stack
76*44844408SAndroid Build Coastguard Worker   /// chained list.
77*44844408SAndroid Build Coastguard Worker   /// Next messages will be targed at the PredicateContext that was removed.
78*44844408SAndroid Build Coastguard Worker   TestResult& popPredicateContext();
79*44844408SAndroid Build Coastguard Worker 
80*44844408SAndroid Build Coastguard Worker   bool failed() const;
81*44844408SAndroid Build Coastguard Worker 
82*44844408SAndroid Build Coastguard Worker   void printFailure(bool printTestName) const;
83*44844408SAndroid Build Coastguard Worker 
84*44844408SAndroid Build Coastguard Worker   // Generic operator that will work with anything ostream can deal with.
85*44844408SAndroid Build Coastguard Worker   template <typename T> TestResult& operator<<(const T& value) {
86*44844408SAndroid Build Coastguard Worker     Json::OStringStream oss;
87*44844408SAndroid Build Coastguard Worker     oss << std::setprecision(16) << std::hexfloat << value;
88*44844408SAndroid Build Coastguard Worker     return addToLastFailure(oss.str());
89*44844408SAndroid Build Coastguard Worker   }
90*44844408SAndroid Build Coastguard Worker 
91*44844408SAndroid Build Coastguard Worker   // Specialized versions.
92*44844408SAndroid Build Coastguard Worker   TestResult& operator<<(bool value);
93*44844408SAndroid Build Coastguard Worker   // std:ostream does not support 64bits integers on all STL implementation
94*44844408SAndroid Build Coastguard Worker   TestResult& operator<<(Json::Int64 value);
95*44844408SAndroid Build Coastguard Worker   TestResult& operator<<(Json::UInt64 value);
96*44844408SAndroid Build Coastguard Worker 
97*44844408SAndroid Build Coastguard Worker private:
98*44844408SAndroid Build Coastguard Worker   TestResult& addToLastFailure(const Json::String& message);
99*44844408SAndroid Build Coastguard Worker   /// Adds a failure or a predicate context
100*44844408SAndroid Build Coastguard Worker   void addFailureInfo(const char* file, unsigned int line, const char* expr,
101*44844408SAndroid Build Coastguard Worker                       unsigned int nestingLevel);
102*44844408SAndroid Build Coastguard Worker   static Json::String indentText(const Json::String& text,
103*44844408SAndroid Build Coastguard Worker                                  const Json::String& indent);
104*44844408SAndroid Build Coastguard Worker 
105*44844408SAndroid Build Coastguard Worker   using Failures = std::deque<Failure>;
106*44844408SAndroid Build Coastguard Worker   Failures failures_;
107*44844408SAndroid Build Coastguard Worker   Json::String name_;
108*44844408SAndroid Build Coastguard Worker   PredicateContext rootPredicateNode_;
109*44844408SAndroid Build Coastguard Worker   PredicateContext::Id lastUsedPredicateId_{0};
110*44844408SAndroid Build Coastguard Worker   /// Failure which is the target of the messages added using operator <<
111*44844408SAndroid Build Coastguard Worker   Failure* messageTarget_{nullptr};
112*44844408SAndroid Build Coastguard Worker };
113*44844408SAndroid Build Coastguard Worker 
114*44844408SAndroid Build Coastguard Worker class TestCase {
115*44844408SAndroid Build Coastguard Worker public:
116*44844408SAndroid Build Coastguard Worker   TestCase();
117*44844408SAndroid Build Coastguard Worker 
118*44844408SAndroid Build Coastguard Worker   virtual ~TestCase();
119*44844408SAndroid Build Coastguard Worker 
120*44844408SAndroid Build Coastguard Worker   void run(TestResult& result);
121*44844408SAndroid Build Coastguard Worker 
122*44844408SAndroid Build Coastguard Worker   virtual const char* testName() const = 0;
123*44844408SAndroid Build Coastguard Worker 
124*44844408SAndroid Build Coastguard Worker protected:
125*44844408SAndroid Build Coastguard Worker   TestResult* result_{nullptr};
126*44844408SAndroid Build Coastguard Worker 
127*44844408SAndroid Build Coastguard Worker private:
128*44844408SAndroid Build Coastguard Worker   virtual void runTestCase() = 0;
129*44844408SAndroid Build Coastguard Worker };
130*44844408SAndroid Build Coastguard Worker 
131*44844408SAndroid Build Coastguard Worker /// Function pointer type for TestCase factory
132*44844408SAndroid Build Coastguard Worker using TestCaseFactory = TestCase* (*)();
133*44844408SAndroid Build Coastguard Worker 
134*44844408SAndroid Build Coastguard Worker class Runner {
135*44844408SAndroid Build Coastguard Worker public:
136*44844408SAndroid Build Coastguard Worker   Runner();
137*44844408SAndroid Build Coastguard Worker 
138*44844408SAndroid Build Coastguard Worker   /// Adds a test to the suite
139*44844408SAndroid Build Coastguard Worker   Runner& add(TestCaseFactory factory);
140*44844408SAndroid Build Coastguard Worker 
141*44844408SAndroid Build Coastguard Worker   /// Runs test as specified on the command-line
142*44844408SAndroid Build Coastguard Worker   /// If no command-line arguments are provided, run all tests.
143*44844408SAndroid Build Coastguard Worker   /// If --list-tests is provided, then print the list of all test cases
144*44844408SAndroid Build Coastguard Worker   /// If --test <testname> is provided, then run test testname.
145*44844408SAndroid Build Coastguard Worker   int runCommandLine(int argc, const char* argv[]) const;
146*44844408SAndroid Build Coastguard Worker 
147*44844408SAndroid Build Coastguard Worker   /// Runs all the test cases
148*44844408SAndroid Build Coastguard Worker   bool runAllTest(bool printSummary) const;
149*44844408SAndroid Build Coastguard Worker 
150*44844408SAndroid Build Coastguard Worker   /// Returns the number of test case in the suite
151*44844408SAndroid Build Coastguard Worker   size_t testCount() const;
152*44844408SAndroid Build Coastguard Worker 
153*44844408SAndroid Build Coastguard Worker   /// Returns the name of the test case at the specified index
154*44844408SAndroid Build Coastguard Worker   Json::String testNameAt(size_t index) const;
155*44844408SAndroid Build Coastguard Worker 
156*44844408SAndroid Build Coastguard Worker   /// Runs the test case at the specified index using the specified TestResult
157*44844408SAndroid Build Coastguard Worker   void runTestAt(size_t index, TestResult& result) const;
158*44844408SAndroid Build Coastguard Worker 
159*44844408SAndroid Build Coastguard Worker   static void printUsage(const char* appName);
160*44844408SAndroid Build Coastguard Worker 
161*44844408SAndroid Build Coastguard Worker private: // prevents copy construction and assignment
162*44844408SAndroid Build Coastguard Worker   Runner(const Runner& other) = delete;
163*44844408SAndroid Build Coastguard Worker   Runner& operator=(const Runner& other) = delete;
164*44844408SAndroid Build Coastguard Worker 
165*44844408SAndroid Build Coastguard Worker private:
166*44844408SAndroid Build Coastguard Worker   void listTests() const;
167*44844408SAndroid Build Coastguard Worker   bool testIndex(const Json::String& testName, size_t& indexOut) const;
168*44844408SAndroid Build Coastguard Worker   static void preventDialogOnCrash();
169*44844408SAndroid Build Coastguard Worker 
170*44844408SAndroid Build Coastguard Worker private:
171*44844408SAndroid Build Coastguard Worker   using Factories = std::deque<TestCaseFactory>;
172*44844408SAndroid Build Coastguard Worker   Factories tests_;
173*44844408SAndroid Build Coastguard Worker };
174*44844408SAndroid Build Coastguard Worker 
175*44844408SAndroid Build Coastguard Worker template <typename T, typename U>
checkEqual(TestResult & result,T expected,U actual,const char * file,unsigned int line,const char * expr)176*44844408SAndroid Build Coastguard Worker TestResult& checkEqual(TestResult& result, T expected, U actual,
177*44844408SAndroid Build Coastguard Worker                        const char* file, unsigned int line, const char* expr) {
178*44844408SAndroid Build Coastguard Worker   if (static_cast<U>(expected) != actual) {
179*44844408SAndroid Build Coastguard Worker     result.addFailure(file, line, expr);
180*44844408SAndroid Build Coastguard Worker     result << "Expected: " << static_cast<U>(expected) << "\n";
181*44844408SAndroid Build Coastguard Worker     result << "Actual  : " << actual;
182*44844408SAndroid Build Coastguard Worker   }
183*44844408SAndroid Build Coastguard Worker   return result;
184*44844408SAndroid Build Coastguard Worker }
185*44844408SAndroid Build Coastguard Worker 
186*44844408SAndroid Build Coastguard Worker Json::String ToJsonString(const char* toConvert);
187*44844408SAndroid Build Coastguard Worker Json::String ToJsonString(Json::String in);
188*44844408SAndroid Build Coastguard Worker #if JSONCPP_USING_SECURE_MEMORY
189*44844408SAndroid Build Coastguard Worker Json::String ToJsonString(std::string in);
190*44844408SAndroid Build Coastguard Worker #endif
191*44844408SAndroid Build Coastguard Worker 
192*44844408SAndroid Build Coastguard Worker TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
193*44844408SAndroid Build Coastguard Worker                              const Json::String& actual, const char* file,
194*44844408SAndroid Build Coastguard Worker                              unsigned int line, const char* expr);
195*44844408SAndroid Build Coastguard Worker 
196*44844408SAndroid Build Coastguard Worker } // namespace JsonTest
197*44844408SAndroid Build Coastguard Worker 
198*44844408SAndroid Build Coastguard Worker /// \brief Asserts that the given expression is true.
199*44844408SAndroid Build Coastguard Worker /// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y;
200*44844408SAndroid Build Coastguard Worker /// JSONTEST_ASSERT( x == y );
201*44844408SAndroid Build Coastguard Worker #define JSONTEST_ASSERT(expr)                                                  \
202*44844408SAndroid Build Coastguard Worker   if (expr) {                                                                  \
203*44844408SAndroid Build Coastguard Worker   } else                                                                       \
204*44844408SAndroid Build Coastguard Worker     result_->addFailure(__FILE__, __LINE__, #expr)
205*44844408SAndroid Build Coastguard Worker 
206*44844408SAndroid Build Coastguard Worker /// \brief Asserts that the given predicate is true.
207*44844408SAndroid Build Coastguard Worker /// The predicate may do other assertions and be a member function of the
208*44844408SAndroid Build Coastguard Worker /// fixture.
209*44844408SAndroid Build Coastguard Worker #define JSONTEST_ASSERT_PRED(expr)                                             \
210*44844408SAndroid Build Coastguard Worker   do {                                                                         \
211*44844408SAndroid Build Coastguard Worker     JsonTest::PredicateContext _minitest_Context = {                           \
212*44844408SAndroid Build Coastguard Worker         result_->predicateId_, __FILE__, __LINE__, #expr, NULL, NULL};         \
213*44844408SAndroid Build Coastguard Worker     result_->predicateStackTail_->next_ = &_minitest_Context;                  \
214*44844408SAndroid Build Coastguard Worker     result_->predicateId_ += 1;                                                \
215*44844408SAndroid Build Coastguard Worker     result_->predicateStackTail_ = &_minitest_Context;                         \
216*44844408SAndroid Build Coastguard Worker     (expr);                                                                    \
217*44844408SAndroid Build Coastguard Worker     result_->popPredicateContext();                                            \
218*44844408SAndroid Build Coastguard Worker   } while (0)
219*44844408SAndroid Build Coastguard Worker 
220*44844408SAndroid Build Coastguard Worker /// \brief Asserts that two values are equals.
221*44844408SAndroid Build Coastguard Worker #define JSONTEST_ASSERT_EQUAL(expected, actual)                                \
222*44844408SAndroid Build Coastguard Worker   JsonTest::checkEqual(*result_, expected, actual, __FILE__, __LINE__,         \
223*44844408SAndroid Build Coastguard Worker                        #expected " == " #actual)
224*44844408SAndroid Build Coastguard Worker 
225*44844408SAndroid Build Coastguard Worker /// \brief Asserts that two values are equals.
226*44844408SAndroid Build Coastguard Worker #define JSONTEST_ASSERT_STRING_EQUAL(expected, actual)                         \
227*44844408SAndroid Build Coastguard Worker   JsonTest::checkStringEqual(*result_, JsonTest::ToJsonString(expected),       \
228*44844408SAndroid Build Coastguard Worker                              JsonTest::ToJsonString(actual), __FILE__,         \
229*44844408SAndroid Build Coastguard Worker                              __LINE__, #expected " == " #actual)
230*44844408SAndroid Build Coastguard Worker 
231*44844408SAndroid Build Coastguard Worker /// \brief Asserts that a given expression throws an exception
232*44844408SAndroid Build Coastguard Worker #define JSONTEST_ASSERT_THROWS(expr)                                           \
233*44844408SAndroid Build Coastguard Worker   do {                                                                         \
234*44844408SAndroid Build Coastguard Worker     bool _threw = false;                                                       \
235*44844408SAndroid Build Coastguard Worker     try {                                                                      \
236*44844408SAndroid Build Coastguard Worker       expr;                                                                    \
237*44844408SAndroid Build Coastguard Worker     } catch (...) {                                                            \
238*44844408SAndroid Build Coastguard Worker       _threw = true;                                                           \
239*44844408SAndroid Build Coastguard Worker     }                                                                          \
240*44844408SAndroid Build Coastguard Worker     if (!_threw)                                                               \
241*44844408SAndroid Build Coastguard Worker       result_->addFailure(__FILE__, __LINE__,                                  \
242*44844408SAndroid Build Coastguard Worker                           "expected exception thrown: " #expr);                \
243*44844408SAndroid Build Coastguard Worker   } while (0)
244*44844408SAndroid Build Coastguard Worker 
245*44844408SAndroid Build Coastguard Worker /// \brief Begin a fixture test case.
246*44844408SAndroid Build Coastguard Worker #define JSONTEST_FIXTURE(FixtureType, name)                                    \
247*44844408SAndroid Build Coastguard Worker   class Test##FixtureType##name : public FixtureType {                         \
248*44844408SAndroid Build Coastguard Worker   public:                                                                      \
249*44844408SAndroid Build Coastguard Worker     static JsonTest::TestCase* factory() {                                     \
250*44844408SAndroid Build Coastguard Worker       return new Test##FixtureType##name();                                    \
251*44844408SAndroid Build Coastguard Worker     }                                                                          \
252*44844408SAndroid Build Coastguard Worker                                                                                \
253*44844408SAndroid Build Coastguard Worker   public: /* overridden from TestCase */                                       \
254*44844408SAndroid Build Coastguard Worker     const char* testName() const override { return #FixtureType "/" #name; }   \
255*44844408SAndroid Build Coastguard Worker     void runTestCase() override;                                               \
256*44844408SAndroid Build Coastguard Worker   };                                                                           \
257*44844408SAndroid Build Coastguard Worker                                                                                \
258*44844408SAndroid Build Coastguard Worker   void Test##FixtureType##name::runTestCase()
259*44844408SAndroid Build Coastguard Worker 
260*44844408SAndroid Build Coastguard Worker #define JSONTEST_FIXTURE_FACTORY(FixtureType, name)                            \
261*44844408SAndroid Build Coastguard Worker   &Test##FixtureType##name::factory
262*44844408SAndroid Build Coastguard Worker 
263*44844408SAndroid Build Coastguard Worker #define JSONTEST_REGISTER_FIXTURE(runner, FixtureType, name)                   \
264*44844408SAndroid Build Coastguard Worker   (runner).add(JSONTEST_FIXTURE_FACTORY(FixtureType, name))
265*44844408SAndroid Build Coastguard Worker 
266*44844408SAndroid Build Coastguard Worker /// \brief Begin a fixture test case.
267*44844408SAndroid Build Coastguard Worker #define JSONTEST_FIXTURE_V2(FixtureType, name, collections)                    \
268*44844408SAndroid Build Coastguard Worker   class Test##FixtureType##name : public FixtureType {                         \
269*44844408SAndroid Build Coastguard Worker   public:                                                                      \
270*44844408SAndroid Build Coastguard Worker     static JsonTest::TestCase* factory() {                                     \
271*44844408SAndroid Build Coastguard Worker       return new Test##FixtureType##name();                                    \
272*44844408SAndroid Build Coastguard Worker     }                                                                          \
273*44844408SAndroid Build Coastguard Worker     static bool collect() {                                                    \
274*44844408SAndroid Build Coastguard Worker       (collections).push_back(JSONTEST_FIXTURE_FACTORY(FixtureType, name));    \
275*44844408SAndroid Build Coastguard Worker       return true;                                                             \
276*44844408SAndroid Build Coastguard Worker     }                                                                          \
277*44844408SAndroid Build Coastguard Worker                                                                                \
278*44844408SAndroid Build Coastguard Worker   public: /* overridden from TestCase */                                       \
279*44844408SAndroid Build Coastguard Worker     const char* testName() const override { return #FixtureType "/" #name; }   \
280*44844408SAndroid Build Coastguard Worker     void runTestCase() override;                                               \
281*44844408SAndroid Build Coastguard Worker   };                                                                           \
282*44844408SAndroid Build Coastguard Worker                                                                                \
283*44844408SAndroid Build Coastguard Worker   static bool test##FixtureType##name##collect =                               \
284*44844408SAndroid Build Coastguard Worker       Test##FixtureType##name::collect();                                      \
285*44844408SAndroid Build Coastguard Worker                                                                                \
286*44844408SAndroid Build Coastguard Worker   void Test##FixtureType##name::runTestCase()
287*44844408SAndroid Build Coastguard Worker 
288*44844408SAndroid Build Coastguard Worker #endif // ifndef JSONTEST_H_INCLUDED
289