VirtualBox

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

Last change on this file since 100762 was 99801, checked in by vboxsync, 19 months ago

Runtime/testcase/{Makefile.kmk,tstRTCRest-1}: Address two
Solaris-specific test failures in RTCRestDouble both of which involve
strtod(3C).

tstRTCRest-1.cpp:testDouble() calls RTJsonParseFromString() to parse
TST_DBL_MIN_STRING1 (a shortened, stringified value of float.h:DBL_MIN)
and ends up in strtod(3C) which fails on Solaris with VERR_OUT_OF_RANGE
(errno=ERANGE) as the value is smaller than the exact value of DBL_MIN
(2-1022). There is already code to handle expected failures for this
value on Linux which returns VERR_INVALID_PARAMETER (errno=EINVAL) so
include VERR_OUT_OF_RANGE for Solaris.

testDouble() also calls RTCRestDouble::fromString() with an argument of
" 0x42 " which is passed to strtod(3C) to convert the supplied string to
a floating-point number. On Solaris, calling strtod(3C) with a
hexadecimal value returns zero unless xpg6 has been set to include
_C99SUSv3_recognize_hexfp (0x1). This is set by the compiler when
C99/SUSv3 behaviour is requested (e.g. with -std=c99). Of the gcc
versions delivered with Solaris, gcc 10 is the first version to default
to C99 behaviour and thus it sets
xpg6 to _C99SUSv3_mode_ON
(0x0000ffff) by default by implicitly linking with values-xpg6.o. Thus
testDouble()'s call to fromString(&obj4, " 0x42 ", ...) can succeed or
fail on Solaris 11 depending on which compiler is used. Address this by
refining the test on Solaris to also check the gcc version.

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

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