VirtualBox

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

Last change on this file since 76553 was 76553, checked in by vboxsync, 5 years ago

scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use