static void test2(RTTEST hTest) { struct TestMap2 *p2 = (struct TestMap2 *)RTTestGuardedAllocTail(hTest, sizeof(TestMap2)); p2->idNil = NIL_TEST2_ID; p2->idLast = TEST2_ID_LAST; /* Some simple tests first. */ RT_ZERO(p2->bmChunkId); RTTEST_CHECK(hTest, ASMBitFirstSet(&p2->bmChunkId[0], TEST2_ID_LAST + 1) == -1); for (uint32_t iBit = 0; iBit <= TEST2_ID_LAST; iBit++) RTTEST_CHECK(hTest, !ASMBitTest(&p2->bmChunkId[0], iBit)); memset(&p2->bmChunkId[0], 0xff, sizeof(p2->bmChunkId)); RTTEST_CHECK(hTest, ASMBitFirstClear(&p2->bmChunkId[0], TEST2_ID_LAST + 1) == -1); for (uint32_t iBit = 0; iBit <= TEST2_ID_LAST; iBit++) RTTEST_CHECK(hTest, ASMBitTest(&p2->bmChunkId[0], iBit)); /* The real test. */ p2->idChunkPrev = 0; RT_ZERO(p2->bmChunkId); ASMBitSet(p2->bmChunkId, NIL_TEST2_ID); uint32_t cLeft = TEST2_ID_LAST; while (cLeft-- > 0) test2AllocId(p2); RTTEST_CHECK(hTest, ASMBitFirstClear(&p2->bmChunkId[0], TEST2_ID_LAST + 1) == -1); }
/** * Tests the array accessors. */ static void tstArray(RTTEST hTest, RTJSONVAL hJsonVal) { uint32_t cItems = 0; RTTEST_CHECK(hTest, RTJsonValueGetArraySize(hJsonVal) == 6); RTTEST_CHECK_RC_OK(hTest, RTJsonValueQueryArraySize(hJsonVal, &cItems)); RTTEST_CHECK(hTest, cItems == RTJsonValueGetArraySize(hJsonVal)); for (uint32_t i = 1; i <= 5; i++) { int64_t i64Num = 0; RTJSONVAL hJsonValItem = NIL_RTJSONVAL; RTTEST_CHECK_RC_OK_RETV(hTest, RTJsonValueQueryByIndex(hJsonVal, i - 1, &hJsonValItem)); RTTEST_CHECK(hTest, RTJsonValueGetType(hJsonValItem) == RTJSONVALTYPE_NUMBER); RTTEST_CHECK_RC_OK_RETV(hTest, RTJsonValueQueryInteger(hJsonValItem, &i64Num)); RTTEST_CHECK(hTest, i64Num == (int64_t)i); RTTEST_CHECK(hTest, RTJsonValueRelease(hJsonValItem) == 1); } /* Last should be string. */ const char *pszStr = NULL; RTJSONVAL hJsonValItem = NIL_RTJSONVAL; RTTEST_CHECK_RC_OK_RETV(hTest, RTJsonValueQueryByIndex(hJsonVal, 5, &hJsonValItem)); RTTEST_CHECK(hTest, RTJsonValueGetType(hJsonValItem) == RTJSONVALTYPE_STRING); RTTEST_CHECK_RC_OK_RETV(hTest, RTJsonValueQueryString(hJsonValItem, &pszStr)); RTTEST_CHECK(hTest, RTJsonValueGetString(hJsonValItem) == pszStr); RTTEST_CHECK(hTest, strcmp(pszStr, "6") == 0); RTTEST_CHECK(hTest, RTJsonValueRelease(hJsonValItem) == 1); }
/** * Thread that allocates * @returns * @param hThreadSelf The thread. * @param pvArg Pointer to fUseCache. */ static DECLCALLBACK(int) tst3Thread(RTTHREAD hThreadSelf, void *pvArg) { PTST3THREAD pThread = (PTST3THREAD)(pvArg); size_t cbObject = pThread->cbObject; uint64_t cIterations = 0; /* wait for the kick-off */ RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(pThread->hEvt, RT_INDEFINITE_WAIT)); /* allocate and free loop */ if (pThread->fUseCache) { while (!g_fTst3Stop) { void *apv[64]; for (unsigned i = 0; i < RT_ELEMENTS(apv); i++) { apv[i] = RTMemCacheAlloc(g_hMemCache); RTTEST_CHECK(g_hTest, apv[i] != NULL); } for (unsigned i = 0; i < RT_ELEMENTS(apv); i++) RTMemCacheFree(g_hMemCache, apv[i]); cIterations += RT_ELEMENTS(apv); } } else { while (!g_fTst3Stop) { void *apv[64]; for (unsigned i = 0; i < RT_ELEMENTS(apv); i++) { apv[i] = RTMemAlloc(cbObject); RTTEST_CHECK(g_hTest, apv[i] != NULL); } for (unsigned i = 0; i < RT_ELEMENTS(apv); i++) RTMemFree(apv[i]); cIterations += RT_ELEMENTS(apv); } } /* report back the status */ pThread->cIterations = cIterations; return VINF_SUCCESS; }
/** * Checks that methods not indended for the given type return the correct error. */ static void tstCorrectnessRcForInvalidType(RTTEST hTest, RTJSONVAL hJsonVal, RTJSONVALTYPE enmType) { #ifndef RT_STRICT /* Enable manually if assertions are enabled or it will assert all over the place for debug builds. */ /** @todo you can disable assertions and all the noise. See RTAssertSetMayPanic and RTAssertSetQuiet. */ if ( enmType != RTJSONVALTYPE_OBJECT && enmType != RTJSONVALTYPE_ARRAY) { /* The iterator API should return errors. */ RTJSONIT hJsonIt = NIL_RTJSONIT; RTTEST_CHECK_RC(hTest, RTJsonIteratorBegin(hJsonVal, &hJsonIt), VERR_JSON_VALUE_INVALID_TYPE); } if (enmType != RTJSONVALTYPE_ARRAY) { /* The Array access methods should return errors. */ uint32_t cItems = 0; RTJSONVAL hJsonValItem = NIL_RTJSONVAL; RTTEST_CHECK(hTest, RTJsonValueGetArraySize(hJsonVal) == 0); RTTEST_CHECK_RC(hTest, RTJsonValueQueryArraySize(hJsonVal, &cItems), VERR_JSON_VALUE_INVALID_TYPE); RTTEST_CHECK_RC(hTest, RTJsonValueQueryByIndex(hJsonVal, 0, &hJsonValItem), VERR_JSON_VALUE_INVALID_TYPE); } if (enmType != RTJSONVALTYPE_OBJECT) { /* The object access methods should return errors. */ RTJSONVAL hJsonValMember = NIL_RTJSONVAL; RTTEST_CHECK_RC(hTest, RTJsonValueQueryByName(hJsonVal, "test", &hJsonValMember), VERR_JSON_VALUE_INVALID_TYPE); } if (enmType != RTJSONVALTYPE_NUMBER) { int64_t i64Num = 0; RTTEST_CHECK_RC(hTest, RTJsonValueQueryInteger(hJsonVal, &i64Num), VERR_JSON_VALUE_INVALID_TYPE); } if (enmType != RTJSONVALTYPE_STRING) { const char *psz = NULL; RTTEST_CHECK(hTest, RTJsonValueGetString(hJsonVal) == NULL); RTTEST_CHECK_RC(hTest, RTJsonValueQueryString(hJsonVal, &psz), VERR_JSON_VALUE_INVALID_TYPE); } #else RT_NOREF3(hTest, hJsonVal, enmType); #endif }
int main(int argc, char **argv) { /* * Init RT+Test. */ RTTEST hTest; int rc = RTTestInitExAndCreate(argc, &argv, 0, "tstRTPathGlob", &hTest); if (rc) return rc; RTTestBanner(hTest); if (argc <= 1) return RTTestSkipAndDestroy(hTest, "Requires arguments"); /* * Manual glob testing. */ for (int i = 1; i < argc; i++) { uint32_t cResults = UINT32_MAX; PCRTPATHGLOBENTRY pHead = (PCRTPATHGLOBENTRY)&cResults; rc = RTPathGlob(argv[i], 0, &pHead, &cResults); RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "#%u '%s' -> %Rrc cResult=%u\n", i, argv[i], rc, cResults); if (RT_SUCCESS(rc)) { uint32_t iEntry = 0; for (PCRTPATHGLOBENTRY pCur = pHead; pCur; pCur = pCur->pNext, iEntry++) { RTTestPrintf(hTest, RTTESTLVL_ALWAYS, " #%3u: '%s'\n", iEntry, pCur->szPath); RTTEST_CHECK(hTest, strlen(pCur->szPath) == pCur->cchPath); } RTPathGlobFree(pHead); } } /* * Summary. */ return RTTestSummaryAndDestroy(hTest); }
/** * Test that the parser returns the correct values for a valid JSON. */ static void tstCorrectness(RTTEST hTest) { RTTestSub(hTest, "Correctness"); RTJSONVAL hJsonVal = NIL_RTJSONVAL; RTTEST_CHECK_RC_OK_RETV(hTest, RTJsonParseFromString(&hJsonVal, g_pszJson, NULL)); if (hJsonVal != NIL_RTJSONVAL) { RTJSONVALTYPE enmType = RTJsonValueGetType(hJsonVal); if (enmType == RTJSONVALTYPE_OBJECT) { /* Excercise the other non object APIs to return VERR_JSON_VALUE_INVALID_TYPE. */ tstCorrectnessRcForInvalidType(hTest, hJsonVal, enmType); tstIterator(hTest, hJsonVal); } else RTTestFailed(hTest, "RTJsonParseFromString() returned an invalid JSON value, expected OBJECT got %u\n", enmType); RTTEST_CHECK(hTest, RTJsonValueRelease(hJsonVal) == 0); } else RTTestFailed(hTest, "RTJsonParseFromString() returned success but no value\n"); }
int main() { /* * Init the runtime and stuff. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstFork", &hTest); if (rc) return rc; RTTestBanner(hTest); #ifdef RT_OS_WINDOWS RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Skipped\n"); #else /* * Get values that are supposed to or change across the fork. */ RTPROCESS const ProcBefore = RTProcSelf(); /* * Fork. */ pid_t pid = fork(); if (pid == 0) { /* * Check that the values has changed. */ rc = 0; if (ProcBefore == RTProcSelf()) { RTTestFailed(hTest, "%RTproc == %RTproc [child]", ProcBefore, RTProcSelf()); rc = 1; } return rc; } if (pid != -1) { /* * Check that the values didn't change. */ RTTEST_CHECK(hTest, ProcBefore == RTProcSelf()); /* * Wait for the child. */ rc = 1; while ( waitpid(pid, &rc, 0) && errno == EINTR) rc = 1; if (!WIFEXITED(rc) || WEXITSTATUS(rc) != 0) RTTestFailed(hTest, "rc=%#x", rc); } else RTTestFailed(hTest, "fork() failed: %d - %s", errno, strerror(errno)); #endif /* * Summary */ return RTTestSummaryAndDestroy(hTest); }
int main(int argc, char **argv) { RTTEST hTest; int rc = RTTestInitAndCreate("tstRTUuid", &hTest); if (rc) return rc; RTTestBanner(hTest); #define CHECK_RC() \ do { if (RT_FAILURE(rc)) { RTTestFailed(hTest, "line %d: rc=%Rrc", __LINE__, rc); } } while (0) RTTestSub(hTest, "RTUuidClear & RTUuisIsNull"); RTUUID UuidNull; rc = RTUuidClear(&UuidNull); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidIsNull(&UuidNull)); RTTEST_CHECK(hTest, RTUuidCompare(&UuidNull, &UuidNull) == 0); RTTestSub(hTest, "RTUuidCreate"); RTUUID Uuid; rc = RTUuidCreate(&Uuid); CHECK_RC(); RTTEST_CHECK(hTest, !RTUuidIsNull(&Uuid)); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid) == 0); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &UuidNull) > 0); RTTEST_CHECK(hTest, RTUuidCompare(&UuidNull, &Uuid) < 0); RTTestSub(hTest, "RTUuidToStr"); char sz[RTUUID_STR_LENGTH]; rc = RTUuidToStr(&Uuid, sz, sizeof(sz)); CHECK_RC(); RTTEST_CHECK(hTest, strlen(sz) == RTUUID_STR_LENGTH - 1); RTTestPrintf(hTest, RTTESTLVL_INFO, "UUID=%s\n", sz); RTTestSub(hTest, "RTUuidFromStr"); RTUUID Uuid2; rc = RTUuidFromStr(&Uuid2, sz); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); char *psz = (char *)RTTestGuardedAllocTail(hTest, RTUUID_STR_LENGTH); if (psz) { RTStrPrintf(psz, RTUUID_STR_LENGTH, "%s", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); for (unsigned off = 1; off < RTUUID_STR_LENGTH; off++) { char *psz2 = psz + off; RTStrPrintf(psz2, RTUUID_STR_LENGTH - off, "%s", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz2), VERR_INVALID_UUID_FORMAT); } RTTestGuardedFree(hTest, psz); } RTUuidClear(&Uuid2); char sz2[RTUUID_STR_LENGTH + 2]; RTStrPrintf(sz2, sizeof(sz2), "{%s}", sz); rc = RTUuidFromStr(&Uuid2, sz2); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); psz = (char *)RTTestGuardedAllocTail(hTest, RTUUID_STR_LENGTH + 2); if (psz) { RTStrPrintf(psz, RTUUID_STR_LENGTH + 2, "{%s}", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); for (unsigned off = 1; off < RTUUID_STR_LENGTH + 2; off++) { char *psz2 = psz + off; RTStrPrintf(psz2, RTUUID_STR_LENGTH + 2 - off, "{%s}", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz2), VERR_INVALID_UUID_FORMAT); } RTTestGuardedFree(hTest, psz); } RTTestSub(hTest, "RTUuidToUtf16"); RTUTF16 wsz[RTUUID_STR_LENGTH]; rc = RTUuidToUtf16(&Uuid, wsz, sizeof(wsz)); CHECK_RC(); RTTEST_CHECK(hTest, RTUtf16Len(wsz) == RTUUID_STR_LENGTH - 1); RTTestSub(hTest, "RTUuidFromUtf16"); rc = RTUuidFromUtf16(&Uuid2, wsz); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); RTUTF16 *pwsz; rc = RTStrToUtf16(sz2, &pwsz); RTTEST_CHECK(hTest, rc == VINF_SUCCESS); if (RT_SUCCESS(rc)) { RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); RTUTF16 *pwsz2 = (RTUTF16*)RTTestGuardedAllocTail(hTest, 2 * (RTUUID_STR_LENGTH + 2)); if (pwsz2) { memcpy(pwsz2, pwsz, 2 * (RTUUID_STR_LENGTH + 2)); RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz2), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); for (unsigned off = 1; off < RTUUID_STR_LENGTH + 2; off++) { RTUTF16 *pwsz3 = pwsz2 + off; memcpy(pwsz3, pwsz, 2 * (RTUUID_STR_LENGTH + 1 - off)); pwsz3[RTUUID_STR_LENGTH + 1 - off] = 0; RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz3), VERR_INVALID_UUID_FORMAT); } RTTestGuardedFree(hTest, pwsz2); } RTUtf16Free(pwsz); } RTTestSub(hTest, "RTUuidCompareStr"); RTTEST_CHECK(hTest, RTUuidCompareStr(&Uuid, sz) == 0); RTTEST_CHECK(hTest, RTUuidCompareStr(&Uuid, "00000000-0000-0000-0000-000000000000") > 0); RTTEST_CHECK(hTest, RTUuidCompareStr(&UuidNull, "00000000-0000-0000-0000-000000000000") == 0); RTTestSub(hTest, "RTUuidCompare2Strs"); RTTEST_CHECK(hTest, RTUuidCompare2Strs(sz, sz) == 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs(sz, "00000000-0000-0000-0000-000000000000") > 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("00000000-0000-0000-0000-000000000000", sz) < 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000") == 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("d95d883b-f91d-4ce5-a5c5-d08bb6a85dec", "a56193c7-3e0b-4c03-9d66-56efb45082f7") > 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("a56193c7-3e0b-4c03-9d66-56efb45082f7", "d95d883b-f91d-4ce5-a5c5-d08bb6a85dec") < 0); /* * Check the binary representation. */ RTTestSub(hTest, "Binary representation"); RTUUID Uuid3; Uuid3.au8[0] = 0x01; Uuid3.au8[1] = 0x23; Uuid3.au8[2] = 0x45; Uuid3.au8[3] = 0x67; Uuid3.au8[4] = 0x89; Uuid3.au8[5] = 0xab; Uuid3.au8[6] = 0xcd; Uuid3.au8[7] = 0x4f; Uuid3.au8[8] = 0x10; Uuid3.au8[9] = 0xb2; Uuid3.au8[10] = 0x54; Uuid3.au8[11] = 0x76; Uuid3.au8[12] = 0x98; Uuid3.au8[13] = 0xba; Uuid3.au8[14] = 0xdc; Uuid3.au8[15] = 0xfe; Uuid3.Gen.u8ClockSeqHiAndReserved = (Uuid3.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80; Uuid3.Gen.u16TimeHiAndVersion = (Uuid3.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000; const char *pszUuid3 = "67452301-ab89-4fcd-90b2-547698badcfe"; rc = RTUuidToStr(&Uuid3, sz, sizeof(sz)); CHECK_RC(); RTTEST_CHECK(hTest, strcmp(sz, pszUuid3) == 0); rc = RTUuidFromStr(&Uuid, pszUuid3); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid3) == 0); RTTEST_CHECK(hTest, memcmp(&Uuid3, &Uuid, sizeof(Uuid)) == 0); /* * checking the clock seq and time hi and version bits... */ RTTestSub(hTest, "Clock seq, time hi, version bits"); RTUUID Uuid4Changes; Uuid4Changes.au64[0] = 0; Uuid4Changes.au64[1] = 0; RTUUID Uuid4Prev; RTUuidCreate(&Uuid4Prev); for (unsigned i = 0; i < 1024; i++) { RTUUID Uuid4; RTUuidCreate(&Uuid4); Uuid4Changes.au64[0] |= Uuid4.au64[0] ^ Uuid4Prev.au64[0]; Uuid4Changes.au64[1] |= Uuid4.au64[1] ^ Uuid4Prev.au64[1]; #if 0 /** @todo make a bit string/dumper similar to %Rhxs/d. */ RTPrintf("tstUuid: %d %d %d %d-%d %d %d %d %d %d %d %d-%d %d %d %d ; %d %d %d %d-%d %d %d %d %d %d %d %d-%d %d %d %d\n", !!(Uuid4.Gen.u16ClockSeq & RT_BIT(0)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(1)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(2)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(3)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(4)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(5)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(6)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(7)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(8)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(9)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(10)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(11)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(12)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(13)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(14)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(15)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(0)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(1)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(2)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(3)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(4)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(5)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(6)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(7)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(8)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(9)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(10)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(11)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(12)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(13)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(14)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(15)) ); #endif Uuid4Prev = Uuid4; } RTUUID Uuid4Fixed; Uuid4Fixed.au64[0] = ~Uuid4Changes.au64[0]; Uuid4Fixed.au64[1] = ~Uuid4Changes.au64[1]; RTTestPrintf(hTest, RTTESTLVL_INFO, "fixed bits: %RTuuid (mask)\n", &Uuid4Fixed); RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid: raw: %.*Rhxs\n", sizeof(Uuid4Fixed), &Uuid4Fixed); Uuid4Prev.au64[0] &= Uuid4Fixed.au64[0]; Uuid4Prev.au64[1] &= Uuid4Fixed.au64[1]; RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid: fixed bits: %RTuuid (value)\n", &Uuid4Prev); RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid: raw: %.*Rhxs\n", sizeof(Uuid4Prev), &Uuid4Prev); /* * Summary. */ return RTTestSummaryAndDestroy(hTest); }
/** * Tests the iterator API for the given JSON array or object value. */ static void tstIterator(RTTEST hTest, RTJSONVAL hJsonVal) { RTJSONIT hJsonIt = NIL_RTJSONIT; int rc = RTJsonIteratorBegin(hJsonVal, &hJsonIt); RTTEST_CHECK(hTest, RT_SUCCESS(rc)); if (RT_SUCCESS(rc)) { const char *pszName = NULL; RTJSONVAL hJsonValMember = NIL_RTJSONVAL; rc = RTJsonIteratorQueryValue(hJsonIt, &hJsonValMember, &pszName); RTTEST_CHECK(hTest, RT_SUCCESS(rc)); RTTEST_CHECK(hTest, pszName != NULL); RTTEST_CHECK(hTest, hJsonValMember != NIL_RTJSONVAL); while (RT_SUCCESS(rc)) { RTJSONVALTYPE enmTypeMember = RTJsonValueGetType(hJsonValMember); tstCorrectnessRcForInvalidType(hTest, hJsonValMember, enmTypeMember); switch (enmTypeMember) { case RTJSONVALTYPE_OBJECT: RTTEST_CHECK(hTest, strcmp(pszName, "subobject") == 0); tstIterator(hTest, hJsonValMember); break; case RTJSONVALTYPE_ARRAY: RTTEST_CHECK(hTest, strcmp(pszName, "array") == 0); tstArray(hTest, hJsonValMember); break; case RTJSONVALTYPE_STRING: { RTTEST_CHECK(hTest, strcmp(pszName, "string") == 0); const char *pszStr = NULL; RTTEST_CHECK_RC_OK(hTest, RTJsonValueQueryString(hJsonValMember, &pszStr)); RTTEST_CHECK(hTest, strcmp(pszStr, "test") == 0); break; } case RTJSONVALTYPE_NUMBER: { RTTEST_CHECK(hTest, strcmp(pszName, "number") == 0); int64_t i64Num = 0; RTTEST_CHECK_RC_OK(hTest, RTJsonValueQueryInteger(hJsonValMember, &i64Num)); RTTEST_CHECK(hTest, i64Num == 100); break; } case RTJSONVALTYPE_NULL: RTTEST_CHECK(hTest, strcmp(pszName, "null") == 0); break; case RTJSONVALTYPE_TRUE: RTTEST_CHECK(hTest, strcmp(pszName, "true") == 0); break; case RTJSONVALTYPE_FALSE: RTTEST_CHECK(hTest, strcmp(pszName, "false") == 0); break; default: RTTestFailed(hTest, "Invalid JSON value type %u returned\n", enmTypeMember); } RTTEST_CHECK(hTest, RTJsonValueRelease(hJsonValMember) == 1); rc = RTJsonIteratorNext(hJsonIt); RTTEST_CHECK(hTest, rc == VINF_SUCCESS || rc == VERR_JSON_ITERATOR_END); if (RT_SUCCESS(rc)) RTTEST_CHECK_RC_OK(hTest, RTJsonIteratorQueryValue(hJsonIt, &hJsonValMember, &pszName)); } RTJsonIteratorFree(hJsonIt); } }