VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTCRest-1.cpp@ 74277

Last change on this file since 74277 was 74277, checked in by vboxsync, 6 years ago

tstRTCRest-1: Fixed crash in testStringMap. bugref:9167

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 100.0 KB
Line 
1/* $Id: tstRTCRest-1.cpp 74277 2018-09-14 16:08:36Z vboxsync $ */
2/** @file
3 * IPRT Testcase - REST C++ classes.
4 */
5
6/*
7 * Copyright (C) 2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/cpp/restbase.h>
32#include <iprt/cpp/restarray.h>
33#include <iprt/cpp/reststringmap.h>
34#include <iprt/cpp/restclient.h>
35
36#include <iprt/ctype.h>
37#include <iprt/err.h>
38#include <iprt/message.h>
39#include <iprt/string.h>
40#include <iprt/test.h>
41
42#include <float.h> /* DBL_MIN, DBL_MAX */
43
44
45/*********************************************************************************************************************************
46* Global Variables *
47*********************************************************************************************************************************/
48static RTTEST g_hTest;
49
50
51static char *toJson(RTCRestObjectBase const *pObj)
52{
53 RTCString str;
54 RTCRestOutputToString Dst(&str, false);
55 pObj->serializeAsJson(Dst);
56
57 static char s_szReturnBuffer[4096];
58 RTStrCopy(s_szReturnBuffer, sizeof(s_szReturnBuffer), str.c_str());
59 return s_szReturnBuffer;
60}
61
62
63static int deserializeFromJson(RTCRestObjectBase *pObj, const char *pszJson, PRTERRINFOSTATIC pErrInfo, const char *pszName)
64{
65 RTJSONVAL hValue;
66 RTTESTI_CHECK_RC_OK_RET(RTJsonParseFromString(&hValue, pszJson, pErrInfo ? RTErrInfoInitStatic(pErrInfo) : NULL), rcCheck);
67 RTCRestJsonPrimaryCursor Cursor(hValue, pszName, pErrInfo ? RTErrInfoInitStatic(pErrInfo) : NULL);
68 return pObj->deserializeFromJson(Cursor.m_Cursor);
69}
70
71
72static int fromString(RTCRestObjectBase *pObj, const char *pszString, PRTERRINFOSTATIC pErrInfo, const char *pszName)
73{
74 RTCString strValue(pszString);
75 return pObj->fromString(strValue, pszName, pErrInfo ? RTErrInfoInitStatic(pErrInfo) : NULL);
76}
77
78
79static void testBool(void)
80{
81 RTTestSub(g_hTest, "RTCRestBool");
82
83 {
84 RTCRestBool obj1;
85 RTTESTI_CHECK(obj1.m_fValue == false);
86 RTTESTI_CHECK(obj1.isNull() == false);
87 RTTESTI_CHECK(strcmp(obj1.typeName(), "bool") == 0);
88 RTTESTI_CHECK(obj1.typeClass() == RTCRestObjectBase::kTypeClass_Bool);
89 }
90
91 {
92 RTCRestBool obj2(true);
93 RTTESTI_CHECK(obj2.m_fValue == true);
94 RTTESTI_CHECK(obj2.isNull() == false);
95 }
96
97 {
98 RTCRestBool obj2(false);
99 RTTESTI_CHECK(obj2.m_fValue == false);
100 RTTESTI_CHECK(obj2.isNull() == false);
101 }
102
103 {
104 /* Value assignments: */
105 RTCRestBool obj3;
106 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
107 RTTESTI_CHECK(obj3.isNull() == true);
108 obj3.assignValue(true);
109 RTTESTI_CHECK(obj3.m_fValue == true);
110 RTTESTI_CHECK(obj3.isNull() == false);
111
112 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
113 RTTESTI_CHECK(obj3.isNull() == true);
114 obj3.assignValue(false);
115 RTTESTI_CHECK(obj3.m_fValue == false);
116 RTTESTI_CHECK(obj3.isNull() == false);
117
118 obj3.assignValue(true);
119 RTTESTI_CHECK(obj3.m_fValue == true);
120 RTTESTI_CHECK(obj3.isNull() == false);
121
122 RTTESTI_CHECK_RC(obj3.resetToDefault(), VINF_SUCCESS);
123 RTTESTI_CHECK(obj3.m_fValue == false);
124 RTTESTI_CHECK(obj3.isNull() == false);
125
126 obj3.assignValue(true);
127 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
128 RTTESTI_CHECK_RC(obj3.resetToDefault(), VINF_SUCCESS);
129 RTTESTI_CHECK(obj3.m_fValue == false);
130 RTTESTI_CHECK(obj3.isNull() == false);
131
132 /* Copy assignments: */
133 RTCRestBool obj3True(true);
134 RTTESTI_CHECK(obj3True.m_fValue == true);
135 RTTESTI_CHECK(obj3True.isNull() == false);
136 RTCRestBool obj3False(false);
137 RTTESTI_CHECK(obj3False.m_fValue == false);
138 RTTESTI_CHECK(obj3False.isNull() == false);
139 RTCRestBool obj3Null;
140 obj3Null.setNull();
141 RTTESTI_CHECK(obj3Null.m_fValue == false);
142 RTTESTI_CHECK(obj3Null.isNull() == true);
143
144 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
145 RTTESTI_CHECK_RC(obj3.assignCopy(obj3True), VINF_SUCCESS);
146 RTTESTI_CHECK(obj3.m_fValue == true);
147 RTTESTI_CHECK(obj3.isNull() == false);
148
149 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Null), VINF_SUCCESS);
150 RTTESTI_CHECK(obj3.m_fValue == false);
151 RTTESTI_CHECK(obj3.isNull() == true);
152
153 RTTESTI_CHECK_RC(obj3.assignCopy(obj3False), VINF_SUCCESS);
154 RTTESTI_CHECK(obj3.m_fValue == false);
155 RTTESTI_CHECK(obj3.isNull() == false);
156
157 obj3 = obj3Null;
158 RTTESTI_CHECK(obj3.m_fValue == false);
159 RTTESTI_CHECK(obj3.isNull() == true);
160
161 obj3 = obj3True;
162 RTTESTI_CHECK(obj3.m_fValue == true);
163 RTTESTI_CHECK(obj3.isNull() == false);
164
165 obj3 = obj3Null;
166 RTTESTI_CHECK(obj3.m_fValue == false);
167 RTTESTI_CHECK(obj3.isNull() == true);
168
169 obj3 = obj3False;
170 RTTESTI_CHECK(obj3.m_fValue == false);
171 RTTESTI_CHECK(obj3.isNull() == false);
172
173 /* setNull implies resetToDefault: */
174 obj3 = obj3True;
175 RTTESTI_CHECK(obj3.m_fValue == true);
176 RTTESTI_CHECK(obj3.isNull() == false);
177 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
178 RTTESTI_CHECK(obj3.isNull() == true);
179 RTTESTI_CHECK(obj3.m_fValue == false);
180
181 /* Copy constructors: */
182 {
183 RTCRestBool obj3a(obj3True);
184 RTTESTI_CHECK(obj3a.m_fValue == true);
185 RTTESTI_CHECK(obj3a.isNull() == false);
186 }
187 {
188 RTCRestBool obj3b(obj3False);
189 RTTESTI_CHECK(obj3b.m_fValue == false);
190 RTTESTI_CHECK(obj3b.isNull() == false);
191 }
192 {
193 RTCRestBool obj3c(obj3Null);
194 RTTESTI_CHECK(obj3c.m_fValue == false);
195 RTTESTI_CHECK(obj3c.isNull() == true);
196 }
197
198 /* Serialization to json: */
199 const char *pszJson = toJson(&obj3True);
200 RTTESTI_CHECK_MSG(strcmp(pszJson, "true") == 0, ("pszJson=%s\n", pszJson));
201 pszJson = toJson(&obj3False);
202 RTTESTI_CHECK_MSG(strcmp(pszJson, "false") == 0, ("pszJson=%s\n", pszJson));
203 pszJson = toJson(&obj3Null);
204 RTTESTI_CHECK_MSG(strcmp(pszJson, "null") == 0, ("pszJson=%s\n", pszJson));
205
206 /* Serialization to string. */
207 RTCString str;
208 str = "lead-in:";
209 RTTESTI_CHECK_RC(obj3True.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
210 RTTESTI_CHECK_MSG(str.equals("lead-in:true"), ("str=%s\n", str.c_str()));
211 RTTESTI_CHECK_RC(obj3True.toString(&str), VINF_SUCCESS);
212 RTTESTI_CHECK_MSG(str.equals("true"), ("str=%s\n", str.c_str()));
213
214 str = "lead-in:";
215 RTTESTI_CHECK_RC(obj3False.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
216 RTTESTI_CHECK_MSG(str.equals("lead-in:false"), ("str=%s\n", str.c_str()));
217 RTTESTI_CHECK_RC(obj3False.toString(&str), VINF_SUCCESS);
218 RTTESTI_CHECK_MSG(str.equals("false"), ("str=%s\n", str.c_str()));
219
220 str = "lead-in:";
221 RTTESTI_CHECK_RC(obj3Null.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
222 RTTESTI_CHECK_MSG(str.equals("lead-in:null"), ("str=%s\n", str.c_str()));
223 RTTESTI_CHECK_RC(obj3Null.toString(&str), VINF_SUCCESS);
224 RTTESTI_CHECK_MSG(str.equals("null"), ("str=%s\n", str.c_str()));
225 }
226
227 /* deserialize: */
228 RTERRINFOSTATIC ErrInfo;
229 {
230 RTCRestBool obj4;
231 obj4.setNull();
232 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "false", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
233 RTTESTI_CHECK(obj4.m_fValue == false);
234 RTTESTI_CHECK(obj4.isNull() == false);
235
236 obj4.setNull();
237 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "true", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
238 RTTESTI_CHECK(obj4.m_fValue == true);
239 RTTESTI_CHECK(obj4.isNull() == false);
240
241 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "null", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
242 RTTESTI_CHECK(obj4.m_fValue == false);
243 RTTESTI_CHECK(obj4.isNull() == true);
244
245 /* object goes to default state on failure: */
246 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "0", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_BOOL);
247 RTTESTI_CHECK(obj4.m_fValue == false);
248 RTTESTI_CHECK(obj4.isNull() == false);
249 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
250
251 obj4.assignValue(true);
252 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"false\"", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_BOOL);
253 RTTESTI_CHECK(obj4.m_fValue == false);
254 RTTESTI_CHECK(obj4.isNull() == false);
255 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
256
257 obj4.setNull();
258 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "[ null ]", NULL, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_BOOL);
259 RTTESTI_CHECK(obj4.m_fValue == false);
260 RTTESTI_CHECK(obj4.isNull() == false);
261
262 obj4.setNull();
263 RTTESTI_CHECK_RC(fromString(&obj4, "true", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
264 RTTESTI_CHECK(obj4.m_fValue == true);
265 RTTESTI_CHECK(obj4.isNull() == false);
266
267 RTTESTI_CHECK_RC(fromString(&obj4, "false", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
268 RTTESTI_CHECK(obj4.m_fValue == false);
269 RTTESTI_CHECK(obj4.isNull() == false);
270
271 obj4.m_fValue = true;
272 RTTESTI_CHECK_RC(fromString(&obj4, "null", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
273 RTTESTI_CHECK(obj4.m_fValue == false);
274 RTTESTI_CHECK(obj4.isNull() == true);
275
276 obj4.setNull();
277 RTTESTI_CHECK_RC(fromString(&obj4, " TrUe ", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
278 RTTESTI_CHECK(obj4.m_fValue == true);
279 RTTESTI_CHECK(obj4.isNull() == false);
280
281 RTTESTI_CHECK_RC(fromString(&obj4, "\tfAlSe;", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
282 RTTESTI_CHECK(obj4.m_fValue == false);
283 RTTESTI_CHECK(obj4.isNull() == false);
284
285 RTTESTI_CHECK_RC(fromString(&obj4, "\r\nfAlSe\n;", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
286 RTTESTI_CHECK(obj4.m_fValue == false);
287 RTTESTI_CHECK(obj4.isNull() == false);
288
289 RTTESTI_CHECK_RC(fromString(&obj4, "\r\tNuLl\n;", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
290 RTTESTI_CHECK(obj4.m_fValue == false);
291 RTTESTI_CHECK(obj4.isNull() == true);
292
293 RTTESTI_CHECK_RC(fromString(&obj4, "1", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_UNABLE_TO_PARSE_STRING_AS_BOOL);
294 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
295
296 RTTESTI_CHECK_RC(fromString(&obj4, "0", NULL, RT_XSTR(__LINE__)), VERR_REST_UNABLE_TO_PARSE_STRING_AS_BOOL);
297 }
298}
299
300class Int64Constants
301{
302public:
303 Int64Constants() {}
304 const char *getSubName() const { return "RTCRestInt64"; }
305 int64_t getMin() const { return INT64_MIN; }
306 const char *getMinStr() const { return "-9223372036854775808"; }
307 int64_t getMax() const { return INT64_MAX; }
308 const char *getMaxStr() const { return "9223372036854775807"; }
309 const char *getTypeName() const { return "int64_t"; }
310 RTCRestObjectBase::kTypeClass getTypeClass() const { return RTCRestObjectBase::kTypeClass_Int64; }
311};
312
313class Int32Constants
314{
315public:
316 Int32Constants() { }
317 const char *getSubName() const { return "RTCRestInt32"; }
318 int32_t getMin() const { return INT32_MIN; }
319 const char *getMinStr() const { return "-2147483648"; }
320 int32_t getMax() const { return INT32_MAX; }
321 const char *getMaxStr() const { return "2147483647"; }
322 const char *getTypeName() const { return "int32_t"; }
323 RTCRestObjectBase::kTypeClass getTypeClass() const { return RTCRestObjectBase::kTypeClass_Int32; }
324};
325
326class Int16Constants
327{
328public:
329 Int16Constants() { }
330 const char *getSubName() const { return "RTCRestInt16"; }
331 int16_t getMin() const { return INT16_MIN; }
332 const char *getMinStr() const { return "-32768"; }
333 int16_t getMax() const { return INT16_MAX; }
334 const char *getMaxStr() const { return "32767"; }
335 const char *getTypeName() const { return "int16_t"; }
336 RTCRestObjectBase::kTypeClass getTypeClass() const { return RTCRestObjectBase::kTypeClass_Int16; }
337};
338
339template<typename RestType, typename IntType, typename ConstantClass>
340void testInteger(void)
341{
342 ConstantClass const Consts;
343 RTTestSub(g_hTest, Consts.getSubName());
344
345 {
346 RestType obj1;
347 RTTESTI_CHECK(obj1.m_iValue == 0);
348 RTTESTI_CHECK(obj1.isNull() == false);
349 RTTESTI_CHECK(strcmp(obj1.typeName(), Consts.getTypeName()) == 0);
350 RTTESTI_CHECK(obj1.typeClass() == Consts.getTypeClass());
351 }
352
353 {
354 RestType obj2(2398);
355 RTTESTI_CHECK(obj2.m_iValue == 2398);
356 RTTESTI_CHECK(obj2.isNull() == false);
357 }
358
359 {
360 RestType obj2(-7345);
361 RTTESTI_CHECK(obj2.m_iValue == -7345);
362 RTTESTI_CHECK(obj2.isNull() == false);
363 }
364
365 {
366 /* Value assignments: */
367 RestType obj3;
368 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
369 RTTESTI_CHECK(obj3.isNull() == true);
370 RTTESTI_CHECK(obj3.m_iValue == 0);
371 obj3.assignValue(-1);
372 RTTESTI_CHECK(obj3.m_iValue == -1);
373 RTTESTI_CHECK(obj3.isNull() == false);
374
375 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
376 RTTESTI_CHECK(obj3.isNull() == true);
377 obj3.assignValue(42);
378 RTTESTI_CHECK(obj3.m_iValue == 42);
379 RTTESTI_CHECK(obj3.isNull() == false);
380
381 obj3.assignValue(Consts.getMax());
382 RTTESTI_CHECK(obj3.m_iValue == Consts.getMax());
383 RTTESTI_CHECK(obj3.isNull() == false);
384
385 obj3.assignValue(Consts.getMin());
386 RTTESTI_CHECK(obj3.m_iValue == Consts.getMin());
387 RTTESTI_CHECK(obj3.isNull() == false);
388
389 /* Reset to default: */
390 RTTESTI_CHECK_RC(obj3.resetToDefault(), VINF_SUCCESS);
391 RTTESTI_CHECK(obj3.m_iValue == 0);
392 RTTESTI_CHECK(obj3.isNull() == false);
393
394 obj3.assignValue(42);
395 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
396 RTTESTI_CHECK_RC(obj3.resetToDefault(), VINF_SUCCESS);
397 RTTESTI_CHECK(obj3.m_iValue == 0);
398 RTTESTI_CHECK(obj3.isNull() == false);
399
400 /* Copy assignments: */
401 RestType obj3Max(Consts.getMax());
402 RTTESTI_CHECK(obj3Max.m_iValue == Consts.getMax());
403 RTTESTI_CHECK(obj3Max.isNull() == false);
404 RestType obj3Min(Consts.getMin());
405 RTTESTI_CHECK(obj3Min.m_iValue == Consts.getMin());
406 RTTESTI_CHECK(obj3Min.isNull() == false);
407 RestType obj3Null;
408 obj3Null.setNull();
409 RTTESTI_CHECK(obj3Null.m_iValue == 0);
410 RTTESTI_CHECK(obj3Null.isNull() == true);
411
412 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
413 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Max), VINF_SUCCESS);
414 RTTESTI_CHECK(obj3.m_iValue == Consts.getMax());
415 RTTESTI_CHECK(obj3.isNull() == false);
416
417 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Null), VINF_SUCCESS);
418 RTTESTI_CHECK(obj3.m_iValue == 0);
419 RTTESTI_CHECK(obj3.isNull() == true);
420
421 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Min), VINF_SUCCESS);
422 RTTESTI_CHECK(obj3.m_iValue == Consts.getMin());
423 RTTESTI_CHECK(obj3.isNull() == false);
424
425 obj3 = obj3Null;
426 RTTESTI_CHECK(obj3.m_iValue == 0);
427 RTTESTI_CHECK(obj3.isNull() == true);
428
429 obj3 = obj3Max;
430 RTTESTI_CHECK(obj3.m_iValue == Consts.getMax());
431 RTTESTI_CHECK(obj3.isNull() == false);
432
433 obj3 = obj3Null;
434 RTTESTI_CHECK(obj3.m_iValue == 0);
435 RTTESTI_CHECK(obj3.isNull() == true);
436
437 obj3 = obj3Min;
438 RTTESTI_CHECK(obj3.m_iValue == Consts.getMin());
439 RTTESTI_CHECK(obj3.isNull() == false);
440
441 /* setNull implies resetToDefault: */
442 obj3 = obj3Max;
443 RTTESTI_CHECK(obj3.m_iValue == Consts.getMax());
444 RTTESTI_CHECK(obj3.isNull() == false);
445 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
446 RTTESTI_CHECK(obj3.isNull() == true);
447 RTTESTI_CHECK(obj3.m_iValue == 0);
448
449 /* Copy constructors: */
450 {
451 RestType obj3a(obj3Max);
452 RTTESTI_CHECK(obj3a.m_iValue == Consts.getMax());
453 RTTESTI_CHECK(obj3a.isNull() == false);
454 }
455 {
456 RestType obj3b(obj3Min);
457 RTTESTI_CHECK(obj3b.m_iValue == Consts.getMin());
458 RTTESTI_CHECK(obj3b.isNull() == false);
459 }
460 {
461 RestType obj3c(obj3Null);
462 RTTESTI_CHECK(obj3c.m_iValue == 0);
463 RTTESTI_CHECK(obj3c.isNull() == true);
464 }
465
466 /* Serialization to json: */
467 const char *pszJson = toJson(&obj3Max);
468 RTTESTI_CHECK_MSG(strcmp(pszJson, Consts.getMaxStr()) == 0, ("pszJson=%s\n", pszJson));
469 pszJson = toJson(&obj3Min);
470 RTTESTI_CHECK_MSG(strcmp(pszJson, Consts.getMinStr()) == 0, ("pszJson=%s\n", pszJson));
471 pszJson = toJson(&obj3Null);
472 RTTESTI_CHECK_MSG(strcmp(pszJson, "null") == 0, ("pszJson=%s\n", pszJson));
473
474 /* Serialization to string. */
475 RTCString str;
476 RTCString strExpect;
477 str = "lead-in:";
478 RTTESTI_CHECK_RC(obj3Max.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
479 strExpect.printf("lead-in:%s", Consts.getMaxStr());
480 RTTESTI_CHECK_MSG(str.equals(strExpect), ("str=%s strExpect=%s\n", str.c_str(), strExpect.c_str()));
481 RTTESTI_CHECK_RC(obj3Max.toString(&str), VINF_SUCCESS);
482 RTTESTI_CHECK_MSG(str.equals(Consts.getMaxStr()), ("str=%s\n", str.c_str()));
483
484 str = "lead-in:";
485 RTTESTI_CHECK_RC(obj3Min.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
486 strExpect.printf("lead-in:%s", Consts.getMinStr());
487 RTTESTI_CHECK_MSG(str.equals(strExpect), ("str=%s strExpect=%s\n", str.c_str(), strExpect.c_str()));
488 RTTESTI_CHECK_RC(obj3Min.toString(&str), VINF_SUCCESS);
489 RTTESTI_CHECK_MSG(str.equals(Consts.getMinStr()), ("str=%s\n", str.c_str()));
490
491 str = "lead-in:";
492 RTTESTI_CHECK_RC(obj3Null.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
493 RTTESTI_CHECK_MSG(str.equals("lead-in:null"), ("str=%s\n", str.c_str()));
494 RTTESTI_CHECK_RC(obj3Null.toString(&str), VINF_SUCCESS);
495 RTTESTI_CHECK_MSG(str.equals("null"), ("str=%s\n", str.c_str()));
496 }
497
498 /* deserialize: */
499 RTERRINFOSTATIC ErrInfo;
500 {
501 /* from json: */
502 RestType obj4;
503 obj4.setNull();
504 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "42", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
505 RTTESTI_CHECK(obj4.m_iValue == 42);
506 RTTESTI_CHECK(obj4.isNull() == false);
507
508 obj4.setNull();
509 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "-22", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
510 RTTESTI_CHECK(obj4.m_iValue == -22);
511 RTTESTI_CHECK(obj4.isNull() == false);
512
513 obj4.setNull();
514 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, Consts.getMaxStr(), &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
515 RTTESTI_CHECK(obj4.m_iValue == Consts.getMax());
516 RTTESTI_CHECK(obj4.isNull() == false);
517
518 obj4.setNull();
519 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, Consts.getMinStr(), &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
520 RTTESTI_CHECK(obj4.m_iValue == Consts.getMin());
521 RTTESTI_CHECK(obj4.isNull() == false);
522
523 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "null", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
524 RTTESTI_CHECK(obj4.m_iValue == 0);
525 RTTESTI_CHECK(obj4.isNull() == true);
526
527 /* object goes to default state on failure: */
528 obj4.assignValue(Consts.getMin());
529 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "0.0", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER);
530 RTTESTI_CHECK(obj4.m_iValue == 0);
531 RTTESTI_CHECK(obj4.isNull() == false);
532 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
533
534 obj4.assignValue(Consts.getMax());
535 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"false\"", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER);
536 RTTESTI_CHECK(obj4.m_iValue == 0);
537 RTTESTI_CHECK(obj4.isNull() == false);
538 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
539
540 obj4.setNull();
541 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "[ null ]", NULL, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER);
542 RTTESTI_CHECK(obj4.m_iValue == 0);
543 RTTESTI_CHECK(obj4.isNull() == false);
544
545 /* from string: */
546 obj4.setNull();
547 RTTESTI_CHECK_RC(fromString(&obj4, "22", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
548 RTTESTI_CHECK(obj4.m_iValue == 22);
549 RTTESTI_CHECK(obj4.isNull() == false);
550
551 RTTESTI_CHECK_RC(fromString(&obj4, "-42", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
552 RTTESTI_CHECK(obj4.m_iValue == -42);
553 RTTESTI_CHECK(obj4.isNull() == false);
554
555 RTTESTI_CHECK_RC(fromString(&obj4, Consts.getMaxStr(), &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
556 RTTESTI_CHECK(obj4.m_iValue == Consts.getMax());
557 RTTESTI_CHECK(obj4.isNull() == false);
558
559 RTTESTI_CHECK_RC(fromString(&obj4, Consts.getMinStr(), &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
560 RTTESTI_CHECK(obj4.m_iValue == Consts.getMin());
561 RTTESTI_CHECK(obj4.isNull() == false);
562
563 obj4.m_iValue = 33;
564 RTTESTI_CHECK_RC(fromString(&obj4, "null", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
565 RTTESTI_CHECK(obj4.m_iValue == 0);
566 RTTESTI_CHECK(obj4.isNull() == true);
567
568 obj4.m_iValue = 33;
569 RTTESTI_CHECK_RC(fromString(&obj4, " nULl;", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
570 RTTESTI_CHECK(obj4.m_iValue == 0);
571 RTTESTI_CHECK(obj4.isNull() == true);
572
573 obj4.setNull();
574 RTTESTI_CHECK_RC(fromString(&obj4, " 0x42 ", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
575 RTTESTI_CHECK(obj4.m_iValue == 0x42);
576 RTTESTI_CHECK(obj4.isNull() == false);
577
578 RTTESTI_CHECK_RC(fromString(&obj4, "\t010\t", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
579 RTTESTI_CHECK(obj4.m_iValue == 8);
580 RTTESTI_CHECK(obj4.isNull() == false);
581
582 RTTESTI_CHECK_RC(fromString(&obj4, "\r\t0X4FDB\t", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
583 RTTESTI_CHECK(obj4.m_iValue == 0x4fdb);
584 RTTESTI_CHECK(obj4.isNull() == false);
585
586 RTTESTI_CHECK_RC(fromString(&obj4, "1.1", &ErrInfo, RT_XSTR(__LINE__)), VERR_TRAILING_CHARS);
587 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
588
589 RTTESTI_CHECK_RC(fromString(&obj4, "false", NULL, RT_XSTR(__LINE__)), VERR_NO_DIGITS);
590 }
591}
592
593
594void testDouble(void)
595{
596 RTTestSub(g_hTest, "RTCRestDouble");
597#if defined(RT_OS_WINDOWS)
598# define DBL_MAX_STRING "1.7976931348623157e+308"
599# define DBL_MIN_STRING "2.2250738585072014e-308"
600#else
601# define DBL_MAX_STRING "1.79769313486231571e+308"
602# define DBL_MIN_STRING "2.22507385850720138e-308"
603#endif
604
605 {
606 RTCRestDouble obj1;
607 RTTESTI_CHECK(obj1.m_rdValue == 0.0);
608 RTTESTI_CHECK(obj1.isNull() == false);
609 RTTESTI_CHECK(strcmp(obj1.typeName(), "double") == 0);
610 RTTESTI_CHECK(obj1.typeClass() == RTCRestObjectBase::kTypeClass_Double);
611 }
612
613 {
614 RTCRestDouble obj2(2398.1);
615 RTTESTI_CHECK(obj2.m_rdValue == 2398.1);
616 RTTESTI_CHECK(obj2.isNull() == false);
617 }
618
619 {
620 RTCRestDouble obj2(-7345.2);
621 RTTESTI_CHECK(obj2.m_rdValue == -7345.2);
622 RTTESTI_CHECK(obj2.isNull() == false);
623 }
624
625 {
626 /* Value assignments: */
627 RTCRestDouble obj3;
628 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
629 RTTESTI_CHECK(obj3.isNull() == true);
630 RTTESTI_CHECK(obj3.m_rdValue == 0.0);
631 obj3.assignValue(-1.0);
632 RTTESTI_CHECK(obj3.m_rdValue == -1.0);
633 RTTESTI_CHECK(obj3.isNull() == false);
634
635 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
636 RTTESTI_CHECK(obj3.isNull() == true);
637 obj3.assignValue(42.42);
638 RTTESTI_CHECK(obj3.m_rdValue == 42.42);
639 RTTESTI_CHECK(obj3.isNull() == false);
640
641 obj3.assignValue(DBL_MAX);
642 RTTESTI_CHECK(obj3.m_rdValue == DBL_MAX);
643 RTTESTI_CHECK(obj3.isNull() == false);
644
645 obj3.assignValue(DBL_MIN);
646 RTTESTI_CHECK(obj3.m_rdValue == DBL_MIN);
647 RTTESTI_CHECK(obj3.isNull() == false);
648
649 /* Reset to default: */
650 RTTESTI_CHECK_RC(obj3.resetToDefault(), VINF_SUCCESS);
651 RTTESTI_CHECK(obj3.m_rdValue == 0.0);
652 RTTESTI_CHECK(obj3.isNull() == false);
653
654 obj3.assignValue(42);
655 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
656 RTTESTI_CHECK_RC(obj3.resetToDefault(), VINF_SUCCESS);
657 RTTESTI_CHECK(obj3.m_rdValue == 0.0);
658 RTTESTI_CHECK(obj3.isNull() == false);
659
660 /* Copy assignments: */
661 RTCRestDouble obj3Max(DBL_MAX);
662 RTTESTI_CHECK(obj3Max.m_rdValue == DBL_MAX);
663 RTTESTI_CHECK(obj3Max.isNull() == false);
664 RTCRestDouble obj3Min(DBL_MIN);
665 RTTESTI_CHECK(obj3Min.m_rdValue == DBL_MIN);
666 RTTESTI_CHECK(obj3Min.isNull() == false);
667 RTCRestDouble obj3Null;
668 obj3Null.setNull();
669 RTTESTI_CHECK(obj3Null.m_rdValue == 0.0);
670 RTTESTI_CHECK(obj3Null.isNull() == true);
671
672 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
673 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Max), VINF_SUCCESS);
674 RTTESTI_CHECK(obj3.m_rdValue == DBL_MAX);
675 RTTESTI_CHECK(obj3.isNull() == false);
676
677 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Null), VINF_SUCCESS);
678 RTTESTI_CHECK(obj3.m_rdValue == 0.0);
679 RTTESTI_CHECK(obj3.isNull() == true);
680
681 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Min), VINF_SUCCESS);
682 RTTESTI_CHECK(obj3.m_rdValue == DBL_MIN);
683 RTTESTI_CHECK(obj3.isNull() == false);
684
685 obj3 = obj3Null;
686 RTTESTI_CHECK(obj3.m_rdValue == 0.0);
687 RTTESTI_CHECK(obj3.isNull() == true);
688
689 obj3 = obj3Max;
690 RTTESTI_CHECK(obj3.m_rdValue == DBL_MAX);
691 RTTESTI_CHECK(obj3.isNull() == false);
692
693 obj3 = obj3Null;
694 RTTESTI_CHECK(obj3.m_rdValue == 0.0);
695 RTTESTI_CHECK(obj3.isNull() == true);
696
697 obj3 = obj3Min;
698 RTTESTI_CHECK(obj3.m_rdValue == DBL_MIN);
699 RTTESTI_CHECK(obj3.isNull() == false);
700
701 /* setNull implies resetToDefault: */
702 obj3 = obj3Max;
703 RTTESTI_CHECK(obj3.m_rdValue == DBL_MAX);
704 RTTESTI_CHECK(obj3.isNull() == false);
705 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
706 RTTESTI_CHECK(obj3.isNull() == true);
707 RTTESTI_CHECK(obj3.m_rdValue == 0.0);
708
709 /* Copy constructors: */
710 {
711 RTCRestDouble obj3a(obj3Max);
712 RTTESTI_CHECK(obj3a.m_rdValue == DBL_MAX);
713 RTTESTI_CHECK(obj3a.isNull() == false);
714 }
715 {
716 RTCRestDouble obj3b(obj3Min);
717 RTTESTI_CHECK(obj3b.m_rdValue == DBL_MIN);
718 RTTESTI_CHECK(obj3b.isNull() == false);
719 }
720 {
721 RTCRestDouble obj3c(obj3Null);
722 RTTESTI_CHECK(obj3c.m_rdValue == 0.0);
723 RTTESTI_CHECK(obj3c.isNull() == true);
724 }
725
726 /* Serialization to json: */
727 const char *pszJson = toJson(&obj3Max);
728 RTTESTI_CHECK_MSG(strcmp(pszJson, DBL_MAX_STRING) == 0, ("pszJson=%s\n", pszJson));
729 pszJson = toJson(&obj3Min);
730 RTTESTI_CHECK_MSG(strcmp(pszJson, DBL_MIN_STRING) == 0, ("pszJson=%s\n", pszJson));
731 pszJson = toJson(&obj3Null);
732 RTTESTI_CHECK_MSG(strcmp(pszJson, "null") == 0, ("pszJson=%s\n", pszJson));
733
734 /* Serialization to string. */
735 RTCString str;
736 RTCString strExpect;
737 str = "lead-in:";
738 RTTESTI_CHECK_RC(obj3Max.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
739 strExpect.printf("lead-in:%s", DBL_MAX_STRING);
740 RTTESTI_CHECK_MSG(str.equals(strExpect), ("str=%s strExpect=%s\n", str.c_str(), strExpect.c_str()));
741 RTTESTI_CHECK_RC(obj3Max.toString(&str), VINF_SUCCESS);
742 RTTESTI_CHECK_MSG(str.equals(DBL_MAX_STRING), ("str=%s\n", str.c_str()));
743
744 str = "lead-in:";
745 RTTESTI_CHECK_RC(obj3Min.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
746 strExpect.printf("lead-in:%s", DBL_MIN_STRING);
747 RTTESTI_CHECK_MSG(str.equals(strExpect), ("str=%s strExpect=%s\n", str.c_str(), strExpect.c_str()));
748 RTTESTI_CHECK_RC(obj3Min.toString(&str), VINF_SUCCESS);
749 RTTESTI_CHECK_MSG(str.equals(DBL_MIN_STRING), ("str=%s\n", str.c_str()));
750
751 str = "lead-in:";
752 RTTESTI_CHECK_RC(obj3Null.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
753 RTTESTI_CHECK_MSG(str.equals("lead-in:null"), ("str=%s\n", str.c_str()));
754 RTTESTI_CHECK_RC(obj3Null.toString(&str), VINF_SUCCESS);
755 RTTESTI_CHECK_MSG(str.equals("null"), ("str=%s\n", str.c_str()));
756 }
757
758 /* deserialize: */
759 RTERRINFOSTATIC ErrInfo;
760 {
761 /* from json: */
762 RTCRestDouble obj4;
763 obj4.setNull();
764 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "42.42", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
765 RTTESTI_CHECK(obj4.m_rdValue == 42.42);
766 RTTESTI_CHECK(obj4.isNull() == false);
767
768 obj4.setNull();
769 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "-22.22", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
770 RTTESTI_CHECK(obj4.m_rdValue == -22.22);
771 RTTESTI_CHECK(obj4.isNull() == false);
772
773 obj4.setNull();
774 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, DBL_MAX_STRING, &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
775 RTTESTI_CHECK(obj4.m_rdValue == DBL_MAX);
776 RTTESTI_CHECK(obj4.isNull() == false);
777
778 obj4.setNull();
779 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, DBL_MIN_STRING, &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
780 RTTESTI_CHECK(obj4.m_rdValue == DBL_MIN);
781 RTTESTI_CHECK(obj4.isNull() == false);
782
783 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "null", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
784 RTTESTI_CHECK(obj4.m_rdValue == 0.0);
785 RTTESTI_CHECK(obj4.isNull() == true);
786
787 obj4.setNull();
788 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "14323", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
789 RTTESTI_CHECK(obj4.m_rdValue == 14323.0);
790 RTTESTI_CHECK(obj4.isNull() == false);
791
792 obj4.setNull();
793 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "-234875", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
794 RTTESTI_CHECK(obj4.m_rdValue == -234875.0);
795 RTTESTI_CHECK(obj4.isNull() == false);
796
797 /* object goes to default state on failure: */
798 obj4.assignValue(DBL_MIN);
799 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "false", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_DOUBLE);
800 RTTESTI_CHECK(obj4.m_rdValue == 0.0);
801 RTTESTI_CHECK(obj4.isNull() == false);
802 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
803
804 obj4.assignValue(DBL_MAX);
805 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"false\"", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_DOUBLE);
806 RTTESTI_CHECK(obj4.m_rdValue == 0.0);
807 RTTESTI_CHECK(obj4.isNull() == false);
808 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
809
810 obj4.setNull();
811 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "[ null ]", NULL, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_DOUBLE);
812 RTTESTI_CHECK(obj4.m_rdValue == 0.0);
813 RTTESTI_CHECK(obj4.isNull() == false);
814
815 /* from string: */
816 obj4.setNull();
817 RTTESTI_CHECK_RC(fromString(&obj4, "22.42", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
818 RTTESTI_CHECK(obj4.m_rdValue == 22.42);
819 RTTESTI_CHECK(obj4.isNull() == false);
820
821 RTTESTI_CHECK_RC(fromString(&obj4, "-42.22", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
822 RTTESTI_CHECK(obj4.m_rdValue == -42.22);
823 RTTESTI_CHECK(obj4.isNull() == false);
824
825 RTTESTI_CHECK_RC(fromString(&obj4, DBL_MAX_STRING, &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
826 RTTESTI_CHECK(obj4.m_rdValue == DBL_MAX);
827 RTTESTI_CHECK(obj4.isNull() == false);
828
829 RTTESTI_CHECK_RC(fromString(&obj4, DBL_MIN_STRING, &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
830 RTTESTI_CHECK(obj4.m_rdValue == DBL_MIN);
831 RTTESTI_CHECK(obj4.isNull() == false);
832
833 obj4.m_rdValue = 33.33;
834 RTTESTI_CHECK_RC(fromString(&obj4, "null", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
835 RTTESTI_CHECK(obj4.m_rdValue == 0.0);
836 RTTESTI_CHECK(obj4.isNull() == true);
837
838 obj4.m_rdValue = 33.33;
839 RTTESTI_CHECK_RC(fromString(&obj4, " nULl;", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
840 RTTESTI_CHECK(obj4.m_rdValue == 0.0);
841 RTTESTI_CHECK(obj4.isNull() == true);
842
843 obj4.setNull();
844 RTTESTI_CHECK_RC(fromString(&obj4, " 42.22 ", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
845 RTTESTI_CHECK(obj4.m_rdValue == 42.22);
846 RTTESTI_CHECK(obj4.isNull() == false);
847
848 RTTESTI_CHECK_RC(fromString(&obj4, "\t010\t", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
849 RTTESTI_CHECK(obj4.m_rdValue ==10.0);
850 RTTESTI_CHECK(obj4.isNull() == false);
851
852 RTTESTI_CHECK_RC(fromString(&obj4, "\r\t03495.344\t\r\n", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
853 RTTESTI_CHECK(obj4.m_rdValue == 3495.344);
854 RTTESTI_CHECK(obj4.isNull() == false);
855
856 RTTESTI_CHECK_RC(fromString(&obj4, "1.1;", &ErrInfo, RT_XSTR(__LINE__)), VERR_TRAILING_CHARS);
857 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
858
859 RTTESTI_CHECK_RC(fromString(&obj4, "false", NULL, RT_XSTR(__LINE__)), VERR_NO_DIGITS);
860
861#if defined(RT_OS_WINDOWS)
862 RTTESTI_CHECK_RC(fromString(&obj4, " 0x42 ", &ErrInfo, RT_XSTR(__LINE__)), VERR_TRAILING_CHARS);
863 RTTESTI_CHECK(obj4.m_rdValue == 0.0);
864#else
865 RTTESTI_CHECK_RC(fromString(&obj4, " 0x42 ", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
866 RTTESTI_CHECK(obj4.m_rdValue == 66.0);
867#endif
868 RTTESTI_CHECK(obj4.isNull() == false);
869 }
870}
871
872
873void testString(const char *pszDummy, ...)
874{
875 RTTestSub(g_hTest, "RTCRestString");
876
877 {
878 RTCRestString obj1;
879 RTTESTI_CHECK(obj1.isEmpty());
880 RTTESTI_CHECK(obj1.isNull() == false);
881 RTTESTI_CHECK(strcmp(obj1.typeName(), "RTCString") == 0);
882 RTTESTI_CHECK(obj1.typeClass() == RTCRestObjectBase::kTypeClass_String);
883 }
884
885 {
886 RTCRestString obj2(RTCString("2398.1"));
887 RTTESTI_CHECK(obj2 == "2398.1");
888 RTTESTI_CHECK(obj2.isNull() == false);
889 }
890
891 {
892 RTCRestString obj2("-7345.2");
893 RTTESTI_CHECK(obj2 == "-7345.2");
894 RTTESTI_CHECK(obj2.isNull() == false);
895 }
896
897 {
898 /* Value assignments: */
899 RTCRestString obj3;
900 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
901 RTTESTI_CHECK(obj3.isNull() == true);
902 RTTESTI_CHECK(obj3.isEmpty());
903 obj3 = "-1.0";
904 RTTESTI_CHECK(obj3 == "-1.0");
905 RTTESTI_CHECK(obj3.isNull() == false);
906
907 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
908 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
909 obj3 = RTCString("-2.0");
910 RTTESTI_CHECK(obj3 == "-2.0");
911 RTTESTI_CHECK(obj3.isNull() == false);
912
913 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
914 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
915 obj3 = RTCRestString("-3.0");
916 RTTESTI_CHECK(obj3 == "-3.0");
917 RTTESTI_CHECK(obj3.isNull() == false);
918
919 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
920 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
921 RTTESTI_CHECK_RC(obj3.assignNoThrow(RTCRestString("4.0")), VINF_SUCCESS);
922 RTTESTI_CHECK(obj3 == "4.0");
923 RTTESTI_CHECK(obj3.isNull() == false);
924
925 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
926 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
927 RTTESTI_CHECK_RC(obj3.assignNoThrow("-4.0"), VINF_SUCCESS);
928 RTTESTI_CHECK(obj3 == "-4.0");
929 RTTESTI_CHECK(obj3.isNull() == false);
930
931 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
932 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
933 RTTESTI_CHECK_RC(obj3.assignNoThrow(RTCRestString("0123456789"), 3, 5), VINF_SUCCESS);
934 RTTESTI_CHECK(obj3 == "34567");
935 RTTESTI_CHECK(obj3.isNull() == false);
936
937 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
938 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
939 RTTESTI_CHECK_RC(obj3.assignNoThrow("0123456789", 4), VINF_SUCCESS);
940 RTTESTI_CHECK(obj3 == "0123");
941 RTTESTI_CHECK(obj3.isNull() == false);
942
943 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
944 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
945 RTTESTI_CHECK_RC(obj3.assignNoThrow(8, 'x'), VINF_SUCCESS);
946 RTTESTI_CHECK(obj3 == "xxxxxxxx");
947 RTTESTI_CHECK(obj3.isNull() == false);
948
949 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
950 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
951 RTTESTI_CHECK_RC(obj3.printfNoThrow("%d%s%d", 42, "asdf", 22), VINF_SUCCESS);
952 RTTESTI_CHECK(obj3 == "42asdf22");
953 RTTESTI_CHECK(obj3.isNull() == false);
954
955 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
956 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
957 va_list va;
958 va_start(va, pszDummy);
959 RTTESTI_CHECK_RC(obj3.printfVNoThrow("asdf", va), VINF_SUCCESS);
960 va_end(va);
961 RTTESTI_CHECK(obj3 == "asdf");
962 RTTESTI_CHECK(obj3.isNull() == false);
963
964 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
965 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
966 obj3.assign(RTCRestString("4.0"));
967 RTTESTI_CHECK(obj3 == "4.0");
968 RTTESTI_CHECK(obj3.isNull() == false);
969
970 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
971 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
972 obj3.assign("-4.0");
973 RTTESTI_CHECK(obj3 == "-4.0");
974 RTTESTI_CHECK(obj3.isNull() == false);
975
976 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
977 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
978 obj3.assign(RTCRestString("0123456789"), 3, 5);
979 RTTESTI_CHECK(obj3 == "34567");
980 RTTESTI_CHECK(obj3.isNull() == false);
981
982 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
983 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
984 obj3.assign("0123456789", 4);
985 RTTESTI_CHECK(obj3 == "0123");
986 RTTESTI_CHECK(obj3.isNull() == false);
987
988 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
989 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
990 obj3.assign(8, 'x');
991 RTTESTI_CHECK(obj3 == "xxxxxxxx");
992 RTTESTI_CHECK(obj3.isNull() == false);
993
994 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
995 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
996 obj3.printf("%d%s%d", 42, "asdf", 22);
997 RTTESTI_CHECK(obj3 == "42asdf22");
998 RTTESTI_CHECK(obj3.isNull() == false);
999
1000 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1001 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
1002 va_start(va, pszDummy);
1003 obj3.printfV("asdf", va);
1004 va_end(va);
1005 RTTESTI_CHECK(obj3 == "asdf");
1006 RTTESTI_CHECK(obj3.isNull() == false);
1007
1008 /* Reset to default: */
1009 RTTESTI_CHECK_RC(obj3.resetToDefault(), VINF_SUCCESS);
1010 RTTESTI_CHECK(obj3.isEmpty());
1011 RTTESTI_CHECK(obj3.isNull() == false);
1012
1013 obj3 = "1";
1014 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1015 RTTESTI_CHECK_RC(obj3.resetToDefault(), VINF_SUCCESS);
1016 RTTESTI_CHECK(obj3.isEmpty());
1017 RTTESTI_CHECK(obj3.isNull() == false);
1018
1019 /* Copy assignments: */
1020 RTCRestString const obj3Max("max");
1021 RTTESTI_CHECK(obj3Max == "max");
1022 RTTESTI_CHECK(obj3Max.isNull() == false);
1023 RTCRestString obj3Null;
1024 obj3Null.setNull();
1025 RTTESTI_CHECK(obj3Null.isEmpty());
1026 RTTESTI_CHECK(obj3Null.isNull() == true);
1027 RTCRestString obj3Empty;
1028 RTTESTI_CHECK(obj3Empty.isEmpty());
1029 RTTESTI_CHECK(obj3Empty.isNull() == false);
1030
1031 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1032 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
1033 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Max), VINF_SUCCESS);
1034 RTTESTI_CHECK(obj3 == "max");
1035 RTTESTI_CHECK(obj3.isNull() == false);
1036
1037 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1038 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
1039 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Null), VINF_SUCCESS);
1040 RTTESTI_CHECK(obj3.isEmpty());
1041 RTTESTI_CHECK(obj3.isNull() == true);
1042
1043 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1044 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
1045 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Empty), VINF_SUCCESS);
1046 RTTESTI_CHECK(obj3 == "");
1047 RTTESTI_CHECK(obj3.isEmpty());
1048 RTTESTI_CHECK(obj3.isNull() == false);
1049
1050 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1051 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
1052 RTTESTI_CHECK_RC(obj3.assignCopy(RTCString("11.0")), VINF_SUCCESS);
1053 RTTESTI_CHECK(obj3 == "11.0");
1054 RTTESTI_CHECK(obj3.isNull() == false);
1055
1056 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1057 RTTESTI_CHECK(obj3.isNull() == true && obj3.isEmpty());
1058 RTTESTI_CHECK_RC(obj3.assignCopy("12.0"), VINF_SUCCESS);
1059 RTTESTI_CHECK(obj3 == "12.0");
1060 RTTESTI_CHECK(obj3.isNull() == false);
1061
1062 /* setNull implies resetToDefault: */
1063 obj3 = obj3Max;
1064 RTTESTI_CHECK(obj3 == "max");
1065 RTTESTI_CHECK(obj3.isNull() == false);
1066 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1067 RTTESTI_CHECK(obj3.isNull() == true);
1068 RTTESTI_CHECK(obj3.isEmpty());
1069
1070 /* Copy constructors: */
1071 {
1072 RTCRestString obj3a(obj3Max);
1073 RTTESTI_CHECK(obj3a == "max");
1074 RTTESTI_CHECK(obj3a.isNull() == false);
1075 }
1076 {
1077 RTCRestString const obj3c(obj3Null);
1078 RTTESTI_CHECK(obj3c.isEmpty());
1079 RTTESTI_CHECK(obj3c.isNull() == true);
1080 }
1081
1082 /* Serialization to json: */
1083 const char *pszJson = toJson(&obj3Max);
1084 RTTESTI_CHECK_MSG(strcmp(pszJson, "\"max\"") == 0, ("pszJson=%s\n", pszJson));
1085 pszJson = toJson(&obj3Null);
1086 RTTESTI_CHECK_MSG(strcmp(pszJson, "null") == 0, ("pszJson=%s\n", pszJson));
1087 pszJson = toJson(&obj3Empty);
1088 RTTESTI_CHECK_MSG(strcmp(pszJson, "\"\"") == 0, ("pszJson=%s\n", pszJson));
1089
1090 /* Serialization to string. */
1091 RTCString str;
1092 RTCString strExpect;
1093 str = "lead-in:";
1094 RTTESTI_CHECK_RC(obj3Max.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
1095 RTTESTI_CHECK_MSG(str.equals("lead-in:max"), ("str=%s\n", str.c_str()));
1096 RTTESTI_CHECK_RC(obj3Max.toString(&str), VINF_SUCCESS);
1097 RTTESTI_CHECK_MSG(str.equals("max"), ("str=%s\n", str.c_str()));
1098
1099 str = "lead-in:";
1100 RTTESTI_CHECK_RC(obj3Empty.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
1101 RTTESTI_CHECK_MSG(str.equals("lead-in:"), ("str=%s\n", str.c_str()));
1102 RTTESTI_CHECK_RC(obj3Empty.toString(&str), VINF_SUCCESS);
1103 RTTESTI_CHECK_MSG(str.equals(""), ("str=%s\n", str.c_str()));
1104
1105 str = "lead-in:";
1106 RTTESTI_CHECK_RC(obj3Null.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
1107 RTTESTI_CHECK_MSG(str.equals("lead-in:"), ("str=%s\n", str.c_str()));
1108 RTTESTI_CHECK_RC(obj3Null.toString(&str), VINF_SUCCESS);
1109 RTTESTI_CHECK_MSG(str.equals(""), ("str=%s\n", str.c_str()));
1110 }
1111
1112 /* deserialize: */
1113 RTERRINFOSTATIC ErrInfo;
1114 {
1115 /* from json: */
1116 RTCRestString obj4;
1117 obj4.setNull();
1118 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"42.42\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1119 RTTESTI_CHECK(obj4 == "42.42");
1120 RTTESTI_CHECK(obj4.isNull() == false);
1121
1122 obj4.setNull();
1123 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"-22.22\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1124 RTTESTI_CHECK(obj4 == "-22.22");
1125 RTTESTI_CHECK(obj4.isNull() == false);
1126
1127 obj4.setNull();
1128 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"maximum\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1129 RTTESTI_CHECK(obj4 == "maximum");
1130 RTTESTI_CHECK(obj4.isNull() == false);
1131
1132 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "null", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1133 RTTESTI_CHECK(obj4.isEmpty());
1134 RTTESTI_CHECK(obj4.isNull() == true);
1135
1136 obj4.setNull();
1137 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"\\u0020\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1138 RTTESTI_CHECK(obj4 == " ");
1139 RTTESTI_CHECK(obj4.isNull() == false);
1140
1141 obj4.setNull();
1142 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"\\u004f\\u004D\\u0047\\u0021 :-)\"",
1143 &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1144 RTTESTI_CHECK(obj4 == "OMG! :-)");
1145 RTTESTI_CHECK(obj4.isNull() == false);
1146
1147 obj4.setNull();
1148 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"42:\\uD801\\udC37\\ud852\\uDf62:42\"", /* U+10437 U+24B62 */
1149 &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1150 RTTESTI_CHECK(obj4 == "42:" "\xf0\x90\x90\xb7" "\xf0\xa4\xad\xa2" ":42");
1151 RTTESTI_CHECK(obj4.isNull() == false);
1152
1153 /* object goes to default state on failure: */
1154 obj4 = "asdf";
1155 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "false", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_STRING);
1156 RTTESTI_CHECK(obj4.isEmpty());
1157 RTTESTI_CHECK(obj4.isNull() == false);
1158 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
1159
1160 obj4 = "asdf";
1161 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "1", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_STRING);
1162 RTTESTI_CHECK(obj4.isEmpty());
1163 RTTESTI_CHECK(obj4.isNull() == false);
1164 RTTESTI_CHECK(RTErrInfoIsSet(&ErrInfo.Core));
1165
1166 obj4.setNull();
1167 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "[ null ]", NULL, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_STRING);
1168 RTTESTI_CHECK(obj4.isEmpty());
1169 RTTESTI_CHECK(obj4.isNull() == false);
1170
1171 /* from string: */
1172 obj4.setNull();
1173 RTTESTI_CHECK_RC(fromString(&obj4, "22.42", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1174 RTTESTI_CHECK(obj4 == "22.42");
1175 RTTESTI_CHECK(obj4.isNull() == false);
1176
1177 RTTESTI_CHECK_RC(fromString(&obj4, "-42.22", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1178 RTTESTI_CHECK(obj4 == "-42.22");
1179 RTTESTI_CHECK(obj4.isNull() == false);
1180
1181 obj4.setNull();
1182 RTTESTI_CHECK_RC(fromString(&obj4, "null", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1183 RTTESTI_CHECK(obj4 == "null");
1184 RTTESTI_CHECK(obj4.isNull() == false);
1185 }
1186}
1187
1188
1189void testDate()
1190{
1191 RTTestSub(g_hTest, "RTCRestDate");
1192 int64_t const iRecent = INT64_C(1536580687739632500);
1193 int64_t const iRecentSec = INT64_C(1536580687000000000);
1194 RTTIMESPEC TimeSpec;
1195
1196#define CHECK_DATE(a_obj, a_fNull, a_fOkay, a_i64Nano, a_sz, a_fUtc) \
1197 do { \
1198 RTTESTI_CHECK((a_obj).isOkay() == (a_fOkay)); \
1199 if ((a_obj).getEpochNano() != (a_i64Nano)) \
1200 RTTestIFailed("line " RT_XSTR(__LINE__) ": getEpochNano=%RI64, expected %RI64", (a_obj).getEpochNano(), (int64_t)(a_i64Nano)); \
1201 if (!(a_obj).getString().equals(a_sz)) \
1202 RTTestIFailed("line " RT_XSTR(__LINE__) ": getString=%s, expected %s", (a_obj).getString().c_str(), a_sz); \
1203 RTTESTI_CHECK((a_obj).isUtc() == (a_fUtc)); \
1204 RTTESTI_CHECK((a_obj).isNull() == (a_fNull)); \
1205 } while (0)
1206#define CHECK_DATE_FMT(a_obj, a_fNull, a_fOkay, a_i64Nano, a_sz, a_fUtc, a_enmFormat) \
1207 do { \
1208 CHECK_DATE(a_obj, a_fNull, a_fOkay, a_i64Nano, a_sz, a_fUtc); \
1209 if ((a_obj).getFormat() != (a_enmFormat)) \
1210 RTTestIFailed("line " RT_XSTR(__LINE__) ": getFormat=%d, expected %d (%s)", (a_obj).getFormat(), (a_enmFormat), #a_enmFormat); \
1211 } while (0)
1212
1213 {
1214 RTCRestDate obj1;
1215 CHECK_DATE(obj1, true, false, 0, "", true);
1216 RTTESTI_CHECK(strcmp(obj1.typeName(), "RTCRestDate") == 0);
1217 RTTESTI_CHECK(obj1.typeClass() == RTCRestObjectBase::kTypeClass_Date);
1218 }
1219
1220 {
1221 /* Value assignments: */
1222 RTCRestDate obj3;
1223 RTTESTI_CHECK_RC(obj3.assignValue(RTTimeSpecSetNano(&TimeSpec, 0), RTCRestDate::kFormat_Rfc3339), VINF_SUCCESS);
1224 CHECK_DATE(obj3, false, true, 0, "1970-01-01T00:00:00Z", true);
1225
1226 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1227 CHECK_DATE(obj3, true, false, 0, "", true);
1228 RTTESTI_CHECK_RC(obj3.assignValueRfc3339(RTTimeSpecSetNano(&TimeSpec, 0)), VINF_SUCCESS);
1229 CHECK_DATE(obj3, false, true, 0, "1970-01-01T00:00:00Z", true);
1230
1231 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1232 CHECK_DATE(obj3, true, false, 0, "", true);
1233 RTTESTI_CHECK_RC(obj3.assignValueRfc2822(RTTimeSpecSetNano(&TimeSpec, 0)), VINF_SUCCESS);
1234 CHECK_DATE(obj3, false, true, 0, "Thu, 1 Jan 1970 00:00:00 -0000", true);
1235
1236 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1237 RTTESTI_CHECK_RC(obj3.assignValueRfc7131(RTTimeSpecSetNano(&TimeSpec, 0)), VINF_SUCCESS);
1238 CHECK_DATE(obj3, false, true, 0, "Thu, 1 Jan 1970 00:00:00 GMT", true);
1239
1240 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1241 RTTESTI_CHECK_RC(obj3.assignValue(RTTimeSpecSetNano(&TimeSpec, 0), RTCRestDate::kFormat_Rfc2822), VINF_SUCCESS);
1242 CHECK_DATE(obj3, false, true, 0, "Thu, 1 Jan 1970 00:00:00 -0000", true);
1243
1244 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1245 RTTESTI_CHECK_RC(obj3.assignValue(RTTimeSpecSetNano(&TimeSpec, 0), RTCRestDate::kFormat_Rfc7131), VINF_SUCCESS);
1246 CHECK_DATE(obj3, false, true, 0, "Thu, 1 Jan 1970 00:00:00 GMT", true);
1247
1248 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1249 RTTESTI_CHECK_RC(obj3.assignValue(RTTimeSpecSetNano(&TimeSpec, 0), RTCRestDate::kFormat_Rfc3339_Fraction_9), VINF_SUCCESS);
1250 CHECK_DATE(obj3, false, true, 0, "1970-01-01T00:00:00.000000000Z", true);
1251
1252 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1253 RTTESTI_CHECK_RC(obj3.assignValue(RTTimeSpecSetNano(&TimeSpec, 0), RTCRestDate::kFormat_Rfc3339_Fraction_6), VINF_SUCCESS);
1254 CHECK_DATE(obj3, false, true, 0, "1970-01-01T00:00:00.000000Z", true);
1255
1256 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1257 RTTESTI_CHECK_RC(obj3.assignValue(RTTimeSpecSetNano(&TimeSpec, 0), RTCRestDate::kFormat_Rfc3339_Fraction_3), VINF_SUCCESS);
1258 CHECK_DATE(obj3, false, true, 0, "1970-01-01T00:00:00.000Z", true);
1259
1260 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1261 RTTESTI_CHECK_RC(obj3.assignValue(RTTimeSpecSetNano(&TimeSpec, 0), RTCRestDate::kFormat_Rfc3339_Fraction_2), VINF_SUCCESS);
1262 CHECK_DATE(obj3, false, true, 0, "1970-01-01T00:00:00.00Z", true);
1263
1264 /* Format changes: */
1265 RTTESTI_CHECK_RC(obj3.assignValue(RTTimeSpecSetNano(&TimeSpec, 59123456789), RTCRestDate::kFormat_Rfc3339_Fraction_9), VINF_SUCCESS);
1266 CHECK_DATE(obj3, false, true, 59123456789, "1970-01-01T00:00:59.123456789Z", true);
1267 RTTESTI_CHECK_RC(obj3.setFormat(RTCRestDate::kFormat_Rfc2822), VINF_SUCCESS);
1268 CHECK_DATE(obj3, false, true, 59123456789, "Thu, 1 Jan 1970 00:00:59 -0000", true);
1269 RTTESTI_CHECK_RC(obj3.setFormat(RTCRestDate::kFormat_Rfc7131), VINF_SUCCESS);
1270 CHECK_DATE(obj3, false, true, 59123456789, "Thu, 1 Jan 1970 00:00:59 GMT", true);
1271 RTTESTI_CHECK_RC(obj3.setFormat(RTCRestDate::kFormat_Rfc3339), VINF_SUCCESS);
1272 CHECK_DATE(obj3, false, true, 59123456789, "1970-01-01T00:00:59Z", true);
1273 RTTESTI_CHECK_RC(obj3.setFormat(RTCRestDate::kFormat_Rfc3339_Fraction_2), VINF_SUCCESS);
1274 CHECK_DATE(obj3, false, true, 59123456789, "1970-01-01T00:00:59.12Z", true);
1275 RTTESTI_CHECK_RC(obj3.setFormat(RTCRestDate::kFormat_Rfc3339_Fraction_3), VINF_SUCCESS);
1276 CHECK_DATE(obj3, false, true, 59123456789, "1970-01-01T00:00:59.123Z", true);
1277 RTTESTI_CHECK_RC(obj3.setFormat(RTCRestDate::kFormat_Rfc3339_Fraction_6), VINF_SUCCESS);
1278 CHECK_DATE(obj3, false, true, 59123456789, "1970-01-01T00:00:59.123456Z", true);
1279 RTTESTI_CHECK_RC(obj3.setFormat(RTCRestDate::kFormat_Rfc3339_Fraction_9), VINF_SUCCESS);
1280 CHECK_DATE(obj3, false, true, 59123456789, "1970-01-01T00:00:59.123456789Z", true);
1281
1282 /* Reset to default and setNull works identically: */
1283 RTTESTI_CHECK_RC(obj3.resetToDefault(), VINF_SUCCESS);
1284 CHECK_DATE(obj3, true, false, 0, "", true);
1285
1286 RTTESTI_CHECK_RC(obj3.assignValue(RTTimeSpecSetNano(&TimeSpec, 0), RTCRestDate::kFormat_Rfc3339_Fraction_2), VINF_SUCCESS);
1287 CHECK_DATE(obj3, false, true, 0, "1970-01-01T00:00:00.00Z", true);
1288 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1289 CHECK_DATE(obj3, true, false, 0, "", true);
1290
1291 /* Copy assignments: */
1292 RTCRestDate obj3Epoch_3339_9;
1293 RTTESTI_CHECK_RC(obj3Epoch_3339_9.assignValue(RTTimeSpecSetNano(&TimeSpec, 0), RTCRestDate::kFormat_Rfc3339_Fraction_9), VINF_SUCCESS);
1294 CHECK_DATE(obj3Epoch_3339_9, false, true, 0, "1970-01-01T00:00:00.000000000Z", true);
1295
1296 RTCRestDate obj3Epoch_7131;
1297 RTTESTI_CHECK_RC(obj3Epoch_7131.assignValue(RTTimeSpecSetNano(&TimeSpec, 0), RTCRestDate::kFormat_Rfc7131), VINF_SUCCESS);
1298 CHECK_DATE(obj3Epoch_7131, false, true, 0, "Thu, 1 Jan 1970 00:00:00 GMT", true);
1299
1300 RTCRestDate obj3Recent_3339;
1301 RTTESTI_CHECK_RC(obj3Recent_3339.assignValue(RTTimeSpecSetNano(&TimeSpec, iRecent), RTCRestDate::kFormat_Rfc3339), VINF_SUCCESS);
1302 CHECK_DATE(obj3Recent_3339, false, true, iRecent, "2018-09-10T11:58:07Z", true);
1303
1304 RTCRestDate obj3Recent_2822;
1305 RTTESTI_CHECK_RC(obj3Recent_2822.assignValue(RTTimeSpecSetNano(&TimeSpec, iRecent), RTCRestDate::kFormat_Rfc2822), VINF_SUCCESS);
1306 CHECK_DATE(obj3Recent_2822, false, true, iRecent, "Mon, 10 Sep 2018 11:58:07 -0000", true);
1307
1308 RTCRestDate const obj3Null;
1309 CHECK_DATE(obj3Null, true, false, 0, "", true);
1310
1311 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1312 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Epoch_3339_9), VINF_SUCCESS);
1313 CHECK_DATE(obj3, false, true, 0, "1970-01-01T00:00:00.000000000Z", true);
1314
1315 RTTESTI_CHECK_RC(obj3.setNull(), VINF_SUCCESS);
1316 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Epoch_7131), VINF_SUCCESS);
1317 CHECK_DATE(obj3, false, true, 0, "Thu, 1 Jan 1970 00:00:00 GMT", true);
1318
1319 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Recent_3339), VINF_SUCCESS);
1320 CHECK_DATE(obj3Recent_2822, false, true, iRecent, "Mon, 10 Sep 2018 11:58:07 -0000", true);
1321
1322 RTTESTI_CHECK_RC(obj3.assignCopy(obj3Null), VINF_SUCCESS);
1323 CHECK_DATE(obj3, true, false, 0, "", true);
1324
1325 obj3 = obj3Recent_2822;
1326 CHECK_DATE(obj3Recent_2822, false, true, iRecent, "Mon, 10 Sep 2018 11:58:07 -0000", true);
1327
1328 obj3 = obj3Epoch_3339_9;
1329 CHECK_DATE(obj3, false, true, 0, "1970-01-01T00:00:00.000000000Z", true);
1330
1331 obj3 = obj3Null;
1332 CHECK_DATE(obj3, true, false, 0, "", true);
1333
1334 /* Copy constructors: */
1335 {
1336 RTCRestDate obj3a(obj3Epoch_3339_9);
1337 CHECK_DATE(obj3a, false, true, 0, "1970-01-01T00:00:00.000000000Z", true);
1338 }
1339 {
1340 RTCRestDate obj3b(obj3Epoch_7131);
1341 CHECK_DATE(obj3b, false, true, 0, "Thu, 1 Jan 1970 00:00:00 GMT", true);
1342 }
1343 {
1344 RTCRestDate obj3c(obj3Recent_3339);
1345 CHECK_DATE(obj3Recent_3339, false, true, iRecent, "2018-09-10T11:58:07Z", true);
1346 }
1347 {
1348 RTCRestDate obj3d(obj3Recent_2822);
1349 CHECK_DATE(obj3d, false, true, iRecent, "Mon, 10 Sep 2018 11:58:07 -0000", true);
1350 }
1351 {
1352 RTCRestDate obj3e(obj3Null);
1353 CHECK_DATE(obj3e, true, false, 0, "", true);
1354 }
1355
1356 /* Serialization to json: */
1357 const char *pszJson = toJson(&obj3Epoch_3339_9);
1358 RTTESTI_CHECK_MSG(strcmp(pszJson, "\"1970-01-01T00:00:00.000000000Z\"") == 0, ("pszJson=%s\n", pszJson));
1359 pszJson = toJson(&obj3Epoch_7131);
1360 RTTESTI_CHECK_MSG(strcmp(pszJson, "\"Thu, 1 Jan 1970 00:00:00 GMT\"") == 0, ("pszJson=%s\n", pszJson));
1361 pszJson = toJson(&obj3Recent_3339);
1362 RTTESTI_CHECK_MSG(strcmp(pszJson, "\"2018-09-10T11:58:07Z\"") == 0, ("pszJson=%s\n", pszJson));
1363 pszJson = toJson(&obj3Recent_2822);
1364 RTTESTI_CHECK_MSG(strcmp(pszJson, "\"Mon, 10 Sep 2018 11:58:07 -0000\"") == 0, ("pszJson=%s\n", pszJson));
1365 pszJson = toJson(&obj3Null);
1366 RTTESTI_CHECK_MSG(strcmp(pszJson, "null") == 0, ("pszJson=%s\n", pszJson));
1367
1368 /* Serialization to string. */
1369 RTCString str;
1370 str = "lead-in:";
1371 RTTESTI_CHECK_RC(obj3Epoch_7131.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
1372 RTTESTI_CHECK_MSG(str.equals("lead-in:Thu, 1 Jan 1970 00:00:00 GMT"), ("str=%s\n", str.c_str()));
1373 RTTESTI_CHECK_RC(obj3Epoch_7131.toString(&str), VINF_SUCCESS);
1374 RTTESTI_CHECK_MSG(str.equals("Thu, 1 Jan 1970 00:00:00 GMT"), ("str=%s\n", str.c_str()));
1375
1376 str = "lead-in:";
1377 RTTESTI_CHECK_RC(obj3Recent_3339.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
1378 RTTESTI_CHECK_MSG(str.equals("lead-in:2018-09-10T11:58:07Z"), ("str=%s\n", str.c_str()));
1379 RTTESTI_CHECK_RC(obj3Recent_3339.toString(&str), VINF_SUCCESS);
1380 RTTESTI_CHECK_MSG(str.equals("2018-09-10T11:58:07Z"), ("str=%s\n", str.c_str()));
1381
1382 str = "lead-in:";
1383 RTTESTI_CHECK_RC(obj3Null.toString(&str, RTCRestObjectBase::kToString_Append), VINF_SUCCESS);
1384 RTTESTI_CHECK_MSG(str.equals("lead-in:null"), ("str=%s\n", str.c_str()));
1385 RTTESTI_CHECK_RC(obj3Null.toString(&str), VINF_SUCCESS);
1386 RTTESTI_CHECK_MSG(str.equals("null"), ("str=%s\n", str.c_str()));
1387 }
1388
1389 /* deserialize: */
1390 RTERRINFOSTATIC ErrInfo;
1391 {
1392 RTCRestDate obj4;
1393 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"Thu, 1 Jan 1970 00:00:00 GMT\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1394 CHECK_DATE_FMT(obj4, false, true, 0, "Thu, 1 Jan 1970 00:00:00 GMT", true, RTCRestDate::kFormat_Rfc7131);
1395
1396 obj4.setNull();
1397 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"Thu, 1 Jan 1970 00:00:00.0000 GMT\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1398 CHECK_DATE_FMT(obj4, false, true, 0, "Thu, 1 Jan 1970 00:00:00.0000 GMT", true, RTCRestDate::kFormat_Rfc7131);
1399
1400 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"1 Jan 1970 00:00:00 GMT\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1401 CHECK_DATE_FMT(obj4, false, true, 0, "1 Jan 1970 00:00:00 GMT", true, RTCRestDate::kFormat_Rfc7131);
1402
1403 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"1 Jan 1970 00:00:00\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1404 CHECK_DATE_FMT(obj4, false, true, 0, "1 Jan 1970 00:00:00", false, RTCRestDate::kFormat_Rfc2822);
1405
1406 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"1 Jan 070 00:00:00\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1407 CHECK_DATE_FMT(obj4, false, true, 0, "1 Jan 070 00:00:00", false, RTCRestDate::kFormat_Rfc2822);
1408
1409 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"2018-09-10T11:58:07Z\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1410 CHECK_DATE_FMT(obj4, false, true, iRecentSec , "2018-09-10T11:58:07Z", true, RTCRestDate::kFormat_Rfc3339);
1411
1412 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"1 Jan 70 00:00:00\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1413 CHECK_DATE_FMT(obj4, false, true, 0, "1 Jan 70 00:00:00", false, RTCRestDate::kFormat_Rfc2822);
1414
1415 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"2018-09-10T11:58:07.739632500Z\"", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1416 CHECK_DATE_FMT(obj4, false, true, iRecent, "2018-09-10T11:58:07.739632500Z", true, RTCRestDate::kFormat_Rfc3339_Fraction_9);
1417
1418 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "null", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1419 CHECK_DATE_FMT(obj4, true, false, 0, "", true, RTCRestDate::kFormat_Rfc3339_Fraction_9);
1420
1421 /* object goes to default state if not string and to non-okay if string: */
1422 RTTESTI_CHECK_RC(obj4.assignValue(RTTimeSpecSetNano(&TimeSpec, iRecent), RTCRestDate::kFormat_Rfc2822), VINF_SUCCESS);
1423 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "true", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_DATE);
1424 CHECK_DATE_FMT(obj4, true, false, 0, "", true, RTCRestDate::kFormat_Rfc2822);
1425
1426 RTTESTI_CHECK_RC(obj4.assignValue(RTTimeSpecSetNano(&TimeSpec, iRecent), RTCRestDate::kFormat_Rfc2822), VINF_SUCCESS);
1427 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"string\"", &ErrInfo, RT_XSTR(__LINE__)), VWRN_REST_UNABLE_TO_DECODE_DATE);
1428 CHECK_DATE_FMT(obj4, false, false, 0, "string", false, RTCRestDate::kFormat_Rfc2822);
1429
1430 RTTESTI_CHECK_RC(obj4.assignValue(RTTimeSpecSetNano(&TimeSpec, iRecent), RTCRestDate::kFormat_Rfc2822), VINF_SUCCESS);
1431 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "\"0x199 string\"", &ErrInfo, RT_XSTR(__LINE__)), VWRN_REST_UNABLE_TO_DECODE_DATE);
1432 CHECK_DATE_FMT(obj4, false, false, 0, "0x199 string", false, RTCRestDate::kFormat_Rfc2822);
1433
1434 RTTESTI_CHECK_RC(obj4.assignValue(RTTimeSpecSetNano(&TimeSpec, iRecent), RTCRestDate::kFormat_Rfc2822), VINF_SUCCESS);
1435 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "[ null ]", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_DATE);
1436 CHECK_DATE_FMT(obj4, true, false, 0, "", true, RTCRestDate::kFormat_Rfc2822);
1437
1438 RTTESTI_CHECK_RC(obj4.assignValue(RTTimeSpecSetNano(&TimeSpec, iRecent), RTCRestDate::kFormat_Rfc2822), VINF_SUCCESS);
1439 RTTESTI_CHECK_RC(deserializeFromJson(&obj4, "{ \"foo\": 1 }", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_WRONG_JSON_TYPE_FOR_DATE);
1440 CHECK_DATE_FMT(obj4, true, false, 0, "", true, RTCRestDate::kFormat_Rfc2822);
1441
1442 /* From string: */
1443 obj4.setNull();
1444 RTTESTI_CHECK_RC(fromString(&obj4, "Thu, 1 Jan 1970 00:00:00 GMT", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1445 CHECK_DATE_FMT(obj4, false, true, 0, "Thu, 1 Jan 1970 00:00:00 GMT", true, RTCRestDate::kFormat_Rfc7131);
1446
1447 RTTESTI_CHECK_RC(fromString(&obj4, "Mon, 10 Sep 2018 11:58:07 -0000", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1448 CHECK_DATE_FMT(obj4, false, true, iRecentSec, "Mon, 10 Sep 2018 11:58:07 -0000", true, RTCRestDate::kFormat_Rfc2822);
1449
1450 RTTESTI_CHECK_RC(fromString(&obj4, "\t\n\rnull;\r\n\t", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1451 CHECK_DATE_FMT(obj4, true, false, 0, "", true, RTCRestDate::kFormat_Rfc2822);
1452
1453 RTTESTI_CHECK_RC(fromString(&obj4, "Mon, 10 Sep 2018 11:58:07 +0000", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1454 CHECK_DATE_FMT(obj4, false, true, iRecentSec, "Mon, 10 Sep 2018 11:58:07 +0000", false, RTCRestDate::kFormat_Rfc2822);
1455
1456 RTTESTI_CHECK_RC(fromString(&obj4, "1970-01-01T00:00:00.000000000Z", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1457 CHECK_DATE_FMT(obj4, false, true, 0, "1970-01-01T00:00:00.000000000Z", true, RTCRestDate::kFormat_Rfc3339_Fraction_9);
1458
1459 RTTESTI_CHECK_RC(fromString(&obj4, "10 Sep 2018 11:58:07 -0000", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1460 CHECK_DATE_FMT(obj4, false, true, iRecentSec, "10 Sep 2018 11:58:07 -0000", true, RTCRestDate::kFormat_Rfc2822);
1461
1462 RTTESTI_CHECK_RC(fromString(&obj4, "null", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1463 CHECK_DATE_FMT(obj4, true, false, 0, "", true, RTCRestDate::kFormat_Rfc2822);
1464
1465 RTTESTI_CHECK_RC(fromString(&obj4, "Mon, 10 Sep 18 11:58:07 -0000", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1466 CHECK_DATE_FMT(obj4, false, true, iRecentSec, "Mon, 10 Sep 18 11:58:07 -0000", true, RTCRestDate::kFormat_Rfc2822);
1467
1468 RTTESTI_CHECK_RC(fromString(&obj4, "fa;se", &ErrInfo, RT_XSTR(__LINE__)), VERR_REST_UNABLE_TO_DECODE_DATE);
1469 CHECK_DATE_FMT(obj4, false, false, 0, "fa;se", false, RTCRestDate::kFormat_Rfc2822);
1470
1471 RTTESTI_CHECK_RC(fromString(&obj4, "10 Sep 18 11:58:07", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1472 CHECK_DATE_FMT(obj4, false, true, iRecentSec, "10 Sep 18 11:58:07", false, RTCRestDate::kFormat_Rfc2822);
1473
1474 obj4.setNull();
1475 RTTESTI_CHECK_RC(fromString(&obj4, "10 Sep 118 11:58:07", &ErrInfo, RT_XSTR(__LINE__)), VINF_SUCCESS);
1476 CHECK_DATE_FMT(obj4, false, true, iRecentSec, "10 Sep 118 11:58:07", false, RTCRestDate::kFormat_Rfc2822);
1477 }
1478}
1479
1480
1481/** Wraps RTCRestInt16 to check for leaks. */
1482class MyRestInt16 : public RTCRestInt16
1483{
1484public:
1485 static size_t s_cInstances;
1486 MyRestInt16() : RTCRestInt16() { s_cInstances++; }
1487 MyRestInt16(MyRestInt16 const &a_rThat) : RTCRestInt16(a_rThat) { s_cInstances++; }
1488 MyRestInt16(int16_t a_iValue) : RTCRestInt16(a_iValue) { s_cInstances++; }
1489 ~MyRestInt16() { s_cInstances--; }
1490};
1491
1492size_t MyRestInt16::s_cInstances = 0;
1493
1494
1495static void verifyArray(RTCRestArray<MyRestInt16> const &rArray, int iLine, unsigned cElements, ...)
1496{
1497 if (rArray.size() != cElements)
1498 RTTestIFailed("line %u: size() -> %zu, expected %u", iLine, rArray.size(), cElements);
1499 va_list va;
1500 va_start(va, cElements);
1501 for (unsigned i = 0; i < cElements; i++)
1502 {
1503 int iExpected = va_arg(va, int);
1504 if (rArray.at(i)->m_iValue != iExpected)
1505 RTTestIFailed("line %u: element #%u: %d, expected %d", iLine, i, rArray.at(i)->m_iValue, iExpected);
1506 }
1507 va_end(va);
1508}
1509
1510
1511static void testArray()
1512{
1513 RTTestSub(g_hTest, "RTCRestArray");
1514
1515 {
1516 RTCRestArray<RTCRestBool> obj1;
1517 RTTESTI_CHECK(obj1.size() == 0);
1518 RTTESTI_CHECK(obj1.isEmpty() == true);
1519 RTTESTI_CHECK(obj1.isNull() == false);
1520 RTTESTI_CHECK(strcmp(obj1.typeName(), "RTCRestArray<ElementType>") == 0);
1521 RTTESTI_CHECK(obj1.typeClass() == RTCRestObjectBase::kTypeClass_Array);
1522 }
1523
1524 /* Some random order insertion and manipulations: */
1525 {
1526 RTCRestArray<MyRestInt16> Arr2;
1527 RTCRestArray<MyRestInt16> const *pConstArr2 = &Arr2;
1528
1529 RTTESTI_CHECK_RC(Arr2.insert(0, new MyRestInt16(3)), VINF_SUCCESS);
1530 verifyArray(Arr2, __LINE__, 1, 3);
1531 RTTESTI_CHECK_RC(Arr2.append( new MyRestInt16(7)), VINF_SUCCESS);
1532 verifyArray(Arr2, __LINE__, 2, 3, 7);
1533 RTTESTI_CHECK_RC(Arr2.insert(1, new MyRestInt16(5)), VINF_SUCCESS);
1534 verifyArray(Arr2, __LINE__, 3, 3, 5, 7);
1535 RTTESTI_CHECK_RC(Arr2.insert(2, new MyRestInt16(6)), VINF_SUCCESS);
1536 verifyArray(Arr2, __LINE__, 4, 3, 5, 6, 7);
1537 RTTESTI_CHECK_RC(Arr2.prepend( new MyRestInt16(0)), VINF_SUCCESS);
1538 verifyArray(Arr2, __LINE__, 5, 0, 3, 5, 6, 7);
1539 RTTESTI_CHECK_RC(Arr2.append( new MyRestInt16(9)), VINF_SUCCESS);
1540 verifyArray(Arr2, __LINE__, 6, 0, 3, 5, 6, 7, 9);
1541 RTTESTI_CHECK_RC(Arr2.insert(5, new MyRestInt16(8)), VINF_SUCCESS);
1542 verifyArray(Arr2, __LINE__, 7, 0, 3, 5, 6, 7, 8, 9);
1543 RTTESTI_CHECK_RC(Arr2.insert(1, new MyRestInt16(1)), VINF_SUCCESS);
1544 verifyArray(Arr2, __LINE__, 8, 0, 1, 3, 5, 6, 7, 8, 9);
1545 RTTESTI_CHECK_RC(Arr2.insert(3, new MyRestInt16(4)), VINF_SUCCESS);
1546 verifyArray(Arr2, __LINE__, 9, 0, 1, 3, 4, 5, 6, 7, 8, 9);
1547 RTTESTI_CHECK_RC(Arr2.insert(2, new MyRestInt16(2)), VINF_SUCCESS);
1548 verifyArray(Arr2, __LINE__, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
1549 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == Arr2.size(), ("%zu vs %zu\n", MyRestInt16::s_cInstances, Arr2.size()));
1550
1551 RTTESTI_CHECK(Arr2.size() == 10);
1552
1553 for (size_t i = 0; i < Arr2.size(); i++)
1554 {
1555 MyRestInt16 *pCur = Arr2.at(i);
1556 RTTESTI_CHECK(pCur->m_iValue == (int16_t)i);
1557
1558 MyRestInt16 const *pCur2 = pConstArr2->at(i);
1559 RTTESTI_CHECK(pCur2->m_iValue == (int16_t)i);
1560 }
1561
1562 RTTESTI_CHECK_RC(Arr2.replace(2, new MyRestInt16(22)), VWRN_ALREADY_EXISTS);
1563 verifyArray(Arr2, __LINE__, 10, 0, 1, 22, 3, 4, 5, 6, 7, 8, 9);
1564
1565 RTTESTI_CHECK_RC(Arr2.replace(7, new MyRestInt16(77)), VWRN_ALREADY_EXISTS);
1566 verifyArray(Arr2, __LINE__, 10, 0, 1, 22, 3, 4, 5, 6, 77, 8, 9);
1567
1568 RTTESTI_CHECK_RC(Arr2.replace(10, new MyRestInt16(10)), VINF_SUCCESS);
1569 verifyArray(Arr2, __LINE__, 11, 0, 1, 22, 3, 4, 5, 6, 77, 8, 9, 10);
1570
1571 RTTESTI_CHECK_RC(Arr2.replaceCopy(2, MyRestInt16(2)), VWRN_ALREADY_EXISTS);
1572 verifyArray(Arr2, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1573 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == Arr2.size(), ("%zu vs %zu\n", MyRestInt16::s_cInstances, Arr2.size()));
1574
1575 /* copy constructor: */
1576 {
1577 RTCRestArray<MyRestInt16> const Arr2Copy(Arr2);
1578 verifyArray(Arr2Copy, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1579 }
1580 verifyArray(Arr2, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1581 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == Arr2.size(), ("%zu vs %zu\n", MyRestInt16::s_cInstances, Arr2.size()));
1582
1583 {
1584 RTCRestArray<MyRestInt16> Arr2Copy2(Arr2);
1585 verifyArray(Arr2Copy2, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1586 RTTESTI_CHECK_RC(Arr2Copy2.removeAt(7), VINF_SUCCESS);
1587 verifyArray(Arr2Copy2, __LINE__, 10, 0, 1, 2, 3, 4, 5, 6, 8, 9, 10);
1588 }
1589 verifyArray(Arr2, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1590 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == Arr2.size(), ("%zu vs %zu\n", MyRestInt16::s_cInstances, Arr2.size()));
1591
1592 /* copy method + clear: */
1593 {
1594 RTCRestArray<MyRestInt16> Arr2Copy3;
1595 RTTESTI_CHECK_RC(Arr2Copy3.assignCopy(Arr2), VINF_SUCCESS);
1596 verifyArray(Arr2Copy3, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1597 Arr2Copy3.at(3)->m_iValue = 33;
1598 verifyArray(Arr2Copy3, __LINE__, 11, 0, 1, 2, 33, 4, 5, 6, 77, 8, 9, 10);
1599 Arr2Copy3.clear();
1600 verifyArray(Arr2Copy3, __LINE__, 0);
1601 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == Arr2.size(), ("%zu vs %zu\n", MyRestInt16::s_cInstances, Arr2.size()));
1602 }
1603 verifyArray(Arr2, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1604 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == Arr2.size(), ("%zu vs %zu\n", MyRestInt16::s_cInstances, Arr2.size()));
1605
1606 /* Check setNull and resetToDefaults with copies: */
1607 {
1608 RTCRestArray<MyRestInt16> Arr2Copy4(Arr2);
1609 verifyArray(Arr2Copy4, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1610
1611 RTTESTI_CHECK_RC(Arr2Copy4.setNull(), VINF_SUCCESS);
1612 verifyArray(Arr2Copy4, __LINE__, 0);
1613 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == Arr2.size(), ("%zu vs %zu\n", MyRestInt16::s_cInstances, Arr2.size()));
1614 RTTESTI_CHECK(Arr2Copy4.isNull() == true);
1615
1616 RTTESTI_CHECK_RC(Arr2Copy4.resetToDefault(), VINF_SUCCESS);
1617 RTTESTI_CHECK(Arr2Copy4.isNull() == false);
1618 verifyArray(Arr2Copy4, __LINE__, 0);
1619 }
1620 verifyArray(Arr2, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1621 {
1622 RTCRestArray<MyRestInt16> Arr2Copy5(Arr2);
1623 verifyArray(Arr2Copy5, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1624
1625 RTTESTI_CHECK_RC(Arr2Copy5.resetToDefault(), VINF_SUCCESS);
1626 verifyArray(Arr2Copy5, __LINE__, 0);
1627 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == Arr2.size(), ("%zu vs %zu\n", MyRestInt16::s_cInstances, Arr2.size()));
1628 RTTESTI_CHECK(Arr2Copy5.isNull() == false);
1629
1630 RTTESTI_CHECK_RC(Arr2Copy5.setNull(), VINF_SUCCESS);
1631 RTTESTI_CHECK(Arr2Copy5.isNull() == true);
1632
1633 RTTESTI_CHECK_RC(Arr2Copy5.append(new MyRestInt16(100)), VINF_SUCCESS);
1634 RTTESTI_CHECK(Arr2Copy5.isNull() == false);
1635 verifyArray(Arr2Copy5, __LINE__, 1, 100);
1636 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == Arr2.size() + 1, ("%zu vs %zu\n", MyRestInt16::s_cInstances, Arr2.size() + 1));
1637 }
1638 verifyArray(Arr2, __LINE__, 11, 0, 1, 2, 3, 4, 5, 6, 77, 8, 9, 10);
1639
1640 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == Arr2.size(), ("%zu vs %zu\n", MyRestInt16::s_cInstances, Arr2.size()));
1641 }
1642 RTTESTI_CHECK_MSG(MyRestInt16::s_cInstances == 0, ("%zu\n", MyRestInt16::s_cInstances));
1643
1644 {
1645 RTCRestArray<RTCRestInt64> Arr3;
1646 RTCRestArray<RTCRestInt64> const *pConstArr3 = &Arr3;
1647
1648 /* Insert a range of numbers into a int64 array. */
1649 for (int64_t i = 0; i < _64K; i++)
1650 {
1651 if (i & 1)
1652 {
1653 RTCRestInt64 toCopy(i);
1654 if (i & 2)
1655 RTTESTI_CHECK_RC(Arr3.insertCopy(i, toCopy), VINF_SUCCESS);
1656 else
1657 RTTESTI_CHECK_RC(Arr3.appendCopy(toCopy), VINF_SUCCESS);
1658 }
1659 else
1660 {
1661 RTCRestInt64 *pDirect = new RTCRestInt64(i);
1662 if (i & 2)
1663 RTTESTI_CHECK_RC(Arr3.insert(i, pDirect), VINF_SUCCESS);
1664 else
1665 RTTESTI_CHECK_RC(Arr3.append(pDirect), VINF_SUCCESS);
1666 }
1667 RTTESTI_CHECK(Arr3.size() == (size_t)i + 1);
1668 RTTESTI_CHECK(Arr3.isEmpty() == false);
1669 }
1670
1671 /* Verify insertions: */
1672 size_t cElements = _64K;
1673 RTTESTI_CHECK(Arr3.size() == cElements);
1674
1675 for (int64_t i = 0; i < _64K; i++)
1676 {
1677 RTCRestInt64 *pCur = Arr3.at(i);
1678 RTTESTI_CHECK(pCur->m_iValue == i);
1679
1680 RTCRestInt64 const *pCur2 = pConstArr3->at(i);
1681 RTTESTI_CHECK(pCur2->m_iValue == i);
1682 }
1683 RTTESTI_CHECK(Arr3.first()->m_iValue == 0);
1684 RTTESTI_CHECK(Arr3.last()->m_iValue == _64K - 1);
1685 RTTESTI_CHECK(pConstArr3->first()->m_iValue == 0);
1686 RTTESTI_CHECK(pConstArr3->last()->m_iValue == _64K - 1);
1687
1688 /* Remove every 3rd element: */
1689 RTTESTI_CHECK(Arr3.size() == cElements);
1690 for (int64_t i = _64K - 1; i >= 0; i -= 3)
1691 {
1692 RTTESTI_CHECK_RC(Arr3.removeAt(i), VINF_SUCCESS);
1693 cElements--;
1694 RTTESTI_CHECK(Arr3.size() == cElements);
1695 }
1696
1697 /* Verify after removal: */
1698 for (int64_t i = 0, iValue = 0; i < (ssize_t)Arr3.size(); i++, iValue++)
1699 {
1700 if ((iValue % 3) == 0)
1701 iValue++;
1702 RTTESTI_CHECK_MSG(Arr3.at(i)->m_iValue == iValue, ("%RI64: %RI64 vs %RI64\n", i, Arr3.at(i)->m_iValue, iValue));
1703 }
1704
1705 /* Clear it and we're done: */
1706 Arr3.clear();
1707 RTTESTI_CHECK(Arr3.size() == 0);
1708 RTTESTI_CHECK(Arr3.isEmpty() == true);
1709 }
1710
1711 {
1712 RTCRestArray<RTCRestInt32> Arr4;
1713
1714 /* Insert a range of numbers into a int32 array, in reverse order. */
1715 for (int32_t i = 0; i < 2048; i++)
1716 {
1717 if (i & 1)
1718 {
1719 RTCRestInt32 toCopy(i);
1720 if (i & 2)
1721 RTTESTI_CHECK_RC(Arr4.insertCopy(0, toCopy), VINF_SUCCESS);
1722 else
1723 RTTESTI_CHECK_RC(Arr4.prependCopy(toCopy), VINF_SUCCESS);
1724 }
1725 else
1726 {
1727 RTCRestInt32 *pDirect = new RTCRestInt32(i);
1728 if (i & 2)
1729 RTTESTI_CHECK_RC(Arr4.insert(0, pDirect), VINF_SUCCESS);
1730 else
1731 RTTESTI_CHECK_RC(Arr4.prepend(pDirect), VINF_SUCCESS);
1732 }
1733 RTTESTI_CHECK((ssize_t)Arr4.size() == i + 1);
1734 RTTESTI_CHECK(Arr4.isEmpty() == false);
1735 }
1736
1737 for (int32_t i = 0, iValue = (int32_t)Arr4.size() - 1; i < (ssize_t)Arr4.size(); i++, iValue--)
1738 RTTESTI_CHECK_MSG(Arr4.at(i)->m_iValue == iValue, ("%RI32: %RI32 vs %RI32\n", i, Arr4.at(i)->m_iValue, iValue));
1739
1740 for (int32_t i = 0; i < 512; i++)
1741 RTTESTI_CHECK_RC(Arr4.removeAt(0), VINF_SUCCESS);
1742 RTTESTI_CHECK(Arr4.size() == 1536);
1743
1744 for (int32_t i = 0; i < 512; i++)
1745 RTTESTI_CHECK_RC(Arr4.removeAt(~(size_t)0), VINF_SUCCESS);
1746 RTTESTI_CHECK(Arr4.size() == 1024);
1747
1748 for (int32_t i = 0, iValue = 1535; i < (ssize_t)Arr4.size(); i++, iValue--)
1749 RTTESTI_CHECK_MSG(Arr4.at(i)->m_iValue == iValue, ("%RI32: %RI32 vs %RI32\n", i, Arr4.at(i)->m_iValue, iValue));
1750 }
1751}
1752
1753
1754static void verifyMap(RTCRestStringMap<MyRestInt16> const &rMap, int iLine, unsigned cEntries, ...)
1755{
1756 if (rMap.size() != cEntries)
1757 RTTestIFailed("line %u: size() -> %zu, expected %u", iLine, rMap.size(), cEntries);
1758 if (rMap.isEmpty() != (cEntries ? false : true))
1759 RTTestIFailed("line %u: isEmpty() -> %RTbool, with %u entries", iLine, rMap.isEmpty(), cEntries);
1760
1761 va_list va;
1762 va_start(va, cEntries);
1763 for (unsigned i = 0; i < cEntries; i++)
1764 {
1765 const char *pszKey = va_arg(va, const char *);
1766 int iValue = va_arg(va, int);
1767 if ( rMap.containsKey(pszKey) != true
1768 || rMap.containsKey(RTCString(pszKey)) != true
1769 || rMap.get(pszKey) == NULL
1770 || rMap.get(RTCString(pszKey)) == NULL)
1771 RTTestIFailed("line %u: entry '%s' not found!", iLine, pszKey);
1772 else if (rMap.get(pszKey)->m_iValue != iValue)
1773 RTTestIFailed("line %u: entry '%s' value mismatch: %d, expected %d",
1774 iLine, pszKey, rMap.get(pszKey)->m_iValue, iValue);
1775 RTTESTI_CHECK(rMap.get(pszKey) == rMap.get(RTCString(pszKey)));
1776 }
1777 va_end(va);
1778 RTTESTI_CHECK(rMap.isNull() == false);
1779
1780 uint64_t fFound = 0;
1781 for (RTCRestStringMapBase::ConstIterator it = rMap.begin(); it != rMap.end(); ++it)
1782 {
1783 MyRestInt16 const *pObj = (MyRestInt16 const *)it.getValue();
1784 RTTESTI_CHECK(RT_VALID_PTR(pObj));
1785
1786 bool fFoundIt = false;
1787 va_start(va, cEntries);
1788 for (unsigned i = 0; i < cEntries; i++)
1789 {
1790 const char *pszKey = va_arg(va, const char *);
1791 int iValue = va_arg(va, int);
1792 if (it.getKey().equals(pszKey))
1793 {
1794 if (fFound & RT_BIT_64(i))
1795 RTTestIFailed("line %u: base enum: entry '%s' returned more than once!", iLine, pszKey);
1796 if (pObj->m_iValue != iValue)
1797 RTTestIFailed("line %u: base enum: entry '%s' value mismatch: %d, expected %d",
1798 iLine, pszKey, pObj->m_iValue, iValue);
1799 fFound |= RT_BIT_64(i);
1800 fFoundIt = true;
1801 va_end(va);
1802 return;
1803 }
1804 }
1805 va_end(va);
1806 if (!fFoundIt)
1807 RTTestIFailed("line %u: base enum: entry '%s' not expected!", iLine, it.getKey().c_str());
1808 }
1809}
1810
1811
1812void testStringMap(void)
1813{
1814 RTTestSub(g_hTest, "RTCRestMap");
1815
1816 {
1817 RTCRestStringMap<RTCRestString> obj1;
1818 RTTESTI_CHECK(obj1.size() == 0);
1819 RTTESTI_CHECK(obj1.isEmpty() == true);
1820 RTTESTI_CHECK(obj1.isNull() == false);
1821 RTTESTI_CHECK(strcmp(obj1.typeName(), "RTCRestStringMap<ValueType>") == 0);
1822 RTTESTI_CHECK(obj1.typeClass() == RTCRestObjectBase::kTypeClass_StringMap);
1823 }
1824
1825 /* Basic operations: */
1826 {
1827 MyRestInt16::s_cInstances = 0;
1828 RTCRestStringMap<MyRestInt16> Map2;
1829 verifyMap(Map2, __LINE__, 0);
1830
1831 RTTESTI_CHECK_RC(Map2.putCopy("0x0004", MyRestInt16(4)), VINF_SUCCESS);
1832 verifyMap(Map2, __LINE__, 1, "0x0004", 4);
1833 RTTESTI_CHECK(MyRestInt16::s_cInstances == 1);
1834 RTTESTI_CHECK_RC(Map2.put("0x0001", new MyRestInt16(1)), VINF_SUCCESS);
1835 verifyMap(Map2, __LINE__, 2, "0x0004",4, "0x0001",1);
1836 RTTESTI_CHECK_RC(Map2.put("0x0003", new MyRestInt16(3)), VINF_SUCCESS);
1837 verifyMap(Map2, __LINE__, 3, "0x0004",4, "0x0001",1, "0x0003",3);
1838 RTTESTI_CHECK_RC(Map2.put("0x0002", new MyRestInt16(2)), VINF_SUCCESS);
1839 verifyMap(Map2, __LINE__, 4, "0x0004",4, "0x0001",1, "0x0003",3, "0x0002",2);
1840 RTTESTI_CHECK(MyRestInt16::s_cInstances == 4);
1841 RTTESTI_CHECK_RC(Map2.put("0x0000", new MyRestInt16(0)), VINF_SUCCESS);
1842 verifyMap(Map2, __LINE__, 5, "0x0004",4, "0x0001",1, "0x0003",3, "0x0002",2, "0x0000",0);
1843 RTTESTI_CHECK(MyRestInt16::s_cInstances == 5);
1844 RTTESTI_CHECK_RC(Map2.putCopy("towel", MyRestInt16(42)), VINF_SUCCESS);
1845 verifyMap(Map2, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0003",3, "0x0002",2, "0x0000",0, "towel",42);
1846 RTTESTI_CHECK(MyRestInt16::s_cInstances == 6);
1847
1848 RTTESTI_CHECK(Map2.containsKey("0x0005") == false);
1849 RTTESTI_CHECK(Map2.get("0x0005") == NULL);
1850
1851 RTTESTI_CHECK(Map2.remove("0x0003") == true);
1852 verifyMap(Map2, __LINE__, 5, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42);
1853 RTTESTI_CHECK(MyRestInt16::s_cInstances == 5);
1854
1855 RTTESTI_CHECK(Map2.remove("0x0003") == false);
1856 verifyMap(Map2, __LINE__, 5, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42);
1857 RTTESTI_CHECK(MyRestInt16::s_cInstances == 5);
1858
1859 RTCRestObjectBase *pNewBase = NULL;
1860 RTTESTI_CHECK_RC(Map2.putNewValue(&pNewBase, "putNewValue"), VINF_SUCCESS);
1861 ((MyRestInt16 *)pNewBase)->m_iValue = 88;
1862 RTTESTI_CHECK(MyRestInt16::s_cInstances == 6);
1863 verifyMap(Map2, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",88);
1864
1865 pNewBase = NULL;
1866 RTTESTI_CHECK_RC(Map2.putNewValue(&pNewBase, RTCString("putNewValue")), VERR_ALREADY_EXISTS);
1867 verifyMap(Map2, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",88);
1868 pNewBase = NULL;
1869 RTTESTI_CHECK_RC(Map2.putNewValue(&pNewBase, RTCString("putNewValue"), true /*a_fReplace*/), VWRN_ALREADY_EXISTS);
1870 verifyMap(Map2, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",0);
1871 RTTESTI_CHECK(MyRestInt16::s_cInstances == 6);
1872
1873 /* Make copy and remove all: */
1874 {
1875 RTCRestStringMap<MyRestInt16> Map2Copy1;
1876
1877 RTTESTI_CHECK_RC(Map2Copy1.assignCopy(Map2), VINF_SUCCESS);
1878 verifyMap(Map2Copy1, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",0);
1879 RTTESTI_CHECK(MyRestInt16::s_cInstances == 12);
1880
1881 RTTESTI_CHECK(Map2Copy1.remove("0x0004") == true);
1882 verifyMap(Map2Copy1, __LINE__, 5, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",0);
1883 RTTESTI_CHECK(MyRestInt16::s_cInstances == 11);
1884
1885 RTTESTI_CHECK(Map2Copy1.remove("putNewValue") == true);
1886 verifyMap(Map2Copy1, __LINE__, 4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42);
1887 RTTESTI_CHECK(MyRestInt16::s_cInstances == 10);
1888
1889 RTTESTI_CHECK(Map2Copy1.remove("towel") == true);
1890 verifyMap(Map2Copy1, __LINE__, 3, "0x0001",1, "0x0002",2, "0x0000",0);
1891 RTTESTI_CHECK(MyRestInt16::s_cInstances == 9);
1892
1893 RTTESTI_CHECK(Map2Copy1.remove("0x0002") == true);
1894 verifyMap(Map2Copy1, __LINE__, 2, "0x0001",1, "0x0000",0);
1895 RTTESTI_CHECK(MyRestInt16::s_cInstances == 8);
1896
1897 RTTESTI_CHECK(Map2Copy1.remove("0x0000") == true);
1898 verifyMap(Map2Copy1, __LINE__, 1, "0x0001",1);
1899 RTTESTI_CHECK(MyRestInt16::s_cInstances == 7);
1900
1901 RTTESTI_CHECK(Map2Copy1.remove("0x0001") == true);
1902 verifyMap(Map2Copy1, __LINE__, 0);
1903 RTTESTI_CHECK(Map2Copy1.isEmpty() == true);
1904 RTTESTI_CHECK(MyRestInt16::s_cInstances == 6);
1905 }
1906 verifyMap(Map2, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",0);
1907
1908 /* Make copy and use clear: */
1909 {
1910 RTCRestStringMap<MyRestInt16> Map2Copy2(Map2);
1911 verifyMap(Map2Copy2, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",0);
1912 RTTESTI_CHECK(MyRestInt16::s_cInstances == 12);
1913 Map2Copy2.clear();
1914 verifyMap(Map2Copy2, __LINE__, 0);
1915 RTTESTI_CHECK(Map2Copy2.isEmpty() == true);
1916 RTTESTI_CHECK(MyRestInt16::s_cInstances == 6);
1917 }
1918 verifyMap(Map2, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",0);
1919
1920 /* Make copy and reset to default: */
1921 {
1922 RTCRestStringMap<MyRestInt16> Map2Copy3(Map2);
1923 verifyMap(Map2Copy3, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",0);
1924 RTTESTI_CHECK(MyRestInt16::s_cInstances == 12);
1925 RTTESTI_CHECK_RC(Map2Copy3.resetToDefault(), VINF_SUCCESS);
1926 verifyMap(Map2Copy3, __LINE__, 0);
1927 RTTESTI_CHECK(Map2Copy3.isEmpty() == true);
1928 RTTESTI_CHECK(MyRestInt16::s_cInstances == 6);
1929 }
1930 verifyMap(Map2, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",0);
1931
1932 /* Make copy and set to null: */
1933 {
1934 RTCRestStringMap<MyRestInt16> Map2Copy4;
1935 Map2Copy4 = Map2;
1936 verifyMap(Map2Copy4, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",0);
1937 RTTESTI_CHECK(MyRestInt16::s_cInstances == 12);
1938 RTTESTI_CHECK_RC(Map2Copy4.setNull(), VINF_SUCCESS);
1939 RTTESTI_CHECK(Map2Copy4.size() == 0);
1940 RTTESTI_CHECK(Map2Copy4.isEmpty() == true);
1941 RTTESTI_CHECK(Map2Copy4.isNull() == true);
1942 RTTESTI_CHECK(MyRestInt16::s_cInstances == 6);
1943 }
1944 verifyMap(Map2, __LINE__, 6, "0x0004",4, "0x0001",1, "0x0002",2, "0x0000",0, "towel",42, "putNewValue",0);
1945 }
1946 RTTESTI_CHECK(MyRestInt16::s_cInstances == 0);
1947
1948 /* Check that null indicator is reset when it should: */
1949 {
1950 RTCRestStringMap<MyRestInt16> Map3;
1951 Map3.setNull();
1952 RTTESTI_CHECK_RC(Map3.setNull(), VINF_SUCCESS);
1953 RTTESTI_CHECK(Map3.size() == 0);
1954 RTTESTI_CHECK(Map3.isEmpty() == true);
1955 RTTESTI_CHECK(Map3.isNull() == true);
1956 RTTESTI_CHECK_RC(Map3.putCopy("not-null-anymore", MyRestInt16(1)), VINF_SUCCESS);
1957 verifyMap(Map3, __LINE__, 1, "not-null-anymore",1);
1958 }
1959 RTTESTI_CHECK(MyRestInt16::s_cInstances == 0);
1960
1961 {
1962 RTCRestStringMap<MyRestInt16> Map4;
1963 Map4.setNull();
1964 RTTESTI_CHECK_RC(Map4.setNull(), VINF_SUCCESS);
1965 RTTESTI_CHECK(Map4.size() == 0);
1966 RTTESTI_CHECK(Map4.isEmpty() == true);
1967 RTTESTI_CHECK(Map4.isNull() == true);
1968 RTCRestObjectBase *pNewBase = NULL;
1969 RTTESTI_CHECK_RC(Map4.putNewValue(&pNewBase, "putNewValue"), VINF_SUCCESS);
1970 verifyMap(Map4, __LINE__, 1, "putNewValue",0);
1971 }
1972 RTTESTI_CHECK(MyRestInt16::s_cInstances == 0);
1973}
1974
1975
1976class TestRequest : public RTCRestClientRequestBase
1977{
1978public:
1979 RTCRestString m_strValue;
1980 RTCRestInt64 m_iValue;
1981 RTCRestArray<RTCRestString> m_Array;
1982 RTCRestStringMap<RTCRestString> m_Map;
1983 /** @todo add more attributes. */
1984
1985 TestRequest(const char *a_pszValue, int64_t a_iValue, unsigned a_cElements, ...)
1986 : RTCRestClientRequestBase()
1987 , m_strValue(a_pszValue)
1988 , m_iValue(a_iValue)
1989 {
1990 m_fIsSet = UINT64_MAX;
1991 va_list va;
1992 va_start(va, a_cElements);
1993 for (unsigned i = 0; i < a_cElements; i++)
1994 m_Array.append(new RTCRestString(va_arg(va, const char *)));
1995 va_end(va);
1996 }
1997
1998 int resetToDefault() RT_OVERRIDE
1999 {
2000 m_strValue = "";
2001 m_iValue = 0;
2002 return m_Array.resetToDefault();
2003 }
2004
2005 int xmitPrepare(RTCString *a_pStrPath, RTCString *a_pStrQuery, RTHTTP a_hHttp, RTCString *a_pStrBody) const RT_OVERRIDE
2006 {
2007 RT_NOREF(a_pStrPath, a_pStrQuery, a_hHttp, a_pStrBody);
2008 return VINF_SUCCESS;
2009 }
2010
2011 void xmitComplete(int a_rcStatus, RTHTTP a_hHttp) const RT_OVERRIDE
2012 {
2013 RT_NOREF(a_rcStatus, a_hHttp);
2014 }
2015
2016 void testPath(const char *a_pszExpected)
2017 {
2018 static PATHPARAMDESC const s_aParams[] =
2019 {
2020 { RT_STR_TUPLE("{string}"), 0, 0 },
2021 { RT_STR_TUPLE("{integer}"), 0, 0 },
2022 { RT_STR_TUPLE("{array}"), 0, 0 },
2023 };
2024 PATHPARAMSTATE aState[] = { { &m_strValue, 0 }, { &m_iValue, 0 }, { &m_Array, 0 } };
2025 RTCString strPath;
2026 RTTESTI_CHECK_RC(doPathParameters(&strPath, RT_STR_TUPLE("my/{integer}/{string}/array:{array}/path"),
2027 s_aParams, aState, RT_ELEMENTS(aState)), VINF_SUCCESS);
2028 RTTESTI_CHECK_MSG(strPath.equals(a_pszExpected), ("actual: '%s'\nexpect: %s\n", strPath.c_str(), a_pszExpected));
2029 }
2030
2031 void testQuery(const char *a_pszCsv,
2032 const char *a_pszSsv,
2033 const char *a_pszTsv,
2034 const char *a_pszPipes,
2035 const char *a_pszMulti)
2036 {
2037 QUERYPARAMDESC aParams[] =
2038 {
2039 { "string", 0, true, 0 },
2040 { "integer", 0, true, 0 },
2041 { "array", 0, true, 0 },
2042 };
2043
2044 RTCRestObjectBase const *apObjects[] = { &m_strValue, &m_iValue, &m_Array };
2045 RTCString strQuery;
2046 RTTESTI_CHECK_RC(doQueryParameters(&strQuery, aParams, apObjects, RT_ELEMENTS(apObjects)), VINF_SUCCESS);
2047 RTTESTI_CHECK_MSG(strQuery.equals(a_pszCsv), ("actual: '%s'\nexpect: %s\n", strQuery.c_str(), a_pszCsv));
2048
2049 strQuery.setNull();
2050 aParams[2].fFlags = RTCRestObjectBase::kCollectionFormat_csv;
2051 RTTESTI_CHECK_RC(doQueryParameters(&strQuery, aParams, apObjects, RT_ELEMENTS(apObjects)), VINF_SUCCESS);
2052 RTTESTI_CHECK_MSG(strQuery.equals(a_pszCsv), ("actual: '%s'\nexpect: %s\n", strQuery.c_str(), a_pszCsv));
2053
2054 strQuery.setNull();
2055 aParams[2].fFlags = RTCRestObjectBase::kCollectionFormat_ssv;
2056 RTTESTI_CHECK_RC(doQueryParameters(&strQuery, aParams, apObjects, RT_ELEMENTS(apObjects)), VINF_SUCCESS);
2057 RTTESTI_CHECK_MSG(strQuery.equals(a_pszSsv), ("actual: '%s'\nexpect: %s\n", strQuery.c_str(), a_pszSsv));
2058
2059 strQuery.setNull();
2060 aParams[2].fFlags = RTCRestObjectBase::kCollectionFormat_tsv;
2061 RTTESTI_CHECK_RC(doQueryParameters(&strQuery, aParams, apObjects, RT_ELEMENTS(apObjects)), VINF_SUCCESS);
2062 RTTESTI_CHECK_MSG(strQuery.equals(a_pszTsv), ("actual: '%s'\nexpect: %s\n", strQuery.c_str(), a_pszTsv));
2063
2064 strQuery.setNull();
2065 aParams[2].fFlags = RTCRestObjectBase::kCollectionFormat_pipes;
2066 RTTESTI_CHECK_RC(doQueryParameters(&strQuery, aParams, apObjects, RT_ELEMENTS(apObjects)), VINF_SUCCESS);
2067 RTTESTI_CHECK_MSG(strQuery.equals(a_pszPipes), ("actual: '%s'\nexpect: %s\n", strQuery.c_str(), a_pszPipes));
2068
2069 strQuery.setNull();
2070 aParams[2].fFlags = RTCRestObjectBase::kCollectionFormat_multi;
2071 RTTESTI_CHECK_RC(doQueryParameters(&strQuery, aParams, apObjects, RT_ELEMENTS(apObjects)), VINF_SUCCESS);
2072 RTTESTI_CHECK_MSG(strQuery.equals(a_pszMulti), ("actual: '%s'\nexpect: %s\n", strQuery.c_str(), a_pszMulti));
2073 }
2074
2075 void testHeader(unsigned a_cHeaders, ...)
2076 {
2077 HEADERPARAMDESC aParams[] =
2078 {
2079 { "x-string", 0, true, 0, false },
2080 { "x-integer", 0, true, 0, false },
2081 { "x-array", 0, true, 0, false },
2082 { "x-map-", 0, true, 0, true },
2083 };
2084 RTCRestObjectBase const *apObjects[] = { &m_strValue, &m_iValue, &m_Array, &m_Map };
2085 RTHTTP hHttp = NIL_RTHTTP;
2086 RTTESTI_CHECK_RC(RTHttpCreate(&hHttp), VINF_SUCCESS);
2087 RTTESTI_CHECK_RC(doHeaderParameters(hHttp, aParams, apObjects, RT_ELEMENTS(apObjects)), VINF_SUCCESS);
2088 RTTESTI_CHECK(RTHttpGetHeaderCount(hHttp) == a_cHeaders);
2089 va_list va;
2090 va_start(va, a_cHeaders);
2091 for (size_t i = 0; i < a_cHeaders; i++)
2092 {
2093 const char *pszField = va_arg(va, const char *);
2094 const char *pszValue = va_arg(va, const char *);
2095 const char *pszActual = RTHttpGetHeader(hHttp, pszField, RTSTR_MAX);
2096 RTTESTI_CHECK_MSG(RTStrCmp(pszActual, pszValue) == 0,
2097 ("Header '%s' value is '%s' rather than '%s'", pszField, pszActual, pszValue));
2098 }
2099 va_end(va);
2100 RTTESTI_CHECK_RC(RTHttpDestroy(hHttp), VINF_SUCCESS);
2101 }
2102};
2103
2104
2105void testClientRequestBase()
2106{
2107 RTTestSub(g_hTest, "RTCRestClientRequestBase");
2108 {
2109 TestRequest Req1("this-is-a-string", 123456789, 5, "1", "22", "333", "444", "555");
2110 Req1.testPath("my/123456789/this-is-a-string/array:1,22,333,444,555/path");
2111 Req1.testQuery("?string=this-is-a-string&integer=123456789&array=1%2C22%2C333%2C444%2C555",
2112 "?string=this-is-a-string&integer=123456789&array=1%2022%20333%20444%20555",
2113 "?string=this-is-a-string&integer=123456789&array=1%0922%09333%09444%09555",
2114 "?string=this-is-a-string&integer=123456789&array=1%7C22%7C333%7C444%7C555",
2115 "?string=this-is-a-string&integer=123456789&array=1&array=22&array=333&array=444&array=555");
2116 Req1.testHeader(3, "x-string","this-is-a-string", "x-integer","123456789", "x-array","1,22,333,444,555");
2117 }
2118 {
2119 TestRequest Req2(";'[]", 42, 3, "null", "foo", "bar");
2120 RTTESTI_CHECK_RC(Req2.m_Map.put("stuff-1", new RTCRestString("stuffy-value-1")), VINF_SUCCESS);
2121 RTTESTI_CHECK_RC(Req2.m_Map.put("stuff-2", new RTCRestString("stuffy-value-2")), VINF_SUCCESS);
2122 RTTESTI_CHECK_RC(Req2.m_Map.put("2222", new RTCRestString("33")), VINF_SUCCESS);
2123 Req2.testPath("my/42/;'[]/array:null,foo,bar/path"); /// @todo shouldn't the string chars (;'[]) be escaped?
2124 Req2.testQuery("?string=%3B%27%5B%5D&integer=42&array=null%2Cfoo%2Cbar",
2125 "?string=%3B%27%5B%5D&integer=42&array=null%20foo%20bar",
2126 "?string=%3B%27%5B%5D&integer=42&array=null%09foo%09bar",
2127 "?string=%3B%27%5B%5D&integer=42&array=null%7Cfoo%7Cbar",
2128 "?string=%3B%27%5B%5D&integer=42&array=null&array=foo&array=bar");
2129 Req2.testHeader(6, "x-string",";'[]", "x-integer","42", "x-array","null,foo,bar",
2130 "x-map-stuff-1","stuffy-value-1",
2131 "x-map-stuff-2","stuffy-value-2",
2132 "x-map-2222","33");
2133 }
2134}
2135
2136
2137class TestResponse : public RTCRestClientResponseBase
2138{
2139public:
2140 RTCRestArray<RTCRestString> *m_pArray;
2141 RTCRestStringMap<RTCRestString> *m_pMap;
2142 RTCRestInt64 *m_pInteger;
2143 RTCRestString *m_pStrContentType;
2144
2145 TestResponse() : m_pArray(NULL), m_pMap(NULL), m_pInteger(NULL), m_pStrContentType(NULL)
2146 { }
2147
2148protected:
2149 virtual int consumeHeader(uint32_t a_uMatchWord, const char *a_pchField, size_t a_cchField,
2150 const char *a_pchValue, size_t a_cchValue) RT_OVERRIDE
2151 {
2152 int rc = RTCRestClientResponseBase::consumeHeader(a_uMatchWord, a_pchField, a_cchField, a_pchValue, a_cchValue);
2153 AssertRCReturn(rc, rc);
2154
2155#define MATCH_FIELD(a_sz) (sizeof(a_sz) - 1 == a_cchField && RTStrNICmpAscii(a_pchField, RT_STR_TUPLE(a_sz)) == 0)
2156 if (MATCH_FIELD("x-array"))
2157 {
2158 if (!m_pArray)
2159 {
2160 m_pArray = new (std::nothrow) RTCRestArray<RTCRestString>();
2161 AssertReturn(m_pArray, VERR_NO_MEMORY);
2162 return deserializeHeader(m_pArray, a_pchValue, a_cchValue, RTCRestObjectBase::kCollectionFormat_csv, "x-array");
2163 }
2164 }
2165 else if (a_cchField >= sizeof("x-map-") - 1 && RTStrNICmpAscii(a_pchField, RT_STR_TUPLE("x-map-")) == 0)
2166 {
2167 if (!m_pMap)
2168 {
2169 m_pMap = new (std::nothrow) RTCRestStringMap<RTCRestString>();
2170 AssertReturn(m_pMap, VERR_NO_MEMORY);
2171 }
2172 return deserializeHeaderIntoMap(m_pMap, a_pchField + 6, a_cchField - 6, a_pchValue, a_cchValue, 0, "x-map-");
2173 }
2174 else if (MATCH_FIELD("x-integer"))
2175 {
2176 if (!m_pInteger)
2177 {
2178 m_pInteger = new (std::nothrow) RTCRestInt64();
2179 AssertReturn(m_pInteger, VERR_NO_MEMORY);
2180 return deserializeHeader(m_pInteger, a_pchValue, a_cchValue, 0, "x-integer");
2181 }
2182 }
2183 else if (MATCH_FIELD("content-type"))
2184 {
2185 if (!m_pStrContentType)
2186 {
2187 m_pStrContentType = new (std::nothrow) RTCRestString();
2188 AssertReturn(m_pStrContentType, VERR_NO_MEMORY);
2189 return deserializeHeader(m_pStrContentType, a_pchValue, a_cchValue, 0, "content-type");
2190 }
2191 }
2192 else
2193 return VWRN_NOT_FOUND;
2194 RT_NOREF(a_uMatchWord);
2195 return addError(VERR_ALREADY_EXISTS, "Already have field '%.*s'!", a_cchField, a_pchField);
2196 }
2197
2198public:
2199 int pushHeader(const char *pszField, const char *pszValue)
2200 {
2201 size_t const cchField = strlen(pszField);
2202 void *pvFieldCopy = RTTestGuardedAllocTail(g_hTest, cchField);
2203 RTTESTI_CHECK_RET(pvFieldCopy, VERR_NO_MEMORY);
2204 memcpy(pvFieldCopy, pszField, cchField);
2205
2206 size_t const cchValue = strlen(pszValue);
2207 void *pvValueCopy = RTTestGuardedAllocTail(g_hTest, cchValue);
2208 RTTESTI_CHECK_RET(pvValueCopy, VERR_NO_MEMORY);
2209 memcpy(pvValueCopy, pszValue, cchValue);
2210
2211 uint32_t uWord = RTHTTP_MAKE_HDR_MATCH_WORD(cchField,
2212 cchField >= 1 ? RT_C_TO_LOWER(pszField[0]) : 0,
2213 cchField >= 2 ? RT_C_TO_LOWER(pszField[1]) : 0,
2214 cchField >= 3 ? RT_C_TO_LOWER(pszField[2]) : 0);
2215 int rc = consumeHeader(uWord, (const char *)pvFieldCopy, cchField, (const char *)pvValueCopy, cchValue);
2216 RTTestGuardedFree(g_hTest, pvValueCopy);
2217 RTTestGuardedFree(g_hTest, pvFieldCopy);
2218 return rc;
2219 }
2220};
2221
2222
2223void testClientResponseBase()
2224{
2225 RTTestSub(g_hTest, "RTCRestClientResponseBase");
2226 {
2227 TestResponse Resp1;
2228 RTTESTI_CHECK_RC(Resp1.pushHeader("content-type", "application/json; charset=utf-8"), VINF_SUCCESS);
2229 RTTESTI_CHECK(Resp1.getContentType().equals("application/json; charset=utf-8"));
2230 RTTESTI_CHECK(Resp1.m_pStrContentType && Resp1.m_pStrContentType->equals("application/json; charset=utf-8"));
2231
2232 RTTESTI_CHECK_RC(Resp1.pushHeader("content-typ2", "oopsy daisy"), VWRN_NOT_FOUND);
2233 RTTESTI_CHECK_RC(Resp1.pushHeader("content-type2", "oopsy daisy"), VWRN_NOT_FOUND);
2234 RTTESTI_CHECK(Resp1.getContentType().equals("application/json; charset=utf-8"));
2235 RTTESTI_CHECK(Resp1.m_pStrContentType && Resp1.m_pStrContentType->equals("application/json; charset=utf-8"));
2236
2237 RTTESTI_CHECK_RC(Resp1.pushHeader("x-integer", "398679406"), VINF_SUCCESS);
2238 RTTESTI_CHECK(Resp1.m_pInteger && Resp1.m_pInteger->m_iValue == 398679406);
2239
2240 RTTESTI_CHECK_RC(Resp1.pushHeader("x-array", "zero,one,two,three"), VINF_SUCCESS);
2241 RTTESTI_CHECK(Resp1.m_pArray && Resp1.m_pArray->size() == 4);
2242
2243 RTTESTI_CHECK_RC(Resp1.pushHeader("x-map-", "empty-key"), VINF_SUCCESS);
2244 RTTESTI_CHECK(Resp1.m_pMap && Resp1.m_pMap->size() == 1 && Resp1.m_pMap->get("") != NULL && Resp1.m_pMap->get("")->equals("empty-key"));
2245
2246 RTTESTI_CHECK_RC(Resp1.pushHeader("x-map-42", "key-is-42"), VINF_SUCCESS);
2247 RTTESTI_CHECK(Resp1.m_pMap && Resp1.m_pMap->size() == 2 && Resp1.m_pMap->get("42") != NULL && Resp1.m_pMap->get("42")->equals("key-is-42"));
2248 }
2249}
2250
2251
2252int main()
2253{
2254 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTRest-1", &g_hTest);
2255 if (rcExit == RTEXITCODE_SUCCESS )
2256 {
2257 testBool();
2258 testInteger<RTCRestInt64, int64_t, Int64Constants>();
2259 testInteger<RTCRestInt32, int32_t, Int32Constants>();
2260 testInteger<RTCRestInt16, int16_t, Int16Constants>();
2261 testDouble();
2262 testString("dummy", 1, 2);
2263 testDate();
2264 testArray();
2265 testStringMap();
2266 testClientRequestBase();
2267 testClientResponseBase();
2268
2269 rcExit = RTTestSummaryAndDestroy(g_hTest);
2270 }
2271 return rcExit;
2272}
2273
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette