1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #include "unittest.h"
16 
17 #include "rapidjson/document.h"
18 
19 using namespace rapidjson;
20 
ReadFile(const char * filename,size_t & length)21 static char* ReadFile(const char* filename, size_t& length) {
22     const char *paths[] = {
23         "jsonchecker",
24         "bin/jsonchecker",
25         "../bin/jsonchecker",
26         "../../bin/jsonchecker",
27         "../../../bin/jsonchecker"
28     };
29     char buffer[1024];
30     FILE *fp = 0;
31     for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
32         sprintf(buffer, "%s/%s", paths[i], filename);
33         fp = fopen(buffer, "rb");
34         if (fp)
35             break;
36     }
37 
38     if (!fp)
39         return 0;
40 
41     fseek(fp, 0, SEEK_END);
42     length = static_cast<size_t>(ftell(fp));
43     fseek(fp, 0, SEEK_SET);
44     char* json = static_cast<char*>(malloc(length + 1));
45     size_t readLength = fread(json, 1, length, fp);
46     json[readLength] = '\0';
47     fclose(fp);
48     return json;
49 }
50 
51 struct NoOpHandler {
NullNoOpHandler52     bool Null() { return true; }
BoolNoOpHandler53     bool Bool(bool) { return true; }
IntNoOpHandler54     bool Int(int) { return true; }
UintNoOpHandler55     bool Uint(unsigned) { return true; }
Int64NoOpHandler56     bool Int64(int64_t) { return true; }
Uint64NoOpHandler57     bool Uint64(uint64_t) { return true; }
DoubleNoOpHandler58     bool Double(double) { return true; }
RawNumberNoOpHandler59     bool RawNumber(const char*, SizeType, bool) { return true; }
StringNoOpHandler60     bool String(const char*, SizeType, bool) { return true; }
StartObjectNoOpHandler61     bool StartObject() { return true; }
KeyNoOpHandler62     bool Key(const char*, SizeType, bool) { return true; }
EndObjectNoOpHandler63     bool EndObject(SizeType) { return true; }
StartArrayNoOpHandler64     bool StartArray() { return true; }
EndArrayNoOpHandler65     bool EndArray(SizeType) { return true; }
66 };
67 
68 
TEST(JsonChecker,Reader)69 TEST(JsonChecker, Reader) {
70     char filename[256];
71 
72     // jsonchecker/failXX.json
73     for (int i = 1; i <= 33; i++) {
74         if (i == 1) // fail1.json is valid in rapidjson, which has no limitation on type of root element (RFC 7159).
75             continue;
76         if (i == 18)    // fail18.json is valid in rapidjson, which has no limitation on depth of nesting.
77             continue;
78 
79         sprintf(filename, "fail%d.json", i);
80         size_t length;
81         char* json = ReadFile(filename, length);
82         if (!json) {
83             printf("jsonchecker file %s not found", filename);
84             ADD_FAILURE();
85             continue;
86         }
87 
88         // Test stack-based parsing.
89         GenericDocument<UTF8<>, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak)
90         document.Parse(json);
91         EXPECT_TRUE(document.HasParseError()) << filename;
92 
93         // Test iterative parsing.
94         document.Parse<kParseIterativeFlag>(json);
95         EXPECT_TRUE(document.HasParseError()) << filename;
96 
97         // Test iterative pull-parsing.
98         Reader reader;
99         StringStream ss(json);
100         NoOpHandler h;
101         reader.IterativeParseInit();
102         while (!reader.IterativeParseComplete()) {
103             if (!reader.IterativeParseNext<kParseDefaultFlags>(ss, h))
104                 break;
105         }
106         EXPECT_TRUE(reader.HasParseError()) << filename;
107 
108         free(json);
109     }
110 
111     // passX.json
112     for (int i = 1; i <= 3; i++) {
113         sprintf(filename, "pass%d.json", i);
114         size_t length;
115         char* json = ReadFile(filename, length);
116         if (!json) {
117             printf("jsonchecker file %s not found", filename);
118             continue;
119         }
120 
121         // Test stack-based parsing.
122         GenericDocument<UTF8<>, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak)
123         document.Parse(json);
124         EXPECT_FALSE(document.HasParseError()) << filename;
125 
126         // Test iterative parsing.
127         document.Parse<kParseIterativeFlag>(json);
128         EXPECT_FALSE(document.HasParseError()) << filename;
129 
130         // Test iterative pull-parsing.
131         Reader reader;
132         StringStream ss(json);
133         NoOpHandler h;
134         reader.IterativeParseInit();
135         while (!reader.IterativeParseComplete()) {
136             if (!reader.IterativeParseNext<kParseDefaultFlags>(ss, h))
137                 break;
138         }
139         EXPECT_FALSE(reader.HasParseError()) << filename;
140 
141         free(json);
142     }
143 }
144