xref: /aosp_15_r20/external/jsoncpp/src/test_lib_json/jsontest.cpp (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 #define _CRT_SECURE_NO_WARNINGS 1 // Prevents deprecation warning with MSVC
7*44844408SAndroid Build Coastguard Worker #include "jsontest.h"
8*44844408SAndroid Build Coastguard Worker #include <cstdio>
9*44844408SAndroid Build Coastguard Worker #include <string>
10*44844408SAndroid Build Coastguard Worker 
11*44844408SAndroid Build Coastguard Worker #if defined(_MSC_VER)
12*44844408SAndroid Build Coastguard Worker // Used to install a report hook that prevent dialog on assertion and error.
13*44844408SAndroid Build Coastguard Worker #include <crtdbg.h>
14*44844408SAndroid Build Coastguard Worker #endif // if defined(_MSC_VER)
15*44844408SAndroid Build Coastguard Worker 
16*44844408SAndroid Build Coastguard Worker #if defined(_WIN32)
17*44844408SAndroid Build Coastguard Worker // Used to prevent dialog on memory fault.
18*44844408SAndroid Build Coastguard Worker // Limits headers included by Windows.h
19*44844408SAndroid Build Coastguard Worker #define WIN32_LEAN_AND_MEAN
20*44844408SAndroid Build Coastguard Worker #define NOSERVICE
21*44844408SAndroid Build Coastguard Worker #define NOMCX
22*44844408SAndroid Build Coastguard Worker #define NOIME
23*44844408SAndroid Build Coastguard Worker #define NOSOUND
24*44844408SAndroid Build Coastguard Worker #define NOCOMM
25*44844408SAndroid Build Coastguard Worker #define NORPC
26*44844408SAndroid Build Coastguard Worker #define NOGDI
27*44844408SAndroid Build Coastguard Worker #define NOUSER
28*44844408SAndroid Build Coastguard Worker #define NODRIVERS
29*44844408SAndroid Build Coastguard Worker #define NOLOGERROR
30*44844408SAndroid Build Coastguard Worker #define NOPROFILER
31*44844408SAndroid Build Coastguard Worker #define NOMEMMGR
32*44844408SAndroid Build Coastguard Worker #define NOLFILEIO
33*44844408SAndroid Build Coastguard Worker #define NOOPENFILE
34*44844408SAndroid Build Coastguard Worker #define NORESOURCE
35*44844408SAndroid Build Coastguard Worker #define NOATOM
36*44844408SAndroid Build Coastguard Worker #define NOLANGUAGE
37*44844408SAndroid Build Coastguard Worker #define NOLSTRING
38*44844408SAndroid Build Coastguard Worker #define NODBCS
39*44844408SAndroid Build Coastguard Worker #define NOKEYBOARDINFO
40*44844408SAndroid Build Coastguard Worker #define NOGDICAPMASKS
41*44844408SAndroid Build Coastguard Worker #define NOCOLOR
42*44844408SAndroid Build Coastguard Worker #define NOGDIOBJ
43*44844408SAndroid Build Coastguard Worker #define NODRAWTEXT
44*44844408SAndroid Build Coastguard Worker #define NOTEXTMETRIC
45*44844408SAndroid Build Coastguard Worker #define NOSCALABLEFONT
46*44844408SAndroid Build Coastguard Worker #define NOBITMAP
47*44844408SAndroid Build Coastguard Worker #define NORASTEROPS
48*44844408SAndroid Build Coastguard Worker #define NOMETAFILE
49*44844408SAndroid Build Coastguard Worker #define NOSYSMETRICS
50*44844408SAndroid Build Coastguard Worker #define NOSYSTEMPARAMSINFO
51*44844408SAndroid Build Coastguard Worker #define NOMSG
52*44844408SAndroid Build Coastguard Worker #define NOWINSTYLES
53*44844408SAndroid Build Coastguard Worker #define NOWINOFFSETS
54*44844408SAndroid Build Coastguard Worker #define NOSHOWWINDOW
55*44844408SAndroid Build Coastguard Worker #define NODEFERWINDOWPOS
56*44844408SAndroid Build Coastguard Worker #define NOVIRTUALKEYCODES
57*44844408SAndroid Build Coastguard Worker #define NOKEYSTATES
58*44844408SAndroid Build Coastguard Worker #define NOWH
59*44844408SAndroid Build Coastguard Worker #define NOMENUS
60*44844408SAndroid Build Coastguard Worker #define NOSCROLL
61*44844408SAndroid Build Coastguard Worker #define NOCLIPBOARD
62*44844408SAndroid Build Coastguard Worker #define NOICONS
63*44844408SAndroid Build Coastguard Worker #define NOMB
64*44844408SAndroid Build Coastguard Worker #define NOSYSCOMMANDS
65*44844408SAndroid Build Coastguard Worker #define NOMDI
66*44844408SAndroid Build Coastguard Worker #define NOCTLMGR
67*44844408SAndroid Build Coastguard Worker #define NOWINMESSAGES
68*44844408SAndroid Build Coastguard Worker #include <windows.h>
69*44844408SAndroid Build Coastguard Worker #endif // if defined(_WIN32)
70*44844408SAndroid Build Coastguard Worker 
71*44844408SAndroid Build Coastguard Worker namespace JsonTest {
72*44844408SAndroid Build Coastguard Worker 
73*44844408SAndroid Build Coastguard Worker // class TestResult
74*44844408SAndroid Build Coastguard Worker // //////////////////////////////////////////////////////////////////
75*44844408SAndroid Build Coastguard Worker 
TestResult()76*44844408SAndroid Build Coastguard Worker TestResult::TestResult() {
77*44844408SAndroid Build Coastguard Worker   // The root predicate has id 0
78*44844408SAndroid Build Coastguard Worker   rootPredicateNode_.id_ = 0;
79*44844408SAndroid Build Coastguard Worker   rootPredicateNode_.next_ = nullptr;
80*44844408SAndroid Build Coastguard Worker   predicateStackTail_ = &rootPredicateNode_;
81*44844408SAndroid Build Coastguard Worker }
82*44844408SAndroid Build Coastguard Worker 
setTestName(const Json::String & name)83*44844408SAndroid Build Coastguard Worker void TestResult::setTestName(const Json::String& name) { name_ = name; }
84*44844408SAndroid Build Coastguard Worker 
addFailure(const char * file,unsigned int line,const char * expr)85*44844408SAndroid Build Coastguard Worker TestResult& TestResult::addFailure(const char* file, unsigned int line,
86*44844408SAndroid Build Coastguard Worker                                    const char* expr) {
87*44844408SAndroid Build Coastguard Worker   /// Walks the PredicateContext stack adding them to failures_ if not already
88*44844408SAndroid Build Coastguard Worker   /// added.
89*44844408SAndroid Build Coastguard Worker   unsigned int nestingLevel = 0;
90*44844408SAndroid Build Coastguard Worker   PredicateContext* lastNode = rootPredicateNode_.next_;
91*44844408SAndroid Build Coastguard Worker   for (; lastNode != nullptr; lastNode = lastNode->next_) {
92*44844408SAndroid Build Coastguard Worker     if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext
93*44844408SAndroid Build Coastguard Worker     {
94*44844408SAndroid Build Coastguard Worker       lastUsedPredicateId_ = lastNode->id_;
95*44844408SAndroid Build Coastguard Worker       addFailureInfo(lastNode->file_, lastNode->line_, lastNode->expr_,
96*44844408SAndroid Build Coastguard Worker                      nestingLevel);
97*44844408SAndroid Build Coastguard Worker       // Link the PredicateContext to the failure for message target when
98*44844408SAndroid Build Coastguard Worker       // popping the PredicateContext.
99*44844408SAndroid Build Coastguard Worker       lastNode->failure_ = &(failures_.back());
100*44844408SAndroid Build Coastguard Worker     }
101*44844408SAndroid Build Coastguard Worker     ++nestingLevel;
102*44844408SAndroid Build Coastguard Worker   }
103*44844408SAndroid Build Coastguard Worker 
104*44844408SAndroid Build Coastguard Worker   // Adds the failed assertion
105*44844408SAndroid Build Coastguard Worker   addFailureInfo(file, line, expr, nestingLevel);
106*44844408SAndroid Build Coastguard Worker   messageTarget_ = &(failures_.back());
107*44844408SAndroid Build Coastguard Worker   return *this;
108*44844408SAndroid Build Coastguard Worker }
109*44844408SAndroid Build Coastguard Worker 
addFailureInfo(const char * file,unsigned int line,const char * expr,unsigned int nestingLevel)110*44844408SAndroid Build Coastguard Worker void TestResult::addFailureInfo(const char* file, unsigned int line,
111*44844408SAndroid Build Coastguard Worker                                 const char* expr, unsigned int nestingLevel) {
112*44844408SAndroid Build Coastguard Worker   Failure failure;
113*44844408SAndroid Build Coastguard Worker   failure.file_ = file;
114*44844408SAndroid Build Coastguard Worker   failure.line_ = line;
115*44844408SAndroid Build Coastguard Worker   if (expr) {
116*44844408SAndroid Build Coastguard Worker     failure.expr_ = expr;
117*44844408SAndroid Build Coastguard Worker   }
118*44844408SAndroid Build Coastguard Worker   failure.nestingLevel_ = nestingLevel;
119*44844408SAndroid Build Coastguard Worker   failures_.push_back(failure);
120*44844408SAndroid Build Coastguard Worker }
121*44844408SAndroid Build Coastguard Worker 
popPredicateContext()122*44844408SAndroid Build Coastguard Worker TestResult& TestResult::popPredicateContext() {
123*44844408SAndroid Build Coastguard Worker   PredicateContext* lastNode = &rootPredicateNode_;
124*44844408SAndroid Build Coastguard Worker   while (lastNode->next_ != nullptr && lastNode->next_->next_ != nullptr) {
125*44844408SAndroid Build Coastguard Worker     lastNode = lastNode->next_;
126*44844408SAndroid Build Coastguard Worker   }
127*44844408SAndroid Build Coastguard Worker   // Set message target to popped failure
128*44844408SAndroid Build Coastguard Worker   PredicateContext* tail = lastNode->next_;
129*44844408SAndroid Build Coastguard Worker   if (tail != nullptr && tail->failure_ != nullptr) {
130*44844408SAndroid Build Coastguard Worker     messageTarget_ = tail->failure_;
131*44844408SAndroid Build Coastguard Worker   }
132*44844408SAndroid Build Coastguard Worker   // Remove tail from list
133*44844408SAndroid Build Coastguard Worker   predicateStackTail_ = lastNode;
134*44844408SAndroid Build Coastguard Worker   lastNode->next_ = nullptr;
135*44844408SAndroid Build Coastguard Worker   return *this;
136*44844408SAndroid Build Coastguard Worker }
137*44844408SAndroid Build Coastguard Worker 
failed() const138*44844408SAndroid Build Coastguard Worker bool TestResult::failed() const { return !failures_.empty(); }
139*44844408SAndroid Build Coastguard Worker 
printFailure(bool printTestName) const140*44844408SAndroid Build Coastguard Worker void TestResult::printFailure(bool printTestName) const {
141*44844408SAndroid Build Coastguard Worker   if (failures_.empty()) {
142*44844408SAndroid Build Coastguard Worker     return;
143*44844408SAndroid Build Coastguard Worker   }
144*44844408SAndroid Build Coastguard Worker 
145*44844408SAndroid Build Coastguard Worker   if (printTestName) {
146*44844408SAndroid Build Coastguard Worker     printf("* Detail of %s test failure:\n", name_.c_str());
147*44844408SAndroid Build Coastguard Worker   }
148*44844408SAndroid Build Coastguard Worker 
149*44844408SAndroid Build Coastguard Worker   // Print in reverse to display the callstack in the right order
150*44844408SAndroid Build Coastguard Worker   for (const auto& failure : failures_) {
151*44844408SAndroid Build Coastguard Worker     Json::String indent(failure.nestingLevel_ * 2, ' ');
152*44844408SAndroid Build Coastguard Worker     if (failure.file_) {
153*44844408SAndroid Build Coastguard Worker       printf("%s%s(%u): ", indent.c_str(), failure.file_, failure.line_);
154*44844408SAndroid Build Coastguard Worker     }
155*44844408SAndroid Build Coastguard Worker     if (!failure.expr_.empty()) {
156*44844408SAndroid Build Coastguard Worker       printf("%s\n", failure.expr_.c_str());
157*44844408SAndroid Build Coastguard Worker     } else if (failure.file_) {
158*44844408SAndroid Build Coastguard Worker       printf("\n");
159*44844408SAndroid Build Coastguard Worker     }
160*44844408SAndroid Build Coastguard Worker     if (!failure.message_.empty()) {
161*44844408SAndroid Build Coastguard Worker       Json::String reindented = indentText(failure.message_, indent + "  ");
162*44844408SAndroid Build Coastguard Worker       printf("%s\n", reindented.c_str());
163*44844408SAndroid Build Coastguard Worker     }
164*44844408SAndroid Build Coastguard Worker   }
165*44844408SAndroid Build Coastguard Worker }
166*44844408SAndroid Build Coastguard Worker 
indentText(const Json::String & text,const Json::String & indent)167*44844408SAndroid Build Coastguard Worker Json::String TestResult::indentText(const Json::String& text,
168*44844408SAndroid Build Coastguard Worker                                     const Json::String& indent) {
169*44844408SAndroid Build Coastguard Worker   Json::String reindented;
170*44844408SAndroid Build Coastguard Worker   Json::String::size_type lastIndex = 0;
171*44844408SAndroid Build Coastguard Worker   while (lastIndex < text.size()) {
172*44844408SAndroid Build Coastguard Worker     Json::String::size_type nextIndex = text.find('\n', lastIndex);
173*44844408SAndroid Build Coastguard Worker     if (nextIndex == Json::String::npos) {
174*44844408SAndroid Build Coastguard Worker       nextIndex = text.size() - 1;
175*44844408SAndroid Build Coastguard Worker     }
176*44844408SAndroid Build Coastguard Worker     reindented += indent;
177*44844408SAndroid Build Coastguard Worker     reindented += text.substr(lastIndex, nextIndex - lastIndex + 1);
178*44844408SAndroid Build Coastguard Worker     lastIndex = nextIndex + 1;
179*44844408SAndroid Build Coastguard Worker   }
180*44844408SAndroid Build Coastguard Worker   return reindented;
181*44844408SAndroid Build Coastguard Worker }
182*44844408SAndroid Build Coastguard Worker 
addToLastFailure(const Json::String & message)183*44844408SAndroid Build Coastguard Worker TestResult& TestResult::addToLastFailure(const Json::String& message) {
184*44844408SAndroid Build Coastguard Worker   if (messageTarget_ != nullptr) {
185*44844408SAndroid Build Coastguard Worker     messageTarget_->message_ += message;
186*44844408SAndroid Build Coastguard Worker   }
187*44844408SAndroid Build Coastguard Worker   return *this;
188*44844408SAndroid Build Coastguard Worker }
189*44844408SAndroid Build Coastguard Worker 
operator <<(Json::Int64 value)190*44844408SAndroid Build Coastguard Worker TestResult& TestResult::operator<<(Json::Int64 value) {
191*44844408SAndroid Build Coastguard Worker   return addToLastFailure(Json::valueToString(value));
192*44844408SAndroid Build Coastguard Worker }
193*44844408SAndroid Build Coastguard Worker 
operator <<(Json::UInt64 value)194*44844408SAndroid Build Coastguard Worker TestResult& TestResult::operator<<(Json::UInt64 value) {
195*44844408SAndroid Build Coastguard Worker   return addToLastFailure(Json::valueToString(value));
196*44844408SAndroid Build Coastguard Worker }
197*44844408SAndroid Build Coastguard Worker 
operator <<(bool value)198*44844408SAndroid Build Coastguard Worker TestResult& TestResult::operator<<(bool value) {
199*44844408SAndroid Build Coastguard Worker   return addToLastFailure(value ? "true" : "false");
200*44844408SAndroid Build Coastguard Worker }
201*44844408SAndroid Build Coastguard Worker 
202*44844408SAndroid Build Coastguard Worker // class TestCase
203*44844408SAndroid Build Coastguard Worker // //////////////////////////////////////////////////////////////////
204*44844408SAndroid Build Coastguard Worker 
205*44844408SAndroid Build Coastguard Worker TestCase::TestCase() = default;
206*44844408SAndroid Build Coastguard Worker 
207*44844408SAndroid Build Coastguard Worker TestCase::~TestCase() = default;
208*44844408SAndroid Build Coastguard Worker 
run(TestResult & result)209*44844408SAndroid Build Coastguard Worker void TestCase::run(TestResult& result) {
210*44844408SAndroid Build Coastguard Worker   result_ = &result;
211*44844408SAndroid Build Coastguard Worker   runTestCase();
212*44844408SAndroid Build Coastguard Worker }
213*44844408SAndroid Build Coastguard Worker 
214*44844408SAndroid Build Coastguard Worker // class Runner
215*44844408SAndroid Build Coastguard Worker // //////////////////////////////////////////////////////////////////
216*44844408SAndroid Build Coastguard Worker 
217*44844408SAndroid Build Coastguard Worker Runner::Runner() = default;
218*44844408SAndroid Build Coastguard Worker 
add(TestCaseFactory factory)219*44844408SAndroid Build Coastguard Worker Runner& Runner::add(TestCaseFactory factory) {
220*44844408SAndroid Build Coastguard Worker   tests_.push_back(factory);
221*44844408SAndroid Build Coastguard Worker   return *this;
222*44844408SAndroid Build Coastguard Worker }
223*44844408SAndroid Build Coastguard Worker 
testCount() const224*44844408SAndroid Build Coastguard Worker size_t Runner::testCount() const { return tests_.size(); }
225*44844408SAndroid Build Coastguard Worker 
testNameAt(size_t index) const226*44844408SAndroid Build Coastguard Worker Json::String Runner::testNameAt(size_t index) const {
227*44844408SAndroid Build Coastguard Worker   TestCase* test = tests_[index]();
228*44844408SAndroid Build Coastguard Worker   Json::String name = test->testName();
229*44844408SAndroid Build Coastguard Worker   delete test;
230*44844408SAndroid Build Coastguard Worker   return name;
231*44844408SAndroid Build Coastguard Worker }
232*44844408SAndroid Build Coastguard Worker 
runTestAt(size_t index,TestResult & result) const233*44844408SAndroid Build Coastguard Worker void Runner::runTestAt(size_t index, TestResult& result) const {
234*44844408SAndroid Build Coastguard Worker   TestCase* test = tests_[index]();
235*44844408SAndroid Build Coastguard Worker   result.setTestName(test->testName());
236*44844408SAndroid Build Coastguard Worker   printf("Testing %s: ", test->testName());
237*44844408SAndroid Build Coastguard Worker   fflush(stdout);
238*44844408SAndroid Build Coastguard Worker #if JSON_USE_EXCEPTION
239*44844408SAndroid Build Coastguard Worker   try {
240*44844408SAndroid Build Coastguard Worker #endif // if JSON_USE_EXCEPTION
241*44844408SAndroid Build Coastguard Worker     test->run(result);
242*44844408SAndroid Build Coastguard Worker #if JSON_USE_EXCEPTION
243*44844408SAndroid Build Coastguard Worker   } catch (const std::exception& e) {
244*44844408SAndroid Build Coastguard Worker     result.addFailure(__FILE__, __LINE__, "Unexpected exception caught:")
245*44844408SAndroid Build Coastguard Worker         << e.what();
246*44844408SAndroid Build Coastguard Worker   }
247*44844408SAndroid Build Coastguard Worker #endif // if JSON_USE_EXCEPTION
248*44844408SAndroid Build Coastguard Worker   delete test;
249*44844408SAndroid Build Coastguard Worker   const char* status = result.failed() ? "FAILED" : "OK";
250*44844408SAndroid Build Coastguard Worker   printf("%s\n", status);
251*44844408SAndroid Build Coastguard Worker   fflush(stdout);
252*44844408SAndroid Build Coastguard Worker }
253*44844408SAndroid Build Coastguard Worker 
runAllTest(bool printSummary) const254*44844408SAndroid Build Coastguard Worker bool Runner::runAllTest(bool printSummary) const {
255*44844408SAndroid Build Coastguard Worker   size_t const count = testCount();
256*44844408SAndroid Build Coastguard Worker   std::deque<TestResult> failures;
257*44844408SAndroid Build Coastguard Worker   for (size_t index = 0; index < count; ++index) {
258*44844408SAndroid Build Coastguard Worker     TestResult result;
259*44844408SAndroid Build Coastguard Worker     runTestAt(index, result);
260*44844408SAndroid Build Coastguard Worker     if (result.failed()) {
261*44844408SAndroid Build Coastguard Worker       failures.push_back(result);
262*44844408SAndroid Build Coastguard Worker     }
263*44844408SAndroid Build Coastguard Worker   }
264*44844408SAndroid Build Coastguard Worker 
265*44844408SAndroid Build Coastguard Worker   if (failures.empty()) {
266*44844408SAndroid Build Coastguard Worker     if (printSummary) {
267*44844408SAndroid Build Coastguard Worker       printf("All %zu tests passed\n", count);
268*44844408SAndroid Build Coastguard Worker     }
269*44844408SAndroid Build Coastguard Worker     return true;
270*44844408SAndroid Build Coastguard Worker   }
271*44844408SAndroid Build Coastguard Worker   for (auto& result : failures) {
272*44844408SAndroid Build Coastguard Worker     result.printFailure(count > 1);
273*44844408SAndroid Build Coastguard Worker   }
274*44844408SAndroid Build Coastguard Worker 
275*44844408SAndroid Build Coastguard Worker   if (printSummary) {
276*44844408SAndroid Build Coastguard Worker     size_t const failedCount = failures.size();
277*44844408SAndroid Build Coastguard Worker     size_t const passedCount = count - failedCount;
278*44844408SAndroid Build Coastguard Worker     printf("%zu/%zu tests passed (%zu failure(s))\n", passedCount, count,
279*44844408SAndroid Build Coastguard Worker            failedCount);
280*44844408SAndroid Build Coastguard Worker   }
281*44844408SAndroid Build Coastguard Worker   return false;
282*44844408SAndroid Build Coastguard Worker }
283*44844408SAndroid Build Coastguard Worker 
testIndex(const Json::String & testName,size_t & indexOut) const284*44844408SAndroid Build Coastguard Worker bool Runner::testIndex(const Json::String& testName, size_t& indexOut) const {
285*44844408SAndroid Build Coastguard Worker   const size_t count = testCount();
286*44844408SAndroid Build Coastguard Worker   for (size_t index = 0; index < count; ++index) {
287*44844408SAndroid Build Coastguard Worker     if (testNameAt(index) == testName) {
288*44844408SAndroid Build Coastguard Worker       indexOut = index;
289*44844408SAndroid Build Coastguard Worker       return true;
290*44844408SAndroid Build Coastguard Worker     }
291*44844408SAndroid Build Coastguard Worker   }
292*44844408SAndroid Build Coastguard Worker   return false;
293*44844408SAndroid Build Coastguard Worker }
294*44844408SAndroid Build Coastguard Worker 
listTests() const295*44844408SAndroid Build Coastguard Worker void Runner::listTests() const {
296*44844408SAndroid Build Coastguard Worker   const size_t count = testCount();
297*44844408SAndroid Build Coastguard Worker   for (size_t index = 0; index < count; ++index) {
298*44844408SAndroid Build Coastguard Worker     printf("%s\n", testNameAt(index).c_str());
299*44844408SAndroid Build Coastguard Worker   }
300*44844408SAndroid Build Coastguard Worker }
301*44844408SAndroid Build Coastguard Worker 
runCommandLine(int argc,const char * argv[]) const302*44844408SAndroid Build Coastguard Worker int Runner::runCommandLine(int argc, const char* argv[]) const {
303*44844408SAndroid Build Coastguard Worker   // typedef std::deque<String> TestNames;
304*44844408SAndroid Build Coastguard Worker   Runner subrunner;
305*44844408SAndroid Build Coastguard Worker   for (int index = 1; index < argc; ++index) {
306*44844408SAndroid Build Coastguard Worker     Json::String opt = argv[index];
307*44844408SAndroid Build Coastguard Worker     if (opt == "--list-tests") {
308*44844408SAndroid Build Coastguard Worker       listTests();
309*44844408SAndroid Build Coastguard Worker       return 0;
310*44844408SAndroid Build Coastguard Worker     }
311*44844408SAndroid Build Coastguard Worker     if (opt == "--test-auto") {
312*44844408SAndroid Build Coastguard Worker       preventDialogOnCrash();
313*44844408SAndroid Build Coastguard Worker     } else if (opt == "--test") {
314*44844408SAndroid Build Coastguard Worker       ++index;
315*44844408SAndroid Build Coastguard Worker       if (index < argc) {
316*44844408SAndroid Build Coastguard Worker         size_t testNameIndex;
317*44844408SAndroid Build Coastguard Worker         if (testIndex(argv[index], testNameIndex)) {
318*44844408SAndroid Build Coastguard Worker           subrunner.add(tests_[testNameIndex]);
319*44844408SAndroid Build Coastguard Worker         } else {
320*44844408SAndroid Build Coastguard Worker           fprintf(stderr, "Test '%s' does not exist!\n", argv[index]);
321*44844408SAndroid Build Coastguard Worker           return 2;
322*44844408SAndroid Build Coastguard Worker         }
323*44844408SAndroid Build Coastguard Worker       } else {
324*44844408SAndroid Build Coastguard Worker         printUsage(argv[0]);
325*44844408SAndroid Build Coastguard Worker         return 2;
326*44844408SAndroid Build Coastguard Worker       }
327*44844408SAndroid Build Coastguard Worker     } else {
328*44844408SAndroid Build Coastguard Worker       printUsage(argv[0]);
329*44844408SAndroid Build Coastguard Worker       return 2;
330*44844408SAndroid Build Coastguard Worker     }
331*44844408SAndroid Build Coastguard Worker   }
332*44844408SAndroid Build Coastguard Worker   bool succeeded;
333*44844408SAndroid Build Coastguard Worker   if (subrunner.testCount() > 0) {
334*44844408SAndroid Build Coastguard Worker     succeeded = subrunner.runAllTest(subrunner.testCount() > 1);
335*44844408SAndroid Build Coastguard Worker   } else {
336*44844408SAndroid Build Coastguard Worker     succeeded = runAllTest(true);
337*44844408SAndroid Build Coastguard Worker   }
338*44844408SAndroid Build Coastguard Worker   return succeeded ? 0 : 1;
339*44844408SAndroid Build Coastguard Worker }
340*44844408SAndroid Build Coastguard Worker 
341*44844408SAndroid Build Coastguard Worker #if defined(_MSC_VER) && defined(_DEBUG)
342*44844408SAndroid Build Coastguard Worker // Hook MSVCRT assertions to prevent dialog from appearing
msvcrtSilentReportHook(int reportType,char * message,int *)343*44844408SAndroid Build Coastguard Worker static int msvcrtSilentReportHook(int reportType, char* message,
344*44844408SAndroid Build Coastguard Worker                                   int* /*returnValue*/) {
345*44844408SAndroid Build Coastguard Worker   // The default CRT handling of error and assertion is to display
346*44844408SAndroid Build Coastguard Worker   // an error dialog to the user.
347*44844408SAndroid Build Coastguard Worker   // Instead, when an error or an assertion occurs, we force the
348*44844408SAndroid Build Coastguard Worker   // application to terminate using abort() after display
349*44844408SAndroid Build Coastguard Worker   // the message on stderr.
350*44844408SAndroid Build Coastguard Worker   if (reportType == _CRT_ERROR || reportType == _CRT_ASSERT) {
351*44844408SAndroid Build Coastguard Worker     // calling abort() cause the ReportHook to be called
352*44844408SAndroid Build Coastguard Worker     // The following is used to detect this case and let's the
353*44844408SAndroid Build Coastguard Worker     // error handler fallback on its default behaviour (
354*44844408SAndroid Build Coastguard Worker     // display a warning message)
355*44844408SAndroid Build Coastguard Worker     static volatile bool isAborting = false;
356*44844408SAndroid Build Coastguard Worker     if (isAborting) {
357*44844408SAndroid Build Coastguard Worker       return TRUE;
358*44844408SAndroid Build Coastguard Worker     }
359*44844408SAndroid Build Coastguard Worker     isAborting = true;
360*44844408SAndroid Build Coastguard Worker 
361*44844408SAndroid Build Coastguard Worker     fprintf(stderr, "CRT Error/Assert:\n%s\n", message);
362*44844408SAndroid Build Coastguard Worker     fflush(stderr);
363*44844408SAndroid Build Coastguard Worker     abort();
364*44844408SAndroid Build Coastguard Worker   }
365*44844408SAndroid Build Coastguard Worker   // Let's other reportType (_CRT_WARNING) be handled as they would by default
366*44844408SAndroid Build Coastguard Worker   return FALSE;
367*44844408SAndroid Build Coastguard Worker }
368*44844408SAndroid Build Coastguard Worker #endif // if defined(_MSC_VER)
369*44844408SAndroid Build Coastguard Worker 
preventDialogOnCrash()370*44844408SAndroid Build Coastguard Worker void Runner::preventDialogOnCrash() {
371*44844408SAndroid Build Coastguard Worker #if defined(_MSC_VER) && defined(_DEBUG)
372*44844408SAndroid Build Coastguard Worker   // Install a hook to prevent MSVCRT error and assertion from
373*44844408SAndroid Build Coastguard Worker   // popping a dialog
374*44844408SAndroid Build Coastguard Worker   // This function a NO-OP in release configuration
375*44844408SAndroid Build Coastguard Worker   // (which cause warning since msvcrtSilentReportHook is not referenced)
376*44844408SAndroid Build Coastguard Worker   _CrtSetReportHook(&msvcrtSilentReportHook);
377*44844408SAndroid Build Coastguard Worker #endif // if defined(_MSC_VER)
378*44844408SAndroid Build Coastguard Worker 
379*44844408SAndroid Build Coastguard Worker   // @todo investigate this handler (for buffer overflow)
380*44844408SAndroid Build Coastguard Worker   // _set_security_error_handler
381*44844408SAndroid Build Coastguard Worker 
382*44844408SAndroid Build Coastguard Worker #if defined(_WIN32)
383*44844408SAndroid Build Coastguard Worker   // Prevents the system from popping a dialog for debugging if the
384*44844408SAndroid Build Coastguard Worker   // application fails due to invalid memory access.
385*44844408SAndroid Build Coastguard Worker   SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
386*44844408SAndroid Build Coastguard Worker                SEM_NOOPENFILEERRORBOX);
387*44844408SAndroid Build Coastguard Worker #endif // if defined(_WIN32)
388*44844408SAndroid Build Coastguard Worker }
389*44844408SAndroid Build Coastguard Worker 
printUsage(const char * appName)390*44844408SAndroid Build Coastguard Worker void Runner::printUsage(const char* appName) {
391*44844408SAndroid Build Coastguard Worker   printf("Usage: %s [options]\n"
392*44844408SAndroid Build Coastguard Worker          "\n"
393*44844408SAndroid Build Coastguard Worker          "If --test is not specified, then all the test cases be run.\n"
394*44844408SAndroid Build Coastguard Worker          "\n"
395*44844408SAndroid Build Coastguard Worker          "Valid options:\n"
396*44844408SAndroid Build Coastguard Worker          "--list-tests: print the name of all test cases on the standard\n"
397*44844408SAndroid Build Coastguard Worker          "              output and exit.\n"
398*44844408SAndroid Build Coastguard Worker          "--test TESTNAME: executes the test case with the specified name.\n"
399*44844408SAndroid Build Coastguard Worker          "                 May be repeated.\n"
400*44844408SAndroid Build Coastguard Worker          "--test-auto: prevent dialog prompting for debugging on crash.\n",
401*44844408SAndroid Build Coastguard Worker          appName);
402*44844408SAndroid Build Coastguard Worker }
403*44844408SAndroid Build Coastguard Worker 
404*44844408SAndroid Build Coastguard Worker // Assertion functions
405*44844408SAndroid Build Coastguard Worker // //////////////////////////////////////////////////////////////////
406*44844408SAndroid Build Coastguard Worker 
ToJsonString(const char * toConvert)407*44844408SAndroid Build Coastguard Worker Json::String ToJsonString(const char* toConvert) {
408*44844408SAndroid Build Coastguard Worker   return Json::String(toConvert);
409*44844408SAndroid Build Coastguard Worker }
410*44844408SAndroid Build Coastguard Worker 
ToJsonString(Json::String in)411*44844408SAndroid Build Coastguard Worker Json::String ToJsonString(Json::String in) { return in; }
412*44844408SAndroid Build Coastguard Worker 
413*44844408SAndroid Build Coastguard Worker #if JSONCPP_USING_SECURE_MEMORY
ToJsonString(std::string in)414*44844408SAndroid Build Coastguard Worker Json::String ToJsonString(std::string in) {
415*44844408SAndroid Build Coastguard Worker   return Json::String(in.data(), in.data() + in.length());
416*44844408SAndroid Build Coastguard Worker }
417*44844408SAndroid Build Coastguard Worker #endif
418*44844408SAndroid Build Coastguard Worker 
checkStringEqual(TestResult & result,const Json::String & expected,const Json::String & actual,const char * file,unsigned int line,const char * expr)419*44844408SAndroid Build Coastguard Worker TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
420*44844408SAndroid Build Coastguard Worker                              const Json::String& actual, const char* file,
421*44844408SAndroid Build Coastguard Worker                              unsigned int line, const char* expr) {
422*44844408SAndroid Build Coastguard Worker   if (expected != actual) {
423*44844408SAndroid Build Coastguard Worker     result.addFailure(file, line, expr);
424*44844408SAndroid Build Coastguard Worker     result << "Expected: '" << expected << "'\n";
425*44844408SAndroid Build Coastguard Worker     result << "Actual  : '" << actual << "'";
426*44844408SAndroid Build Coastguard Worker   }
427*44844408SAndroid Build Coastguard Worker   return result;
428*44844408SAndroid Build Coastguard Worker }
429*44844408SAndroid Build Coastguard Worker 
430*44844408SAndroid Build Coastguard Worker } // namespace JsonTest
431