aboutsummaryrefslogtreecommitdiffstats
path: root/libparc/parc/concurrent/test
diff options
context:
space:
mode:
Diffstat (limited to 'libparc/parc/concurrent/test')
-rw-r--r--libparc/parc/concurrent/test/.gitignore10
-rw-r--r--libparc/parc/concurrent/test/CMakeLists.txt25
-rw-r--r--libparc/parc/concurrent/test/test_parc_AtomicUint16.c361
-rw-r--r--libparc/parc/concurrent/test/test_parc_AtomicUint32.c361
-rw-r--r--libparc/parc/concurrent/test/test_parc_AtomicUint64.c361
-rw-r--r--libparc/parc/concurrent/test/test_parc_AtomicUint8.c361
-rw-r--r--libparc/parc/concurrent/test/test_parc_FutureTask.c317
-rw-r--r--libparc/parc/concurrent/test/test_parc_Lock.c352
-rwxr-xr-xlibparc/parc/concurrent/test/test_parc_Notifier.c267
-rwxr-xr-xlibparc/parc/concurrent/test/test_parc_RingBuffer_1x1.c325
-rwxr-xr-xlibparc/parc/concurrent/test/test_parc_RingBuffer_NxM.c106
-rw-r--r--libparc/parc/concurrent/test/test_parc_ScheduledTask.c244
-rw-r--r--libparc/parc/concurrent/test/test_parc_ScheduledThreadPool.c301
-rwxr-xr-xlibparc/parc/concurrent/test/test_parc_Synchronizer.c179
-rw-r--r--libparc/parc/concurrent/test/test_parc_Thread.c264
-rw-r--r--libparc/parc/concurrent/test/test_parc_ThreadPool.c273
-rw-r--r--libparc/parc/concurrent/test/test_parc_Timer.c213
17 files changed, 4320 insertions, 0 deletions
diff --git a/libparc/parc/concurrent/test/.gitignore b/libparc/parc/concurrent/test/.gitignore
new file mode 100644
index 00000000..2c9fe4f5
--- /dev/null
+++ b/libparc/parc/concurrent/test/.gitignore
@@ -0,0 +1,10 @@
+test_parc_Notifier
+test_parc_RingBuffer_1x1
+test_parc_RingBuffer_NxM
+test_parc_AtomicUint64
+test_parc_Barrier
+test_parc_AtomicUint16
+test_parc_AtomicUint32
+test_parc_AtomicUint8
+test_parc_Synchronizer
+test_parc_Lock
diff --git a/libparc/parc/concurrent/test/CMakeLists.txt b/libparc/parc/concurrent/test/CMakeLists.txt
new file mode 100644
index 00000000..092d0202
--- /dev/null
+++ b/libparc/parc/concurrent/test/CMakeLists.txt
@@ -0,0 +1,25 @@
+set(TestsExpectedToPass
+ test_parc_AtomicUint16
+ test_parc_AtomicUint32
+ test_parc_AtomicUint64
+ test_parc_AtomicUint8
+ test_parc_FutureTask
+ test_parc_Lock
+ test_parc_Notifier
+ test_parc_RingBuffer_1x1
+ test_parc_RingBuffer_NxM
+ test_parc_ScheduledTask
+ test_parc_ScheduledThreadPool
+ test_parc_Synchronizer
+ test_parc_Thread
+ test_parc_ThreadPool
+ test_parc_Timer
+ )
+
+# Enable gcov output for the tests
+add_definitions(--coverage)
+set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
+
+foreach(test ${TestsExpectedToPass})
+ AddTest(${test})
+endforeach()
diff --git a/libparc/parc/concurrent/test/test_parc_AtomicUint16.c b/libparc/parc/concurrent/test/test_parc_AtomicUint16.c
new file mode 100644
index 00000000..ed97cc95
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_AtomicUint16.c
@@ -0,0 +1,361 @@
+/*
+ * 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_AtomicUint16.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+
+#include <inttypes.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_AtomicUint16)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Macros);
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_AtomicUint16)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_AtomicUint16)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(7);
+ assertNotNull(instance, "Expeced non-null result from parcAtomicUint16_Create();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcAtomicUint16_Acquire, instance);
+
+ parcAtomicUint16_Release(&instance);
+ assertNull(instance, "Expected null result from parcAtomicUint16_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint16_Compare);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint16_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint16_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint16_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint16_IsValid);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint16_SubtractImpl);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint16_AddImpl);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint16_CompareAndSwapImpl);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint16_Compare)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(7);
+ PARCAtomicUint16 *high = parcAtomicUint16_Create(8);
+ PARCAtomicUint16 *low = parcAtomicUint16_Create(6);
+ PARCAtomicUint16 *equal = parcAtomicUint16_Create(7);
+
+ int actual = parcAtomicUint16_Compare(instance, high);
+ assertTrue(actual < 0, "Expected < 0");
+ actual = parcAtomicUint16_Compare(instance, low);
+ assertTrue(actual > 0, "Expected > 0");
+ actual = parcAtomicUint16_Compare(instance, equal);
+ assertTrue(actual == 0, "Expected == 0");
+
+ parcAtomicUint16_Release(&instance);
+ parcAtomicUint16_Release(&high);
+ parcAtomicUint16_Release(&low);
+ parcAtomicUint16_Release(&equal);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint16_Copy)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(7);
+ PARCAtomicUint16 *copy = parcAtomicUint16_Copy(instance);
+
+ assertTrue(parcAtomicUint16_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcAtomicUint16_Release(&instance);
+ parcAtomicUint16_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint16_Equals)
+{
+ PARCAtomicUint16 *x = parcAtomicUint16_Create(7);
+ PARCAtomicUint16 *y = parcAtomicUint16_Create(7);
+ PARCAtomicUint16 *z = parcAtomicUint16_Create(7);
+ PARCAtomicUint16 *u1 = parcAtomicUint16_Create(6);
+
+ parcObjectTesting_AssertEquals(x, y, z, u1, NULL);
+
+ parcAtomicUint16_Release(&x);
+ parcAtomicUint16_Release(&y);
+ parcAtomicUint16_Release(&z);
+ parcAtomicUint16_Release(&u1);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint16_HashCode)
+{
+ PARCAtomicUint16 *x = parcAtomicUint16_Create(7);
+ parcAtomicUint16_HashCode(x);
+ parcAtomicUint16_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint16_IsValid)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(7);
+ assertTrue(parcAtomicUint16_IsValid(instance), "Expected parcAtomicUint16_Create to result in a valid instance.");
+
+ parcAtomicUint16_Release(&instance);
+ assertFalse(parcAtomicUint16_IsValid(instance), "Expected parcAtomicUint16_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint16_SubtractImpl)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(7);
+
+ parcAtomicUint16_SubtractImpl(instance, 1);
+
+ uint16_t actual = parcAtomicUint16_GetValue(instance);
+
+ assertTrue(actual == 6, "Expected 6, actual %" PRIu16, actual);
+ parcAtomicUint16_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint16_AddImpl)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(7);
+
+ parcAtomicUint16_AddImpl(instance, 1);
+
+ uint16_t actual = parcAtomicUint16_GetValue(instance);
+
+ assertTrue(actual == 8, "Expected 8, actual %" PRIu16, actual);
+ parcAtomicUint16_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint16_CompareAndSwapImpl)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(7);
+
+ bool actual = parcAtomicUint16_CompareAndSwapImpl(instance, 7, 8);
+
+ assertTrue(actual, "Expected parcAtomicUint16_CompareAndSwapImpl to return true");
+ parcAtomicUint16_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Macros)
+{
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint16_Subtract);
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint16_Add);
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint16_CompareAndSwap);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Macros)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Macros)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint16_Subtract)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(7);
+
+ parcAtomicUint16_Subtract(instance, 1);
+
+ uint16_t actual = parcAtomicUint16_GetValue(instance);
+
+ assertTrue(actual == 6, "Expected 6, actual %" PRIu16, actual);
+ parcAtomicUint16_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint16_Add)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(7);
+
+ parcAtomicUint16_Add(instance, 1);
+
+ uint16_t actual = parcAtomicUint16_GetValue(instance);
+
+ assertTrue(actual == 8, "Expected 8, actual %" PRIu16, actual);
+ parcAtomicUint16_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint16_CompareAndSwap)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(7);
+
+ bool actual = parcAtomicUint16_CompareAndSwap(instance, 7, 8);
+
+ assertTrue(actual, "Expected parcAtomicUint16_CompareAndSwap to return true");
+ parcAtomicUint16_Release(&instance);
+}
+
+
+LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint16_Subtract_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint16_Add_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint16_CompareAndSwap_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint16_SubtractImpl);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint16_AddImpl);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint16_CompareAndSwapImpl);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint16_Subtract_MACRO)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(65535);
+
+ while (parcAtomicUint16_Subtract(instance, 1) > 0) {
+ ;
+ }
+
+ parcAtomicUint16_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint16_Add_MACRO)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(1);
+
+ while (parcAtomicUint16_Add(instance, 1) < 65535) {
+ ;
+ }
+
+ parcAtomicUint16_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint16_CompareAndSwap_MACRO)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(0);
+
+ for (uint16_t i = 0; i < 65535; i++) {
+ bool actual = parcAtomicUint16_CompareAndSwap(instance, i, i + 1);
+ assertTrue(actual, "Expected parcAtomicUint16_CompareAndSwap to return true");
+ }
+
+ parcAtomicUint16_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint16_SubtractImpl)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(65535);
+
+ while (parcAtomicUint16_SubtractImpl(instance, 1) > 0) {
+ ;
+ }
+
+ parcAtomicUint16_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint16_AddImpl)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(1);
+
+ while (parcAtomicUint16_AddImpl(instance, 1) < 65535) {
+ ;
+ }
+
+ parcAtomicUint16_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint16_CompareAndSwapImpl)
+{
+ PARCAtomicUint16 *instance = parcAtomicUint16_Create(0);
+
+ for (uint16_t i = 0; i < 65535; i++) {
+ bool actual = parcAtomicUint16_CompareAndSwapImpl(instance, i, i + 1);
+ assertTrue(actual, "Expected parcAtomicUint16_CompareAndSwapImpl to return true");
+ }
+
+ parcAtomicUint16_Release(&instance);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_AtomicUint16);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/concurrent/test/test_parc_AtomicUint32.c b/libparc/parc/concurrent/test/test_parc_AtomicUint32.c
new file mode 100644
index 00000000..1649cf1c
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_AtomicUint32.c
@@ -0,0 +1,361 @@
+/*
+ * 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_AtomicUint64.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+
+#include <inttypes.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_AtomicUint64)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Macros);
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_AtomicUint64)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_AtomicUint64)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+ assertNotNull(instance, "Expeced non-null result from parcAtomicUint64_Create();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcAtomicUint64_Acquire, instance);
+
+ parcAtomicUint64_Release(&instance);
+ assertNull(instance, "Expected null result from parcAtomicUint64_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_Compare);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_IsValid);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_SubtractImpl);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_AddImpl);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_CompareAndSwapImpl);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_Compare)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+ PARCAtomicUint64 *high = parcAtomicUint64_Create(8);
+ PARCAtomicUint64 *low = parcAtomicUint64_Create(6);
+ PARCAtomicUint64 *equal = parcAtomicUint64_Create(7);
+
+ int actual = parcAtomicUint64_Compare(instance, high);
+ assertTrue(actual < 0, "Expected < 0");
+ actual = parcAtomicUint64_Compare(instance, low);
+ assertTrue(actual > 0, "Expected > 0");
+ actual = parcAtomicUint64_Compare(instance, equal);
+ assertTrue(actual == 0, "Expected == 0");
+
+ parcAtomicUint64_Release(&instance);
+ parcAtomicUint64_Release(&high);
+ parcAtomicUint64_Release(&low);
+ parcAtomicUint64_Release(&equal);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_Copy)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+ PARCAtomicUint64 *copy = parcAtomicUint64_Copy(instance);
+
+ assertTrue(parcAtomicUint64_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcAtomicUint64_Release(&instance);
+ parcAtomicUint64_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_Equals)
+{
+ PARCAtomicUint64 *x = parcAtomicUint64_Create(7);
+ PARCAtomicUint64 *y = parcAtomicUint64_Create(7);
+ PARCAtomicUint64 *z = parcAtomicUint64_Create(7);
+ PARCAtomicUint64 *u1 = parcAtomicUint64_Create(6);
+
+ parcObjectTesting_AssertEquals(x, y, z, u1, NULL);
+
+ parcAtomicUint64_Release(&x);
+ parcAtomicUint64_Release(&y);
+ parcAtomicUint64_Release(&z);
+ parcAtomicUint64_Release(&u1);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_HashCode)
+{
+ PARCAtomicUint64 *x = parcAtomicUint64_Create(7);
+ parcAtomicUint64_HashCode(x);
+ parcAtomicUint64_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_IsValid)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+ assertTrue(parcAtomicUint64_IsValid(instance), "Expected parcAtomicUint64_Create to result in a valid instance.");
+
+ parcAtomicUint64_Release(&instance);
+ assertFalse(parcAtomicUint64_IsValid(instance), "Expected parcAtomicUint64_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_SubtractImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ parcAtomicUint64_SubtractImpl(instance, 1);
+
+ uint64_t actual = parcAtomicUint64_GetValue(instance);
+
+ assertTrue(actual == 6, "Expected 6, actual %" PRIu64, actual);
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_AddImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ parcAtomicUint64_AddImpl(instance, 1);
+
+ uint64_t actual = parcAtomicUint64_GetValue(instance);
+
+ assertTrue(actual == 8, "Expected 8, actual %" PRIu64, actual);
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_CompareAndSwapImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ bool actual = parcAtomicUint64_CompareAndSwapImpl(instance, 7, 8);
+
+ assertTrue(actual, "Expected parcAtomicUint64_CompareAndSwapImpl to return true");
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Macros)
+{
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint64_Subtract);
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint64_Add);
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint64_CompareAndSwap);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Macros)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Macros)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint64_Subtract)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ parcAtomicUint64_Subtract(instance, 1);
+
+ uint64_t actual = parcAtomicUint64_GetValue(instance);
+
+ assertTrue(actual == 6, "Expected 6, actual %" PRIu64, actual);
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint64_Add)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ parcAtomicUint64_Add(instance, 1);
+
+ uint64_t actual = parcAtomicUint64_GetValue(instance);
+
+ assertTrue(actual == 8, "Expected 8, actual %" PRIu64, actual);
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint64_CompareAndSwap)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ bool actual = parcAtomicUint64_CompareAndSwap(instance, 7, 8);
+
+ assertTrue(actual, "Expected parcAtomicUint64_CompareAndSwap to return true");
+ parcAtomicUint64_Release(&instance);
+}
+
+
+LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_Subtract_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_Add_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_CompareAndSwap_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_SubtractImpl);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_AddImpl);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_CompareAndSwapImpl);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_Subtract_MACRO)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(100000000);
+
+ while (parcAtomicUint64_Subtract(instance, 1) > 0) {
+ ;
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_Add_MACRO)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(1);
+
+ while (parcAtomicUint64_Add(instance, 1) < 100000000) {
+ ;
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_CompareAndSwap_MACRO)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(0);
+
+ for (uint64_t i = 0; i < 100000000; i++) {
+ bool actual = parcAtomicUint64_CompareAndSwap(instance, i, i + 1);
+ assertTrue(actual, "Expected parcAtomicUint64_CompareAndSwap to return true");
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_SubtractImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(100000000);
+
+ while (parcAtomicUint64_SubtractImpl(instance, 1) > 0) {
+ ;
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_AddImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(1);
+
+ while (parcAtomicUint64_AddImpl(instance, 1) < 100000000) {
+ ;
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_CompareAndSwapImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(0);
+
+ for (uint64_t i = 0; i < 100000000; i++) {
+ bool actual = parcAtomicUint64_CompareAndSwapImpl(instance, i, i + 1);
+ assertTrue(actual, "Expected parcAtomicUint64_CompareAndSwapImpl to return true");
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_AtomicUint64);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/concurrent/test/test_parc_AtomicUint64.c b/libparc/parc/concurrent/test/test_parc_AtomicUint64.c
new file mode 100644
index 00000000..1649cf1c
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_AtomicUint64.c
@@ -0,0 +1,361 @@
+/*
+ * 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_AtomicUint64.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+
+#include <inttypes.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_AtomicUint64)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Macros);
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_AtomicUint64)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_AtomicUint64)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+ assertNotNull(instance, "Expeced non-null result from parcAtomicUint64_Create();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcAtomicUint64_Acquire, instance);
+
+ parcAtomicUint64_Release(&instance);
+ assertNull(instance, "Expected null result from parcAtomicUint64_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_Compare);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_IsValid);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_SubtractImpl);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_AddImpl);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint64_CompareAndSwapImpl);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_Compare)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+ PARCAtomicUint64 *high = parcAtomicUint64_Create(8);
+ PARCAtomicUint64 *low = parcAtomicUint64_Create(6);
+ PARCAtomicUint64 *equal = parcAtomicUint64_Create(7);
+
+ int actual = parcAtomicUint64_Compare(instance, high);
+ assertTrue(actual < 0, "Expected < 0");
+ actual = parcAtomicUint64_Compare(instance, low);
+ assertTrue(actual > 0, "Expected > 0");
+ actual = parcAtomicUint64_Compare(instance, equal);
+ assertTrue(actual == 0, "Expected == 0");
+
+ parcAtomicUint64_Release(&instance);
+ parcAtomicUint64_Release(&high);
+ parcAtomicUint64_Release(&low);
+ parcAtomicUint64_Release(&equal);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_Copy)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+ PARCAtomicUint64 *copy = parcAtomicUint64_Copy(instance);
+
+ assertTrue(parcAtomicUint64_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcAtomicUint64_Release(&instance);
+ parcAtomicUint64_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_Equals)
+{
+ PARCAtomicUint64 *x = parcAtomicUint64_Create(7);
+ PARCAtomicUint64 *y = parcAtomicUint64_Create(7);
+ PARCAtomicUint64 *z = parcAtomicUint64_Create(7);
+ PARCAtomicUint64 *u1 = parcAtomicUint64_Create(6);
+
+ parcObjectTesting_AssertEquals(x, y, z, u1, NULL);
+
+ parcAtomicUint64_Release(&x);
+ parcAtomicUint64_Release(&y);
+ parcAtomicUint64_Release(&z);
+ parcAtomicUint64_Release(&u1);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_HashCode)
+{
+ PARCAtomicUint64 *x = parcAtomicUint64_Create(7);
+ parcAtomicUint64_HashCode(x);
+ parcAtomicUint64_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_IsValid)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+ assertTrue(parcAtomicUint64_IsValid(instance), "Expected parcAtomicUint64_Create to result in a valid instance.");
+
+ parcAtomicUint64_Release(&instance);
+ assertFalse(parcAtomicUint64_IsValid(instance), "Expected parcAtomicUint64_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_SubtractImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ parcAtomicUint64_SubtractImpl(instance, 1);
+
+ uint64_t actual = parcAtomicUint64_GetValue(instance);
+
+ assertTrue(actual == 6, "Expected 6, actual %" PRIu64, actual);
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_AddImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ parcAtomicUint64_AddImpl(instance, 1);
+
+ uint64_t actual = parcAtomicUint64_GetValue(instance);
+
+ assertTrue(actual == 8, "Expected 8, actual %" PRIu64, actual);
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint64_CompareAndSwapImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ bool actual = parcAtomicUint64_CompareAndSwapImpl(instance, 7, 8);
+
+ assertTrue(actual, "Expected parcAtomicUint64_CompareAndSwapImpl to return true");
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Macros)
+{
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint64_Subtract);
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint64_Add);
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint64_CompareAndSwap);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Macros)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Macros)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint64_Subtract)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ parcAtomicUint64_Subtract(instance, 1);
+
+ uint64_t actual = parcAtomicUint64_GetValue(instance);
+
+ assertTrue(actual == 6, "Expected 6, actual %" PRIu64, actual);
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint64_Add)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ parcAtomicUint64_Add(instance, 1);
+
+ uint64_t actual = parcAtomicUint64_GetValue(instance);
+
+ assertTrue(actual == 8, "Expected 8, actual %" PRIu64, actual);
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint64_CompareAndSwap)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(7);
+
+ bool actual = parcAtomicUint64_CompareAndSwap(instance, 7, 8);
+
+ assertTrue(actual, "Expected parcAtomicUint64_CompareAndSwap to return true");
+ parcAtomicUint64_Release(&instance);
+}
+
+
+LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_Subtract_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_Add_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_CompareAndSwap_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_SubtractImpl);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_AddImpl);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint64_CompareAndSwapImpl);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_Subtract_MACRO)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(100000000);
+
+ while (parcAtomicUint64_Subtract(instance, 1) > 0) {
+ ;
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_Add_MACRO)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(1);
+
+ while (parcAtomicUint64_Add(instance, 1) < 100000000) {
+ ;
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_CompareAndSwap_MACRO)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(0);
+
+ for (uint64_t i = 0; i < 100000000; i++) {
+ bool actual = parcAtomicUint64_CompareAndSwap(instance, i, i + 1);
+ assertTrue(actual, "Expected parcAtomicUint64_CompareAndSwap to return true");
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_SubtractImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(100000000);
+
+ while (parcAtomicUint64_SubtractImpl(instance, 1) > 0) {
+ ;
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_AddImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(1);
+
+ while (parcAtomicUint64_AddImpl(instance, 1) < 100000000) {
+ ;
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint64_CompareAndSwapImpl)
+{
+ PARCAtomicUint64 *instance = parcAtomicUint64_Create(0);
+
+ for (uint64_t i = 0; i < 100000000; i++) {
+ bool actual = parcAtomicUint64_CompareAndSwapImpl(instance, i, i + 1);
+ assertTrue(actual, "Expected parcAtomicUint64_CompareAndSwapImpl to return true");
+ }
+
+ parcAtomicUint64_Release(&instance);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_AtomicUint64);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/concurrent/test/test_parc_AtomicUint8.c b/libparc/parc/concurrent/test/test_parc_AtomicUint8.c
new file mode 100644
index 00000000..5b89d052
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_AtomicUint8.c
@@ -0,0 +1,361 @@
+/*
+ * 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_AtomicUint8.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+
+#include <inttypes.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_AtomicUint8)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Macros);
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_AtomicUint8)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_AtomicUint8)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(7);
+ assertNotNull(instance, "Expeced non-null result from parcAtomicUint8_Create();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcAtomicUint8_Acquire, instance);
+
+ parcAtomicUint8_Release(&instance);
+ assertNull(instance, "Expected null result from parcAtomicUint8_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint8_Compare);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint8_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint8_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint8_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint8_IsValid);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint8_SubtractImpl);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint8_AddImpl);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicUint8_CompareAndSwapImpl);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint8_Compare)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(7);
+ PARCAtomicUint8 *high = parcAtomicUint8_Create(8);
+ PARCAtomicUint8 *low = parcAtomicUint8_Create(6);
+ PARCAtomicUint8 *equal = parcAtomicUint8_Create(7);
+
+ int actual = parcAtomicUint8_Compare(instance, high);
+ assertTrue(actual < 0, "Expected < 0");
+ actual = parcAtomicUint8_Compare(instance, low);
+ assertTrue(actual > 0, "Expected > 0");
+ actual = parcAtomicUint8_Compare(instance, equal);
+ assertTrue(actual == 0, "Expected == 0");
+
+ parcAtomicUint8_Release(&instance);
+ parcAtomicUint8_Release(&high);
+ parcAtomicUint8_Release(&low);
+ parcAtomicUint8_Release(&equal);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint8_Copy)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(7);
+ PARCAtomicUint8 *copy = parcAtomicUint8_Copy(instance);
+
+ assertTrue(parcAtomicUint8_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcAtomicUint8_Release(&instance);
+ parcAtomicUint8_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint8_Equals)
+{
+ PARCAtomicUint8 *x = parcAtomicUint8_Create(7);
+ PARCAtomicUint8 *y = parcAtomicUint8_Create(7);
+ PARCAtomicUint8 *z = parcAtomicUint8_Create(7);
+ PARCAtomicUint8 *u1 = parcAtomicUint8_Create(6);
+
+ parcObjectTesting_AssertEquals(x, y, z, u1, NULL);
+
+ parcAtomicUint8_Release(&x);
+ parcAtomicUint8_Release(&y);
+ parcAtomicUint8_Release(&z);
+ parcAtomicUint8_Release(&u1);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint8_HashCode)
+{
+ PARCAtomicUint8 *x = parcAtomicUint8_Create(7);
+ parcAtomicUint8_HashCode(x);
+ parcAtomicUint8_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint8_IsValid)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(7);
+ assertTrue(parcAtomicUint8_IsValid(instance), "Expected parcAtomicUint8_Create to result in a valid instance.");
+
+ parcAtomicUint8_Release(&instance);
+ assertFalse(parcAtomicUint8_IsValid(instance), "Expected parcAtomicUint8_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint8_SubtractImpl)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(7);
+
+ parcAtomicUint8_SubtractImpl(instance, 1);
+
+ uint8_t actual = parcAtomicUint8_GetValue(instance);
+
+ assertTrue(actual == 6, "Expected 6, actual %" PRIu8, actual);
+ parcAtomicUint8_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint8_AddImpl)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(7);
+
+ parcAtomicUint8_AddImpl(instance, 1);
+
+ uint8_t actual = parcAtomicUint8_GetValue(instance);
+
+ assertTrue(actual == 8, "Expected 8, actual %" PRIu8, actual);
+ parcAtomicUint8_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicUint8_CompareAndSwapImpl)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(7);
+
+ bool actual = parcAtomicUint8_CompareAndSwapImpl(instance, 7, 8);
+
+ assertTrue(actual, "Expected parcAtomicUint8_CompareAndSwapImpl to return true");
+ parcAtomicUint8_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Macros)
+{
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint8_Subtract);
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint8_Add);
+ LONGBOW_RUN_TEST_CASE(Macros, parcAtomicUint8_CompareAndSwap);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Macros)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Macros)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint8_Subtract)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(7);
+
+ parcAtomicUint8_Subtract(instance, 1);
+
+ uint8_t actual = parcAtomicUint8_GetValue(instance);
+
+ assertTrue(actual == 6, "Expected 6, actual %" PRIu8, actual);
+ parcAtomicUint8_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint8_Add)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(7);
+
+ parcAtomicUint8_Add(instance, 1);
+
+ uint8_t actual = parcAtomicUint8_GetValue(instance);
+
+ assertTrue(actual == 8, "Expected 8, actual %" PRIu8, actual);
+ parcAtomicUint8_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Macros, parcAtomicUint8_CompareAndSwap)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(7);
+
+ bool actual = parcAtomicUint8_CompareAndSwap(instance, 7, 8);
+
+ assertTrue(actual, "Expected parcAtomicUint8_CompareAndSwap to return true");
+ parcAtomicUint8_Release(&instance);
+}
+
+
+LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint8_Subtract_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint8_Add_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint8_CompareAndSwap_MACRO);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint8_SubtractImpl);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint8_AddImpl);
+ LONGBOW_RUN_TEST_CASE(Performance, parcAtomicUint8_CompareAndSwapImpl);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint8_Subtract_MACRO)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(255);
+
+ while (parcAtomicUint8_Subtract(instance, 1) > 0) {
+ ;
+ }
+
+ parcAtomicUint8_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint8_Add_MACRO)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(1);
+
+ while (parcAtomicUint8_Add(instance, 1) < 255) {
+ ;
+ }
+
+ parcAtomicUint8_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint8_CompareAndSwap_MACRO)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(0);
+
+ for (uint8_t i = 0; i < 255; i++) {
+ bool actual = parcAtomicUint8_CompareAndSwap(instance, i, i + 1);
+ assertTrue(actual, "Expected parcAtomicUint8_CompareAndSwap to return true");
+ }
+
+ parcAtomicUint8_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint8_SubtractImpl)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(255);
+
+ while (parcAtomicUint8_SubtractImpl(instance, 1) > 0) {
+ ;
+ }
+
+ parcAtomicUint8_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint8_AddImpl)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(1);
+
+ while (parcAtomicUint8_AddImpl(instance, 1) < 255) {
+ ;
+ }
+
+ parcAtomicUint8_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Performance, parcAtomicUint8_CompareAndSwapImpl)
+{
+ PARCAtomicUint8 *instance = parcAtomicUint8_Create(0);
+
+ for (uint8_t i = 0; i < 255; i++) {
+ bool actual = parcAtomicUint8_CompareAndSwapImpl(instance, i, i + 1);
+ assertTrue(actual, "Expected parcAtomicUint8_CompareAndSwapImpl to return true");
+ }
+
+ parcAtomicUint8_Release(&instance);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_AtomicUint8);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/concurrent/test/test_parc_FutureTask.c b/libparc/parc/concurrent/test/test_parc_FutureTask.c
new file mode 100644
index 00000000..c30d2cae
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_FutureTask.c
@@ -0,0 +1,317 @@
+/*
+ * 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_FutureTask.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_DisplayIndented.h>
+
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_FutureTask)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Object);
+ LONGBOW_RUN_TEST_FIXTURE(Specialization);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_FutureTask)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_FutureTask)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease_PARCObject);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ longBowTestCase_SetInt(testCase, "initialAllocations", parcMemory_Outstanding());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ int initialAllocations = longBowTestCase_GetInt(testCase, "initialAllocations");
+
+ if (!parcMemoryTesting_ExpectedOutstanding(initialAllocations, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static void *
+_function(PARCFutureTask *task, void *parameter)
+{
+ return parameter;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCFutureTask *instance = parcFutureTask_Create(_function, _function);
+ assertNotNull(instance, "Expected non-null result from parcFutureTask_Create(_function, _function);");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcFutureTask_Acquire, instance);
+
+ parcFutureTask_Release(&instance);
+ assertNull(instance, "Expected null result from parcFutureTask_Release();");
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease_PARCObject)
+{
+ PARCBuffer *object = parcBuffer_Allocate(10);
+
+ PARCFutureTask *instance = parcFutureTask_Create(_function, object);
+ parcBuffer_Release(&object);
+
+ assertNotNull(instance, "Expected non-null result from parcFutureTask_Create(_function, object);");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcFutureTask_Acquire, instance);
+
+ parcFutureTask_Release(&instance);
+ assertNull(instance, "Expected null result from parcFutureTask_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Object)
+{
+ LONGBOW_RUN_TEST_CASE(Object, parcFutureTask_Compare);
+ LONGBOW_RUN_TEST_CASE(Object, parcFutureTask_Copy);
+ LONGBOW_RUN_TEST_CASE(Object, parcFutureTask_Display);
+ LONGBOW_RUN_TEST_CASE(Object, parcFutureTask_Equals);
+ LONGBOW_RUN_TEST_CASE(Object, parcFutureTask_HashCode);
+ LONGBOW_RUN_TEST_CASE(Object, parcFutureTask_IsValid);
+ LONGBOW_RUN_TEST_CASE(Object, parcFutureTask_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Object, parcFutureTask_ToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Object)
+{
+ longBowTestCase_SetInt(testCase, "initialAllocations", parcMemory_Outstanding());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Object)
+{
+ int initialAllocations = longBowTestCase_GetInt(testCase, "initialAllocations");
+
+ if (!parcMemoryTesting_ExpectedOutstanding(initialAllocations, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Object, parcFutureTask_Compare)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Object, parcFutureTask_Copy)
+{
+ PARCFutureTask *instance = parcFutureTask_Create(_function, _function);
+ PARCFutureTask *copy = parcFutureTask_Copy(instance);
+ assertTrue(parcFutureTask_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcFutureTask_Release(&instance);
+ parcFutureTask_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Object, parcFutureTask_Display)
+{
+ PARCFutureTask *instance = parcFutureTask_Create(_function, _function);
+ parcFutureTask_Display(instance, 0);
+ parcFutureTask_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcFutureTask_Equals)
+{
+ PARCFutureTask *x = parcFutureTask_Create(_function, _function);
+ PARCFutureTask *y = parcFutureTask_Create(_function, _function);
+ PARCFutureTask *z = parcFutureTask_Create(_function, _function);
+ PARCFutureTask *u1 = parcFutureTask_Create(_function, NULL);
+
+ parcObjectTesting_AssertEquals(x, y, z, u1, NULL);
+
+ parcFutureTask_Release(&x);
+ parcFutureTask_Release(&y);
+ parcFutureTask_Release(&z);
+ parcFutureTask_Release(&u1);
+}
+
+LONGBOW_TEST_CASE(Object, parcFutureTask_HashCode)
+{
+ PARCFutureTask *x = parcFutureTask_Create(_function, _function);
+ PARCFutureTask *y = parcFutureTask_Create(_function, _function);
+
+ parcObjectTesting_AssertHashCode(x, y);
+
+ parcFutureTask_Release(&x);
+ parcFutureTask_Release(&y);
+}
+
+LONGBOW_TEST_CASE(Object, parcFutureTask_IsValid)
+{
+ PARCFutureTask *instance = parcFutureTask_Create(_function, _function);
+ assertTrue(parcFutureTask_IsValid(instance), "Expected parcFutureTask_Create to result in a valid instance.");
+
+ parcFutureTask_Release(&instance);
+ assertFalse(parcFutureTask_IsValid(instance), "Expected parcFutureTask_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Object, parcFutureTask_ToJSON)
+{
+ PARCFutureTask *instance = parcFutureTask_Create(_function, _function);
+
+ PARCJSON *json = parcFutureTask_ToJSON(instance);
+
+ parcJSON_Release(&json);
+
+ parcFutureTask_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcFutureTask_ToString)
+{
+ PARCFutureTask *instance = parcFutureTask_Create(_function, _function);
+
+ char *string = parcFutureTask_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcFutureTask_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+ parcFutureTask_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Specialization)
+{
+ LONGBOW_RUN_TEST_CASE(Specialization, parcFutureTask_Cancel);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcFutureTask_Get);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcFutureTask_IsCancelled);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcFutureTask_IsDone);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcFutureTask_Run);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcFutureTask_RunAndReset);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Specialization)
+{
+ longBowTestCase_SetInt(testCase, "initialAllocations", parcMemory_Outstanding());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Specialization)
+{
+ int initialAllocations = longBowTestCase_GetInt(testCase, "initialAllocations");
+
+ if (!parcMemoryTesting_ExpectedOutstanding(initialAllocations, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Specialization, parcFutureTask_Cancel)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ bool parcFutureTask_Cancel(PARCFutureTask *task, bool mayInterruptIfRunning);
+
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcFutureTask_Get)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ PARCFutureTaskResult result = parcFutureTask_Get(task, PARCTimeout_Immediate);
+
+ assertTrue(parcExecution_Is(result.execution, PARCExecution_Timeout), "Expected Timeout, actual %s",
+ parcExecution_GetMessage(result.execution));
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcFutureTask_IsCancelled)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ bool actual = parcFutureTask_IsCancelled(task);
+ assertFalse(actual, "Expected true.");
+
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcFutureTask_IsDone)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ bool actual = parcFutureTask_IsDone(task);
+
+ assertFalse(actual, "Expected false.");
+
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcFutureTask_Run)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ parcFutureTask_Run(task);
+
+ PARCFutureTaskResult actual = parcFutureTask_Get(task, PARCTimeout_Immediate);
+
+ assertTrue(parcFutureTask_IsDone(task), "Expected parcFutureTask_IsDone to be true.");
+ assertTrue(parcExecution_Is(actual.execution, PARCExecution_OK),
+ "Expected OK, actual %s", parcExecution_GetMessage(actual.execution));
+ assertTrue(actual.value == _function, "Expected actual to point to _function");
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcFutureTask_RunAndReset)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ bool actual = parcFutureTask_RunAndReset(task);
+
+ assertTrue(actual, "Expectd parcFutureTask_RunAndReset to return true.");
+ assertFalse(parcFutureTask_IsDone(task), "Expected parcFutureTask_IsDone to be false");
+ parcFutureTask_Release(&task);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_FutureTask);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/concurrent/test/test_parc_Lock.c b/libparc/parc/concurrent/test/test_parc_Lock.c
new file mode 100644
index 00000000..731df04a
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_Lock.c
@@ -0,0 +1,352 @@
+/*
+ * 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_Lock.c"
+
+#include <stdio.h>
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_DisplayIndented.h>
+
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_Lock)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Locking);
+ LONGBOW_RUN_TEST_FIXTURE(WaitNotify);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Lock)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Lock)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCLock *instance = parcLock_Create();
+ assertNotNull(instance, "Expected non-null result from parcLock_Create().");
+
+ parcObjectTesting_AssertAcquire(instance);
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcLock_Acquire, instance);
+
+ parcLock_Release(&instance);
+ assertNull(instance, "Expected null result from parcLock_Release().");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcLock_Display);
+ LONGBOW_RUN_TEST_CASE(Global, parcLock_IsValid);
+ LONGBOW_RUN_TEST_CASE(Global, parcLock_ToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcLock_Display)
+{
+ PARCLock *lock = parcLock_Create();
+ parcLock_Display(lock, 0);
+ parcLock_Release(&lock);
+}
+
+LONGBOW_TEST_CASE(Global, parcLock_IsValid)
+{
+ PARCLock *instance = parcLock_Create();
+ assertTrue(parcLock_IsValid(instance), "Expected parcLock_Create to result in a valid instance.");
+
+ parcLock_Release(&instance);
+ assertFalse(parcLock_IsValid(instance), "Expected parcLock_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Global, parcLock_ToString)
+{
+ PARCLock *instance = parcLock_Create();
+
+ char *string = parcLock_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcLock_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+ parcLock_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Locking)
+{
+ LONGBOW_RUN_TEST_CASE(Locking, parcLock_TryLock_Unlock);
+ LONGBOW_RUN_TEST_CASE(Locking, parcLock_TryLock_AlreadyLocked);
+ LONGBOW_RUN_TEST_CASE(Locking, parcLock_Lock_Unlock);
+ LONGBOW_RUN_TEST_CASE(Locking, parcLock_Lock_AlreadyLocked);
+ LONGBOW_RUN_TEST_CASE(Locking, parcLock_Lock_AlreadyLocked);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Locking)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Locking)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ 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(Locking, parcLock_TryLock_Unlock)
+{
+ PARCLock *lock = parcLock_Create();
+
+ bool actual = parcLock_TryLock(lock);
+
+ assertTrue(actual, "Expected parcObject_TryLock to succeed.");
+
+ actual = parcLock_IsLocked(lock);
+ assertTrue(actual, "Expected parcObject_IsLocked to be true.");
+
+ actual = parcLock_Unlock(lock);
+ assertTrue(actual, "Expected parcObject_Unlock to succeed.");
+
+ actual = parcLock_IsLocked(lock);
+ assertTrue(actual, "Expected parcObject_IsLocked to be false.");
+
+ parcLock_Release((PARCLock **) &lock);
+}
+
+LONGBOW_TEST_CASE(Locking, parcLock_Lock_Unlock)
+{
+ PARCLock *lock = parcLock_Create();
+
+ bool actual = parcLock_Lock(lock);
+
+ assertTrue(actual, "Expected parcObject_Lock to succeed.");
+
+ actual = parcLock_IsLocked(lock);
+ assertTrue(actual, "Expected parcObject_IsLocked to be true.");
+
+ actual = parcLock_Unlock(lock);
+ assertTrue(actual, "Expected parcObject_Unlock to succeed.");
+
+ actual = parcLock_IsLocked(lock);
+ assertTrue(actual, "Expected parcObject_IsLocked to be false.");
+
+ parcLock_Release((PARCLock **) &lock);
+}
+
+LONGBOW_TEST_CASE(Locking, parcLock_TryLock_AlreadyLocked)
+{
+ PARCLock *lock = parcLock_Create();
+
+ bool actual = parcLock_TryLock(lock);
+
+ assertTrue(actual, "Expected parcObject_TryLock to succeed.");
+
+ actual = parcLock_TryLock(lock);
+
+ assertFalse(actual, "Expected parcObject_TryLock to fail when already locked.");
+
+ actual = parcLock_Unlock(lock);
+ assertTrue(actual, "Expected parcObject_Unlock to succeed.");
+
+ parcLock_Release((PARCLock **) &lock);
+}
+
+LONGBOW_TEST_CASE(Locking, parcLock_Lock_AlreadyLocked)
+{
+ PARCLock *lock = parcLock_Create();
+
+ bool actual = parcLock_Lock(lock);
+
+ assertTrue(actual, "Expected parcObject_Lock to succeed.");
+
+ actual = parcLock_Lock(lock);
+
+ assertFalse(actual, "Expected parcObject_Lock to fail when already locked by the same thread.");
+
+ actual = parcLock_Unlock(lock);
+ assertTrue(actual, "Expected parcObject_Unlock to succeed.");
+
+ parcLock_Release((PARCLock **) &lock);
+}
+
+LONGBOW_TEST_FIXTURE(WaitNotify)
+{
+ LONGBOW_RUN_TEST_CASE(WaitNotify, parcLock_WaitNotify);
+ LONGBOW_RUN_TEST_CASE(WaitNotify, parcLock_WaitNotify2);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(WaitNotify)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(WaitNotify)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static int _sharedValue;
+
+static void *
+waiter(void *data)
+{
+ PARCLock *lock = data;
+
+ while (parcLock_TryLock(lock) == false) {
+ ;
+ }
+ parcLock_Wait(lock);
+
+ _sharedValue++;
+ parcLock_Unlock(lock);
+
+ return data;
+}
+
+LONGBOW_TEST_CASE(WaitNotify, parcLock_WaitNotify)
+{
+ PARCLock *lock = parcLock_Create();
+
+ _sharedValue = 0;
+
+ pthread_t thread_A;
+ pthread_t thread_B;
+ pthread_t thread_C;
+ pthread_create(&thread_A, NULL, waiter, lock);
+ pthread_create(&thread_B, NULL, waiter, lock);
+ pthread_create(&thread_C, NULL, waiter, lock);
+
+ while (_sharedValue != 3) {
+ while (parcLock_TryLock(lock) == false) {
+ ;
+ }
+ parcLock_Notify(lock);
+ parcLock_Unlock(lock);
+ }
+
+ pthread_join(thread_A, NULL);
+
+ parcLock_Release((PARCLock **) &lock);
+}
+
+static void *
+decrement(void *data)
+{
+ PARCLock *lock = data;
+
+ while (parcLock_TryLock(lock) == false) {
+ assertTrue(write(1, ".", 1) == 1, "Write failed.");
+ }
+ while (_sharedValue < 12) {
+ parcLock_Wait(lock);
+ _sharedValue--;
+ }
+ parcLock_Unlock(lock);
+
+ return data;
+}
+
+LONGBOW_TEST_CASE(WaitNotify, parcLock_WaitNotify2)
+{
+ PARCLock *lock = parcLock_Create();
+
+ _sharedValue = 0;
+
+ pthread_t thread_A;
+ pthread_create(&thread_A, NULL, decrement, lock);
+
+ _sharedValue = 2;
+ while (parcLock_TryLock(lock) == false) {
+ assertTrue(write(1, ".", 1) == 1, "Write failed.");
+ }
+ while (_sharedValue <= 12) {
+ printf("%d\n", _sharedValue);
+ parcLock_Notify(lock);
+ _sharedValue += 2;
+ }
+ parcLock_Unlock(lock);
+
+ parcLock_Notify(lock);
+ pthread_join(thread_A, NULL);
+
+ parcLock_Release((PARCLock **) &lock);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Lock);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/concurrent/test/test_parc_Notifier.c b/libparc/parc/concurrent/test/test_parc_Notifier.c
new file mode 100755
index 00000000..97ce6615
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_Notifier.c
@@ -0,0 +1,267 @@
+/*
+ * 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_Notifier.c"
+
+#include <sys/time.h>
+#include <pthread.h>
+#include <poll.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(parc_Notifier)
+{
+ // 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(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Notifier)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Notifier)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcNotifier_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, parcNotifier_Create_Release);
+ LONGBOW_RUN_TEST_CASE(Global, parcNotifier_PauseEvent_NotPaused);
+ LONGBOW_RUN_TEST_CASE(Global, parcNotifier_PauseEvent_AlreadyPaused);
+ LONGBOW_RUN_TEST_CASE(Global, parcNotifier_StartEvents);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcNotifier_Notify_First);
+ LONGBOW_RUN_TEST_CASE(Global, parcNotifier_Notify_Twice);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcNotifier_ThreadedTest);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ------
+typedef struct test_data {
+ volatile int barrier;
+ PARCNotifier *notifier;
+
+ unsigned notificationsToSend;
+ unsigned notificationsSent;
+
+ unsigned notificationsToRecieve;
+ unsigned notificationsReceived;
+
+ pthread_t producerThread;
+ pthread_t consumerThread;
+} TestData;
+
+
+void *
+consumer(void *p)
+{
+ TestData *data = (TestData *) p;
+ --data->barrier;
+ while (data->barrier) {
+ ;
+ }
+
+ struct pollfd pfd;
+ pfd.fd = parcNotifier_Socket(data->notifier);
+ pfd.events = POLLIN;
+
+ while (data->notificationsReceived < data->notificationsToRecieve) {
+ if (poll(&pfd, 1, -1)) {
+ data->notificationsReceived++;
+ parcNotifier_PauseEvents(data->notifier);
+ usleep(rand() % 1024 + 1024);
+ printf("skipped = %d\n", data->notifier->skippedNotify);
+ parcNotifier_StartEvents(data->notifier);
+ }
+ }
+
+ --data->barrier;
+
+ printf("Consumer exiting: received %d\n", data->notificationsReceived);
+ pthread_exit((void *) NULL);
+}
+
+void *
+producer(void *p)
+{
+ TestData *data = (TestData *) p;
+ --data->barrier;
+ while (data->barrier) {
+ ;
+ }
+
+ while (data->barrier == 0) {
+ if (parcNotifier_Notify(data->notifier)) {
+ }
+ data->notificationsSent++;
+ usleep(rand() % 1024 + 512);
+ }
+
+ printf("Producer exiting: sent %d\n", data->notificationsSent);
+ pthread_exit((void *) NULL);
+}
+
+LONGBOW_TEST_CASE(Global, parcNotifier_Acquire)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcNotifier_Create_Release)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcNotifier_PauseEvent_NotPaused)
+{
+ PARCNotifier *notifier = parcNotifier_Create();
+
+ parcNotifier_PauseEvents(notifier);
+ assertTrue(notifier->paused == 1, "Not paused, got %d expected %d", notifier->paused, 1);
+ assertTrue(notifier->skippedNotify == 0, "Wrong skipped, got %d expected %d", notifier->skippedNotify, 0);
+
+ parcNotifier_Release(&notifier);
+}
+
+LONGBOW_TEST_CASE(Global, parcNotifier_PauseEvent_AlreadyPaused)
+{
+ PARCNotifier *notifier = parcNotifier_Create();
+
+ parcNotifier_PauseEvents(notifier);
+
+ // now pause again
+ parcNotifier_PauseEvents(notifier);
+
+ assertTrue(notifier->paused == 1, "Not paused, got %d expected %d", notifier->paused, 1);
+ assertTrue(notifier->skippedNotify == 0, "Wrong skipped, got %d expected %d", notifier->skippedNotify, 0);
+
+ parcNotifier_Release(&notifier);
+}
+
+
+LONGBOW_TEST_CASE(Global, parcNotifier_ThreadedTest)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ data->notifier = parcNotifier_Create();
+ data->notificationsToSend = 10;
+ data->notificationsToRecieve = data->notificationsToSend;
+ data->notificationsSent = 0;
+ data->notificationsReceived = 0;
+ data->barrier = 2;
+
+ pthread_create(&data->consumerThread, NULL, consumer, data);
+ pthread_create(&data->producerThread, NULL, producer, data);
+
+ // wait for them to exit
+ pthread_join(data->producerThread, NULL);
+ pthread_join(data->consumerThread, NULL);
+
+ assertTrue(data->notificationsReceived >= data->notificationsToRecieve,
+ "Did not write all items got %u expected %u\n",
+ data->notificationsReceived,
+ data->notificationsToRecieve);
+
+ parcNotifier_Release(&data->notifier);
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_CASE(Global, parcNotifier_StartEvents)
+{
+ testUnimplemented("unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcNotifier_Notify_First)
+{
+ PARCNotifier *notifier = parcNotifier_Create();
+
+ bool success = parcNotifier_Notify(notifier);
+ assertTrue(success, "Did not succeed on first notify");
+ assertTrue(notifier->paused == 1, "Not paused, got %d expected %d", notifier->paused, 1);
+ assertTrue(notifier->skippedNotify == 0, "Wrong skipped, got %d expected %d", notifier->skippedNotify, 0);
+
+ parcNotifier_Release(&notifier);
+}
+
+
+LONGBOW_TEST_CASE(Global, parcNotifier_Notify_Twice)
+{
+ PARCNotifier *notifier = parcNotifier_Create();
+
+ parcNotifier_Notify(notifier);
+
+ bool success = parcNotifier_Notify(notifier);
+ assertFalse(success, "Should have failed on second notify");
+ assertTrue(notifier->paused == 1, "Not paused, got %d expected %d", notifier->paused, 1);
+ assertTrue(notifier->skippedNotify == 1, "Wrong skipped, got %d expected %d", notifier->skippedNotify, 1);
+
+ parcNotifier_Release(&notifier);
+}
+
+// ===============================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Notifier);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/concurrent/test/test_parc_RingBuffer_1x1.c b/libparc/parc/concurrent/test/test_parc_RingBuffer_1x1.c
new file mode 100755
index 00000000..a977dfbc
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_RingBuffer_1x1.c
@@ -0,0 +1,325 @@
+/*
+ * 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_RingBuffer_1x1.c"
+
+#include <sys/time.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(parc_RingBuffer_1x1)
+{
+ // 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(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_RingBuffer_1x1)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_RingBuffer_1x1)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcRingBuffer1x1_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, parcRingBuffer1x1_Create_Release);
+ LONGBOW_RUN_TEST_CASE(Global, parcRingBuffer1x1_Create_NonPower2);
+ LONGBOW_RUN_TEST_CASE(Global, parcRingBuffer1x1_Get_Put);
+ LONGBOW_RUN_TEST_CASE(Global, parcRingBuffer1x1_Remaining_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, parcRingBuffer1x1_Remaining_Half);
+ LONGBOW_RUN_TEST_CASE(Global, parcRingBuffer1x1_Remaining_Full);
+ LONGBOW_RUN_TEST_CASE(Global, parcRingBuffer1x1_Put_ToCapacity);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ------
+typedef struct test_ringbuffer {
+ unsigned itemsToWrite;
+ volatile unsigned itemsWritten;
+ volatile unsigned itemsRead;
+ volatile bool blocked;
+
+ PARCRingBuffer1x1 *producerBuffer;
+ PARCRingBuffer1x1 *consumerBuffer;
+
+ pthread_t producerThread;
+ pthread_t consumerThread;
+} TestRingBuffer;
+
+
+void *
+consumer(void *p)
+{
+ TestRingBuffer *trb = (TestRingBuffer *) p;
+
+ while (trb->blocked) {
+ // nothing to do.
+ }
+
+ while (trb->itemsRead < trb->itemsToWrite) {
+ uint32_t *data;
+ bool success = parcRingBuffer1x1_Get(trb->consumerBuffer, (void **) &data);
+ if (success) {
+ assertTrue(*data == trb->itemsRead, "Got out of order item %u expected %u\n", *data, trb->itemsRead);
+ parcMemory_Deallocate((void **) &data);
+ trb->itemsRead++;
+ }
+ }
+
+ pthread_exit((void *) NULL);
+}
+
+void *
+producer(void *p)
+{
+ TestRingBuffer *trb = (TestRingBuffer *) p;
+
+ while (trb->blocked) {
+ // nothing to do
+ }
+
+ while (trb->itemsWritten < trb->itemsToWrite) {
+ uint32_t *data = parcMemory_Allocate(sizeof(uint32_t));
+ assertNotNull(data, "parcMemory_Allocate(%zu) returned NULL", sizeof(uint32_t));
+ *data = trb->itemsWritten;
+
+ bool success = false;
+ do {
+ success = parcRingBuffer1x1_Put(trb->producerBuffer, data);
+ } while (!success);
+ trb->itemsWritten++;
+ }
+
+ pthread_exit((void *) NULL);
+}
+
+LONGBOW_TEST_CASE(Global, parcRingBuffer1x1_Acquire)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, parcRingBuffer1x1_Create_NonPower2, .event = &LongBowAssertEvent)
+{
+ // this will assert because the number of elements is not a power of 2
+ parcRingBuffer1x1_Create(3, NULL);
+}
+
+LONGBOW_TEST_CASE(Global, parcRingBuffer1x1_Create_Release)
+{
+ PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(1024, NULL);
+ parcRingBuffer1x1_Release(&ring);
+ assertTrue(parcMemory_Outstanding() == 0, "Non-zero memory balance: %u", parcMemory_Outstanding());
+
+ printf("ring buffer entry size: %zu\n", sizeof(PARCRingBuffer1x1));
+}
+
+LONGBOW_TEST_CASE(Global, parcRingBuffer1x1_Get_Put)
+{
+ TestRingBuffer *trb = parcMemory_AllocateAndClear(sizeof(TestRingBuffer));
+ assertNotNull(trb, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestRingBuffer));
+ trb->producerBuffer = parcRingBuffer1x1_Create(128, NULL);
+ trb->consumerBuffer = parcRingBuffer1x1_Acquire(trb->producerBuffer);
+
+ trb->itemsToWrite = 100000;
+ trb->blocked = true;
+
+ pthread_create(&trb->consumerThread, NULL, consumer, trb);
+ pthread_create(&trb->producerThread, NULL, producer, trb);
+
+ struct timeval t0, t1;
+
+ gettimeofday(&t0, NULL);
+ trb->blocked = false;
+
+ // wait for them to exit
+ pthread_join(trb->producerThread, NULL);
+ pthread_join(trb->consumerThread, NULL);
+ gettimeofday(&t1, NULL);
+
+ timersub(&t1, &t0, &t1);
+
+ assertTrue(trb->itemsWritten == trb->itemsToWrite,
+ "Did not write all items got %u expected %u\n",
+ trb->itemsWritten,
+ trb->itemsToWrite);
+
+ assertTrue(trb->itemsRead == trb->itemsToWrite,
+ "Did not read all items got %u expected %u\n",
+ trb->itemsRead,
+ trb->itemsToWrite);
+
+ double sec = t1.tv_sec + t1.tv_usec * 1E-6;
+
+ printf("Passed %u items in %.6f seconds, %.2f items/sec\n",
+ trb->itemsWritten,
+ sec,
+ trb->itemsWritten / sec);
+
+ parcRingBuffer1x1_Release(&trb->consumerBuffer);
+ parcRingBuffer1x1_Release(&trb->producerBuffer);
+ parcMemory_Deallocate((void **) &trb);
+}
+
+LONGBOW_TEST_CASE(Global, parcRingBuffer1x1_Remaining_Empty)
+{
+ uint32_t capacity = 128;
+ PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(capacity, NULL);
+ uint32_t remaining = parcRingBuffer1x1_Remaining(ring);
+ parcRingBuffer1x1_Release(&ring);
+
+ // -1 because the ring buffer is always -1
+ assertTrue(remaining == capacity - 1, "Got wrong remaining, got %u expecting %u\n", remaining, capacity);
+}
+
+LONGBOW_TEST_CASE(Global, parcRingBuffer1x1_Remaining_Half)
+{
+ uint32_t capacity = 128;
+ PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(capacity, NULL);
+ for (int i = 0; i < capacity / 2; i++) {
+ parcRingBuffer1x1_Put(ring, &i);
+ }
+
+ uint32_t remaining = parcRingBuffer1x1_Remaining(ring);
+ parcRingBuffer1x1_Release(&ring);
+
+ // -1 because the ring buffer is always -1
+ assertTrue(remaining == capacity / 2 - 1, "Got wrong remaining, got %u expecting %u\n", remaining, capacity / 2 - 1);
+}
+
+LONGBOW_TEST_CASE(Global, parcRingBuffer1x1_Remaining_Full)
+{
+ uint32_t capacity = 128;
+ PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(capacity, NULL);
+ for (int i = 0; i < capacity - 1; i++) {
+ parcRingBuffer1x1_Put(ring, &i);
+ }
+
+ uint32_t remaining = parcRingBuffer1x1_Remaining(ring);
+ parcRingBuffer1x1_Release(&ring);
+
+ assertTrue(remaining == 0, "Got wrong remaining, got %u expecting %u\n", remaining, 0);
+}
+
+LONGBOW_TEST_CASE(Global, parcRingBuffer1x1_Put_ToCapacity)
+{
+ uint32_t capacity = 128;
+ PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(capacity, NULL);
+ for (int i = 0; i < capacity - 1; i++) {
+ parcRingBuffer1x1_Put(ring, &i);
+ }
+
+ // this next put should fail
+ bool success = parcRingBuffer1x1_Put(ring, &capacity);
+
+ parcRingBuffer1x1_Release(&ring);
+
+ assertFalse(success, "Should have failed on final put because data structure is full\n");
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _create);
+ LONGBOW_RUN_TEST_CASE(Local, _destroy);
+ LONGBOW_RUN_TEST_CASE(Local, _isPowerOfTwo);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Local, _create)
+{
+ testUnimplemented("");
+}
+
+static void
+_testDestoryer(void **ptr)
+{
+ parcBuffer_Release((PARCBuffer **) ptr);
+}
+
+LONGBOW_TEST_CASE(Local, _destroy)
+{
+ // put something in the ring and don't remove it. Make sure the destroyer catches it.
+
+ uint32_t capacity = 128;
+ PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(capacity, _testDestoryer);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(5);
+ parcRingBuffer1x1_Put(ring, buffer);
+
+ parcRingBuffer1x1_Release(&ring);
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance, expected 0 got %u", parcMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Local, _isPowerOfTwo)
+{
+ struct test_struct {
+ uint32_t value;
+ bool isPow2;
+ } test_vector[] = { { 0, false }, { 1, true }, { 2, true }, { 15, false }, { 16, true }, { 32, true }, { UINT32_MAX, true } };
+
+ for (int i = 0; test_vector[i].value != UINT32_MAX; i++) {
+ bool test = _isPowerOfTwo(test_vector[i].value);
+ assertTrue(test == test_vector[i].isPow2, "Got wrong result for value %u, got %d expected %d\n", test_vector[i].value, test, test_vector[i].isPow2);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_RingBuffer_1x1);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/concurrent/test/test_parc_RingBuffer_NxM.c b/libparc/parc/concurrent/test/test_parc_RingBuffer_NxM.c
new file mode 100755
index 00000000..974da053
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_RingBuffer_NxM.c
@@ -0,0 +1,106 @@
+/*
+ * 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_RingBuffer_NxM.c"
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(parc_RingBuffer_NxM)
+{
+ // 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(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_RingBuffer_NxM)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_RingBuffer_NxM)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Tests leak memory by %d allocations\n", outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _destroy);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static void
+_testDestoryer(void **ptr)
+{
+ parcBuffer_Release((PARCBuffer **) ptr);
+}
+
+LONGBOW_TEST_CASE(Local, _destroy)
+{
+ // put something in the ring and don't remove it. Make sure the destroyer catches it.
+
+ uint32_t capacity = 128;
+ PARCRingBufferNxM *ring = parcRingBufferNxM_Create(capacity, _testDestoryer);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(5);
+ parcRingBufferNxM_Put(ring, buffer);
+
+ parcRingBufferNxM_Release(&ring);
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance, expected 0 got %u", parcMemory_Outstanding());
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_RingBuffer_NxM);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/concurrent/test/test_parc_ScheduledTask.c b/libparc/parc/concurrent/test/test_parc_ScheduledTask.c
new file mode 100644
index 00000000..3655be93
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_ScheduledTask.c
@@ -0,0 +1,244 @@
+/*
+ * 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_ScheduledTask.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_DisplayIndented.h>
+
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_ScheduledTask)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Object);
+ LONGBOW_RUN_TEST_FIXTURE(Specialization);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_ScheduledTask)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_ScheduledTask)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+void *
+_function(PARCFutureTask *task, void *parameter)
+{
+ return parameter;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ PARCScheduledTask *instance = parcScheduledTask_Create(task, 0);
+ assertNotNull(instance, "Expected non-null result from parcScheduledTask_Create();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcScheduledTask_Acquire, instance);
+
+ parcScheduledTask_Release(&instance);
+ assertNull(instance, "Expected null result from parcScheduledTask_Release();");
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_FIXTURE(Object)
+{
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledTask_Compare);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledTask_Copy);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledTask_Display);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledTask_Equals);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledTask_HashCode);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledTask_IsValid);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledTask_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledTask_ToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Object)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Object)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledTask_Compare)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledTask_Copy)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ PARCScheduledTask *instance = parcScheduledTask_Create(task, 0);
+ PARCScheduledTask *copy = parcScheduledTask_Copy(instance);
+ assertTrue(parcScheduledTask_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcScheduledTask_Release(&instance);
+ parcScheduledTask_Release(&copy);
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledTask_Display)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ PARCScheduledTask *instance = parcScheduledTask_Create(task, 0);
+ parcScheduledTask_Display(instance, 0);
+ parcScheduledTask_Release(&instance);
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledTask_Equals)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ PARCScheduledTask *x = parcScheduledTask_Create(task, 0);
+ PARCScheduledTask *y = parcScheduledTask_Create(task, 0);
+ PARCScheduledTask *z = parcScheduledTask_Create(task, 0);
+
+ parcObjectTesting_AssertEquals(x, y, z, NULL);
+
+ parcScheduledTask_Release(&x);
+ parcScheduledTask_Release(&y);
+ parcScheduledTask_Release(&z);
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledTask_HashCode)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ PARCScheduledTask *x = parcScheduledTask_Create(task, 0);
+ PARCScheduledTask *y = parcScheduledTask_Create(task, 0);
+
+ parcObjectTesting_AssertHashCode(x, y);
+
+ parcScheduledTask_Release(&x);
+ parcScheduledTask_Release(&y);
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledTask_IsValid)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ PARCScheduledTask *instance = parcScheduledTask_Create(task, 0);
+ assertTrue(parcScheduledTask_IsValid(instance), "Expected parcScheduledTask_Create to result in a valid instance.");
+
+ parcScheduledTask_Release(&instance);
+ assertFalse(parcScheduledTask_IsValid(instance), "Expected parcScheduledTask_Release to result in an invalid instance.");
+
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledTask_ToJSON)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ PARCScheduledTask *instance = parcScheduledTask_Create(task, 0);
+
+ PARCJSON *json = parcScheduledTask_ToJSON(instance);
+
+ parcJSON_Release(&json);
+
+ parcScheduledTask_Release(&instance);
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledTask_ToString)
+{
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ PARCScheduledTask *instance = parcScheduledTask_Create(task, 0);
+
+ char *string = parcScheduledTask_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcScheduledTask_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+ parcScheduledTask_Release(&instance);
+ parcFutureTask_Release(&task);
+}
+
+LONGBOW_TEST_FIXTURE(Specialization)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Specialization)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Specialization)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_ScheduledTask);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
+
+
diff --git a/libparc/parc/concurrent/test/test_parc_ScheduledThreadPool.c b/libparc/parc/concurrent/test/test_parc_ScheduledThreadPool.c
new file mode 100644
index 00000000..f466d72a
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_ScheduledThreadPool.c
@@ -0,0 +1,301 @@
+/*
+ * 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_ScheduledThreadPool.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_DisplayIndented.h>
+
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_ScheduledThreadPool)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Object);
+ LONGBOW_RUN_TEST_FIXTURE(Specialization);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_ScheduledThreadPool)
+{
+ 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_ScheduledThreadPool)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ longBowTestCase_SetInt(testCase, "initalAllocations", parcMemory_Outstanding());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ int initialAllocations = longBowTestCase_GetInt(testCase, "initalAllocations");
+ if (!parcMemoryTesting_ExpectedOutstanding(initialAllocations, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCScheduledThreadPool *instance = parcScheduledThreadPool_Create(3);
+ assertNotNull(instance, "Expected non-null result from parcScheduledThreadPool_Create();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcScheduledThreadPool_Acquire, instance);
+ parcScheduledThreadPool_ShutdownNow(instance);
+
+ assertTrue(parcObject_GetReferenceCount(instance) == 1, "Expected 1 reference count. Actual %llu", parcObject_GetReferenceCount(instance));
+
+ parcScheduledThreadPool_Release(&instance);
+ assertNull(instance, "Expected null result from parcScheduledThreadPool_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Object)
+{
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledThreadPool_Compare);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledThreadPool_Copy);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledThreadPool_Display);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledThreadPool_Equals);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledThreadPool_HashCode);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledThreadPool_IsValid);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledThreadPool_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Object, parcScheduledThreadPool_ToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Object)
+{
+ longBowTestCase_SetInt(testCase, "initalAllocations", parcMemory_Outstanding());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Object)
+{
+ int initialAllocations = longBowTestCase_GetInt(testCase, "initalAllocations");
+ if (!parcMemoryTesting_ExpectedOutstanding(initialAllocations, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledThreadPool_Compare)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledThreadPool_Copy)
+{
+ PARCScheduledThreadPool *instance = parcScheduledThreadPool_Create(3);
+ PARCScheduledThreadPool *copy = parcScheduledThreadPool_Copy(instance);
+ assertTrue(parcScheduledThreadPool_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcScheduledThreadPool_ShutdownNow(instance);
+ parcScheduledThreadPool_ShutdownNow(copy);
+
+ parcScheduledThreadPool_Release(&instance);
+ parcScheduledThreadPool_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledThreadPool_Display)
+{
+ PARCScheduledThreadPool *instance = parcScheduledThreadPool_Create(2);
+ parcScheduledThreadPool_Display(instance, 0);
+ parcScheduledThreadPool_ShutdownNow(instance);
+ parcScheduledThreadPool_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledThreadPool_Equals)
+{
+ PARCScheduledThreadPool *x = parcScheduledThreadPool_Create(2);
+ PARCScheduledThreadPool *y = parcScheduledThreadPool_Create(2);
+ PARCScheduledThreadPool *z = parcScheduledThreadPool_Create(2);
+ PARCScheduledThreadPool *u1 = parcScheduledThreadPool_Create(3);
+
+ parcObjectTesting_AssertEquals(x, y, z, u1, NULL);
+
+ parcScheduledThreadPool_ShutdownNow(x);
+ parcScheduledThreadPool_ShutdownNow(y);
+ parcScheduledThreadPool_ShutdownNow(z);
+ parcScheduledThreadPool_ShutdownNow(u1);
+
+ parcScheduledThreadPool_Release(&x);
+ parcScheduledThreadPool_Release(&y);
+ parcScheduledThreadPool_Release(&z);
+ parcScheduledThreadPool_Release(&u1);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledThreadPool_HashCode)
+{
+ PARCScheduledThreadPool *x = parcScheduledThreadPool_Create(2);
+ PARCScheduledThreadPool *y = parcScheduledThreadPool_Create(2);
+
+ parcObjectTesting_AssertHashCode(x, y);
+
+ parcScheduledThreadPool_ShutdownNow(x);
+ parcScheduledThreadPool_ShutdownNow(y);
+
+ parcScheduledThreadPool_Release(&x);
+ parcScheduledThreadPool_Release(&y);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledThreadPool_IsValid)
+{
+ PARCScheduledThreadPool *instance = parcScheduledThreadPool_Create(2);
+ assertTrue(parcScheduledThreadPool_IsValid(instance), "Expected parcScheduledThreadPool_Create to result in a valid instance.");
+
+ parcScheduledThreadPool_ShutdownNow(instance);
+
+ parcScheduledThreadPool_Release(&instance);
+ assertFalse(parcScheduledThreadPool_IsValid(instance), "Expected parcScheduledThreadPool_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledThreadPool_ToJSON)
+{
+ PARCScheduledThreadPool *instance = parcScheduledThreadPool_Create(2);
+
+ PARCJSON *json = parcScheduledThreadPool_ToJSON(instance);
+
+ parcJSON_Release(&json);
+
+ parcScheduledThreadPool_ShutdownNow(instance);
+ parcScheduledThreadPool_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcScheduledThreadPool_ToString)
+{
+ PARCScheduledThreadPool *instance = parcScheduledThreadPool_Create(2);
+
+ char *string = parcScheduledThreadPool_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcScheduledThreadPool_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+ parcScheduledThreadPool_ShutdownNow(instance);
+ parcScheduledThreadPool_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Specialization)
+{
+ LONGBOW_RUN_TEST_CASE(Specialization, OneJob);
+ LONGBOW_RUN_TEST_CASE(Specialization, Idle);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcScheduledThreadPool_Schedule);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Specialization)
+{
+ longBowTestCase_SetInt(testCase, "initalAllocations", parcMemory_Outstanding());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Specialization)
+{
+ int initialAllocations = longBowTestCase_GetInt(testCase, "initalAllocations");
+ if (!parcMemoryTesting_ExpectedOutstanding(initialAllocations, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Specialization, Idle)
+{
+ PARCScheduledThreadPool *pool = parcScheduledThreadPool_Create(3);
+
+ sleep(2);
+
+ parcScheduledThreadPool_ShutdownNow(pool);
+
+ parcScheduledThreadPool_Release(&pool);
+}
+
+static void *
+_function(PARCFutureTask *task, void *parameter)
+{
+ printf("Hello World\n");
+ return parameter;
+}
+
+LONGBOW_TEST_CASE(Specialization, OneJob)
+{
+ PARCScheduledThreadPool *pool = parcScheduledThreadPool_Create(3);
+
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ parcScheduledThreadPool_Schedule(pool, task, parcTimeout_MilliSeconds(2000));
+ printf("references %lld\n", parcObject_GetReferenceCount(task));
+ parcFutureTask_Release(&task);
+
+ sleep(5);
+
+ parcScheduledThreadPool_ShutdownNow(pool);
+
+ parcScheduledThreadPool_Release(&pool);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcScheduledThreadPool_Schedule)
+{
+ PARCScheduledThreadPool *pool = parcScheduledThreadPool_Create(3);
+
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+
+ parcScheduledThreadPool_Schedule(pool, task, parcTimeout_MilliSeconds(2000));
+
+ parcFutureTask_Release(&task);
+
+ parcScheduledThreadPool_Shutdown(pool);
+// parcScheduledThreadPool_AwaitTermination(pool, PARCTimeout_Never);
+
+// uint64_t count = parcScheduledThreadPool_GetCompletedTaskCount(pool);
+// assertTrue(count == 5, "Expected 5, actual %lld", count);
+
+ parcScheduledThreadPool_ShutdownNow(pool);
+
+ parcScheduledThreadPool_Release(&pool);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_ScheduledThreadPool);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/concurrent/test/test_parc_Synchronizer.c b/libparc/parc/concurrent/test/test_parc_Synchronizer.c
new file mode 100755
index 00000000..34d9c711
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_Synchronizer.c
@@ -0,0 +1,179 @@
+/*
+ * 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_Synchronizer.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_Synchronizer)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Synchronizer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Synchronizer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCSynchronizer *instance = parcSynchronizer_Create();
+ assertNotNull(instance, "Expeced non-null result from parcSynchronizer_Create();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcSynchronizer_Acquire, instance);
+
+ parcSynchronizer_Release(&instance);
+ assertNull(instance, "Expeced null result from parcSynchronizer_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcSynchronizer_Display);
+ LONGBOW_RUN_TEST_CASE(Global, parcSynchronizer_IsValid);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcSynchronizer_TryLock);
+ LONGBOW_RUN_TEST_CASE(Global, parcSynchronizer_LockUnlock);
+ LONGBOW_RUN_TEST_CASE(Global, parcSynchronizer_TryLock_Fail);
+ LONGBOW_RUN_TEST_CASE(Global, parcSynchronizer_IsLocked);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcSynchronizer_Display)
+{
+ PARCSynchronizer *instance = parcSynchronizer_Create();
+ assertTrue(parcSynchronizer_IsValid(instance), "Expected parcSynchronizer_Create to result in a valid instance.");
+
+ parcSynchronizer_Display(instance, 0);
+ parcSynchronizer_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcSynchronizer_IsValid)
+{
+ PARCSynchronizer *instance = parcSynchronizer_Create();
+ assertTrue(parcSynchronizer_IsValid(instance), "Expected parcSynchronizer_Create to result in a valid instance.");
+
+ parcSynchronizer_Release(&instance);
+ assertFalse(parcSynchronizer_IsValid(instance), "Expected parcSynchronizer_Create to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Global, parcSynchronizer_TryLock)
+{
+ PARCSynchronizer *instance = parcSynchronizer_Create();
+
+ bool actual = parcSynchronizer_TryLock(instance);
+ assertTrue(actual, "Expected parcSynchronizer_TryLock to be successful.");
+
+ parcSynchronizer_Unlock(instance);
+ parcSynchronizer_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcSynchronizer_TryLock_Fail)
+{
+ PARCSynchronizer *instance = parcSynchronizer_Create();
+
+ parcSynchronizer_Lock(instance);
+ bool actual = parcSynchronizer_TryLock(instance);
+ assertFalse(actual, "Expected parcSynchronizer_TryLock to be unsuccessful.");
+
+ parcSynchronizer_Unlock(instance);
+ parcSynchronizer_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcSynchronizer_LockUnlock)
+{
+ PARCSynchronizer *instance = parcSynchronizer_Create();
+
+ parcSynchronizer_Lock(instance);
+ parcSynchronizer_Unlock(instance);
+
+ parcSynchronizer_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcSynchronizer_IsLocked)
+{
+ PARCSynchronizer *instance = parcSynchronizer_Create();
+ assertFalse(parcSynchronizer_IsLocked(instance), "Expected the synchronizer to be unlocked.");
+
+ parcSynchronizer_Lock(instance);
+ assertTrue(parcSynchronizer_IsLocked(instance), "Expected the synchronizer to be unlocked.");
+
+ parcSynchronizer_Unlock(instance);
+ assertFalse(parcSynchronizer_IsLocked(instance), "Expected the synchronizer to be unlocked.");
+
+ parcSynchronizer_Release(&instance);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Synchronizer);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
+
+
diff --git a/libparc/parc/concurrent/test/test_parc_Thread.c b/libparc/parc/concurrent/test/test_parc_Thread.c
new file mode 100644
index 00000000..22ca31bf
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_Thread.c
@@ -0,0 +1,264 @@
+/*
+ * 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_ThreadPool.c"
+
+#include <stdio.h>
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_DisplayIndented.h>
+
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_Thread)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Object);
+ LONGBOW_RUN_TEST_FIXTURE(Specialization);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Thread)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Thread)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ longBowTestCase_SetInt(testCase, "initialAllocations", parcMemory_Outstanding());
+
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ longBowTestCase_Set(testCase, "object", buffer);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ PARCBuffer *buffer = longBowTestCase_Get(testCase, "object");
+ parcBuffer_Release(&buffer);
+
+ uint32_t initialAllocations = (uint32_t) longBowTestCase_Get(testCase, "initialAllocations");
+ if (!parcMemoryTesting_ExpectedOutstanding(initialAllocations, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static void *
+_function(PARCThread *thread, void *parameter)
+{
+ return NULL;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCBuffer *buffer = longBowTestCase_Get(testCase, "object");
+ PARCThread *thread = parcThread_Create(_function, buffer);
+
+ assertNotNull(thread, "Expected non-null result from parcThread_Create();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcThread_Acquire, thread);
+
+ parcThread_Release(&thread);
+ assertNull(thread, "Expected null result from parcThread_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Object)
+{
+ LONGBOW_RUN_TEST_CASE(Object, parcThread_Compare);
+ LONGBOW_RUN_TEST_CASE(Object, parcThread_Copy);
+ LONGBOW_RUN_TEST_CASE(Object, parcThread_Display);
+ LONGBOW_RUN_TEST_CASE(Object, parcThread_Equals);
+ LONGBOW_RUN_TEST_CASE(Object, parcThread_HashCode);
+ LONGBOW_RUN_TEST_CASE(Object, parcThread_IsValid);
+ LONGBOW_RUN_TEST_CASE(Object, parcThread_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Object, parcThread_ToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Object)
+{
+ longBowTestCase_SetInt(testCase, "initialAllocations", parcMemory_Outstanding());
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ longBowTestCase_Set(testCase, "object", buffer);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Object)
+{
+ PARCBuffer *buffer = longBowTestCase_Get(testCase, "object");
+ parcBuffer_Release(&buffer);
+
+ uint32_t initialAllocations = (uint32_t) longBowTestCase_Get(testCase, "initialAllocations");
+ if (!parcMemoryTesting_ExpectedOutstanding(initialAllocations, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Object, parcThread_Compare)
+{
+// testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Object, parcThread_Copy)
+{
+ PARCBuffer *buffer = longBowTestCase_Get(testCase, "object");
+ PARCThread *instance = parcThread_Create(_function, buffer);
+ PARCThread *copy = parcThread_Copy(instance);
+
+ assertTrue(parcThread_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcThread_Release(&instance);
+ parcThread_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Object, parcThread_Display)
+{
+ PARCBuffer *buffer = longBowTestCase_Get(testCase, "object");
+ PARCThread *instance = parcThread_Create(_function, buffer);
+ parcThread_Display(instance, 0);
+
+
+ parcThread_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcThread_Equals)
+{
+ PARCBuffer *buffer = longBowTestCase_Get(testCase, "object");
+ PARCThread *x = parcThread_Create(_function, buffer);
+ PARCThread *y = parcThread_Create(_function, buffer);
+ PARCThread *z = parcThread_Create(_function, buffer);
+
+ parcObjectTesting_AssertEquals(x, y, z, NULL);
+
+ parcThread_Release(&x);
+ parcThread_Release(&y);
+ parcThread_Release(&z);
+}
+
+LONGBOW_TEST_CASE(Object, parcThread_HashCode)
+{
+ PARCBuffer *buffer = longBowTestCase_Get(testCase, "object");
+ PARCThread *x = parcThread_Create(_function, buffer);
+ PARCThread *y = parcThread_Create(_function, buffer);
+
+ parcObjectTesting_AssertHashCode(x, y);
+
+ parcThread_Release(&x);
+ parcThread_Release(&y);
+}
+
+LONGBOW_TEST_CASE(Object, parcThread_IsValid)
+{
+ PARCBuffer *buffer = longBowTestCase_Get(testCase, "object");
+ PARCThread *instance = parcThread_Create(_function, buffer);
+ assertTrue(parcThread_IsValid(instance), "Expected parcThread_Create to result in a valid instance.");
+
+
+ parcThread_Release(&instance);
+ assertFalse(parcThread_IsValid(instance), "Expected parcThread_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Object, parcThread_ToJSON)
+{
+ PARCBuffer *buffer = longBowTestCase_Get(testCase, "object");
+ PARCThread *instance = parcThread_Create(_function, buffer);
+
+ PARCJSON *json = parcThread_ToJSON(instance);
+
+ parcJSON_Release(&json);
+
+
+ parcThread_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcThread_ToString)
+{
+ PARCBuffer *buffer = longBowTestCase_Get(testCase, "object");
+ PARCThread *instance = parcThread_Create(_function, buffer);
+
+ char *string = parcThread_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcThread_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+
+ parcThread_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Specialization)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ LONGBOW_RUN_TEST_CASE(Object, parcThread_Execute);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Specialization)
+{
+ longBowTestCase_SetInt(testCase, "initialAllocations", parcMemory_Outstanding());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Specialization)
+{
+ uint32_t initialAllocations = (uint32_t) longBowTestCase_Get(testCase, "initialAllocations");
+ if (!parcMemoryTesting_ExpectedOutstanding(initialAllocations, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Object, parcThread_Execute)
+{
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Thread);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
+
+
diff --git a/libparc/parc/concurrent/test/test_parc_ThreadPool.c b/libparc/parc/concurrent/test/test_parc_ThreadPool.c
new file mode 100644
index 00000000..6ed6e4d3
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_ThreadPool.c
@@ -0,0 +1,273 @@
+/*
+ * 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_ThreadPool.c"
+
+#include <stdio.h>
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_DisplayIndented.h>
+
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_ThreadPool)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Object);
+ LONGBOW_RUN_TEST_FIXTURE(Specialization);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_ThreadPool)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_ThreadPool)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCThreadPool *pool = parcThreadPool_Create(6);
+ assertNotNull(pool, "Expected non-null result from parcThreadPool_Create();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcThreadPool_Acquire, pool);
+
+ parcThreadPool_ShutdownNow(pool);
+
+ parcThreadPool_Release(&pool);
+ assertNull(pool, "Expected null result from parcThreadPool_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Object)
+{
+ LONGBOW_RUN_TEST_CASE(Object, parcThreadPool_Compare);
+ LONGBOW_RUN_TEST_CASE(Object, parcThreadPool_Copy);
+ LONGBOW_RUN_TEST_CASE(Object, parcThreadPool_Display);
+ LONGBOW_RUN_TEST_CASE(Object, parcThreadPool_Equals);
+ LONGBOW_RUN_TEST_CASE(Object, parcThreadPool_HashCode);
+ LONGBOW_RUN_TEST_CASE(Object, parcThreadPool_IsValid);
+ LONGBOW_RUN_TEST_CASE(Object, parcThreadPool_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Object, parcThreadPool_ToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Object)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Object)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Object, parcThreadPool_Compare)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Object, parcThreadPool_Copy)
+{
+ PARCThreadPool *instance = parcThreadPool_Create(6);
+ PARCThreadPool *copy = parcThreadPool_Copy(instance);
+ assertTrue(parcThreadPool_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcThreadPool_ShutdownNow(instance);
+ parcThreadPool_ShutdownNow(copy);
+
+ parcThreadPool_Release(&instance);
+ parcThreadPool_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Object, parcThreadPool_Display)
+{
+ PARCThreadPool *instance = parcThreadPool_Create(6);
+ parcThreadPool_Display(instance, 0);
+
+ parcThreadPool_ShutdownNow(instance);
+
+ parcThreadPool_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcThreadPool_Equals)
+{
+ PARCThreadPool *x = parcThreadPool_Create(6);
+ PARCThreadPool *y = parcThreadPool_Create(6);
+ PARCThreadPool *z = parcThreadPool_Create(6);
+
+ parcObjectTesting_AssertEquals(x, y, z, NULL);
+
+ parcThreadPool_ShutdownNow(x);
+ parcThreadPool_ShutdownNow(y);
+ parcThreadPool_ShutdownNow(z);
+
+ parcThreadPool_Release(&x);
+ parcThreadPool_Release(&y);
+ parcThreadPool_Release(&z);
+}
+
+LONGBOW_TEST_CASE(Object, parcThreadPool_HashCode)
+{
+ PARCThreadPool *x = parcThreadPool_Create(6);
+ PARCThreadPool *y = parcThreadPool_Create(6);
+
+ parcObjectTesting_AssertHashCode(x, y);
+
+ parcThreadPool_ShutdownNow(x);
+ parcThreadPool_ShutdownNow(y);
+
+ parcThreadPool_Release(&x);
+ parcThreadPool_Release(&y);
+}
+
+LONGBOW_TEST_CASE(Object, parcThreadPool_IsValid)
+{
+ PARCThreadPool *instance = parcThreadPool_Create(6);
+ assertTrue(parcThreadPool_IsValid(instance), "Expected parcThreadPool_Create to result in a valid instance.");
+
+ parcThreadPool_ShutdownNow(instance);
+
+ parcThreadPool_Release(&instance);
+ assertFalse(parcThreadPool_IsValid(instance), "Expected parcThreadPool_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Object, parcThreadPool_ToJSON)
+{
+ PARCThreadPool *instance = parcThreadPool_Create(6);
+
+ PARCJSON *json = parcThreadPool_ToJSON(instance);
+
+ parcJSON_Release(&json);
+
+ parcThreadPool_ShutdownNow(instance);
+
+ parcThreadPool_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcThreadPool_ToString)
+{
+ PARCThreadPool *instance = parcThreadPool_Create(6);
+
+ char *string = parcThreadPool_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcThreadPool_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+
+ parcThreadPool_ShutdownNow(instance);
+
+ parcThreadPool_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Specialization)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ LONGBOW_RUN_TEST_CASE(Object, parcThreadPool_Execute);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Specialization)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Specialization)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+void *
+_function(PARCFutureTask *task, void *parameter)
+{
+ printf("Hello World\n");
+ return parameter;
+}
+
+LONGBOW_TEST_CASE(Object, parcThreadPool_Execute)
+{
+ dprintf(1, "-----\n");
+ PARCThreadPool *pool = parcThreadPool_Create(6);
+
+ PARCFutureTask *task = parcFutureTask_Create(_function, _function);
+ parcThreadPool_Execute(pool, task);
+ parcThreadPool_Execute(pool, task);
+ parcThreadPool_Execute(pool, task);
+ parcThreadPool_Execute(pool, task);
+ parcThreadPool_Execute(pool, task);
+ parcFutureTask_Release(&task);
+
+ parcThreadPool_Shutdown(pool);
+ bool shutdownSuccess = parcThreadPool_AwaitTermination(pool, PARCTimeout_Never);
+
+ assertTrue(shutdownSuccess, "parcThreadPool_AwaitTermination timed-out");
+
+ uint64_t count = parcThreadPool_GetCompletedTaskCount(pool);
+ assertTrue(count == 5, "Expected 5, actual %lld", count);
+
+
+ parcThreadPool_Release(&pool);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_ThreadPool);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
+
+
diff --git a/libparc/parc/concurrent/test/test_parc_Timer.c b/libparc/parc/concurrent/test/test_parc_Timer.c
new file mode 100644
index 00000000..5bc7ae6c
--- /dev/null
+++ b/libparc/parc/concurrent/test/test_parc_Timer.c
@@ -0,0 +1,213 @@
+/*
+ * 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_Timer.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_DisplayIndented.h>
+
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_Timer)
+{
+ // 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(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Object);
+ LONGBOW_RUN_TEST_FIXTURE(Specialization);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Timer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Timer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease)
+{
+ PARCTimer *instance = parcTimer_Create();
+ assertNotNull(instance, "Expected non-null result from parcTimer_Create();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcTimer_Acquire, instance);
+
+ parcTimer_Release(&instance);
+ assertNull(instance, "Expected null result from parcTimer_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Object)
+{
+ LONGBOW_RUN_TEST_CASE(Object, parcTimer_Compare);
+ LONGBOW_RUN_TEST_CASE(Object, parcTimer_Copy);
+ LONGBOW_RUN_TEST_CASE(Object, parcTimer_Display);
+ LONGBOW_RUN_TEST_CASE(Object, parcTimer_Equals);
+ LONGBOW_RUN_TEST_CASE(Object, parcTimer_HashCode);
+ LONGBOW_RUN_TEST_CASE(Object, parcTimer_IsValid);
+ LONGBOW_RUN_TEST_CASE(Object, parcTimer_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Object, parcTimer_ToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Object)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Object)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Object, parcTimer_Compare)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Object, parcTimer_Copy)
+{
+ PARCTimer *instance = parcTimer_Create();
+ PARCTimer *copy = parcTimer_Copy(instance);
+ assertTrue(parcTimer_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcTimer_Release(&instance);
+ parcTimer_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Object, parcTimer_Display)
+{
+ PARCTimer *instance = parcTimer_Create();
+ parcTimer_Display(instance, 0);
+ parcTimer_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcTimer_Equals)
+{
+ PARCTimer *x = parcTimer_Create();
+ PARCTimer *y = parcTimer_Create();
+ PARCTimer *z = parcTimer_Create();
+
+ parcObjectTesting_AssertEquals(x, y, z, NULL);
+
+ parcTimer_Release(&x);
+ parcTimer_Release(&y);
+ parcTimer_Release(&z);
+}
+
+LONGBOW_TEST_CASE(Object, parcTimer_HashCode)
+{
+ PARCTimer *x = parcTimer_Create();
+ PARCTimer *y = parcTimer_Create();
+
+ parcObjectTesting_AssertHashCode(x, y);
+
+ parcTimer_Release(&x);
+ parcTimer_Release(&y);
+}
+
+LONGBOW_TEST_CASE(Object, parcTimer_IsValid)
+{
+ PARCTimer *instance = parcTimer_Create();
+ assertTrue(parcTimer_IsValid(instance), "Expected parcTimer_Create to result in a valid instance.");
+
+ parcTimer_Release(&instance);
+ assertFalse(parcTimer_IsValid(instance), "Expected parcTimer_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Object, parcTimer_ToJSON)
+{
+ PARCTimer *instance = parcTimer_Create();
+
+ PARCJSON *json = parcTimer_ToJSON(instance);
+
+ parcJSON_Release(&json);
+
+ parcTimer_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcTimer_ToString)
+{
+ PARCTimer *instance = parcTimer_Create();
+
+ char *string = parcTimer_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcTimer_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+ parcTimer_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Specialization)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Specialization)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Specialization)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Timer);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
+
+