From ec688b4723a041044226358bcd4dd6e2da39da49 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Thu, 23 Feb 2017 17:01:02 +0100 Subject: Initial commit: cframework. Longbow and Libparc Change-Id: I90378dbd30da6033b20fb1f829b3b822cf366c59 Signed-off-by: Luca Muscariello --- libparc/parc/algol/test/test_parc_Object.c | 1580 ++++++++++++++++++++++++++++ 1 file changed, 1580 insertions(+) create mode 100755 libparc/parc/algol/test/test_parc_Object.c (limited to 'libparc/parc/algol/test/test_parc_Object.c') diff --git a/libparc/parc/algol/test/test_parc_Object.c b/libparc/parc/algol/test/test_parc_Object.c new file mode 100755 index 00000000..687654fe --- /dev/null +++ b/libparc/parc/algol/test/test_parc_Object.c @@ -0,0 +1,1580 @@ +/* + * 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 "../parc_Object.c" + +#include +#include + +#include + +#include +#include + +#include +#include + +typedef struct { + int calledCount; + int val; +} _dummy_object; + +typedef _dummy_object _DummyObject; + +static void +_dummy_Destroy(_DummyObject **obj __attribute__((unused))) +{ +} + +static _DummyObject * +_dummy_Copy(const _DummyObject *obj); + + +static bool +_dummy_Equals(const _DummyObject *x, const _DummyObject *y) +{ + const _DummyObject *dummy1 = x; + const _DummyObject *dummy2 = y; + return (dummy1->calledCount == dummy2->calledCount); +} + +static int +_dummy_Compare(const _DummyObject *x, const _DummyObject *y) +{ + const _DummyObject *dummy1 = x; + const _DummyObject *dummy2 = y; + if (dummy1->calledCount == dummy2->calledCount) { + return 0; + } else if (dummy1->calledCount < dummy2->calledCount) { + return -1; + } else { + return 1; + } +} + +static uint32_t +_dummy_HashCode(const _DummyObject *obj) +{ + _DummyObject *dummy = (_DummyObject *) obj; + dummy->calledCount++; + return 1337; +} + +static char * +_dummy_ToString(const _DummyObject *x __attribute__((unused))) +{ + char *str = (char *) parcMemory_Allocate(6); + char *test = "dummy"; + sprintf(str, "%s", test); + return str; +} + +static PARCJSON * +_dummy_ToJSON(const _DummyObject *x __attribute__((unused))) +{ + PARCJSON *json = parcJSON_ParseString("{ \"type\" : \"dummy\" }"); + return json; +} + +parcObject_Override(_DummyObject, PARCObject, + .destroy = (PARCObjectDestroy *) _dummy_Destroy, + .copy = (PARCObjectCopy *) _dummy_Copy, + .toString = (PARCObjectToString *) _dummy_ToString, + .equals = (PARCObjectEquals *) _dummy_Equals, + .compare = (PARCObjectCompare *) _dummy_Compare, + .hashCode = (PARCObjectHashCode *) _dummy_HashCode, + .toJSON = (PARCObjectToJSON *) _dummy_ToJSON); + +static _DummyObject * +_dummy_Copy(const _DummyObject *obj) +{ + _DummyObject *newDummy = parcObject_CreateInstance(_DummyObject); + const _DummyObject *dummy = obj; + newDummy->calledCount = dummy->calledCount; + return newDummy; +} + +typedef _dummy_object _DummyObjectNoHash; +parcObject_ExtendPARCObject(_DummyObjectNoHash, + _dummy_Destroy, + _dummy_Copy, + _dummy_ToString, + _dummy_Equals, + _dummy_Compare, + NULL, + _dummy_ToJSON); + +static bool +_meta_destructor_true(PARCObject **objPtr) +{ + return true; +} + +static bool +_meta_destructor_false(PARCObject **objPtr) +{ + (*objPtr) = NULL; + return false; +} + +static PARCObject * +_meta_copy(const PARCObject *ptr) +{ + _DummyObject *d = parcMemory_AllocateAndClear(sizeof(_DummyObject)); + _DummyObject *xx = (_DummyObject *) ptr; + d->val = xx->val; + return d; +} + +static bool +_meta_equals(const PARCObject *x, const PARCObject *y) +{ + _DummyObject *xx = (_DummyObject *) x; + _DummyObject *yy = (_DummyObject *) y; + return (xx->val == yy->val); +} + +static int +_meta_compare(const PARCObject *x, const PARCObject *y) +{ + _DummyObject *xx = (_DummyObject *) x; + _DummyObject *yy = (_DummyObject *) y; + + if (xx->val == yy->val) { + return 0; + } else if (xx->val < yy->val) { + return -1; + } else { + return 1; + } +} + +static PARCHashCode +_meta_hashCode(const PARCObject *ptr) +{ + _DummyObject *xx = (_DummyObject *) ptr; + return xx->val; +} + +static char * +_meta_toString(const PARCObject *ptr) +{ + _DummyObject *xx = (_DummyObject *) ptr; + + char *result; + parcMemory_MemAlign((void **) &result, sizeof(void *), sizeof(char)); + assertNotNull(result, "parcMemory_Allocate returned NULL"); + + char *p = result; + sprintf(result, "%d", xx->val); + + return p; +} + +static PARCJSON * +_meta_toJson(const PARCObject *ptr) +{ + _DummyObject *xx = (_DummyObject *) ptr; + + PARCJSON *json = parcJSON_Create(); + parcJSON_AddInteger(json, "value", xx->val); + + return json; +} + +static const PARCMemoryInterface *_originalMemoryProvider; + +LONGBOW_TEST_RUNNER(parcObject) +{ + LONGBOW_RUN_TEST_FIXTURE(Performance); + LONGBOW_RUN_TEST_FIXTURE(PARCObjectDescriptor); + LONGBOW_RUN_TEST_FIXTURE(Static); + LONGBOW_RUN_TEST_FIXTURE(StaticObjects); + LONGBOW_RUN_TEST_FIXTURE(Meta); + LONGBOW_RUN_TEST_FIXTURE(AcquireRelease); + LONGBOW_RUN_TEST_FIXTURE(Global); + LONGBOW_RUN_TEST_FIXTURE(Subclasses); + LONGBOW_RUN_TEST_FIXTURE(Fail); + LONGBOW_RUN_TEST_FIXTURE(Locking); + LONGBOW_RUN_TEST_FIXTURE(WaitNotify); + LONGBOW_RUN_TEST_FIXTURE(Synchronization); +} + +LONGBOW_TEST_RUNNER_SETUP(parcObject) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_RUNNER_TEARDOWN(parcObject) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Static) +{ + LONGBOW_RUN_TEST_CASE(Static, _objectHeaderIsValid); + LONGBOW_RUN_TEST_CASE(Static, _parcObject_PrefixLength); +} + +LONGBOW_TEST_FIXTURE_SETUP(Static) +{ + _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Static) +{ + parcMemory_SetInterface(_originalMemoryProvider); + return LONGBOW_STATUS_SUCCEEDED; +} + +struct timeval _testObject; + +parcObject_Override(_testObject, PARCObject); + +LONGBOW_TEST_CASE(Static, _objectHeaderIsValid) +{ + PARCObject *object = parcObject_CreateInstanceImpl(&_testObject_Descriptor); + + _PARCObjectHeader *header = _parcObject_Header(object); + + assertTrue(_parcObjectHeader_IsValid(header, object), "Expected _parcObject_HeaderHeaderIsValid to be valid"); + + parcObject_Release(&object); +} + +LONGBOW_TEST_CASE(Static, _parcObject_PrefixLength) +{ + // Test that the result is a multiple of the alignment value and greater than the size of _PARCObjectHeader. + + // Compute the power of 2 value of sizeof(void *) + unsigned int v = sizeof(void *); + unsigned int r = 0; // r will be lg(v) + + while (v >>= 1) { + r++; + } + PARCObjectDescriptor descriptor; + + for (int i = r; i < 20; i++) { + descriptor.objectAlignment = 1 << i; + size_t actual = _parcObject_PrefixLength(&descriptor); + assertTrue((actual & (descriptor.objectAlignment - 1)) == 0, + "Alignment needs to be a multiple of %u", descriptor.objectAlignment); + } +} + +LONGBOW_TEST_FIXTURE(AcquireRelease) +{ + LONGBOW_RUN_TEST_CASE(AcquireRelease, parcObject_Acquire); + LONGBOW_RUN_TEST_CASE(AcquireRelease, parcObject_Release); +// LONGBOW_RUN_TEST_CASE(AcquireRelease, parcObject_Acquire_Invalid); +} + +LONGBOW_TEST_FIXTURE_SETUP(AcquireRelease) +{ + _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(AcquireRelease) +{ + parcSafeMemory_ReportAllocation(STDOUT_FILENO); + parcMemory_SetInterface(_originalMemoryProvider); + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(AcquireRelease, parcObject_Acquire) +{ + struct timeval *expected = parcObject_CreateInstanceImpl(&_testObject_Descriptor); + + parcObjectTesting_AssertAcquireReleaseContract(parcObject_Acquire, expected); + parcObject_Release((void **) &expected); +} + +LONGBOW_TEST_CASE(AcquireRelease, parcObject_Release) +{ + struct timeval *time = parcObject_CreateInstanceImpl(&_testObject_Descriptor); + parcObject_AssertValid(time); + + time->tv_sec = 1; + time->tv_usec = 2; + + PARCReferenceCount count = parcObject_Release((PARCObject **) &time); + assertTrue(count == 0, "Expected reference count to be zero"); + assertTrue(time == 0, "Expected memory pointer to be NULL after destroy."); +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcObject_Create); +// LONGBOW_RUN_TEST_CASE(Global, parcObject_CreateAndClear); + LONGBOW_RUN_TEST_CASE(Global, parcObject_IsValid); + LONGBOW_RUN_TEST_CASE(Global, parcObject_IsValid_NotValid); + LONGBOW_RUN_TEST_CASE(Global, parcObject_IsInstanceOf); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Copy_Default); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Copy); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Release); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Compare_Default); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Compare_NoOverride); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Compare); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Equals_Default); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Equals_NoOverride); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Equals); + LONGBOW_RUN_TEST_CASE(Global, parcObject_HashCode_Default); + LONGBOW_RUN_TEST_CASE(Global, parcObject_HashCode_NoOverride); + LONGBOW_RUN_TEST_CASE(Global, parcObject_HashCode); + LONGBOW_RUN_TEST_CASE(Global, parcObject_ToString_Default); + LONGBOW_RUN_TEST_CASE(Global, parcObject_ToString_NoOverride); + LONGBOW_RUN_TEST_CASE(Global, parcObject_ToString); + LONGBOW_RUN_TEST_CASE(Global, parcObject_ToJSON_Default); + LONGBOW_RUN_TEST_CASE(Global, parcObject_ToJSON_NoOverride); + LONGBOW_RUN_TEST_CASE(Global, parcObject_ToJSON); + LONGBOW_RUN_TEST_CASE(Global, parcObject_GetReferenceCount); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Display_Default); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Display_NoOverride); + LONGBOW_RUN_TEST_CASE(Global, parcObject_Display); + LONGBOW_RUN_TEST_CASE(Global, parcObject_GetDescriptor); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO); + + parcMemory_SetInterface(_originalMemoryProvider); + + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, parcObject_Release) +{ + struct timeval *time = parcObject_CreateInstanceImpl(&_testObject_Descriptor); + parcObject_AssertValid(time); + + time->tv_sec = 1; + time->tv_usec = 2; + + PARCReferenceCount count = parcObject_Release((PARCObject **) &time); + assertTrue(count == 0, "Expected reference count to be zero"); + assertTrue(time == 0, "Expected memory pointer to be NULL after destroy."); +} + +LONGBOW_TEST_CASE(Global, parcObject_Create) +{ + struct timeval *time = parcObject_CreateInstanceImpl(&_testObject_Descriptor); + parcObject_AssertValid(time); + + time->tv_sec = 1; + time->tv_usec = 2; + + PARCReferenceCount count = parcObject_Release((PARCObject **) &time); + assertTrue(count == 0, "Expected reference count to be zero"); + assertTrue(time == 0, "Expected memory pointer to be NULL after destroy."); +} + +//LONGBOW_TEST_CASE(Global, parcObject_CreateAndClear) +//{ +// struct timeval *time = parcObject_CreateAndClear(struct timeval); +// parcObject_AssertValid(time); +// +// time->tv_sec = 1; +// time->tv_usec = 2; +// +// PARCReferenceCount count = parcObject_Release((PARCObject **) &time); +// assertTrue(count == 0, "Expected reference count to be zero"); +// assertTrue(time == 0, "Expected memory pointer to be NULL after destroy."); +//} + +LONGBOW_TEST_CASE(Global, parcObject_IsValid) +{ + PARCObject *object = parcObject_CreateInstanceImpl(&_testObject_Descriptor); + assertTrue(parcObject_IsValid(object), "Expected valid PARCObject"); + + parcObject_Release(&object); +} + +LONGBOW_TEST_CASE(Global, parcObject_IsInstanceOf) +{ + _DummyObject *dummy1 = parcObject_CreateInstance(_DummyObject); + assertTrue(parcObject_IsInstanceOf(dummy1, &PARCObject_Descriptor), + "Expected _DummyObject to be an instance of PARCObject"); + + parcObject_Release((PARCObject **) &dummy1); +} + +LONGBOW_TEST_CASE(Global, parcObject_IsValid_NotValid) +{ + PARCObject *object = parcObject_CreateInstanceImpl(&_testObject_Descriptor); + PARCObject *alias = object; + parcObject_Release(&object); + assertFalse(parcObject_IsValid(object), "Expected invalid PARCObject"); + assertFalse(parcObject_IsValid(alias), "Expected invalid PARCObject"); +} + +LONGBOW_TEST_CASE(Global, parcObject_Copy_Default) +{ + struct timeval *time = parcObject_CreateInstanceImpl(&_testObject_Descriptor); + parcObject_AssertValid(time); + + time->tv_sec = 1; + time->tv_usec = 2; + + struct timeval *copy = parcObject_Copy(time); + + parcObject_AssertValid(copy); + + assertTrue(copy->tv_sec == 1, "Expected tv_sec to equal 1"); + assertTrue(copy->tv_usec == 2, "Expected tv_usec to equal 2"); + + PARCReferenceCount count = parcObject_Release((PARCObject **) ©); + assertTrue(count == 0, "Expected reference count to be zero"); + assertTrue(copy == 0, "Expected memory pointer to be NULL after destroy."); + + parcObject_Release((PARCObject *) &time); +} + +LONGBOW_TEST_CASE(Global, parcObject_Copy) +{ + _DummyObject *dummy1 = parcObject_CreateInstance(_DummyObject); + dummy1->calledCount = 100; + + _DummyObject *dummy2 = parcObject_Copy(dummy1); + + assertTrue(dummy2->calledCount == dummy1->calledCount, + "Expected called counts to be the same. Got %d, expected %d.", dummy1->calledCount, dummy2->calledCount); + + parcObject_Release((PARCObject **) &dummy1); + parcObject_Release((PARCObject **) &dummy2); +} + +LONGBOW_TEST_CASE(Global, parcObject_Compare_Default) +{ + struct timeval *time1 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + parcObject_AssertValid(time1); + + time1->tv_sec = 1; + time1->tv_usec = 2; + + struct timeval *time2 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + parcObject_AssertValid(time2); + + time2->tv_sec = 1; + time2->tv_usec = 2; + + int compareResult = parcObject_Compare(time1, time2); + assertTrue(compareResult == 0, "Expected objects to compare equal. Comparison result: %d", compareResult); + compareResult = parcObject_Compare(time1, time1); + assertTrue(compareResult == 0, "Expected same object to be equal since they have identical pointer addresses. Comparison result: %d", compareResult); + + parcObject_Release((PARCObject *) &time1); + parcObject_Release((PARCObject *) &time2); +} + +LONGBOW_TEST_CASE(Global, parcObject_Compare_NoOverride) +{ + const PARCObjectDescriptor *descriptor = + parcObjectDescriptor_Create("override", + sizeof(struct timeval), sizeof(void*), + true, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL); + struct timeval *time1 = parcObject_CreateAndClearInstanceImpl(descriptor); + parcObject_AssertValid(time1); + + time1->tv_sec = 1; + time1->tv_usec = 2; + + struct timeval *time2 = parcObject_CreateAndClearInstanceImpl(descriptor); + parcObject_AssertValid(time2); + + time2->tv_sec = 1; + time2->tv_usec = 2; + + int compareResult = parcObject_Compare(time1, time2); + assertTrue(compareResult == 0, "Expected objects to compare equal. Comparison result: %d", compareResult); + compareResult = parcObject_Compare(time1, time1); + assertTrue(compareResult == 0, "Expected same object to be equal since they have identical pointer addresses. Comparison result: %d", compareResult); + + parcObject_Release((PARCObject *) &time1); + parcObject_Release((PARCObject *) &time2); + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor); +} + +LONGBOW_TEST_CASE(Global, parcObject_Compare) +{ + _DummyObject *value = parcObject_CreateAndClearInstance(_DummyObject); + _DummyObject *equality[2]; + equality[0] = parcObject_CreateAndClearInstance(_DummyObject); + equality[1] = NULL; + _DummyObject *lesser[2]; + lesser[0] = parcObject_CreateAndClearInstance(_DummyObject); + lesser[1] = NULL; + + _DummyObject *greater[2]; + greater[0] = parcObject_CreateAndClearInstance(_DummyObject); + greater[1] = NULL; + + value->calledCount = 50; + equality[0]->calledCount = 50; + lesser[0]->calledCount = 10; + greater[0]->calledCount = 80; + + parcObjectTesting_AssertCompareTo(parcObject_Compare, value, equality, lesser, greater); + + parcObject_Release((void **) &value); + parcObject_Release((void **) &equality[0]); + parcObject_Release((void **) &lesser[0]); + parcObject_Release((void **) &greater[0]); +} + +LONGBOW_TEST_CASE(Global, parcObject_Equals_Default) +{ + struct timeval *x = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + memset(x, 0, sizeof(struct timeval)); + x->tv_sec = 1; + x->tv_usec = 2; + + struct timeval *y = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + memset(y, 0, sizeof(struct timeval)); + y->tv_sec = 1; + y->tv_usec = 2; + + assertTrue(parcObject_Equals(x, y), "Expected equality"); + + struct timeval *z = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + z->tv_sec = 1; + z->tv_usec = 2; + + struct timeval *unequal1 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + unequal1->tv_sec = 1; + unequal1->tv_usec = 1; + + struct timeval *unequal2 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + unequal2->tv_sec = 0; + unequal2->tv_usec = 0; + + parcObjectTesting_AssertEqualsFunction(parcObject_Equals, x, y, z, unequal1, unequal2, NULL); + + parcObject_Release((PARCObject *) &x); + parcObject_Release((PARCObject *) &y); + parcObject_Release((PARCObject *) &z); + parcObject_Release((PARCObject *) &unequal1); + parcObject_Release((PARCObject *) &unequal2); +} + +LONGBOW_TEST_CASE(Global, parcObject_Equals_NoOverride) +{ + const PARCObjectDescriptor *descriptor = + parcObjectDescriptor_Create("override", sizeof(struct timeval), sizeof(void*), true, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL); + + struct timeval *x = parcObject_CreateAndClearInstanceImpl(descriptor); + memset(x, 0, sizeof(struct timeval)); + x->tv_sec = 1; + x->tv_usec = 2; + + struct timeval *y = parcObject_CreateAndClearInstanceImpl(descriptor); + memset(y, 0, sizeof(struct timeval)); + y->tv_sec = 1; + y->tv_usec = 2; + + assertTrue(parcObject_Equals(x, y), "Expected equality"); + + struct timeval *z = parcObject_CreateAndClearInstanceImpl(descriptor); + z->tv_sec = 1; + z->tv_usec = 2; + + struct timeval *unequal1 = parcObject_CreateAndClearInstanceImpl(descriptor); + unequal1->tv_sec = 1; + unequal1->tv_usec = 1; + + struct timeval *unequal2 = parcObject_CreateAndClearInstanceImpl(descriptor); + unequal2->tv_sec = 0; + unequal2->tv_usec = 0; + + parcObjectTesting_AssertEqualsFunction(parcObject_Equals, x, y, z, unequal1, unequal2, NULL); + + parcObject_Release((PARCObject *) &x); + parcObject_Release((PARCObject *) &y); + parcObject_Release((PARCObject *) &z); + parcObject_Release((PARCObject *) &unequal1); + parcObject_Release((PARCObject *) &unequal2); + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor); +} + +LONGBOW_TEST_CASE(Global, parcObject_Equals) +{ + _DummyObject *x = parcObject_CreateInstance(_DummyObject); + x->calledCount = 100; + _DummyObject *y = parcObject_CreateInstance(_DummyObject); + y->calledCount = 100; + _DummyObject *z = parcObject_CreateInstance(_DummyObject); + z->calledCount = 100; + + _DummyObject *unequal1 = parcObject_CreateInstance(_DummyObject); + unequal1->calledCount = 50; + + PARCObject *unequal2 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + + PARCObjectDescriptor dummyMeta2 = parcObject_DescriptorName(_DummyObject); + _DummyObject *unequal3 = parcObject_CreateAndClearInstanceImpl(&dummyMeta2); + unequal3->calledCount = 100; + + PARCObject *unequal4 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + + parcObjectTesting_AssertEqualsFunction(parcObject_Equals, x, y, z, unequal1, unequal2, unequal3, unequal4, NULL); + + parcObject_Release((PARCObject **) &x); + parcObject_Release((PARCObject **) &y); + parcObject_Release((PARCObject **) &z); + parcObject_Release((PARCObject **) &unequal1); + parcObject_Release((PARCObject **) &unequal2); + parcObject_Release((PARCObject **) &unequal3); + parcObject_Release((PARCObject **) &unequal4); +} + +LONGBOW_TEST_CASE(Global, parcObject_HashCode_Default) +{ + struct timeval *time = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + parcObject_AssertValid(time); + + time->tv_sec = 1; + time->tv_usec = 2; + + PARCHashCode hashCode = parcObject_HashCode(time); + PARCHashCode expected = parcHashCode_Hash((void *) time, sizeof(struct timeval)); + assertTrue(hashCode == expected, "Hash codes do not match. Got %" PRIPARCHashCode ", expected %" PRIPARCHashCode ".", hashCode, expected); + + parcObject_Release((PARCObject *) &time); +} + +LONGBOW_TEST_CASE(Global, parcObject_HashCode_NoOverride) +{ + const PARCObjectDescriptor *descriptor = + parcObjectDescriptor_Create("override", sizeof(struct timeval), sizeof(void*), true, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL); + struct timeval *time = parcObject_CreateAndClearInstanceImpl(descriptor); + parcObject_AssertValid(time); + + time->tv_sec = 1; + time->tv_usec = 2; + + PARCHashCode hashCode = parcObject_HashCode(time); + PARCHashCode expected = parcHashCode_Hash((void *) time, sizeof(struct timeval)); + assertTrue(hashCode == expected, "Hash codes do not match. Got %" PRIPARCHashCode ", expected %" PRIPARCHashCode ".", hashCode, expected); + + parcObject_Release((PARCObject *) &time); + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor); +} + +LONGBOW_TEST_CASE(Global, parcObject_HashCode) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + + PARCHashCode hashCode = parcObject_HashCode(dummy); + assertTrue(hashCode == 1337, "Expected hashcode to be 1337, got %" PRIPARCHashCode, hashCode); + + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_CASE(Global, parcObject_ToString) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + + char *strRep = parcObject_ToString(dummy); + assertTrue(strcmp(strRep, "dummy") == 0, "Expected 'dummy' string representation, got %s", strRep); + + parcMemory_Deallocate((void **) &strRep); + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_CASE(Global, parcObject_ToString_Default) +{ + _DummyObject *dummy = parcObject_CreateAndClearInstanceImpl(&_DummyObject_Descriptor); + + char *strRep = parcObject_ToString(dummy); + + parcMemory_Deallocate((void **) &strRep); + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_CASE(Global, parcObject_ToString_NoOverride) +{ + const PARCObjectDescriptor *descriptor = + parcObjectDescriptor_Create("override", sizeof(struct timeval), sizeof(void*), true, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL); + _DummyObject *dummy = parcObject_CreateAndClearInstanceImpl(descriptor); + + char *strRep = parcObject_ToString(dummy); + + parcMemory_Deallocate((void **) &strRep); + parcObject_Release((PARCObject **) &dummy); + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor); +} + +LONGBOW_TEST_CASE(Global, parcObject_ToJSON_Default) +{ + size_t expectedSize = sizeof(struct timeval); + PARCObject *memory = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor); + + PARCJSON *json = parcObject_ToJSON(memory); + + const PARCJSONPair *lengthPair = parcJSON_GetPairByName(json, "objectLength"); + PARCJSONValue *lengthValue = parcJSONPair_GetValue(lengthPair); + uint64_t actualLength = parcJSONValue_GetInteger(lengthValue); + + const PARCJSONPair *alignmentPair = parcJSON_GetPairByName(json, "objectAlignment"); + PARCJSONValue *alignmentValue = parcJSONPair_GetValue(alignmentPair); + int alignment = (int) parcJSONValue_GetInteger(alignmentValue); + + assertTrue(actualLength >= expectedSize, + "Expected length to be >= %zd, actual %" PRIu64 "", expectedSize, actualLength); + assertTrue(alignment == sizeof(void *), "Expected objectAlignment to be %zd, got %d", + sizeof(void *), alignment); + + parcJSON_Release(&json); + parcObject_Release(&memory); +} + +LONGBOW_TEST_CASE(Global, parcObject_ToJSON) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + + PARCJSON *json = parcObject_ToJSON(dummy); + char *strRep = parcJSON_ToString(json); + assertTrue(strcmp(strRep, "{ \"type\" : \"dummy\" }") == 0, "Expected fixed JSON object with a specific string representation, got %s", strRep); + + parcMemory_Deallocate((void **) &strRep); + parcJSON_Release(&json); + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_CASE(Global, parcObject_ToJSON_NoOverride) +{ + const PARCObjectDescriptor *descriptor = + parcObjectDescriptor_Create("override", sizeof(struct timeval), sizeof(void*), true, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL); + + size_t expectedSize = sizeof(struct timeval); + PARCObject *memory = parcObject_CreateAndClearInstanceImpl(descriptor); + + PARCJSON *json = parcObject_ToJSON(memory); + const PARCJSONPair *lengthPair = parcJSON_GetPairByName(json, "objectLength"); + PARCJSONValue *lengthValue = parcJSONPair_GetValue(lengthPair); + uint64_t actualLength = parcJSONValue_GetInteger(lengthValue); + + const PARCJSONPair *alignmentPair = parcJSON_GetPairByName(json, "objectAlignment"); + PARCJSONValue *alignmentValue = parcJSONPair_GetValue(alignmentPair); + int alignment = (int) parcJSONValue_GetInteger(alignmentValue); + + assertTrue(actualLength >= expectedSize, + "Expected length to be >= %zd, actual %" PRIu64 "", expectedSize, actualLength); + assertTrue(alignment == sizeof(void *), "Expected objectAlignment to be %zd, got %d", + sizeof(void *), alignment); + + parcJSON_Release(&json); + parcObject_Release(&memory); + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor); +} + +LONGBOW_TEST_CASE(Global, parcObject_GetReferenceCount) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + PARCReferenceCount refCount = parcObject_GetReferenceCount(dummy); + assertTrue(refCount == 1, "Expected reference count to be 1, got %" PRIu64 "", refCount); + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_CASE(Global, parcObject_Display_Default) +{ + _DummyObject *dummy = parcObject_CreateAndClearInstanceImpl(&_DummyObject_Descriptor); + parcObject_Display(dummy, 0); + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_CASE(Global, parcObject_Display_NoOverride) +{ + const PARCObjectDescriptor *descriptor = + parcObjectDescriptor_Create("override", sizeof(struct timeval), sizeof(void*), true, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL); + + _DummyObject *dummy = parcObject_CreateAndClearInstanceImpl(descriptor); + parcObject_Display(dummy, 0); + parcObject_Release((PARCObject **) &dummy); + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor); +} + +LONGBOW_TEST_CASE(Global, parcObject_Display) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + parcObject_Display(dummy, 0); + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_CASE(Global, parcObject_GetDescriptor) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + const PARCObjectDescriptor *descriptor = parcObject_GetDescriptor(dummy); + + assertTrue(descriptor == &_DummyObject_Descriptor, "Expected pointer to _DummyObject_Descriptor"); + + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_FIXTURE(Subclasses) +{ + LONGBOW_RUN_TEST_CASE(Subclasses, parcObject_Copy); +} + +LONGBOW_TEST_FIXTURE_SETUP(Subclasses) +{ + _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Subclasses) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO); + parcMemory_SetInterface(_originalMemoryProvider); + + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Subclasses, parcObject_Copy) +{ + const PARCObjectDescriptor *objectType = + parcObjectDescriptor_Create("Dummy", sizeof(_DummyObject), sizeof(void*), true, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL); + + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + parcObject_SetDescriptor(dummy, objectType); + + dummy->calledCount = 100; + + _DummyObject *dummy2 = parcObject_Copy(dummy); + + assertTrue(dummy2->calledCount == dummy->calledCount, + "Expected called counts to be the same. Got %d, expected %d.", dummy->calledCount, dummy2->calledCount); + + parcObject_Release((PARCObject **) &dummy); + parcObject_Release((PARCObject **) &dummy2); + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &objectType); +} + +LONGBOW_TEST_FIXTURE(Locking) +{ + LONGBOW_RUN_TEST_CASE(Locking, parcObject_TryLock_Unlock); + LONGBOW_RUN_TEST_CASE(Locking, parcObject_Lock_Unlock); + LONGBOW_RUN_TEST_CASE(Locking, parcObject_TryLock_AlreadyLockedSameThread); + LONGBOW_RUN_TEST_CASE(Locking, parcObject_Lock_AlreadyLocked); +} +static uint32_t initialAllocations; + +LONGBOW_TEST_FIXTURE_SETUP(Locking) +{ + _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + initialAllocations = parcMemory_Outstanding(); + + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + + longBowTestCase_SetClipBoardData(testCase, dummy); + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Locking) +{ + _DummyObject *dummy = longBowTestCase_GetClipBoardData(testCase); + + parcObject_Release((PARCObject **) &dummy); + + if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) { + parcSafeMemory_ReportAllocation(STDOUT_FILENO); + parcMemory_SetInterface(_originalMemoryProvider); + return LONGBOW_STATUS_MEMORYLEAK; + } + parcMemory_SetInterface(_originalMemoryProvider); + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Locking, parcObject_TryLock_Unlock) +{ + _DummyObject *dummy = longBowTestCase_GetClipBoardData(testCase); + + bool actual = parcObject_TryLock(dummy); + + assertTrue(actual, "Expected parcObject_TryLock to succeed."); + + actual = parcObject_IsLocked(dummy); + assertTrue(actual, "Expected parcObject_IsLocked to be true."); + + actual = parcObject_Unlock(dummy); + assertTrue(actual, "Expected parcObject_Unlock to succeed."); + + actual = parcObject_IsLocked(dummy); + assertFalse(actual, "Expected parcObject_IsLocked to be false."); +} + +LONGBOW_TEST_CASE(Locking, parcObject_Lock_Unlock) +{ + _DummyObject *dummy = longBowTestCase_GetClipBoardData(testCase); + + bool actual = parcObject_Lock(dummy); + + assertTrue(actual, "Expected parcObject_Lock to succeed."); + + actual = parcObject_IsLocked(dummy); + assertTrue(actual, "Expected parcObject_IsLocked to be true."); + + actual = parcObject_Unlock(dummy); + assertTrue(actual, "Expected parcObject_Unlock to succeed."); + + actual = parcObject_IsLocked(dummy); + assertFalse(actual, "Expected parcObject_IsLocked to be false."); +} + +LONGBOW_TEST_CASE_EXPECTS(Locking, parcObject_TryLock_AlreadyLockedSameThread, .event = &LongBowTrapCannotObtainLockEvent) +{ + _DummyObject *dummy = longBowTestCase_GetClipBoardData(testCase); + + bool actual = parcObject_TryLock(dummy); + + assertTrue(actual, "Expected parcObject_TryLock to succeed."); + + actual = parcObject_TryLock(dummy); + + assertFalse(actual, "Expected parcObject_TryLock to fail when already locked by the same thread."); + + actual = parcObject_Unlock(dummy); + assertTrue(actual, "Expected parcObject_Unlock to succeed."); +} + +LONGBOW_TEST_CASE_EXPECTS(Locking, parcObject_Lock_AlreadyLocked, .event = &LongBowTrapCannotObtainLockEvent) +{ + _DummyObject *dummy = longBowTestCase_GetClipBoardData(testCase); + + bool actual = parcObject_Lock(dummy); + + assertTrue(actual, "Expected parcObject_Lock to succeed."); + + actual = parcObject_IsLocked(dummy); + assertTrue(actual, "Expected locked object to indicate being locked."); + + parcObject_Lock(dummy); +} + +LONGBOW_TEST_FIXTURE(WaitNotify) +{ + LONGBOW_RUN_TEST_CASE(WaitNotify, parcObject_WaitNotify); + LONGBOW_RUN_TEST_CASE(WaitNotify, parcObject_WaitNotify2); + LONGBOW_RUN_TEST_CASE(WaitNotify, parcObject_WaitUntil); + LONGBOW_RUN_TEST_CASE(WaitNotify, parcObject_WaitFor); + LONGBOW_RUN_TEST_CASE(WaitNotify, parcObject_WaitNotifyAll); +} + +LONGBOW_TEST_FIXTURE_SETUP(WaitNotify) +{ + _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(WaitNotify) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO); + + parcMemory_SetInterface(_originalMemoryProvider); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +// Just wait until told to wakeup, then increment a counter and unlock. +static void * +waiter(void *data) +{ + _DummyObject *dummy = data; + + while (parcObject_TryLock(dummy) == false) { + ; + } + assertTrue(parcObject_IsLocked(dummy), "%p object %p not locked.", (void *) pthread_self(), (void *) dummy); + parcObject_Wait(dummy); + + dummy->val++; + parcObject_Unlock(dummy); + + return data; +} + +LONGBOW_TEST_CASE(WaitNotify, parcObject_WaitNotify) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + + dummy->val = 0; + + pthread_t thread_A; + pthread_t thread_B; + pthread_t thread_C; + pthread_create(&thread_A, NULL, waiter, dummy); + pthread_create(&thread_B, NULL, waiter, dummy); + pthread_create(&thread_C, NULL, waiter, dummy); + + while (dummy->val != 3) { + while (parcObject_TryLock(dummy) == false) { + ; + } + parcObject_Notify(dummy); + parcObject_Unlock(dummy); + } + + pthread_join(thread_A, NULL); +// pthread_join(thread_B, NULL); +// pthread_join(thread_C, NULL); + + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_CASE(WaitNotify, parcObject_WaitNotifyAll) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + + dummy->val = 0; + + pthread_t thread_A; + pthread_t thread_B; + pthread_t thread_C; + pthread_create(&thread_A, NULL, waiter, dummy); + pthread_create(&thread_B, NULL, waiter, dummy); + pthread_create(&thread_C, NULL, waiter, dummy); + + while (dummy->val != 3) { + while (parcObject_TryLock(dummy) == false) { + ; + } + parcObject_NotifyAll(dummy); + parcObject_Unlock(dummy); + } + + pthread_join(thread_A, NULL); +// pthread_join(thread_B, NULL); +// pthread_join(thread_C, NULL); + + assertTrue(dummy->val == 3, "Expected the counter to be 3, actual %d", dummy->val); + + parcObject_Release((PARCObject **) &dummy); +} + +static void * +decrement(void *data) +{ + _DummyObject *dummy = data; + + while (parcObject_TryLock(dummy) == false) { + ; + } + while (dummy->val < 12) { + parcObject_Wait(dummy); + dummy->val--; + } + parcObject_Unlock(dummy); + + return data; +} + +LONGBOW_TEST_CASE(WaitNotify, parcObject_WaitNotify2) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + + dummy->val = 0; + + pthread_t thread_A; + pthread_create(&thread_A, NULL, decrement, dummy); + + dummy->val = 2; + while (parcObject_TryLock(dummy) == false) { + ; + } + while (dummy->val <= 12) { + parcObject_Notify(dummy); + dummy->val += 2; + } + parcObject_Unlock(dummy); + + pthread_join(thread_A, NULL); + + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_CASE(WaitNotify, parcObject_WaitUntil) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + + dummy->val = 0; + + time_t now; + time_t then; + time(&then); + if (parcObject_Lock(dummy)) { + struct timespec future; + future.tv_sec = then + 3; + future.tv_nsec = 0; + parcObject_WaitUntil(dummy, &future); + + time(&now); + long expected = now - 1; // Subtract 1 because the future may have been computed at the 999,999,999 nanosecond mark. + assertTrue(now >= expected, "Expected now %ld, to be later than than %ld", now, expected); + parcObject_Unlock(dummy); + } + + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_CASE(WaitNotify, parcObject_WaitFor) +{ + _DummyObject *dummy = parcObject_CreateInstance(_DummyObject); + + dummy->val = 0; + + time_t now; + time_t then; + time(&then); + if (parcObject_Lock(dummy)) { + uint64_t nanoSeconds = 1000000000; + parcObject_WaitFor(dummy, nanoSeconds); + + time(&now); + now++; // Advance now by 1 because of the precision mismatch between gettimeofday and nanosecond resolution of parcObject_WaitFor + assertTrue(now >= then + (nanoSeconds / 1000000000), + "Expected now %ld, to be later than time %" PRIu64, now, then + (nanoSeconds / 1000000000)); + parcObject_Unlock(dummy); + } + + parcObject_Release((PARCObject **) &dummy); +} + +LONGBOW_TEST_FIXTURE(Fail) +{ +} + +typedef struct { + PARCObject *value; +} TestData; + +LONGBOW_TEST_FIXTURE_SETUP(Fail) +{ + _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + TestData *data = parcMemory_AllocateAndClear(sizeof(TestData)); + assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData)); + data->value = parcObject_CreateInstance(_DummyObjectNoHash); + if (data->value == NULL) { + return LONGBOW_STATUS_SETUP_FAILED; + } + longBowTestCase_SetClipBoardData(testCase, data); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Fail) +{ + TestData *data = longBowTestCase_GetClipBoardData(testCase); + parcObject_Release(&data->value); + parcMemory_Deallocate((void **) &data); + + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO); + + parcMemory_SetInterface(_originalMemoryProvider); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false) +{ + LONGBOW_RUN_TEST_CASE(Performance, _parcObject_PrefixLength_10000000); + LONGBOW_RUN_TEST_CASE(Performance, parcObject_CreateRelease); + LONGBOW_RUN_TEST_CASE(Performance, parcObject_Create); + LONGBOW_RUN_TEST_CASE(Performance, parcObject_AcquireRelease); +} + +LONGBOW_TEST_FIXTURE_SETUP(Performance) +{ + parcMemory_SetInterface(&PARCStdlibMemoryAsPARCMemory); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Performance) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Performance, _parcObject_PrefixLength_10000000) +{ + // Test that the result is a multiple of the alignment value and greater than the size of _PARCObjectHeader. + + // Compute the power of 2 value of sizeof(void *) + unsigned int v = sizeof(void *); + unsigned int r = 0; // r will be lg(v) + + while (v >>= 1) { + r++; + } + + PARCObjectDescriptor descriptor; + + for (int i = r; i < 20; i++) { + descriptor.objectAlignment = 1 << i; + size_t actual = _parcObject_PrefixLength(&descriptor); + assertTrue((actual & (descriptor.objectAlignment - 1)) == 0, + "Alignment needs to be a multiple of %u", descriptor.objectAlignment); + } +} + +#define OBJECT_COUNT 10000000 +#define OBJECT_SIZE 1200 + +typedef struct { char bytes[OBJECT_SIZE]; } PerformanceObject; + +parcObject_Override(PerformanceObject, PARCObject); + +LONGBOW_TEST_CASE(Performance, parcObject_CreateRelease) +{ + for (int i = 0; i < OBJECT_COUNT; i++) { + PARCObject *object = parcObject_CreateInstanceImpl(&PerformanceObject_Descriptor); + + PARCObject *object1 = parcObject_Acquire(object); + PARCObject *object2 = parcObject_Acquire(object); + parcObject_Release(&object1); + parcObject_Release(&object2); + + parcObject_Release(&object); + } +} + +void *objects[OBJECT_COUNT]; + +LONGBOW_TEST_CASE(Performance, parcObject_AcquireRelease) +{ + PARCObject *object = parcObject_CreateInstanceImpl(&PerformanceObject_Descriptor); + + for (int i = 0; i < OBJECT_COUNT; i++) { + objects[i] = parcObject_Acquire(object); + } + + for (int i = 0; i < OBJECT_COUNT; i++) { + parcObject_Release(&objects[i]); + } + + parcObject_Release(&object); +} + +LONGBOW_TEST_CASE(Performance, parcObject_Create) +{ + for (int i = 0; i < OBJECT_COUNT; i++) { + objects[i] = parcObject_CreateInstanceImpl(&PerformanceObject_Descriptor); + } + + for (int i = 0; i < OBJECT_COUNT; i++) { + parcObject_Release(&objects[i]); + } +} + +LONGBOW_TEST_FIXTURE(Meta) +{ + LONGBOW_RUN_TEST_CASE(Meta, _metaDestructor_True); + LONGBOW_RUN_TEST_CASE(Meta, _metaDestructor_False); + LONGBOW_RUN_TEST_CASE(Meta, _metaDestructor_None); + + LONGBOW_RUN_TEST_CASE(Meta, parcObjectDescriptor_Create); +} + +LONGBOW_TEST_FIXTURE_SETUP(Meta) +{ + _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + _DummyObject *data; + parcMemory_MemAlign((void **) &data, sizeof(void *), sizeof(_DummyObject)); + data->val = 10; + longBowTestCase_SetClipBoardData(testCase, data); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Meta) +{ + _DummyObject *data = longBowTestCase_GetClipBoardData(testCase); + parcMemory_Deallocate((void **) &data); + + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO); + parcMemory_SetInterface(_originalMemoryProvider); + if (outstandingAllocations != 0) { + printf("%s leaks %d memory allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Meta, parcObjectDescriptor_Create) +{ + const PARCObjectDescriptor *interface = parcObjectDescriptor_Create("Meta", + sizeof(struct timeval), sizeof(void*), + true, + _meta_destructor_true, NULL, _meta_copy, _meta_toString, + _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, + &PARCObject_Descriptor, NULL); + + assertNotNull(interface, "Expected interface instance to be allocated correctly."); + + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &interface); + assertNull(interface, "Expected parcObjectDescriptor_Destroy to NULL the input pointer"); +} + +LONGBOW_TEST_CASE(Meta, _metaDestructor_True) +{ + const PARCObjectDescriptor *interface = + parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true, + _meta_destructor_true, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, + &PARCObject_Descriptor, NULL); + _DummyObject *data = longBowTestCase_GetClipBoardData(testCase); + bool actual = _parcObject_Destructor(interface, (PARCObject **) &data); + + assertTrue(actual, "Expected destructor to return true."); + + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &interface); +} + +LONGBOW_TEST_CASE(Meta, _metaDestructor_False) +{ + const PARCObjectDescriptor *descriptor = + parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true, + _meta_destructor_false, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, + &PARCObject_Descriptor, NULL); + _DummyObject *data = longBowTestCase_GetClipBoardData(testCase); + bool actual = _parcObject_Destructor(descriptor, (PARCObject **) &data); + + assertNull(data, "Expected destructor function to have been called to nullify the reference."); + assertFalse(actual, "Expected destructor to return false."); + + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor); +} + +LONGBOW_TEST_CASE(Meta, _metaDestructor_None) +{ + const PARCObjectDescriptor *interface = parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true, + NULL, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, &PARCObject_Descriptor, NULL); + _DummyObject *data = longBowTestCase_GetClipBoardData(testCase); + _parcObject_Destructor(interface, (void **) &data); + + assertNotNull(data, "Expected destructor function to have been called to nullify the reference."); + + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &interface); +} + +LONGBOW_TEST_FIXTURE(PARCObjectDescriptor) +{ + LONGBOW_RUN_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_Create); + LONGBOW_RUN_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_CreateExtension); + LONGBOW_RUN_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_GetSuperType); + LONGBOW_RUN_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_GetTypeState); +} + +LONGBOW_TEST_FIXTURE_SETUP(PARCObjectDescriptor) +{ + longBowTestCase_SetInt(testCase, "initialAllocations", parcMemory_Outstanding()); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(PARCObjectDescriptor) +{ + int initialAllocations = longBowTestCase_GetInt(testCase, "initialAllocations"); + + uint32_t outstandingAllocations = parcMemory_Outstanding() - initialAllocations; + + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations); + parcSafeMemory_ReportAllocation(STDOUT_FILENO); + return LONGBOW_STATUS_MEMORYLEAK; + } + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_Create) +{ + const PARCObjectDescriptor *descriptor = parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true, + NULL, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, &PARCObject_Descriptor, NULL); + + parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor); +} + +LONGBOW_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_CreateExtension) +{ + PARCObjectDescriptor *descriptor = parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true, + NULL, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, &PARCObject_Descriptor, NULL); + + PARCObjectDescriptor *extension = parcObjectDescriptor_CreateExtension(descriptor, "Extension"); + + parcObjectDescriptor_Destroy(&extension); + parcObjectDescriptor_Destroy(&descriptor); +} + +LONGBOW_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_GetSuperType) +{ + PARCObjectDescriptor *descriptor = parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true, + NULL, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, &PARCObject_Descriptor, NULL); + + const PARCObjectDescriptor *superType = parcObjectDescriptor_GetSuperType(descriptor); + + assertTrue(superType == &PARCObject_Descriptor, "Expected a pointer to PARCObject_Descriptor"); + + parcObjectDescriptor_Destroy(&descriptor); +} + +LONGBOW_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_GetTypeState) +{ + PARCObjectDescriptor *descriptor = parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true, + NULL, NULL, _meta_copy, _meta_toString, _meta_equals, + _meta_compare, _meta_hashCode, _meta_toJson, NULL, + &PARCObject_Descriptor, + (PARCObjectTypeState *) &PARCObject_Descriptor); + + PARCObjectTypeState *state = parcObjectDescriptor_GetTypeState(descriptor); + + assertTrue(state == &PARCObject_Descriptor, "Expected a pointer to PARCObject_Descriptor"); + + parcObjectDescriptor_Destroy(&descriptor); +} + +LONGBOW_TEST_FIXTURE(StaticObjects) +{ + LONGBOW_RUN_TEST_CASE(StaticObjects, parcObject_WrapImpl); + LONGBOW_RUN_TEST_CASE(StaticObjects, parcObject_InitInstanceImpl); + LONGBOW_RUN_TEST_CASE(StaticObjects, parcObject_InitAndClearInstanceImpl); +} + +LONGBOW_TEST_FIXTURE_SETUP(StaticObjects) +{ + _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(StaticObjects) +{ + parcMemory_SetInterface(_originalMemoryProvider); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(StaticObjects, parcObject_WrapImpl) +{ + char *origin = (char[parcObject_TotalSize(sizeof(void*), 10)]) { 0 }; + + PARCObject *result = parcObject_WrapImpl(origin, &parcObject_DescriptorName(PARCObject)); + + parcObject_AssertValid(result); + + parcObject_Release(&result); +} + +PARCObject *globalObject = parcObject_Instance(PARCObject, sizeof(void*), 10); + +LONGBOW_TEST_CASE(StaticObjects, parcObject_InitInstanceImpl) +{ + parcObject_InitInstanceImpl(globalObject, &PARCObject_Descriptor); + + parcObject_AssertValid(globalObject); + +// parcObject_Release(&globalObject); +} + +LONGBOW_TEST_CASE(StaticObjects, parcObject_InitAndClearInstanceImpl) +{ + parcObject_InitAndClearInstanceImpl(globalObject, &PARCObject_Descriptor); + + parcObject_AssertValid(globalObject); + +// parcObject_Release(&globalObject); +} + +LONGBOW_TEST_FIXTURE(Synchronization) +{ + LONGBOW_RUN_TEST_CASE(Synchronization, parcObject_SynchronizeBegin); +} + +LONGBOW_TEST_FIXTURE_SETUP(Synchronization) +{ + _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Synchronization) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO); + + parcMemory_SetInterface(_originalMemoryProvider); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Synchronization, parcObject_SynchronizeBegin) +{ + PARCObject *dummy = parcObject_CreateInstance(_DummyObject); + + bool result = parcObject_BarrierSet(dummy); + assertTrue(result, "Expected parcObject_BarrierSet to always return true."); + + _PARCObjectHeader *header = _parcObject_Header(dummy); + assertTrue(header->barrier, "Expected the header barrier to be set."); + + result = parcObject_BarrierUnset(dummy); + assertFalse(result, "Expected parcObject_BarrierUnset to always return false."); + assertFalse(header->barrier, "Expected the header barrier to NOT be set."); + + parcObject_Release(&dummy); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parcObject); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} + -- cgit 1.2.3-korg