diff options
Diffstat (limited to 'libparc/parc/algol/test/test_parc_JSONValue.c')
-rw-r--r-- | libparc/parc/algol/test/test_parc_JSONValue.c | 1365 |
1 files changed, 1365 insertions, 0 deletions
diff --git a/libparc/parc/algol/test/test_parc_JSONValue.c b/libparc/parc/algol/test/test_parc_JSONValue.c new file mode 100644 index 00000000..804eb690 --- /dev/null +++ b/libparc/parc/algol/test/test_parc_JSONValue.c @@ -0,0 +1,1365 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Include the file(s) containing the functions to be tested. +// This permits internal static functions to be visible to this Test Framework. + +#include "../parc_JSONValue.c" +#include <LongBow/unit-test.h> + +#include <stdio.h> +#include <fcntl.h> +#include <inttypes.h> + +#include "../parc_List.h" +#include "../parc_ArrayList.h" +#include "../parc_SafeMemory.h" +#include "../parc_Memory.h" + +#include <parc/testing/parc_ObjectTesting.h> + +LONGBOW_TEST_RUNNER(parc_JSONValue) +{ + // The following Test Fixtures will run their corresponding Test Cases. + // Test Fixtures are run in the order specified, but all tests should be idempotent. + // Never rely on the execution order of tests or share state between them. + LONGBOW_RUN_TEST_FIXTURE(Static); + LONGBOW_RUN_TEST_FIXTURE(JSONValue_CreateAcquireRelease); + LONGBOW_RUN_TEST_FIXTURE(JSONValue); + LONGBOW_RUN_TEST_FIXTURE(JSONValueParsing); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_JSONValue) +{ + parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_JSONValue) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(JSONValue_CreateAcquireRelease) +{ + LONGBOW_RUN_TEST_CASE(JSONValue_CreateAcquireRelease, _createValue); + LONGBOW_RUN_TEST_CASE(JSONValue_CreateAcquireRelease, parcJSONValue_AcquireRelease); +} + +LONGBOW_TEST_FIXTURE_SETUP(JSONValue_CreateAcquireRelease) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(JSONValue_CreateAcquireRelease) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO); + if (outstandingAllocations != 0) { + printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(JSONValue_CreateAcquireRelease, _createValue) +{ + PARCJSONValue *result = parcJSONValue_CreateFromNULL(); + + assertNotNull(result, "Expected non-null return value from _createValue"); + assertTrue(parcJSONValue_IsNull(result), + "Expected PARCJSONValueType_Null"); + + parcJSONValue_Release(&result); + assertNull(result, "Expected parcJSONValue_Release to NULL the instance pointer."); +} + + +LONGBOW_TEST_CASE(JSONValue_CreateAcquireRelease, parcJSONValue_AcquireRelease) +{ + PARCJSONValue *result = parcJSONValue_CreateFromNULL(); + + assertNotNull(result, "Expected non-null return value from _createValue"); + assertTrue(parcJSONValue_IsNull(result), + "Expected PARCJSONValueType_Null"); + + PARCJSONValue *actual = parcJSONValue_Acquire(result); + assertTrue(result == actual, "Expected parcJSONValue_Acquire return value to be same as the original."); + + parcJSONValue_Release(&actual); + parcJSONValue_Release(&result); + assertNull(result, "Expected parcJSONValue_Release to NULL the instance pointer."); +} + + +LONGBOW_TEST_FIXTURE(JSONValue) +{ + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_NULL); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Boolean); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Float); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Integer); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_String); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_JSON); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Array); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Timespec); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Timeval); + + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_IsValid); + + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Display); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_BuildString); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_NULL); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_Array); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_Boolean); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_Float); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_Integer); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_String); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_CreateCString); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_JSON); + + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_NULL); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_Boolean); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_Integer); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_Float); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_String); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_Object); + LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_Array); +} + +LONGBOW_TEST_FIXTURE_SETUP(JSONValue) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(JSONValue) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO); + if (outstandingAllocations != 0) { + printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_IsValid) +{ + bool actual = parcJSONValue_IsValid(NULL); + assertFalse(actual, "Expected a NULL value to be invalid"); + + PARCJSONValue *value = parcJSONValue_CreateFromNULL(); + + actual = parcJSONValue_IsValid(value); + parcJSONValue_Release(&value); + assertTrue(actual, "Expected a NULL value to be invalid"); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_JSON) +{ + PARCJSON *json = parcJSON_Create(); + PARCJSONValue *value = parcJSONValue_CreateFromJSON(json); + + assertTrue(parcJSONValue_IsJSON(value), + "Expected PARCJSONValueType_JSON"); + + assertTrue(parcJSONValue_GetJSON(value) == json, + "Expected parcJSONValue_GetJSON to return the original instance pointer."); + parcJSONValue_Release(&value); + assertNull(value, "Expected NULL pointer."); + parcJSON_Release(&json); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Timeval) +{ + struct timeval timeval = { .tv_sec = 42, .tv_usec = 23 }; + PARCJSONValue *value = parcJSONValue_CreateFromTimeval(&timeval); + + assertTrue(parcJSONValue_IsJSON(value), + "Expected PARCJSONValueType_JSON"); + + struct timeval actual; + parcJSONValue_GetTimeval(value, &actual); + assertTrue(timeval.tv_sec == actual.tv_sec, "Expected seconds to be equal."); + assertTrue(timeval.tv_usec == actual.tv_usec, "Expected seconds to be equal."); + + parcJSONValue_Release(&value); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Timespec) +{ + struct timespec timespec = { .tv_sec = 42, .tv_nsec = 23 }; + PARCJSONValue *value = parcJSONValue_CreateFromTimespec(×pec); + + assertTrue(parcJSONValue_IsJSON(value), + "Expected PARCJSONValueType_JSON"); + + struct timespec testTS; + parcJSONValue_GetTimespec(value, &testTS); + assertTrue(memcmp(×pec, &testTS, sizeof(struct timespec)) == 0, + "Expected parcJSONValue_GetTimespec to return the original instance pointer."); + parcJSONValue_Release(&value); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_NULL) +{ + PARCJSONValue *value = parcJSONValue_CreateFromNULL(); + + assertTrue(value->type == PARCJSONValueType_Null, + "Expected PARCJSONValueType_Null, actual %d", value->type); + assertTrue(parcJSONValue_IsNull(value), + "Expected PARCJSONValueType_Null"); + parcJSONValue_Release(&value); + assertNull(value, "Expected NULL pointer."); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Boolean) +{ + bool expected = true; + PARCJSONValue *value = parcJSONValue_CreateFromBoolean(expected); + + assertTrue(value->type == PARCJSONValueType_Boolean, + "Expected PARCJSONValueType_BooleanON_VALUE_BOOLEAN, actual %d", value->type); + assertTrue(value->value.boolean == expected, "Expected %d actual %d", expected, value->value.boolean); + + assertTrue(parcJSONValue_IsBoolean(value), + "Expected PARCJSONValueType_Boolean"); + assertTrue(parcJSONValue_GetBoolean(value), "Expected value to be true"); + parcJSONValue_Release(&value); + assertNull(value, "Expected NULL pointer."); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Float) +{ + double expected = 3.1415; + PARCJSONValue *value = parcJSONValue_CreateFromFloat(expected); + + assertTrue(parcJSONValue_IsNumber(value), + "Expected parcJSONValue_IsNumber to be true."); + assertTrue(parcJSONValue_GetFloat(value) == expected, + "Expected %g, actual %Lg", expected, parcJSONValue_GetFloat(value)); + + char *expectedString = "3.141500"; + char *actualString = parcJSONValue_ToString(value); + assertTrue(strcmp(expectedString, actualString) == 0, "Exepcted %s, actual %s", expectedString, actualString); + parcMemory_Deallocate((void **) &actualString); + + parcJSONValue_Release(&value); + assertNull(value, "Expected NULL pointer."); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Integer) +{ + int expected = 31415; + PARCJSONValue *value = parcJSONValue_CreateFromInteger(expected); + + assertTrue(parcJSONValue_IsNumber(value), + "Expected parcJSONValue_IsNumber"); + int64_t actual = parcJSONValue_GetInteger(value); + assertTrue(expected == actual, "Expected %d, actual %" PRIi64 "", expected, actual); + parcJSONValue_Release(&value); + assertNull(value, "Expected NULL pointer."); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_String) +{ + PARCBuffer *expected = parcBuffer_WrapCString("31415"); + PARCJSONValue *value = parcJSONValue_CreateFromString(expected); + + assertTrue(value->type == PARCJSONValueType_String, + "Expected parcJSONValueType.String, actual %d", value->type); + assertTrue(parcBuffer_Equals(value->value.string, expected), + "Expected %s actual %s", parcBuffer_ToString(expected), parcBuffer_ToString(value->value.string)); + assertTrue(parcJSONValue_IsString(value), + "Expected PARCJSONValueType_String"); + + assertTrue(parcBuffer_Equals(parcJSONValue_GetString(value), expected), "Expected value did not match actual value"); + parcJSONValue_Release(&value); + assertNull(value, "Expected NULL pointer."); + parcBuffer_Release(&expected); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_CreateCString) +{ + PARCBuffer *expected = parcBuffer_WrapCString("31415"); + + PARCJSONValue *value = parcJSONValue_CreateFromCString("31415"); + + assertTrue(value->type == PARCJSONValueType_String, + "Expected parcJSONValueType.String, actual %d", value->type); + + assertTrue(parcBuffer_Equals(parcJSONValue_GetString(value), expected), "Assert:") + { + char *expectedString = parcBuffer_ToString(expected); + char *actualString = parcBuffer_ToString(parcJSONValue_GetString(value)); + printf("Expected '%s', actual '%s'", expectedString, actualString); + parcMemory_Deallocate((void **) &expectedString); + parcMemory_Deallocate((void **) &actualString); + } + + parcJSONValue_Release(&value); + assertNull(value, "Expected NULL pointer."); + parcBuffer_Release(&expected); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Array) +{ + PARCJSONArray *array = parcJSONArray_Create(); + + PARCJSONValue *value = parcJSONValue_CreateFromNULL(); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromJSONArray(array); + + parcJSONValue_Release(&value); + + parcJSONArray_Release(&array); + assertNull(value, "Expected NULL pointer."); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_BuildString) +{ + PARCJSONArray *array = parcJSONArray_Create(); + + PARCJSONValue *value = parcJSONValue_CreateFromNULL(); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromBoolean(false); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromBoolean(true); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromInteger(31415); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + + PARCBuffer *stringValue = parcBuffer_WrapCString("stringA/stringB"); + value = parcJSONValue_CreateFromString(stringValue); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + parcBuffer_Release(&stringValue); + + value = parcJSONValue_CreateFromJSONArray(array); + parcJSONArray_Release(&array); + + // Uncompacted + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcJSONValue_BuildString(value, composer, false); + + PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer); + char *actual = parcBuffer_ToString(tempBuffer); + parcBuffer_Release(&tempBuffer); + parcBufferComposer_Release(&composer); + + char *expected = "[ null, false, true, 31415, \"stringA\\/stringB\" ]"; + + assertTrue(strcmp(actual, expected) == 0, + "Expected '%s', actual '%s'", expected, actual); + + parcMemory_Deallocate((void **) &actual); + + // Compacted + composer = parcBufferComposer_Create(); + parcJSONValue_BuildString(value, composer, true); + + tempBuffer = parcBufferComposer_ProduceBuffer(composer); + actual = parcBuffer_ToString(tempBuffer); + parcBuffer_Release(&tempBuffer); + parcBufferComposer_Release(&composer); + + expected = "[null,false,true,31415,\"stringA/stringB\"]"; + + assertTrue(strcmp(actual, expected) == 0, + "Expected '%s', actual '%s'", expected, actual); + + parcMemory_Deallocate((void **) &actual); + + + parcJSONValue_Release(&value); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_Array) +{ + PARCJSONArray *array = parcJSONArray_Create(); + + PARCJSONValue *value = parcJSONValue_CreateFromNULL(); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromBoolean(false); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromBoolean(true); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromInteger(31415); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + + PARCBuffer *stringValue = parcBuffer_WrapCString("stringA/stringB"); + value = parcJSONValue_CreateFromString(stringValue); + parcJSONArray_AddValue(array, value); + parcJSONValue_Release(&value); + parcBuffer_Release(&stringValue); + + value = parcJSONValue_CreateFromJSONArray(array); + parcJSONArray_Release(&array); + + char *expected = "[ null, false, true, 31415, \"stringA\\/stringB\" ]"; + char *actual = parcJSONValue_ToString(value); + + assertTrue(strcmp(actual, expected) == 0, + "Expected '%s', actual '%s'", expected, actual); + + parcMemory_Deallocate((void **) &actual); + parcJSONValue_Release(&value); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Display) +{ + PARCJSONValue *value = parcJSONValue_CreateFromNULL(); + parcJSONValue_Display(value, 0); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromBoolean(true); + parcJSONValue_Display(value, 0); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromCString("hello"); + parcJSONValue_Display(value, 0); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromFloat(3.14); + parcJSONValue_Display(value, 0); + parcJSONValue_Release(&value); + + value = parcJSONValue_CreateFromInteger(314); + parcJSONValue_Display(value, 0); + parcJSONValue_Release(&value); + + PARCJSONArray *array = parcJSONArray_Create(); + value = parcJSONValue_CreateFromJSONArray(array); + parcJSONValue_Display(value, 0); + parcJSONValue_Release(&value); + parcJSONArray_Release(&array); + + PARCJSON *json = parcJSON_Create(); + value = parcJSONValue_CreateFromJSON(json); + parcJSONValue_Display(value, 0); + parcJSONValue_Release(&value); + parcJSON_Release(&json); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_NULL) +{ + char *expected = "null"; + PARCJSONValue *value = parcJSONValue_CreateFromNULL(); + + char *actual = parcJSONValue_ToString(value); + assertTrue(strcmp(actual, expected) == 0, "Expected '%s', actual '%s'", expected, actual); + + parcMemory_Deallocate((void **) &actual); + parcJSONValue_Release(&value); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_Boolean) +{ + char *expected = "true"; + PARCJSONValue *value = parcJSONValue_CreateFromBoolean(expected); + + char *actual = parcJSONValue_ToString(value); + assertTrue(strcmp(actual, expected) == 0, "Expected '%s', actual '%s'", expected, actual); + + parcMemory_Deallocate((void **) &actual); + parcJSONValue_Release(&value); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_Float) +{ + struct test_values { + char *string; + long double value; + long double error; + } successful[] = { + { "-0.0415e-12", -0.0415e-12, 0.00001e-12 }, + { "-0.0415e12", -0.0415e12, 0.00001e12 }, + { "-0.0415", -0.0415, 0.00001 }, + { "-3.0415", -3.0415, 0.00001 }, + { "123.456", 123.456, 0.0001 }, + { "123.456e78", 123.456e78, 0.0001e78 }, + { "123.456e-78", 123.456e-78, 0.0001e-78 }, + { "123.456e-78", 123.456e-78, 0.0001e-78 }, + { "4e1", 40.0, 0.0001e-78 }, + { NULL }, + }; + + for (int i = 0; successful[i].string != NULL; i++) { + PARCBuffer *buffer = parcBuffer_WrapCString(successful[i].string); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + PARCJSONValue *expected = _parcJSONValue_NumberParser(parser); + + char *string = parcJSONValue_ToString(expected); + assertTrue(strcmp(successful[i].string, string) == 0, + "Expected %s, actual %s", successful[i].string, string); + parcMemory_Deallocate((void **) &string); + + parcJSONValue_Release(&expected); + parcJSONParser_Release(&parser); + } +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_Integer) +{ + char *expected = "31415"; + PARCJSONValue *value = parcJSONValue_CreateFromInteger(31415); + + char *actual = parcJSONValue_ToString(value); + assertTrue(strcmp(actual, expected) == 0, + "Expected '%s', actual '%s'", expected, actual); + + parcMemory_Deallocate((void **) &actual); + parcJSONValue_Release(&value); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_String) +{ + char *input = "31415\b"; + char *expected = "\"31415\\b\""; + + PARCBuffer *stringValue = parcBuffer_WrapCString(input); + PARCJSONValue *value = parcJSONValue_CreateFromString(stringValue); + parcBuffer_Release(&stringValue); + + char *actual = parcJSONValue_ToString(value); + assertTrue(strcmp(actual, expected) == 0, "Expected '%s', actual '%s'", expected, actual); + + parcMemory_Deallocate((void **) &actual); + parcJSONValue_Release(&value); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_JSON) +{ + char *expected = "{ }"; + PARCJSON *json = parcJSON_Create(); + PARCJSONValue *value = parcJSONValue_CreateFromJSON(json); + parcJSON_Release(&json); + + char *actual = parcJSONValue_ToString(value); + assertTrue(strcmp(actual, expected) == 0, "Expected '%s', actual '%s'", expected, actual); + + parcMemory_Deallocate((void **) &actual); + parcJSONValue_Release(&value); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_NULL) +{ + PARCJSONValue *example = parcJSONValue_CreateFromNULL(); + + PARCJSONValue *equal1 = parcJSONValue_CreateFromNULL(); + PARCJSONValue *equal2 = parcJSONValue_CreateFromNULL(); + + PARCBuffer *stringBuffer = parcBuffer_AllocateCString("Hello"); + PARCJSONValue *string = parcJSONValue_CreateFromString(stringBuffer); + parcBuffer_Release(&stringBuffer); + + parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, example, equal1, equal2, string); + + parcJSONValue_Release(&string); + parcJSONValue_Release(&equal2); + parcJSONValue_Release(&equal1); + parcJSONValue_Release(&example); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_Boolean) +{ + PARCJSONValue *example = parcJSONValue_CreateFromBoolean(true); + + PARCJSONValue *equal1 = parcJSONValue_CreateFromBoolean(true); + PARCJSONValue *equal2 = parcJSONValue_CreateFromBoolean(true); + + PARCJSONValue *unequal1 = parcJSONValue_CreateFromBoolean(false); + + PARCBuffer *stringBuffer = parcBuffer_AllocateCString("Hello"); + PARCJSONValue *string = parcJSONValue_CreateFromString(stringBuffer); + parcBuffer_Release(&stringBuffer); + + parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, example, equal1, equal2, unequal1, string); + + parcJSONValue_Release(&string); + parcJSONValue_Release(&unequal1); + parcJSONValue_Release(&equal2); + parcJSONValue_Release(&equal1); + parcJSONValue_Release(&example); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_Integer) +{ + PARCJSONValue *example = parcJSONValue_CreateFromInteger(31415); + + PARCJSONValue *equal1 = parcJSONValue_CreateFromInteger(31415); + PARCJSONValue *equal2 = parcJSONValue_CreateFromInteger(31415); + + PARCJSONValue *unequal1 = parcJSONValue_CreateFromInteger(4); + + PARCBuffer *stringBuffer = parcBuffer_AllocateCString("Hello"); + PARCJSONValue *string = parcJSONValue_CreateFromString(stringBuffer); + parcBuffer_Release(&stringBuffer); + + parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, example, equal1, equal2, unequal1, string); + + parcJSONValue_Release(&string); + parcJSONValue_Release(&unequal1); + parcJSONValue_Release(&equal2); + parcJSONValue_Release(&equal1); + parcJSONValue_Release(&example); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_Float) +{ + PARCJSONValue *example = parcJSONValue_CreateFromFloat(3.1415); + + PARCJSONValue *equal1 = parcJSONValue_CreateFromFloat(3.1415); + PARCJSONValue *equal2 = parcJSONValue_CreateFromFloat(3.1415); + + PARCJSONValue *unequal1 = parcJSONValue_CreateFromFloat(4.0); + + PARCBuffer *stringBuffer = parcBuffer_AllocateCString("Hello"); + PARCJSONValue *string = parcJSONValue_CreateFromString(stringBuffer); + parcBuffer_Release(&stringBuffer); + + parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, example, equal1, equal2, unequal1, string); + + parcJSONValue_Release(&string); + parcJSONValue_Release(&unequal1); + parcJSONValue_Release(&equal2); + parcJSONValue_Release(&equal1); + parcJSONValue_Release(&example); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_String) +{ + PARCBuffer *stringBuffer = parcBuffer_AllocateCString("Hello"); + PARCJSONValue *example = parcJSONValue_CreateFromString(stringBuffer); + parcBuffer_Release(&stringBuffer); + + stringBuffer = parcBuffer_AllocateCString("Hello"); + PARCJSONValue *equal1 = parcJSONValue_CreateFromString(stringBuffer); + parcBuffer_Release(&stringBuffer); + + stringBuffer = parcBuffer_AllocateCString("Hello"); + PARCJSONValue *equal2 = parcJSONValue_CreateFromString(stringBuffer); + parcBuffer_Release(&stringBuffer); + + PARCJSONValue *unequal1 = parcJSONValue_CreateFromFloat(4.0); + + stringBuffer = parcBuffer_AllocateCString("World"); + PARCJSONValue *string = parcJSONValue_CreateFromString(stringBuffer); + parcBuffer_Release(&stringBuffer); + + parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, example, equal1, equal2, unequal1, string); + + parcJSONValue_Release(&string); + parcJSONValue_Release(&unequal1); + parcJSONValue_Release(&equal2); + parcJSONValue_Release(&equal1); + parcJSONValue_Release(&example); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_Object) +{ + char *string = "{ \"name\" : 1, \"name2\" : 2 }"; + + PARCBuffer *buffer = parcBuffer_WrapCString(string); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + PARCJSONValue *x = parcJSONValue_ObjectParser(parser); + parcJSONParser_Release(&parser); + + assertTrue(parcJSONValue_IsJSON(x), "Expected a JSON Object value."); + + buffer = parcBuffer_WrapCString(string); + parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + PARCJSONValue *y = parcJSONValue_ObjectParser(parser); + parcJSONParser_Release(&parser); + + buffer = parcBuffer_WrapCString(string); + parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + PARCJSONValue *z = parcJSONValue_ObjectParser(parser); + parcJSONParser_Release(&parser); + + PARCJSONValue *unequal1 = parcJSONValue_CreateFromFloat(4.0); + + PARCJSON *json = parcJSON_Create(); + PARCJSONValue *unequal2 = parcJSONValue_CreateFromJSON(json); + parcJSON_Release(&json); + + parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, x, y, z, unequal1, unequal2); + + parcJSONValue_Release(&x); + parcJSONValue_Release(&y); + parcJSONValue_Release(&z); + parcJSONValue_Release(&unequal1); + parcJSONValue_Release(&unequal2); +} + +LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_Array) +{ + char *string = "[ \"name\", 1, true, false, null, [ ], { } ]"; + + PARCBuffer *buffer = parcBuffer_WrapCString(string); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + PARCJSONValue *x = _parcJSONValue_ArrayParser(parser); + parcJSONParser_Release(&parser); + + assertTrue(parcJSONValue_IsArray(x), "Expected a JSON Array value."); + + buffer = parcBuffer_WrapCString(string); + parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + PARCJSONValue *y = _parcJSONValue_ArrayParser(parser); + parcJSONParser_Release(&parser); + + buffer = parcBuffer_WrapCString(string); + parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + PARCJSONValue *z = _parcJSONValue_ArrayParser(parser); + parcJSONParser_Release(&parser); + + PARCJSONValue *unequal1 = parcJSONValue_CreateFromFloat(4.0); + + PARCJSONArray *array = parcJSONArray_Create(); + PARCJSONValue *unequal2 = parcJSONValue_CreateFromJSONArray(array); + parcJSONArray_Release(&array); + + parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, x, y, z, unequal1, unequal2); + + parcJSONValue_Release(&x); + parcJSONValue_Release(&y); + parcJSONValue_Release(&z); + parcJSONValue_Release(&unequal1); + parcJSONValue_Release(&unequal2); +} + +LONGBOW_TEST_FIXTURE(JSONValueParsing) +{ + LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_NullParser); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_NullParser_Bad); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_TrueParser); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_TrueParser_Bad); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_FalseParser); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_FalseParser_Bad); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_StringParser); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser_Bad_Pair); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser_Bad_Pair2); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_ArrayParser); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_StringParser_BAD); + + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_NumberParser_BatchedFloat); + + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Comma); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_CloseBracket); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Null); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_True); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_False); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_String); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Array); + LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Object); +} + +LONGBOW_TEST_FIXTURE_SETUP(JSONValueParsing) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(JSONValueParsing) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO); + if (outstandingAllocations != 0) { + printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_NullParser) +{ + char *string = "null"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = _parcJSONValue_NullParser(parser); + + assertTrue(parcJSONValue_IsNull(actual), "Expected a JSON Null value."); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_NullParser_Bad) +{ + char *string = "nulx"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = _parcJSONValue_NullParser(parser); + + assertNull(actual, "Expected a NULL return value"); + + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_TrueParser) +{ + char *string = "true"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = _parcJSONValue_TrueParser(parser); + + assertTrue(parcJSONValue_IsBoolean(actual), "Expected a JSON Boolean value."); + assertTrue(parcJSONValue_GetBoolean(actual), "Expected true."); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_TrueParser_Bad) +{ + char *string = "trux"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = _parcJSONValue_TrueParser(parser); + + assertNull(actual, "Expected a NULL return value"); + + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_FalseParser) +{ + char *string = "false"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = _parcJSONValue_FalseParser(parser); + + assertTrue(parcJSONValue_IsBoolean(actual), "Expected a JSON Boolean value."); + assertFalse(parcJSONValue_GetBoolean(actual), "Expected false."); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_FalseParser_Bad) +{ + char *string = "falsx"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = _parcJSONValue_FalseParser(parser); + + assertNull(actual, "Expected a NULL return value"); + + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_StringParser) +{ + char *parserInput = "\"\\\" \\\\ \\b \\f \\n \\r \\t \\/\""; + PARCBuffer *buffer = parcBuffer_WrapCString(parserInput); + PARCBuffer *expected = parcBuffer_AllocateCString("\" \\ \b \f \n \r \t /"); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = _parcJSONValue_StringParser(parser); + + assertTrue(parcJSONValue_IsString(actual), + "Expected a JSON String value."); + + assertTrue(parcBuffer_Equals(expected, actual->value.string), + "Expected '%s' actual '%s'", parcBuffer_ToString(expected), parcBuffer_ToString(actual->value.string)) + { + parcBuffer_Display(expected, 0); + parcBuffer_Display(actual->value.string, 0); + } + + char *string = parcJSONValue_ToString(actual); + assertTrue(strcmp(parserInput, string) == 0, + "Expected %s, actual %s", parserInput, string); + + parcMemory_Deallocate((void **) &string); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&expected); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_StringParser_BAD) +{ + char *bad[] = { + "\"\t\"", + "\"", + NULL + }; + + for (int i = 0; bad[i] != NULL; i++) { + char *parserInput = bad[i]; + PARCBuffer *buffer = parcBuffer_WrapCString(parserInput); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = _parcJSONValue_StringParser(parser); + + assertNull(actual, "Expected failure"); + parcBuffer_Release(&buffer); + parcJSONParser_Release(&parser); + } +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser) +{ + char *string = "{ \"name\" : 1, \"name2\" : 2 }"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = parcJSONValue_ObjectParser(parser); + + assertTrue(parcJSONValue_IsJSON(actual), "Expected a JSON Object value."); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser_Bad_Pair) +{ + char *string = "{ \"name\" , \"name2\" : 2 }"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = parcJSONValue_ObjectParser(parser); + + assertNull(actual, "Expected parcJSONValue_ObjectParser to return NULL indicating failure"); + + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser_Bad_Pair2) +{ + char *string = "{ 2 }"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = parcJSONValue_ObjectParser(parser); + + assertNull(actual, "Expected parcJSONValue_ObjectParser to return NULL indicating failure"); + + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_ArrayParser) +{ + char *string = "[ \"name\", 1, true, false, null, [ ], { } ]"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = _parcJSONValue_ArrayParser(parser); + + assertTrue(parcJSONValue_IsArray(actual), "Expected a JSON Array value."); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_NumberParser_BatchedFloat) +{ + struct test_values { + char *string; + char *expectedString; + long double floatValue; + int64_t integerValue; + long double floatTolerance; + } successful[] = { + { "0", "0", 0.0, 0, 0 }, + { " 1", "1", 1.0, 1, 0 }, + { "-1", "-1", -1.0, -1, 0 }, + { "1e1", "1e1", 1.0e1, 10, 0 }, + { "-2e1", "-2e1", -2.0e1, -2e1, 0 }, + { "-2e+1", "-2e1", -2.0e+1, -2e+1, 0 }, + { " 1.0", "1", 1.0, 1, 0 }, + { "3e-1", "3e-1", 3e-1, 0, 0.01e-1 }, + { "100e-2", "100e-2", 100e-2, 100e-2, 0.0001 }, + { "123.456e11", "123.456e11", 123.456e11, 12345600000000, 0.0001e11 }, + { "-0.0415e-12", "-0.0415e-12", -0.0415e-12, 0, 0.00001e-12 }, + { "-0.0415e12", "-0.0415e12", -0.0415e12, -41500000000, 0.00001e12 }, + { "-0.0415", "-0.0415", -0.0415, 0, 0.00001 }, + { "-3.0415", "-3.0415", -3.0415, -3, 0.00001 }, + { "123.456", "123.456", 123.456, 123, 0.0001 }, + { "123.456e+11", "123.456e11", 123.456e+11, 12345600000000, 0.0001e+11 }, + { "123.456e-11", "123.456e-11", 123.456e-11, 0, 0.0001e-11 }, + { "1e-1", "1e-1", 1e-1, 0, 0.1e-1 }, + { NULL }, + }; + + for (int i = 0; successful[i].string != NULL; i++) { + PARCBuffer *buffer = parcBuffer_WrapCString(successful[i].string); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + PARCJSONValue *expected = _parcJSONValue_NumberParser(parser); + assertNotNull(expected, "_parcJSONValue_NumberParser returned NULL"); + + long double floatValue = parcJSONValue_GetFloat(expected); + + assertTrue(fabsl(floatValue - successful[i].floatValue) <= successful[i].floatTolerance, + "Expected %Lf actual %Lf", successful[i].floatValue, floatValue); + + char *string = parcJSONValue_ToString(expected); + assertTrue(strcmp(successful[i].expectedString, string) == 0, + "Expected %s actual %s", successful[i].expectedString, string); + parcMemory_Deallocate((void **) &string); + + int64_t integerValue = parcJSONValue_GetInteger(expected); + assertTrue(integerValue == (int64_t) successful[i].integerValue, + "Expected %" PRIi64 " actual %" PRIi64 "", (int64_t) successful[i].integerValue, integerValue); + + parcJSONValue_Release(&expected); + parcJSONParser_Release(&parser); + } +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Comma) +{ + char *string = ", null"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = parcJSONValue_Parser(parser); + + assertNull(actual, "Expected parcJSONValue_Parser to return NULL when encountering a comma"); + + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_CloseBracket) +{ + char *string = "], null"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = parcJSONValue_Parser(parser); + + assertNull(actual, "Expected parcJSONValue_Parser to return NULL when encountering a ]"); + + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Null) +{ + char *string = " null"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = parcJSONValue_Parser(parser); + + assertTrue(parcJSONValue_IsNull(actual), + "Expected parcJSONValue_Parser to return a Null JSON value when encountering 'null'"); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_True) +{ + char *string = " true"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = parcJSONValue_Parser(parser); + + assertTrue(parcJSONValue_IsBoolean(actual), + "Expected parcJSONValue_Parser to return a boolean JSON value when encountering 'true'"); + assertTrue(parcJSONValue_GetBoolean(actual), + "Expected true"); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_False) +{ + char *string = " false"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = parcJSONValue_Parser(parser); + + assertTrue(parcJSONValue_IsBoolean(actual), + "Expected parcJSONValue_Parser to return a boolean JSON value when encountering 'false'"); + assertFalse(parcJSONValue_GetBoolean(actual), + "Expected true"); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_String) +{ + char *string = " \"string\""; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = parcJSONValue_Parser(parser); + + assertTrue(parcJSONValue_IsString(actual), + "Expected parcJSONValue_Parser to return a string JSON value"); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Array) +{ + char *string = " [ ]"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *value = parcJSONValue_Parser(parser); + + assertTrue(parcJSONValue_IsArray(value), + "Expected parcJSONValue_Parser to return a array JSON value"); + + PARCJSONArray *array = parcJSONValue_GetArray(value); + assertNotNull(array, "Expected a non-null pointer to a PARCJSONArray"); + + parcJSONValue_Release(&value); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Object) +{ + char *string = " { }"; + PARCBuffer *buffer = parcBuffer_WrapCString(string); + + PARCJSONParser *parser = parcJSONParser_Create(buffer); + PARCJSONValue *actual = parcJSONValue_Parser(parser); + + assertTrue(parcJSONValue_IsJSON(actual), + "Expected parcJSONValue_Parser to return a JSON object value"); + + parcJSONValue_Release(&actual); + parcJSONParser_Release(&parser); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_FIXTURE(Static) +{ + LONGBOW_RUN_TEST_CASE(Static, _parseSign_Negative); + LONGBOW_RUN_TEST_CASE(Static, _parseSign_NotASign); + LONGBOW_RUN_TEST_CASE(Static, _parseSign_Nil); + + LONGBOW_RUN_TEST_CASE(Static, _parseWholeNumber); + LONGBOW_RUN_TEST_CASE(Static, _parseOptionalFraction); + LONGBOW_RUN_TEST_CASE(Static, _parseOptionalExponent); +} + +LONGBOW_TEST_FIXTURE_SETUP(Static) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Static) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Static, _parseSign_Negative) +{ + char *string = "-"; + + PARCBuffer *buffer = parcBuffer_WrapCString(string); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + int sign; + bool result = _parseSign(parser, &sign); + + assertTrue(result, "Expected true from _parseSign()"); + + parcJSONParser_Release(&parser); +} + +LONGBOW_TEST_CASE(Static, _parseSign_NotASign) +{ + char *string = "asd"; + + PARCBuffer *buffer = parcBuffer_WrapCString(string); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + int sign; + bool result = _parseSign(parser, &sign); + + assertFalse(result, "Expected true from _parseSign()"); + + parcJSONParser_Release(&parser); +} + +LONGBOW_TEST_CASE(Static, _parseSign_Nil) +{ + char *string = ""; + + PARCBuffer *buffer = parcBuffer_WrapCString(string); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + int sign; + bool result = _parseSign(parser, &sign); + + assertTrue(result, "Expected true from _parseSign()"); + + parcJSONParser_Release(&parser); +} + +LONGBOW_TEST_CASE(Static, _parseWholeNumber) +{ + struct test_values { + char *string; + long double value; + } successful[] = { + { "0", 0 }, + { "1", 1 }, + { "123", 123 }, + { NULL }, + }; + + for (int i = 0; successful[i].string != NULL; i++) { + PARCBuffer *buffer = parcBuffer_WrapCString(successful[i].string); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + int64_t value = 0; + + bool actual = _parseWholeNumber(parser, &value); + + assertTrue(actual, "Expected true from _parseNumber()"); + assertTrue(value == successful[i].value, + "Expected %Lf actual %" PRIi64 "", successful[i].value, value); + parcJSONParser_Release(&parser); + } +} + +LONGBOW_TEST_CASE(Static, _parseOptionalFraction) +{ + struct test_values { + char *string; + long double value; + bool correct; + } successful[] = { + { ".0", 0, true }, + { ".", 0, false }, + { ".1", 1, true }, + { "crap", 0, false }, + { "}", 0, true }, + { NULL }, + }; + + for (int i = 0; successful[i].string != NULL; i++) { + PARCBuffer *buffer = parcBuffer_WrapCString(successful[i].string); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + int64_t value = 0; + int log10OfFraction; + + bool actual = _parseOptionalFraction(parser, &value, &log10OfFraction); + + assertTrue(actual == successful[i].correct, "Expected true from _parseNumber()"); + assertTrue(value == successful[i].value, + "Expected %Lf actual %" PRIi64 "", successful[i].value, value); + parcJSONParser_Release(&parser); + } +} + +LONGBOW_TEST_CASE(Static, _parseOptionalExponent) +{ + struct test_values { + char *string; + long double value; + bool correct; + } successful[] = { + { "e", 0, false }, + { "ex", 0, false }, + { "e-1", -1, true }, + { "e1", 1, true }, + { "e+1", 1, true }, + { "x", 0, false }, + { NULL }, + }; + + for (int i = 0; successful[i].string != NULL; i++) { + PARCBuffer *buffer = parcBuffer_WrapCString(successful[i].string); + PARCJSONParser *parser = parcJSONParser_Create(buffer); + parcBuffer_Release(&buffer); + + int64_t value = 0; + + bool actual = _parseOptionalExponent(parser, &value); + + assertTrue(actual == successful[i].correct, "Expected true from _parseNumber()"); + assertTrue(value == successful[i].value, + "Expected %Lf actual %" PRIi64 "", successful[i].value, value); + parcJSONParser_Release(&parser); + } +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_JSONValue); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} |