xref: /haiku/src/tests/kits/shared/JsonEndToEndTest.cpp (revision 4c07199d8201fcf267e90be0d24b76799d03cea6)
1 /*
2  * Copyright 2017-2023, Andrew Lindesay <apl@lindesay.co.nz>
3  * Distributed under the terms of the MIT License.
4  */
5 #include "JsonEndToEndTest.h"
6 
7 #include <AutoDeleter.h>
8 
9 #include <Json.h>
10 #include <JsonTextWriter.h>
11 
12 #include <cppunit/TestCaller.h>
13 #include <cppunit/TestSuite.h>
14 
15 #include "ChecksumJsonEventListener.h"
16 #include "FakeJsonDataGenerator.h"
17 #include "JsonSamples.h"
18 
19 
20 using namespace BPrivate;
21 
22 
23 static const size_t kHighVolumeItemCount = 10000;
24 static const uint32 kChecksumLimit = 100000;
25 
26 
27 JsonEndToEndTest::JsonEndToEndTest()
28 {
29 }
30 
31 
32 JsonEndToEndTest::~JsonEndToEndTest()
33 {
34 }
35 
36 
37 /*! Just here so it is possible to extract timings for the data generation cost.
38 */
39 
40 void
41 JsonEndToEndTest::TestHighVolumeStringSampleGenerationOnly()
42 {
43 	FakeJsonStreamDataIO* inputData = new FakeJsonStringStreamDataIO(kHighVolumeItemCount,
44 		kChecksumLimit);
45 	char c;
46 
47 	while (inputData->Read(&c, 1) == 1) {
48 		// do nothing
49 	}
50 }
51 
52 
53 /*! Just here so it is possible to extract timings for the data generation cost.
54 */
55 
56 void
57 JsonEndToEndTest::TestHighVolumeNumberSampleGenerationOnly()
58 {
59 	FakeJsonStreamDataIO* inputData = new FakeJsonNumberStreamDataIO(kHighVolumeItemCount,
60 		kChecksumLimit);
61 	char c;
62 
63 	while (inputData->Read(&c, 1) == 1) {
64 		// do nothing
65 	}
66 }
67 
68 
69 void
70 JsonEndToEndTest::TestHighVolumeStringParsing()
71 {
72 	FakeJsonStreamDataIO* inputData = new FakeJsonStringStreamDataIO(kHighVolumeItemCount,
73 		kChecksumLimit);
74 	ChecksumJsonEventListener* listener = new ChecksumJsonEventListener(kChecksumLimit);
75 
76 	// ----------------------
77     BPrivate::BJson::Parse(inputData, listener);
78     // ----------------------
79 
80 	CPPUNIT_ASSERT_EQUAL(B_OK, listener->Error());
81 	CPPUNIT_ASSERT_EQUAL(inputData->Checksum(), listener->Checksum());
82 }
83 
84 
85 void
86 JsonEndToEndTest::TestHighVolumeNumberParsing()
87 {
88 	FakeJsonStreamDataIO* inputData = new FakeJsonNumberStreamDataIO(kHighVolumeItemCount,
89 		kChecksumLimit);
90 	ChecksumJsonEventListener* listener = new ChecksumJsonEventListener(kChecksumLimit);
91 
92 	// ----------------------
93     BPrivate::BJson::Parse(inputData, listener);
94     // ----------------------
95 
96 	CPPUNIT_ASSERT_EQUAL(B_OK, listener->Error());
97 	CPPUNIT_ASSERT_EQUAL(inputData->Checksum(), listener->Checksum());
98 }
99 
100 
101 void
102 JsonEndToEndTest::TestParseAndWrite(const char* input, const char* expectedOutput)
103 {
104 	BDataIO* inputData = new BMemoryIO(input, strlen(input));
105 	ObjectDeleter<BDataIO> inputDataDeleter(inputData);
106 	BMallocIO* outputData = new BMallocIO();
107 	ObjectDeleter<BMallocIO> outputDataDeleter(outputData);
108 	BPrivate::BJsonTextWriter* listener
109 		= new BJsonTextWriter(outputData);
110 	ObjectDeleter<BPrivate::BJsonTextWriter> listenerDeleter(listener);
111 
112 // ----------------------
113 	BPrivate::BJson::Parse(inputData, listener);
114 // ----------------------
115 
116 	CPPUNIT_ASSERT_EQUAL(B_OK, listener->ErrorStatus());
117 	fprintf(stderr, "in           >%s<\n", input);
118 	fprintf(stderr, "expected out >%s<\n", expectedOutput);
119 	fprintf(stderr, "actual out   >%s<\n", (char*)outputData->Buffer());
120 	CPPUNIT_ASSERT_MESSAGE("expected did no equal actual output",
121 		0 == strncmp(expectedOutput, (char*)outputData->Buffer(),
122 			strlen(expectedOutput)));
123 }
124 
125 
126 void
127 JsonEndToEndTest::TestNullA()
128 {
129 	TestParseAndWrite(JSON_SAMPLE_NULL_A_IN,
130 		JSON_SAMPLE_NULL_A_EXPECTED_OUT);
131 }
132 
133 
134 void
135 JsonEndToEndTest::TestTrueA()
136 {
137 	TestParseAndWrite(JSON_SAMPLE_TRUE_A_IN,
138 		JSON_SAMPLE_TRUE_A_EXPECTED_OUT);
139 }
140 
141 
142 void
143 JsonEndToEndTest::TestFalseA()
144 {
145 	TestParseAndWrite(JSON_SAMPLE_FALSE_A_IN,
146 		JSON_SAMPLE_FALSE_A_EXPECTED_OUT);
147 }
148 
149 
150 void
151 JsonEndToEndTest::TestNumberA()
152 {
153 	TestParseAndWrite(JSON_SAMPLE_NUMBER_A_IN,
154 		JSON_SAMPLE_NUMBER_A_EXPECTED_OUT);
155 }
156 
157 
158 void
159 JsonEndToEndTest::TestStringA()
160 {
161 	TestParseAndWrite(JSON_SAMPLE_STRING_A_IN,
162 		JSON_SAMPLE_STRING_A_EXPECTED_OUT);
163 }
164 
165 
166 void
167 JsonEndToEndTest::TestStringB()
168 {
169 	TestParseAndWrite(JSON_SAMPLE_STRING_B_IN,
170 		JSON_SAMPLE_STRING_B_EXPECTED_OUT);
171 }
172 
173 
174 /* In this test, there are some UTF-8 characters. */
175 
176 void
177 JsonEndToEndTest::TestStringA2()
178 {
179 	TestParseAndWrite(JSON_SAMPLE_STRING_A2_IN,
180 		JSON_SAMPLE_STRING_A_EXPECTED_OUT);
181 }
182 
183 
184 void
185 JsonEndToEndTest::TestArrayA()
186 {
187 	TestParseAndWrite(JSON_SAMPLE_ARRAY_A_IN, JSON_SAMPLE_ARRAY_A_EXPECTED_OUT);
188 }
189 
190 
191 void
192 JsonEndToEndTest::TestArrayB()
193 {
194 	TestParseAndWrite(JSON_SAMPLE_ARRAY_B_IN, JSON_SAMPLE_ARRAY_B_EXPECTED_OUT);
195 }
196 
197 
198 void
199 JsonEndToEndTest::TestObjectA()
200 {
201 	TestParseAndWrite(JSON_SAMPLE_OBJECT_A_IN,
202 		JSON_SAMPLE_OBJECT_A_EXPECTED_OUT);
203 }
204 
205 
206 /*! This method will test an element being unterminated; such an object that
207     is missing the terminating "}" symbol or a string that has no closing
208     quote.  This is tested here because the writer
209 */
210 
211 void
212 JsonEndToEndTest::TestUnterminated(const char *input)
213 {
214 	BDataIO* inputData = new BMemoryIO(input, strlen(input));
215 	ObjectDeleter<BDataIO> inputDataDeleter(inputData);
216 	BMallocIO* outputData = new BMallocIO();
217 	ObjectDeleter<BMallocIO> outputDataDeleter(outputData);
218 	BPrivate::BJsonTextWriter* listener
219 		= new BJsonTextWriter(outputData);
220 	ObjectDeleter<BPrivate::BJsonTextWriter> listenerDeleter(listener);
221 
222 // ----------------------
223 	BPrivate::BJson::Parse(inputData, listener);
224 // ----------------------
225 
226 	CPPUNIT_ASSERT_EQUAL(B_BAD_DATA, listener->ErrorStatus());
227 }
228 
229 
230 void
231 JsonEndToEndTest::TestStringUnterminated()
232 {
233 	TestUnterminated(JSON_SAMPLE_BROKEN_UNTERMINATED_STRING);
234 }
235 
236 void
237 JsonEndToEndTest::TestArrayUnterminated()
238 {
239 	TestUnterminated(JSON_SAMPLE_BROKEN_UNTERMINATED_ARRAY);
240 }
241 
242 void
243 JsonEndToEndTest::TestObjectUnterminated()
244 {
245 	TestUnterminated(JSON_SAMPLE_BROKEN_UNTERMINATED_OBJECT);
246 }
247 
248 
249 /*static*/ void
250 JsonEndToEndTest::AddTests(BTestSuite& parent)
251 {
252 	CppUnit::TestSuite& suite = *new CppUnit::TestSuite("JsonEndToEndTest");
253 
254 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
255 		"JsonEndToEndTest::TestNullA", &JsonEndToEndTest::TestNullA));
256 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
257 		"JsonEndToEndTest::TestTrueA", &JsonEndToEndTest::TestTrueA));
258 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
259 		"JsonEndToEndTest::TestFalseA", &JsonEndToEndTest::TestFalseA));
260 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
261 		"JsonEndToEndTest::TestNumberA", &JsonEndToEndTest::TestNumberA));
262 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
263 		"JsonEndToEndTest::TestStringA", &JsonEndToEndTest::TestStringA));
264 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
265 		"JsonEndToEndTest::TestStringA2", &JsonEndToEndTest::TestStringA2));
266 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
267 		"JsonEndToEndTest::TestStringB", &JsonEndToEndTest::TestStringB));
268 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
269 		"JsonEndToEndTest::TestArrayA", &JsonEndToEndTest::TestArrayA));
270 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
271 		"JsonEndToEndTest::TestArrayB", &JsonEndToEndTest::TestArrayB));
272 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
273 		"JsonEndToEndTest::TestObjectA", &JsonEndToEndTest::TestObjectA));
274 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
275 		"JsonEndToEndTest::TestStringUnterminated",
276 		&JsonEndToEndTest::TestStringUnterminated));
277 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
278 		"JsonEndToEndTest::TestArrayUnterminated",
279 		&JsonEndToEndTest::TestArrayUnterminated));
280 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
281 		"JsonEndToEndTest::TestHighVolumeStringParsing",
282 		&JsonEndToEndTest::TestHighVolumeStringParsing));
283 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
284 		"JsonEndToEndTest::TestHighVolumeNumberParsing",
285 		&JsonEndToEndTest::TestHighVolumeNumberParsing));
286 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
287 		"JsonEndToEndTest::TestHighVolumeStringSampleGenerationOnly",
288 		&JsonEndToEndTest::TestHighVolumeStringSampleGenerationOnly));
289 	suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
290 		"JsonEndToEndTest::TestHighVolumeNumberSampleGenerationOnly",
291 		&JsonEndToEndTest::TestHighVolumeNumberSampleGenerationOnly));
292 
293 	parent.addTest("JsonEndToEndTest", &suite);
294 }
295