1/*
2 * Copyright 2017, Andrew Lindesay <apl@lindesay.co.nz>
3 * Distributed under the terms of the MIT License.
4 */
5#include "JsonToMessageTest.h"
6
7#include <Json.h>
8
9#include <cppunit/TestCaller.h>
10#include <cppunit/TestSuite.h>
11
12#include "JsonSamples.h"
13
14
15#define LOOPS_TEST_OBJECT_A_FOR_PERFORMANCE 100000
16
17using namespace BPrivate;
18
19
20JsonToMessageTest::JsonToMessageTest()
21{
22}
23
24
25JsonToMessageTest::~JsonToMessageTest()
26{
27}
28
29
30void
31JsonToMessageTest::TestArrayA()
32{
33	BMessage message;
34	BMessage subMessage;
35	BString stringValue;
36	double doubleValue;
37
38	// ----------------------
39	BJson::Parse(JSON_SAMPLE_ARRAY_A_IN, message);
40	// ----------------------
41
42	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [0]", B_OK,
43		message.FindString("0", &stringValue));
44	CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [0]", BString("1234"), stringValue);
45
46	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [1]", B_OK,
47		message.FindDouble("1", &doubleValue));
48	CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [1]", 4567, doubleValue);
49
50	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2]", B_OK,
51		message.FindMessage("2", &subMessage));
52
53	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2.0]", B_OK,
54		subMessage.FindString("0", &stringValue));
55	CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [2.0]", BString("A"), stringValue);
56
57	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2.1]", B_OK,
58		subMessage.FindString("1", &stringValue));
59	CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [2.1]", BString("b"), stringValue);
60
61	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2.2]", B_OK,
62		subMessage.FindString("2", &stringValue));
63	CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [2.2]", BString("C\xc3\xa9zanne"),
64		stringValue);
65}
66
67
68void
69JsonToMessageTest::TestArrayB()
70{
71	BMessage message;
72	BMessage subMessage;
73	BMessage subSubMessage;
74	BString stringValue;
75
76	// ----------------------
77	BJson::Parse(JSON_SAMPLE_ARRAY_B_IN, message);
78	// ----------------------
79
80	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [0]", B_OK,
81		message.FindString("0", &stringValue));
82	CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [0]", BString("Whirinaki"), stringValue);
83
84	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [1]", B_OK,
85		message.FindString("1", &stringValue));
86	CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [1]", BString("Wellington"), stringValue);
87
88	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2]", B_OK,
89		message.FindMessage("2", &subMessage));
90
91	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2.0]", B_OK,
92		subMessage.FindMessage("key", &subSubMessage));
93
94	CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2.0.0]", B_OK,
95		subSubMessage.FindString("0", &stringValue));
96	CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [2.0.0]", BString("value"), stringValue);
97}
98
99
100void
101JsonToMessageTest::TestObjectA()
102{
103	BMessage message;
104	BMessage subMessage;
105	BString stringValue;
106
107	// ----------------------
108	BJson::Parse(JSON_SAMPLE_OBJECT_A_IN, message);
109	// ----------------------
110
111	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindString("weather", &stringValue));
112	CPPUNIT_ASSERT_EQUAL(BString("raining"), stringValue);
113
114	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindString("humidity", &stringValue));
115	CPPUNIT_ASSERT_EQUAL(BString("too-high"), stringValue);
116
117	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("daysOfWeek", &subMessage));
118
119	CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindString("0", &stringValue));
120	CPPUNIT_ASSERT_EQUAL(BString("MON"), stringValue);
121
122	CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindString("1", &stringValue));
123	CPPUNIT_ASSERT_EQUAL(BString("TUE"), stringValue);
124
125	CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindString("2", &stringValue));
126	CPPUNIT_ASSERT_EQUAL(BString("WED"), stringValue);
127
128	CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindString("3", &stringValue));
129	CPPUNIT_ASSERT_EQUAL(BString("THR"), stringValue);
130
131	CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindString("4", &stringValue));
132	CPPUNIT_ASSERT_EQUAL(BString("FRI"), stringValue);
133}
134
135
136/*! This is not a real test, but is a convenient point at which to implement a
137    performance test.
138*/
139
140void
141JsonToMessageTest::TestObjectAForPerformance()
142{
143	int i;
144
145	for (i=0; i < LOOPS_TEST_OBJECT_A_FOR_PERFORMANCE; i++)
146		TestObjectA();
147}
148
149
150void
151JsonToMessageTest::TestObjectB()
152{
153	BMessage message;
154	bool boolValue;
155	void *ptrValue; // this is how NULL is represented.
156
157	// ----------------------
158	BJson::Parse(JSON_SAMPLE_OBJECT_B_IN, message);
159	// ----------------------
160
161	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindBool("testTrue", &boolValue));
162	CPPUNIT_ASSERT_EQUAL(true, boolValue);
163
164	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindBool("testFalse", &boolValue));
165	CPPUNIT_ASSERT_EQUAL(false, boolValue);
166
167	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindPointer("testNull", &ptrValue));
168	CPPUNIT_ASSERT_EQUAL(0, (addr_t)ptrValue);
169}
170
171
172void
173JsonToMessageTest::TestObjectC()
174{
175	BMessage message;
176	BMessage subMessage;
177	BString stringValue;
178
179	// ----------------------
180	BJson::Parse(JSON_SAMPLE_OBJECT_C_IN, message);
181	// ----------------------
182
183	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindString("key", &stringValue));
184	CPPUNIT_ASSERT_EQUAL(BString("value"), stringValue);
185}
186
187
188void
189JsonToMessageTest::TestUnterminatedObject()
190{
191	BMessage message;
192
193	// ----------------------
194	status_t result = BJson::Parse(JSON_SAMPLE_BROKEN_UNTERMINATED_OBJECT,
195		message);
196	// ----------------------
197
198	CPPUNIT_ASSERT_EQUAL(B_BAD_DATA, result);
199}
200
201
202void
203JsonToMessageTest::TestUnterminatedArray()
204{
205	BMessage message;
206
207	// ----------------------
208	status_t result = BJson::Parse(JSON_SAMPLE_BROKEN_UNTERMINATED_ARRAY,
209		message);
210	// ----------------------
211
212	CPPUNIT_ASSERT_EQUAL(B_BAD_DATA, result);
213}
214
215
216void JsonToMessageTest::TestHaikuDepotFetchBatch()
217{
218	const unsigned char input[] = JSON_SAMPLE_HDS_FETCH_BATCH_PKGS;
219	BMessage message;
220	BMessage resultMessage;
221	BMessage pkgsMessage;
222	BMessage pkgMessage1;
223	double modifyTimestampDouble;
224	double expectedModifyTimestampDouble = 1488785331631.0;
225
226	// ----------------------
227	status_t result = BJson::Parse((char*)input,
228		message);
229	// ----------------------
230
231	CPPUNIT_ASSERT_EQUAL(B_OK, result);
232
233		// this is quite a large test input so a random sample "thing to
234		// check" is chosen to indicate that the parse was successful.
235
236	CPPUNIT_ASSERT_EQUAL_MESSAGE("result", B_OK,
237		message.FindMessage("result", &resultMessage));
238	CPPUNIT_ASSERT_EQUAL_MESSAGE("pkgs", B_OK,
239		resultMessage.FindMessage("pkgs", &pkgsMessage));
240	CPPUNIT_ASSERT_EQUAL_MESSAGE("1", B_OK,
241		pkgsMessage.FindMessage("1", &pkgMessage1));
242	CPPUNIT_ASSERT_EQUAL_MESSAGE("modifyTimestamp", B_OK,
243		pkgMessage1.FindDouble("modifyTimestamp", &modifyTimestampDouble));
244
245	CPPUNIT_ASSERT_EQUAL(expectedModifyTimestampDouble, modifyTimestampDouble);
246}
247
248
249/*static*/ void
250JsonToMessageTest::AddTests(BTestSuite& parent)
251{
252	CppUnit::TestSuite& suite = *new CppUnit::TestSuite(
253		"JsonToMessageTest");
254
255	suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
256		"JsonToMessageTest::TestArrayA",
257		&JsonToMessageTest::TestArrayA));
258
259	suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
260		"JsonToMessageTest::TestArrayB",
261		&JsonToMessageTest::TestArrayB));
262
263	suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
264		"JsonToMessageTest::TestObjectA",
265		&JsonToMessageTest::TestObjectA));
266
267	suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
268		"JsonToMessageTest::TestObjectB",
269		&JsonToMessageTest::TestObjectB));
270
271	suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
272		"JsonToMessageTest::TestObjectC",
273		&JsonToMessageTest::TestObjectC));
274
275	suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
276		"JsonToMessageTest::TestUnterminatedObject",
277		&JsonToMessageTest::TestUnterminatedObject));
278
279	suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
280		"JsonToMessageTest::TestUnterminatedArray",
281		&JsonToMessageTest::TestUnterminatedArray));
282
283	suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
284		"JsonToMessageTest::TestHaikuDepotFetchBatch",
285		&JsonToMessageTest::TestHaikuDepotFetchBatch));
286
287//	suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
288//		"JsonToMessageTest::TestObjectAForPerformance",
289//		&JsonToMessageTest::TestObjectAForPerformance));
290
291	parent.addTest("JsonToMessageTest", &suite);
292}
293