VirtualBox

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

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

tstRTCRest-1: Array test fix. bugref:9167

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