1/*
2 * Copyright 2017-2020, Andrew Lindesay <apl@lindesay.co.nz>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5
6#include "DumpExportRepositorySource.h"
7#include "DumpExportRepository.h"
8#include "DumpExportRepositoryJsonListener.h"
9#include "DumpExportRepositoryJsonListenerTest.h"
10
11#include <stdio.h>
12
13#include <AutoDeleter.h>
14#include <Json.h>
15
16#include <cppunit/TestCaller.h>
17#include <cppunit/TestSuite.h>
18
19// This repository example is valid, but does have some additional
20// rubbish data at the start.  Some values have been shortened to make
21// testing easier.
22
23#define SINGLE_REPOSITORY_WITH_RUBBISH "{\n" \
24	"  \"rubbish\": {\n" \
25	"    \"key\": \"value\",\n" \
26	"    \"anylist\": [\n" \
27	"      1,\n" \
28	"      2,\n" \
29	"      3,\n" \
30	"      null\n" \
31	"    ]\n" \
32	"  },\n" \
33	"  \"code\": \"haikuports\",\n" \
34	"  \"name\": \"HaikuPorts\",\n" \
35	"  \"description\": \"HaikuPorts is a centralized collection...\",\n" \
36	"  \"informationUrl\": \"https://example.com\",\n" \
37	"  \"repositorySources\": [\n" \
38	"    {\n" \
39	"      \"code\": \"haikuports_x86_64\",\n" \
40	"      \"identifier\": \"haiku:hpkr:haikuports_x86_64\",\n" \
41	"      \"extraIdentifiers\":[\"zing\"]\n" \
42	"    },\n" \
43	"    {\n" \
44	"      \"code\": \"haikuports_x86_gcc2\",\n" \
45	"      \"identifier\": \"haiku:hpkr:haikuports_x86_gcc2\"\n" \
46	"    }\n" \
47	"  ]\n" \
48	"}\n"
49
50// this is more or less the data that would come back from the server when
51// a bulk list of repositories is requested.  Some values have been shortened
52// to make testing easier.
53
54#define BULK_CONTAINER_REPOSITORY_WITH_RUBBISH "{\n" \
55   "  \"info\": {\n" \
56   "    \"createTimestamp\": 1506547178986,\n" \
57   "    \"createTimestampIso\": \"2017-09-27 21:19:38\",\n" \
58   "    \"dataModifiedTimestamp\": 1500605691000,\n" \
59   "    \"dataModifiedTimestampIso\": \"2017-07-21 02:54:51\",\n" \
60   "    \"agent\": \"hds\",\n" \
61   "    \"agentVersion\": \"1.0.87\"\n" \
62   "  },\n" \
63   "  \"items\": [\n" \
64   "    {\n" \
65   "      \"code\": \"fatelk\",\n" \
66   "      \"name\": \"FatElk\",\n" \
67   "      \"informationUrl\": \"http://fatelk.com/\",\n" \
68   "      \"repositorySources\": [\n" \
69   "        {\n" \
70   "          \"code\": \"fatelk_x86_gcc2\",\n" \
71   "          \"identifier\": \"can-be-anything\",\n" \
72   "          \"extraIdentifiers\":[\"zing\"]\n" \
73   "        }\n" \
74   "      ]\n" \
75   "    },\n" \
76   "    {\n" \
77   "      \"code\": \"besly\",\n" \
78   "      \"name\": \"BeSly\",\n" \
79   "      \"informationUrl\": \"http://www.software.besly.de/\",\n" \
80   "      \"repositorySources\": [\n" \
81   "        {\n" \
82   "          \"code\": \"besly_x86_gcc2\",\n" \
83   "          \"identifier\": \"haiku:hpkr:wojfqdi23e\"\n" \
84   "        }\n" \
85   "      ]\n" \
86   "    },\n" \
87   "    {\n" \
88   "      \"code\": \"clasqm\",\n" \
89   "      \"name\": \"Clasqm\",\n" \
90   "      \"informationUrl\": \"http://AA18\",\n" \
91   "      \"repositorySources\": [\n" \
92   "        {\n" \
93   "          \"code\": \"clasqm_x86_64\",\n" \
94   "          \"identifier\": \"haiku:hpkr:23r829rro\"\n" \
95   "        },\n" \
96   "        {\n" \
97   "          \"code\": \"clasqm_x86_gcc2\",\n" \
98   "          \"identifier\": \"haiku:hpkr:joihir32r\"\n" \
99   "        }\n" \
100   "      ]\n" \
101   "    },\n" \
102   "    {\n" \
103   "      \"code\": \"haikuports\",\n" \
104   "      \"name\": \"HaikuPorts\",\n" \
105   "      \"description\": \"HaikuPorts is a centralized collection ...\",\n" \
106   "      \"informationUrl\": \"https://github.com/haikuports/haikuports\",\n" \
107   "      \"repositorySources\": [\n" \
108   "        {\n" \
109   "          \"code\": \"haikuports_x86_64\",\n" \
110   "          \"identifier\": \"haiku:hpkr:jqod2333r3r\"\n" \
111   "        },\n" \
112   "        {\n" \
113   "          \"code\": \"haikuports_x86_gcc2\",\n" \
114   "          \"identifier\": \"haiku:hpkr:wyeuhfwiewe\"\n" \
115   "        }\n" \
116   "      ]\n" \
117   "    }\n" \
118   "  ]\n" \
119   "}"
120
121
122class TestBulkContainerItemListener : public DumpExportRepositoryListener {
123public:
124							TestBulkContainerItemListener();
125		virtual				~TestBulkContainerItemListener();
126
127			bool			Handle(DumpExportRepository* item);
128			void			Complete();
129
130			BString			ConcatenatedCodes();
131			BString			ConcatenatedSourcesUrls();
132			bool			WasCompleteInvoked();
133
134private:
135			bool			fWasCompleteInvoked;
136			BString			fConcatenatedCodes;
137			BString			fConcatenatedSourcesUrl;
138};
139
140
141DumpExportRepositoryJsonListenerTest::DumpExportRepositoryJsonListenerTest()
142{
143}
144
145
146DumpExportRepositoryJsonListenerTest::~DumpExportRepositoryJsonListenerTest()
147{
148}
149
150
151void
152DumpExportRepositoryJsonListenerTest::TestBulkContainer()
153{
154	BDataIO* inputData = new BMemoryIO(BULK_CONTAINER_REPOSITORY_WITH_RUBBISH,
155		strlen(BULK_CONTAINER_REPOSITORY_WITH_RUBBISH));
156	ObjectDeleter<BDataIO> inputDataDeleter(inputData);
157
158	TestBulkContainerItemListener itemListener;
159
160	BulkContainerDumpExportRepositoryJsonListener* listener =
161		new BulkContainerDumpExportRepositoryJsonListener(&itemListener);
162	ObjectDeleter<BulkContainerDumpExportRepositoryJsonListener>
163		listenerDeleter(listener);
164
165// ----------------------
166	BPrivate::BJson::Parse(inputData, listener);
167// ----------------------
168
169	CPPUNIT_ASSERT_EQUAL_MESSAGE("!B_OK",
170		B_OK, listener->ErrorStatus());
171	CPPUNIT_ASSERT_EQUAL_MESSAGE("!WasCompleteInvoked",
172		true, itemListener.WasCompleteInvoked());
173	CPPUNIT_ASSERT_EQUAL_MESSAGE("!ConcatenatedCodes",
174		BString("fatelk besly clasqm haikuports"),
175		itemListener.ConcatenatedCodes());
176	CPPUNIT_ASSERT_EQUAL_MESSAGE("!ConcatenatedSourcesUrls",
177		BString("can-be-anything"
178			" haiku:hpkr:wojfqdi23e"
179			" haiku:hpkr:23r829rro"
180			" haiku:hpkr:joihir32r"
181			" haiku:hpkr:jqod2333r3r"
182			" haiku:hpkr:wyeuhfwiewe"),
183		itemListener.ConcatenatedSourcesUrls());
184}
185
186
187void
188DumpExportRepositoryJsonListenerTest::TestSingle()
189{
190	BDataIO* inputData = new BMemoryIO(SINGLE_REPOSITORY_WITH_RUBBISH,
191		strlen(SINGLE_REPOSITORY_WITH_RUBBISH));
192	ObjectDeleter<BDataIO> inputDataDeleter(inputData);
193
194	SingleDumpExportRepositoryJsonListener* listener =
195		new SingleDumpExportRepositoryJsonListener();
196	ObjectDeleter<SingleDumpExportRepositoryJsonListener>
197		listenerDeleter(listener);
198
199// ----------------------
200	BPrivate::BJson::Parse(inputData, listener);
201// ----------------------
202
203	DumpExportRepository *repository = listener->Target();
204	ObjectDeleter<DumpExportRepository> repositoryDeleter(repository);
205
206	CPPUNIT_ASSERT_EQUAL(B_OK, listener->ErrorStatus());
207
208	CPPUNIT_ASSERT_EQUAL(
209		BString("haikuports"), *(repository->Code()));
210	CPPUNIT_ASSERT_EQUAL(
211		BString("HaikuPorts"), *(repository->Name()));
212	CPPUNIT_ASSERT_EQUAL(
213		BString("HaikuPorts is a centralized collection..."),
214		*(repository->Description()));
215	CPPUNIT_ASSERT_EQUAL(
216		BString("https://example.com"),
217		*(repository->InformationUrl()));
218	CPPUNIT_ASSERT_EQUAL(2, repository->CountRepositorySources());
219
220	DumpExportRepositorySource *source0 =
221		repository->RepositorySourcesItemAt(0);
222	DumpExportRepositorySource *source1 =
223		repository->RepositorySourcesItemAt(1);
224
225	CPPUNIT_ASSERT_EQUAL(BString("haikuports_x86_64"), *(source0->Code()));
226	CPPUNIT_ASSERT_EQUAL(BString("haiku:hpkr:haikuports_x86_64"), *(source0->Identifier()));
227	CPPUNIT_ASSERT_EQUAL(BString("zing"), *(source0->ExtraIdentifiersItemAt(0)));
228
229	CPPUNIT_ASSERT_EQUAL(BString("haikuports_x86_gcc2"), *(source1->Code()));
230	CPPUNIT_ASSERT_EQUAL(BString("haiku:hpkr:haikuports_x86_gcc2"), *(source1->Identifier()));
231}
232
233
234/*static*/ void
235DumpExportRepositoryJsonListenerTest::AddTests(BTestSuite& parent)
236{
237	CppUnit::TestSuite& suite = *new CppUnit::TestSuite(
238		"DumpExportRepositoryJsonListenerTest");
239
240	suite.addTest(
241		new CppUnit::TestCaller<DumpExportRepositoryJsonListenerTest>(
242			"DumpExportRepositoryJsonListenerTest::TestSingle",
243			&DumpExportRepositoryJsonListenerTest::TestSingle));
244
245	suite.addTest(
246		new CppUnit::TestCaller<DumpExportRepositoryJsonListenerTest>(
247			"DumpExportRepositoryJsonListenerTest::TestBulkContainer",
248			&DumpExportRepositoryJsonListenerTest::TestBulkContainer));
249
250	parent.addTest("DumpExportRepositoryJsonListenerTest", &suite);
251}
252
253
254TestBulkContainerItemListener::TestBulkContainerItemListener()
255{
256	fWasCompleteInvoked = false;
257}
258
259
260TestBulkContainerItemListener::~TestBulkContainerItemListener()
261{
262}
263
264/*! Note that the item object will be deleted after this method
265    is invoked.  The Handle method need not take responsibility
266    for this.
267*/
268
269bool
270TestBulkContainerItemListener::Handle(DumpExportRepository* item)
271{
272	int32 i;
273
274	if (!fConcatenatedCodes.IsEmpty())
275		fConcatenatedCodes.Append(" ");
276
277	fConcatenatedCodes.Append(item->Code()->String());
278
279	for (i = 0; i < item->CountRepositorySources(); i++) {
280		if (!fConcatenatedSourcesUrl.IsEmpty())
281    		fConcatenatedSourcesUrl.Append(" ");
282
283		fConcatenatedSourcesUrl.Append(
284			item->RepositorySourcesItemAt(i)->Identifier()->String());
285	}
286
287	return true;
288}
289
290
291void
292TestBulkContainerItemListener::Complete()
293{
294	fWasCompleteInvoked = true;
295}
296
297
298BString
299TestBulkContainerItemListener::ConcatenatedCodes()
300{
301	return fConcatenatedCodes;
302}
303
304
305BString
306TestBulkContainerItemListener::ConcatenatedSourcesUrls()
307{
308	return fConcatenatedSourcesUrl;
309}
310
311
312bool
313TestBulkContainerItemListener::WasCompleteInvoked()
314{
315	return fWasCompleteInvoked;
316}
317