aboutsummaryrefslogtreecommitdiffstats
path: root/libparc/parc/algol/test/test_parc_Buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'libparc/parc/algol/test/test_parc_Buffer.c')
-rw-r--r--libparc/parc/algol/test/test_parc_Buffer.c1502
1 files changed, 1502 insertions, 0 deletions
diff --git a/libparc/parc/algol/test/test_parc_Buffer.c b/libparc/parc/algol/test/test_parc_Buffer.c
new file mode 100644
index 00000000..99b3bfd6
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Buffer.c
@@ -0,0 +1,1502 @@
+/*
+ * 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 <config.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <LongBow/unit-test.h>
+#include <LongBow/debugging.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../parc_Buffer.c"
+
+LONGBOW_TEST_RUNNER(parcBuffer)
+{
+ // 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(CreateDestroy);
+ LONGBOW_RUN_TEST_FIXTURE(Static);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(GettersSetters);
+ LONGBOW_RUN_TEST_FIXTURE(CreateDestroyErrors);
+ LONGBOW_RUN_TEST_FIXTURE(Errors);
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parcBuffer)
+{
+ 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(parcBuffer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateDestroy)
+{
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcBuffer_Allocate);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcBuffer_Allocate_0);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcBuffer_Allocate_AcquireRelease);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcBuffer_Allocate_SIZE_MAX);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcBuffer_Wrap);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcBuffer_Wrap_NULL);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcBuffer_Wrap_WithOffset);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcBuffer_AllocateCString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateDestroy)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateDestroy)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks %d memory allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcBuffer_Allocate)
+{
+ PARCBuffer *actual = parcBuffer_Allocate(10);
+ assertTrue(parcBuffer_Position(actual) == 0, "Expected initial position to be 0.");
+ assertTrue(parcBuffer_Limit(actual) == 10, "Expected initial limit to be 10.");
+ assertTrue(_markIsDiscarded(actual), "Expected initial mark to be discarded.");
+
+ parcBuffer_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcBuffer_Allocate_0)
+{
+ PARCBuffer *actual = parcBuffer_Allocate(0);
+ assertTrue(parcBuffer_Position(actual) == 0, "Expected initial position to be 0.");
+ assertTrue(parcBuffer_Limit(actual) == 0, "Expected initial limit to be 10.");
+ assertTrue(_markIsDiscarded(actual), "Expected initial mark to be discarded.");
+
+ parcBuffer_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcBuffer_Allocate_SIZE_MAX)
+{
+ PARCBuffer *actual = parcBuffer_Allocate(SIZE_MAX);
+ assertNull(actual, "Expected parcBuffer_Allocate to return NULL");
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcBuffer_Wrap_NULL)
+{
+ PARCBuffer *actual = parcBuffer_Wrap(NULL, 10, 0, 10);
+ assertNull(actual, "Expected parcBuffer_Wrap to return NULL");
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcBuffer_Wrap)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *actual = parcBuffer_Wrap(array, 10, 0, 10);
+ assertTrue(parcBuffer_Position(actual) == 0, "Expected initial position to be 0.");
+ assertTrue(parcBuffer_Limit(actual) == sizeof(array) / sizeof(array[0]), "Expected initial limit to be 10.");
+ assertTrue(_markIsDiscarded(actual), "Expected initial mark to be discarded.");
+
+ parcBuffer_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcBuffer_Wrap_WithOffset)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *actual = parcBuffer_Wrap(array, 10, 3, 10);
+ assertTrue(parcBuffer_Capacity(actual) == 10, "Expected initial capacity to be 3.");
+ assertTrue(parcBuffer_Limit(actual) == 10, "Expected initial limit to be 3.");
+ assertTrue(parcBuffer_Position(actual) == 3, "Expected initial position to be 0.");
+ assertTrue(_markIsDiscarded(actual), "Expected initial mark to be discarded.");
+
+ parcBuffer_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcBuffer_AllocateCString)
+{
+ PARCBuffer *buffer = parcBuffer_AllocateCString("Hello World");
+ assertNotNull(buffer, "Expected parcBuffer_AllocateCString to return non-null value");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcBuffer_Allocate_AcquireRelease)
+{
+ PARCBuffer *expected = parcBuffer_Allocate(10);
+ PARCBuffer *actual = parcBuffer_Acquire(expected);
+
+ assertTrue(expected == actual, "Expected %p, actual %p", (void *) expected, (void *) actual);
+
+ parcBuffer_Release(&expected);
+ assertTrue(expected == NULL, "Expected parcBuffer_Release to NULL the pointer.");
+ parcBuffer_Release(&actual);
+ assertTrue(actual == NULL, "Expected parcBuffer_Release to NULL the pointer.");
+}
+
+LONGBOW_TEST_FIXTURE(CreateDestroyErrors)
+{
+ LONGBOW_RUN_TEST_CASE(CreateDestroyErrors, parcBuffer_Allocate_AcquireRelease_TooMany);
+ LONGBOW_RUN_TEST_CASE(CreateDestroyErrors, parcBuffer_WrapByteArray_limit_exceeds_capacity);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateDestroyErrors)
+{
+ PARCByteArray *array = parcByteArray_Allocate(10);
+ longBowTestCase_SetClipBoardData(testCase, array);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateDestroyErrors)
+{
+ PARCByteArray *array = longBowTestCase_GetClipBoardData(testCase);
+ parcByteArray_Release(&array);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks %d memory allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE_EXPECTS(CreateDestroyErrors, parcBuffer_Allocate_AcquireRelease_TooMany, .event = &LongBowTrapIllegalValue)
+{
+ PARCBuffer *expected = parcBuffer_Allocate(10);
+ PARCBuffer *actual = parcBuffer_Acquire(expected);
+ PARCBuffer *alias = actual;
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&actual);
+ parcBuffer_Release(&alias); // this must fail.
+}
+
+LONGBOW_TEST_CASE_EXPECTS(CreateDestroyErrors, parcBuffer_WrapByteArray_limit_exceeds_capacity, .event = &LongBowAssertEvent)
+{
+ PARCByteArray *array = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCBuffer *buffer = parcBuffer_WrapByteArray(array, 0, parcByteArray_Capacity(array) + 1);
+
+ assertNotNull(buffer, "Expected NULL");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+// LONGBOW_RUN_TEST_CASE(Global, HELPME);
+// LONGBOW_RUN_TEST_CASE(Global, HELPME2);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Array);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_ArrayOffset);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Clear);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Clone);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Duplicate);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Clone_WithOffset);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Compare);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Equals_ZeroLength);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Equals_Bug80);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Flip);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_GetByte);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_GetBytes);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_GetBytes_Incremental);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_HasRemaining);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_HashCode_ZeroRemaining);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Mark);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Resize_Growing);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Resize_Growing_AtLimit);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Resize_Shrinking);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Resize_Shrinking_AtLimit);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Resize_Example);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Resize_Slice);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Overlay);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Position);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_PutBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_PutBuffer_ZeroLength_operand);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_PutByte);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_PutBytes);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_PutIndex);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_PutUint16);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_PutCString);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Remaining);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Rewind);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_SetLimit);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_SetLimit_TruncatePosition);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_SetPosition);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_Slice);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_ToString);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_ToString_ZeroRemaining);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_SkipOver);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_SkipOver_NotFound);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_SkipTo_NotFound);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_SkipTo);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_FindUint8);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_FindUint8_NotFound);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_IsValid_True);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_ParseNumeric_Decimal);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_ParseNumeric_Hexadecimal);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_ParseHexString);
+ LONGBOW_RUN_TEST_CASE(Global, parcBuffer_CreateFromArray);
+}
+
+static size_t _longBowGlobal_Global_outstanding;
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ _longBowGlobal_Global_outstanding = parcMemory_Outstanding();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ LongBowStatus result = LONGBOW_STATUS_SUCCEEDED;
+
+ size_t allocationsLeaked = parcMemory_Outstanding() - _longBowGlobal_Global_outstanding;
+
+ if (allocationsLeaked) {
+ printf("%s leaks memory by %zd allocations\n", longBowTestCase_GetName(testCase), allocationsLeaked);
+ parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ result = LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return result;
+}
+
+LONGBOW_TEST_CASE(Global, HELPME)
+{
+ uint8_t decodeBytes[] = { 0x00, 0x02, 0x00, 0x0A, 'b', 'r', 'a', 'n', 'd', 'y', 'w', 'i', 'n', 'e' };
+ PARCBuffer *b1 = parcBuffer_Wrap(decodeBytes, sizeof(decodeBytes), 0, sizeof(decodeBytes));
+
+ // b1 is a buffer wrapping a byte array.
+ // This will take 2 allocations: 1 for the buffer and 1 for the wrapper around the byte array.
+
+ PARCBuffer *s2 = parcBuffer_Slice(b1);
+
+ // s2 is another buffer referencing the wrapper created in the original buffer.
+ // This will increase the allocations by 1 for the buffer making it 3.
+
+ // **** DO NOT RELEASE s2
+
+ parcBuffer_Release(&b1);
+ // This releases the b1 buffer, deallocating it. The wrapper around the original byte array still has a reference to it from s2.
+ // The number of allocations is reduced by 1, making it 2 (1 for s2, and 1 for the wrapper it references)
+
+ assertTrue(parcMemory_Outstanding() == 2, "memory imbalance");
+
+ parcBuffer_Release(&s2);
+
+ assertTrue(parcMemory_Outstanding() == 0, "memory imbalance must be 0, actual %d", parcMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, HELPME2)
+{
+ uint8_t decodeBytes[] = { 0x00, 0x02, 0x00, 0x0A, 'b', 'r', 'a', 'n', 'd', 'y', 'w', 'i', 'n', 'e' };
+ PARCBuffer *b1 = parcBuffer_Allocate(sizeof(decodeBytes));
+ // This will create a buffer, a wrapper, and an allocated array of bytes to wrap.
+ // The number of allocations is 3.
+
+ parcBuffer_PutArray(b1, sizeof(decodeBytes), decodeBytes);
+ parcBuffer_Flip(b1);
+
+ PARCBuffer *s2 = parcBuffer_Slice(b1);
+ // The number of allocations is 4.
+
+ // **** DO NOT RELEASE s2
+
+ parcBuffer_Release(&b1);
+ // The number of allocations is now 3, the slice buffer, the wrapper, and the allocated array of bytes.
+
+ // This will now correctly assert
+ assertTrue(parcMemory_Outstanding() == 3, "memory imbalance");
+
+ parcBuffer_Release(&s2);
+ assertTrue(parcMemory_Outstanding() == 0, "memory imbalance");
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Equals)
+{
+ PARCBuffer *x = parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 10);
+ PARCBuffer *y = parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 10);
+ PARCBuffer *z = parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 10);
+
+ // _Pragma("GCC diagnostic push")
+ // _Pragma("GCC diagnostic ignored \"-Wzero-length-array\"")
+ // _Pragma("GCC diagnostic ignored \"-Wgnu-empty-initializer\"")
+ struct hack {
+ uint8_t dummy;
+ uint8_t empty[];
+ };
+ struct hack h = { 0 };
+ PARCBuffer *u0 = parcBuffer_Wrap(h.empty, 0, 0, 0);
+ // _Pragma("GCC diagnostic pop")
+
+ PARCBuffer *u1 = parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10 }, 10, 0, 10);
+ PARCBuffer *u2 = parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 9, 0, 9);
+ PARCBuffer *u3 = parcBuffer_Wrap((uint8_t [9]) { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 9, 0, 9);
+ PARCBuffer *u4 = parcBuffer_SetPosition(parcBuffer_Wrap((uint8_t [9]) { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 9, 0, 9), 2);
+ PARCBuffer *u5 = parcBuffer_SetPosition(parcBuffer_Wrap((uint8_t [9]) { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 9, 0, 9), 9);
+ PARCBuffer *u6 = parcBuffer_SetPosition(parcBuffer_Wrap((uint8_t [9]) { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 9, 0, 9), 9);
+ PARCBuffer *u7 = parcBuffer_Wrap((uint8_t [9]) { 0 }, 0, 0, 0);
+
+ parcObjectTesting_AssertEqualsFunction(parcBuffer_Equals, x, y, z, u0, u1, u2, u3, u4, u5, u6, u7, NULL);
+
+ parcBuffer_Release(&x);
+ parcBuffer_Release(&y);
+ parcBuffer_Release(&z);
+ parcBuffer_Release(&u0);
+ parcBuffer_Release(&u1);
+ parcBuffer_Release(&u2);
+ parcBuffer_Release(&u3);
+ parcBuffer_Release(&u4);
+ parcBuffer_Release(&u5);
+ parcBuffer_Release(&u6);
+ parcBuffer_Release(&u7);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Equals_ZeroLength)
+{
+ // _Pragma("GCC diagnostic push")
+ // _Pragma("GCC diagnostic ignored \"-Wzero-length-array\"")
+ // _Pragma("GCC diagnostic ignored \"-Wgnu-empty-initializer\"")
+
+ struct hack {
+ uint8_t dummy;
+ uint8_t empty[];
+ };
+ struct hack h = { 0 };
+ PARCBuffer *x = parcBuffer_Wrap(h.empty, 0, 0, 0);
+ PARCBuffer *y = parcBuffer_Wrap(h.empty, 0, 0, 0);
+ PARCBuffer *z = parcBuffer_Wrap(h.empty, 0, 0, 0);
+
+ // _Pragma("GCC diagnostic pop")
+
+ PARCBuffer *u1 = parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10 }, 10, 0, 10);
+ PARCBuffer *u2 = parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 9, 0, 9);
+
+ parcObjectTesting_AssertEqualsFunction(parcBuffer_Equals, x, y, z, u1, u2, NULL);
+
+ parcBuffer_Release(&x);
+ parcBuffer_Release(&y);
+ parcBuffer_Release(&z);
+ parcBuffer_Release(&u1);
+ parcBuffer_Release(&u2);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Equals_Bug80)
+{
+ PARCBuffer *x = parcBuffer_WrapCString("a");
+ PARCBuffer *y = parcBuffer_WrapCString("a");
+ PARCBuffer *z = parcBuffer_WrapCString("a");
+ PARCBuffer *u1 = parcBuffer_WrapCString("b");
+ PARCBuffer *u2 = parcBuffer_WrapCString("");
+ PARCBuffer *u3 = parcBuffer_WrapCString("ab");
+
+ parcObjectTesting_AssertEqualsFunction(parcBuffer_Equals, x, y, z, u1, u2, u3);
+
+ parcBuffer_Release(&x);
+ parcBuffer_Release(&y);
+ parcBuffer_Release(&z);
+ parcBuffer_Release(&u1);
+ parcBuffer_Release(&u2);
+ parcBuffer_Release(&u3);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Compare)
+{
+ PARCBuffer *x = parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 10);
+ PARCBuffer *y = parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 10);
+
+ PARCBuffer *equivalent[] = {
+ x,
+ y,
+ NULL
+ };
+ PARCBuffer *lesser[] = {
+ parcBuffer_Wrap((uint8_t [9]) { 0 }, 0, 0, 0),
+ parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8}, 10, 0, 10),
+ parcBuffer_Wrap((uint8_t [9]) { 0, 1, 2, 3, 4, 5, 5, 7, 8,}, 9, 0, 9),
+ NULL
+ };
+ PARCBuffer *greater[] = {
+ parcBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10 }, 10, 0, 10),
+ parcBuffer_Wrap((uint8_t [11]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 11, 0, 11),
+ NULL
+ };
+
+ parcObjectTesting_AssertCompareTo(parcBuffer_Compare, x, equivalent, lesser, greater);
+
+ parcBuffer_Release(&x);
+ parcBuffer_Release(&y);
+
+ for (int i = 0; lesser[i] != NULL; i++) {
+ parcBuffer_Release(&lesser[i]);
+ }
+ for (int i = 0; greater[i] != NULL; i++) {
+ parcBuffer_Release(&greater[i]);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Array)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(expected, 10, 0, 10);
+
+ PARCByteArray *array = parcBuffer_Array(buffer);
+ uint8_t *actual = parcByteArray_Array(array);
+
+ parcBuffer_Release(&buffer);
+
+ assertTrue(expected == actual,
+ "Expected %p, actual %p", (void *) expected, (void *) actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Resize_Growing)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ PARCBuffer *buffer = parcBuffer_Allocate(12);
+ parcBuffer_PutArray(buffer, sizeof(expected), expected);
+
+ parcBuffer_SetPosition(buffer, 5);
+ parcBuffer_SetLimit(buffer, 11);
+ parcBuffer_Mark(buffer);
+
+ parcBuffer_Resize(buffer, 20);
+
+ assertTrue(buffer->position == 5, "Expected position at %d, actual %zd", 5, buffer->position);
+ assertTrue(buffer->mark == 5, "Expected mark at %d, actual %zd", 5, buffer->mark);
+ assertTrue(buffer->limit == 11, "Expected limit at %d, actual %zd", 11, buffer->limit);
+ assertTrue(parcBuffer_Capacity(buffer) == 20, "Expected capacity at %d, actual %zd", 20, parcBuffer_Capacity(buffer));
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Resize_Growing_AtLimit)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ PARCBuffer *buffer = parcBuffer_Allocate(12);
+ parcBuffer_PutArray(buffer, sizeof(expected), expected);
+
+ parcBuffer_SetPosition(buffer, 5);
+ parcBuffer_Mark(buffer);
+
+ parcBuffer_Resize(buffer, 20);
+
+ assertTrue(buffer->position == 5, "Expected position at %d, actual %zd", 5, buffer->position);
+ assertTrue(buffer->mark == 5, "Expected mark at %d, actual %zd", 5, buffer->mark);
+ assertTrue(buffer->limit == 20, "Expected limit at %d, actual %zd", 20, buffer->limit);
+ assertTrue(parcBuffer_Capacity(buffer) == 20, "Expected capacity at %d, actual %zd", 20, parcBuffer_Capacity(buffer));
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Resize_Shrinking)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer, sizeof(expected), expected);
+
+ parcBuffer_SetPosition(buffer, 3);
+ parcBuffer_SetLimit(buffer, 4);
+ parcBuffer_Mark(buffer);
+
+ parcBuffer_Resize(buffer, 5);
+
+ assertTrue(buffer->position == 3, "Expected position at %d, actual %zd", 3, buffer->position);
+ assertTrue(buffer->mark == 3, "Expected mark to be 3");
+ assertTrue(buffer->limit == 4, "Expected limit at %d, actual %zd", 4, buffer->limit);
+ assertTrue(parcBuffer_Capacity(buffer) == 5, "Expected capacity at %d, actual %zd", 5, parcBuffer_Capacity(buffer));
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Resize_Shrinking_AtLimit)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer, sizeof(expected), expected);
+
+ parcBuffer_SetPosition(buffer, 5);
+ parcBuffer_SetLimit(buffer, 5);
+ parcBuffer_Mark(buffer);
+
+ parcBuffer_Resize(buffer, 3);
+
+ assertTrue(buffer->position == 3, "Expected position at %d, actual %zd", 3, buffer->position);
+ assertTrue(_markIsDiscarded(buffer), "Expected mark to be discarded");
+ assertTrue(buffer->limit == 3, "Expected limit at %d, actual %zd", 3, buffer->limit);
+ assertTrue(parcBuffer_Capacity(buffer) == 3, "Expected capacity at %d, actual %zd", 3, parcBuffer_Capacity(buffer));
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Resize_Example)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("Hello World");
+ parcBuffer_Resize(buffer, 4);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Resize_Slice)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("Hello World");
+ parcBuffer_SetPosition(buffer, 5);
+ PARCBuffer *slice = parcBuffer_Slice(buffer);
+
+ parcBuffer_Resize(slice, 4);
+
+ parcBuffer_Release(&buffer);
+ parcBuffer_Release(&slice);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Flip)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer, 10, expected);
+ parcBuffer_Flip(buffer);
+ assertTrue(parcBuffer_Position(buffer) == 0, "Expected position to be 0.");
+ assertTrue(parcBuffer_Limit(buffer) == 10, "Expected limit to be 10.");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Clear)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer, 10, expected);
+ parcBuffer_Clear(buffer);
+ assertTrue(parcBuffer_Position(buffer) == 0, "Expected position to be 0.");
+ assertTrue(parcBuffer_Limit(buffer) == 10, "Expected limit to be 10.");
+ assertTrue(buffer->mark >= parcBuffer_Capacity(buffer), "Expected the mark to be unset.");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_ArrayOffset)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ size_t expected = 5;
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, expected, 10);
+
+ size_t actual = parcBuffer_ArrayOffset(buffer);
+ parcBuffer_Release(&buffer);
+
+ assertTrue(0 == actual,
+ "Expected offset to be 0, actual %zd", actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Position)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+
+ size_t expected = 5;
+ parcBuffer_SetPosition(buffer, expected);
+
+ size_t actual = parcBuffer_Position(buffer);
+
+ assertTrue(expected == actual,
+ "Expected position to be 0, actual %zd", actual);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Overlay)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ uint8_t expected[5] = { 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+
+ size_t position = 5;
+ parcBuffer_SetPosition(buffer, position);
+ uint8_t *actual = parcBuffer_Overlay(buffer, sizeof(array) - position);
+
+ assertTrue(memcmp(expected, actual, sizeof(expected)) == 0,
+ "Array contents should not be different.");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Clone)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *original = parcBuffer_Wrap(array, 10, 0, 10);
+
+ PARCBuffer *clone = parcBuffer_Copy(original);
+
+ assertTrue(clone != original, "Expected the clone to be a different instance.");
+
+ assertTrue(parcBuffer_Equals(original, clone), "Expected clone to be equal to the original.");
+
+ parcBuffer_Release(&original);
+ assertNull(original, "Expected the parcBuffer_Release function to NULL the pointer.");
+
+ parcBuffer_Release(&clone);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Clone_WithOffset)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *original = parcBuffer_Wrap(array, 10, 0, 10);
+ parcBuffer_SetLimit(original, 9);
+ parcBuffer_SetPosition(original, 1);
+ PARCBuffer *range = parcBuffer_Slice(original);
+
+ PARCBuffer *clone = parcBuffer_Copy(range);
+
+ assertTrue(clone != original, "Expected the clone to be a different instance.");
+
+ assertTrue(parcBuffer_Equals(range, clone), "Expected clone to be equal to the original.");
+
+ parcBuffer_Release(&clone);
+ parcBuffer_Release(&range);
+ parcBuffer_Release(&original);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_SetPosition)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+
+ size_t expected = 2;
+ parcBuffer_SetPosition(buffer, expected);
+ size_t actual = parcBuffer_Position(buffer);
+
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_SetLimit)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+
+ size_t expected = 2;
+ parcBuffer_SetLimit(buffer, expected);
+ size_t actual = parcBuffer_Limit(buffer);
+
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_SetLimit_TruncatePosition)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+
+ parcBuffer_SetPosition(buffer, 5);
+ parcBuffer_Mark(buffer);
+
+ size_t expected = 2;
+ parcBuffer_SetLimit(buffer, expected);
+ size_t actual = parcBuffer_Limit(buffer);
+
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Slice)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+ parcBuffer_GetUint8(buffer);
+
+ PARCBuffer *actual = parcBuffer_Slice(buffer);
+ assertTrue(parcBuffer_Position(actual) == 0,
+ "Expected position to be 0");
+ assertTrue(parcBuffer_Limit(actual) == parcBuffer_Remaining(buffer),
+ "Expected position to be %zd", parcBuffer_Remaining(buffer));
+ assertTrue(_markIsDiscarded(actual), "Expected the mark to be discarded.");
+
+ parcBuffer_Release(&buffer);
+ parcBuffer_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Remaining)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+
+ size_t expected = 2;
+ parcBuffer_SetLimit(buffer, expected);
+ size_t actual = parcBuffer_Limit(buffer);
+
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_HasRemaining)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+ bool actual = parcBuffer_HasRemaining(buffer);
+
+ assertTrue(actual, "Expected true");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Rewind)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+ parcBuffer_SetPosition(buffer, 4);
+ size_t actual = parcBuffer_Position(buffer);
+ assertTrue(actual == 4, "Expected position to be at 4.");
+
+ parcBuffer_Rewind(buffer);
+
+ actual = parcBuffer_Position(buffer);
+ assertTrue(actual == 0, "Expected position to be at 0.");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Duplicate)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+ parcBuffer_SetPosition(buffer, 4);
+
+ PARCBuffer *buffer2 = parcBuffer_Duplicate(buffer);
+
+ assertTrue(buffer != buffer2, "Expected distinct pointers to the different buffers.");
+ assertTrue(parcBuffer_Position(buffer) == parcBuffer_Position(buffer2), "Expected equal position values.");
+ assertTrue(parcBuffer_Limit(buffer) == parcBuffer_Limit(buffer2), "Expected equal limit values.");
+ assertTrue(parcBuffer_Capacity(buffer) == parcBuffer_Capacity(buffer2), "Expected equal capacity values.");
+
+ parcBuffer_Rewind(buffer);
+ assertFalse(parcBuffer_Position(buffer) == parcBuffer_Position(buffer2), "Expected unequal position values.");
+
+ parcBuffer_Release(&buffer);
+ parcBuffer_Release(&buffer2);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_Mark)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+
+ size_t expected = 2;
+ parcBuffer_SetPosition(buffer, expected);
+ parcBuffer_Mark(buffer);
+ parcBuffer_SetPosition(buffer, 4);
+ parcBuffer_Reset(buffer);
+ size_t actual = parcBuffer_Position(buffer);
+
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_PutByte)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+
+ uint8_t expectedValue = 1;
+ parcBuffer_PutUint8(buffer, expectedValue);
+
+ size_t expectedPosition = 1;
+ size_t actualPosition = parcBuffer_Position(buffer);
+
+ parcBuffer_SetPosition(buffer, 0);
+ uint8_t actualValue = parcBuffer_GetAtIndex(buffer, 0);
+ parcBuffer_Release(&buffer);
+
+ assertTrue(expectedValue == actualValue,
+ "Expected %d, actual %d", expectedValue, actualValue);
+ assertTrue(expectedPosition == actualPosition,
+ "Expected %zu, actual %zu", expectedPosition, actualPosition);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_PutCString)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+
+ char *expectedValue = "abcdefg";
+ parcBuffer_PutCString(buffer, expectedValue);
+
+ size_t expectedPosition = 8;
+ size_t actualPosition = parcBuffer_Position(buffer);
+
+ uint8_t zero = parcBuffer_GetAtIndex(buffer, 7);
+
+ assertTrue(zero == 0, "Expected zero, actual %d", zero);
+
+ assertTrue(expectedPosition == actualPosition,
+ "Expected %zu, actual %zu", expectedPosition, actualPosition);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_PutUint16)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+
+ uint16_t expectedValue = 0x1234;
+ parcBuffer_PutUint16(buffer, expectedValue);
+
+ size_t expectedPosition = 2;
+ size_t actualPosition = parcBuffer_Position(buffer);
+ assertTrue(expectedPosition == actualPosition,
+ "Expected position %zd, actual %zd", expectedPosition, actualPosition);
+
+ parcBuffer_Flip(buffer);
+ uint16_t actualValue = parcBuffer_GetUint16(buffer);
+
+ actualPosition = parcBuffer_Position(buffer);
+
+ parcBuffer_Release(&buffer);
+
+ assertTrue(expectedValue == actualValue,
+ "Expected %d, actual %d", expectedValue, actualValue);
+ assertTrue(expectedPosition == actualPosition,
+ "Expected %zu, actual %zu", expectedPosition, actualPosition);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_PutIndex)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+
+ uint8_t expected = 1;
+ parcBuffer_PutAtIndex(buffer, 0, expected);
+ uint8_t actual = parcBuffer_GetAtIndex(buffer, 0);
+
+ parcBuffer_Release(&buffer);
+
+ assertTrue(expected == actual,
+ "Expected %" PRIu8 ", actual %" PRIu8 "", expected, actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_PutBytes)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer, 10, array);
+
+ size_t expected = parcBuffer_Limit(buffer);
+ size_t actual = parcBuffer_Position(buffer);
+
+ assertTrue(expected == actual, "Expected position to be at the limit.");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_PutBuffer)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer1 = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer1, 5, array);
+
+ PARCBuffer *buffer2 = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer2, 5, &array[5]);
+ parcBuffer_Flip(buffer2);
+
+ parcBuffer_PutBuffer(buffer1, buffer2);
+
+ size_t expected = parcBuffer_Limit(buffer1);
+ size_t actual = parcBuffer_Position(buffer1);
+
+ assertTrue(expected == actual, "Expected position to be at the limit. Expected %zd, actual %zd", expected, actual);
+ assertTrue(memcmp(array, parcByteArray_Array(buffer1->array), sizeof(array)) == 0,
+ "Array content differs.");
+
+ parcBuffer_Release(&buffer1);
+ parcBuffer_Release(&buffer2);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_GetByte)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer, sizeof(expected), expected);
+ parcBuffer_Flip(buffer);
+
+ uint8_t actual = parcBuffer_GetUint8(buffer);
+
+ assertTrue(expected[0] == actual,
+ "Expected %d, actual %d", expected[0], actual);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_GetBytes)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ uint8_t actual[10];
+
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer, sizeof(expected), expected);
+ parcBuffer_Flip(buffer);
+
+ parcBuffer_GetBytes(buffer, sizeof(actual), actual);
+
+ assertTrue(memcmp(expected, actual, sizeof(actual)) == 0,
+ "Expected arrays to be equal.");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_GetBytes_Incremental)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ uint8_t actual[10];
+
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer, sizeof(expected), expected);
+ parcBuffer_Flip(buffer);
+
+ parcBuffer_GetBytes(buffer, 1, actual);
+ assertTrue(parcBuffer_Position(buffer) == 1, "Expected position to be %d\n", 1);
+ assertTrue(actual[0] == expected[0], "Expected %d, actual %d", expected[0], actual[0]);
+ parcBuffer_GetBytes(buffer, 1, actual);
+ assertTrue(parcBuffer_Position(buffer) == 2, "Expected position to be 2, actual %zd\n", parcBuffer_Position(buffer));
+ assertTrue(actual[0] == expected[1], "Expected %d, actual %d", expected[1], actual[0]);
+ parcBuffer_GetBytes(buffer, 1, actual);
+ assertTrue(parcBuffer_Position(buffer) == 3, "Expected position to be 3, actual %zd\n", parcBuffer_Position(buffer));
+ assertTrue(actual[0] == expected[2], "Expected %d, actual %d", expected[2], actual[0]);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_PutBuffer_ZeroLength_operand)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer1 = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer1, 10, array);
+
+ PARCBuffer *buffer2 = parcBuffer_Allocate(0);
+ parcBuffer_PutBuffer(buffer1, buffer2);
+
+ size_t expected = parcBuffer_Limit(buffer1);
+ size_t actual = parcBuffer_Position(buffer1);
+
+ assertTrue(expected == actual, "Expected position to be at the limit.");
+
+ parcBuffer_Release(&buffer1);
+ parcBuffer_Release(&buffer2);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_HashCode)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer1 = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer1, 10, array);
+ parcBuffer_Flip(buffer1);
+
+ PARCBuffer *buffer2 = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer2, 10, array);
+ parcBuffer_Flip(buffer2);
+
+ PARCHashCode hashX = parcBuffer_HashCode(buffer1);
+ PARCHashCode hashY = parcBuffer_HashCode(buffer2);
+
+ assertTrue(hashX == hashY, "Expected %" PRIPARCHashCode ", actual %" PRIPARCHashCode, hashX, hashY);
+
+ parcBuffer_Release(&buffer1);
+ parcBuffer_Release(&buffer2);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_HashCode_ZeroRemaining)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer1 = parcBuffer_Allocate(10);
+ parcBuffer_PutArray(buffer1, 10, array);
+
+ PARCHashCode hashX = parcBuffer_HashCode(buffer1);
+
+ assertTrue(hashX == 0, "Expected 0, actual %" PRIPARCHashCode, hashX);
+
+ parcBuffer_Release(&buffer1);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_ToString)
+{
+ uint8_t array[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 'x' };
+
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(array) - 1);
+ parcBuffer_PutArray(buffer, sizeof(array) - 1, array);
+ parcBuffer_Flip(buffer);
+
+ char *actual = parcBuffer_ToString(buffer);
+
+ assertTrue(strcmp("hello world", actual) == 0, "Expected 'hello world', actual %s", actual);
+
+ parcMemory_Deallocate((void **) &actual);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_ToString_ZeroRemaining)
+{
+ uint8_t array[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 'x' };
+
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(array) - 1);
+ parcBuffer_PutArray(buffer, sizeof(array) - 1, array);
+// parcBuffer_Flip(buffer);
+
+ char *actual = parcBuffer_ToString(buffer);
+
+ assertTrue(strcmp("", actual) == 0, "Expected '', actual %s", actual);
+
+ parcMemory_Deallocate((void **) &actual);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_SkipOver)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("Hello World");
+ uint8_t skipOverBytes[] = { 'H', 0 };
+
+ bool actual = parcBuffer_SkipOver(buffer, 1, skipOverBytes);
+
+ assertTrue(actual, "Expected parcBuffer_SkipOver to return true.");
+
+ uint8_t peekByte = parcBuffer_PeekByte(buffer);
+
+ assertTrue(peekByte == 'e', "Expected buffer to point to 'e', actual '%c'", peekByte);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_SkipOver_NotFound)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("Hello World");
+
+ bool actual = parcBuffer_SkipOver(buffer, 8, (uint8_t *) "Helo Wrd");
+
+ assertFalse(actual, "Expected parcBuffer_SkipOver to return false.");
+
+ assertTrue(parcBuffer_Remaining(buffer) == 0,
+ "Expected buffer to have no remaining bytes. Actual %zd", parcBuffer_Remaining(buffer));
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_SkipTo)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("Hello World");
+ uint8_t skipToBytes[] = { 'l', 0 };
+
+ bool actual = parcBuffer_SkipTo(buffer, 1, skipToBytes);
+
+ assertTrue(actual, "Expected parcBuffer_SkipOver to return true.");
+
+ uint8_t peekByte = parcBuffer_PeekByte(buffer);
+
+ assertTrue(peekByte == 'l', "Expected buffer to point to 'l', actual '%c'", peekByte);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_SkipTo_NotFound)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("Hello World");
+
+ bool actual = parcBuffer_SkipTo(buffer, 1, (uint8_t *) "x");
+
+ assertFalse(actual, "Expected parcBuffer_SkipOver to return false.");
+ assertTrue(parcBuffer_Remaining(buffer) == 0,
+ "Expected buffer to have no remaining bytes. Actual %zd", parcBuffer_Remaining(buffer));
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_FindUint8)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("Hello World");
+ size_t index = parcBuffer_FindUint8(buffer, 'e');
+ assertTrue(index == 1, "Expected index to be 1, actual %zu", index);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_FindUint8_NotFound)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("Hello World");
+ size_t index = parcBuffer_FindUint8(buffer, 'z');
+ assertTrue(index == SIZE_MAX, "Expected index to be SIZE_MAX, actual %zu", index);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_IsValid_True)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("Hello World");
+ bool actual = parcBuffer_IsValid(buffer);
+ assertTrue(actual, "Expected PARCBuffer to be valid");
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_ParseNumeric_Decimal)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("123abc");
+
+ uint64_t actual = parcBuffer_ParseNumeric(buffer);
+
+ assertTrue(actual == 123, "Expected 123, actual %" PRIu64 "", actual);
+ assertTrue(parcBuffer_Position(buffer) == 3, "Expected position to be 3, actual %zd", parcBuffer_Position(buffer));
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_ParseNumeric_Hexadecimal)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("0x123xyz");
+
+ uint64_t actual = parcBuffer_ParseNumeric(buffer);
+
+ assertTrue(actual == 0x123, "Expected 0x123, actual %" PRIx64 "", actual);
+ assertTrue(parcBuffer_Position(buffer) == 5, "Expected position to be 5, actual %zd", parcBuffer_Position(buffer));
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_ParseHexString)
+{
+ char *expected = "00";
+ PARCBuffer *buffer = parcBuffer_ParseHexString("3030");
+ parcBuffer_Flip(buffer);
+ char *actual = parcBuffer_ToString(buffer);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected %s, actual %s", expected, actual);
+
+ parcMemory_Deallocate(&actual);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBuffer_CreateFromArray)
+{
+ char *expected = "0123456789ABCDEF";
+ PARCBuffer *buffer = parcBuffer_CreateFromArray(expected, strlen(expected));
+
+ assertTrue(parcBuffer_Position(buffer) == 16, "Expected position to be at 15, actual %zd", parcBuffer_Position(buffer));
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_FIXTURE(GettersSetters)
+{
+ LONGBOW_RUN_TEST_CASE(GettersSetters, parcPutGetUint8);
+ LONGBOW_RUN_TEST_CASE(GettersSetters, parcPutGetUint16);
+ LONGBOW_RUN_TEST_CASE(GettersSetters, parcPutGetUint32);
+ LONGBOW_RUN_TEST_CASE(GettersSetters, parcPutGetUint64);
+ LONGBOW_RUN_TEST_CASE(GettersSetters, parcBuffer_ToHexString);
+ LONGBOW_RUN_TEST_CASE(GettersSetters, parcBuffer_ToHexString_NULLBuffer);
+ LONGBOW_RUN_TEST_CASE(GettersSetters, parcBuffer_Display);
+ LONGBOW_RUN_TEST_CASE(GettersSetters, parcBuffer_Display_NULL);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(GettersSetters)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(100);
+
+ longBowTestCase_SetClipBoardData(testCase, buffer);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(GettersSetters)
+{
+ PARCBuffer *buffer = longBowTestCase_GetClipBoardData(testCase);
+ parcBuffer_Release(&buffer);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(GettersSetters, parcPutGetUint8)
+{
+ PARCBuffer *buffer = longBowTestCase_GetClipBoardData(testCase);
+
+ uint8_t expected = 0x12;
+ parcBuffer_PutUint8(buffer, expected);
+ parcBuffer_Flip(buffer);
+ uint8_t actual = parcBuffer_GetUint8(buffer);
+
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+}
+
+LONGBOW_TEST_CASE(GettersSetters, parcPutGetUint16)
+{
+ PARCBuffer *buffer = longBowTestCase_GetClipBoardData(testCase);
+
+ uint16_t expected = 0x1234;
+ parcBuffer_PutUint16(buffer, expected);
+ parcBuffer_Flip(buffer);
+ uint16_t actual = parcBuffer_GetUint16(buffer);
+
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+}
+
+LONGBOW_TEST_CASE(GettersSetters, parcPutGetUint32)
+{
+ PARCBuffer *buffer = longBowTestCase_GetClipBoardData(testCase);
+
+ uint32_t expected = 0x12345678;
+ parcBuffer_PutUint32(buffer, expected);
+ parcBuffer_Flip(buffer);
+ uint32_t actual = parcBuffer_GetUint32(buffer);
+
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+}
+
+LONGBOW_TEST_CASE(GettersSetters, parcPutGetUint64)
+{
+ PARCBuffer *buffer = longBowTestCase_GetClipBoardData(testCase);
+
+ uint64_t expected = 0x1234567812345678;
+ parcBuffer_PutUint64(buffer, expected);
+ parcBuffer_Flip(buffer);
+ uint64_t actual = parcBuffer_GetUint64(buffer);
+
+ assertTrue(expected == actual, "Expected %" PRIu64 ", actual %" PRIu64 "", expected, actual);
+}
+
+LONGBOW_TEST_CASE(GettersSetters, parcBuffer_ToHexString)
+{
+ PARCBuffer *buffer = longBowTestCase_GetClipBoardData(testCase);
+
+ uint64_t expected = 0x1234567812345678;
+ parcBuffer_PutUint64(buffer, expected);
+ parcBuffer_Flip(buffer);
+ char *hexString = parcBuffer_ToHexString(buffer);
+
+ assertTrue(strcmp("1234567812345678", hexString) == 0, "Expected 1234567812345678, actual %s", hexString);
+ parcMemory_Deallocate((void **) &hexString);
+}
+
+LONGBOW_TEST_CASE(GettersSetters, parcBuffer_ToHexString_NULLBuffer)
+{
+ char *hexString = parcBuffer_ToHexString(NULL);
+
+ assertTrue(strcmp("null", hexString) == 0, "Expected null, actual %s", hexString);
+ parcMemory_Deallocate((void **) &hexString);
+}
+
+LONGBOW_TEST_CASE(GettersSetters, parcBuffer_Display)
+{
+ PARCBuffer *buffer = longBowTestCase_GetClipBoardData(testCase);
+
+ uint64_t expected = 0x1234567812345678;
+ parcBuffer_PutUint64(buffer, expected);
+ parcBuffer_Flip(buffer);
+ parcBuffer_Display(buffer, 0);
+}
+
+LONGBOW_TEST_CASE(GettersSetters, parcBuffer_Display_NULL)
+{
+ parcBuffer_Display(NULL, 0);
+}
+
+LONGBOW_TEST_FIXTURE(Errors)
+{
+ LONGBOW_RUN_TEST_CASE(Errors, parcBuffer_GetByte_Underflow);
+ LONGBOW_RUN_TEST_CASE(Errors, parcBuffer_Mark_mark_exceeds_position);
+}
+
+typedef struct parc_buffer_longbow_clipboard {
+ PARCBuffer *buffer;
+} parcBuffer_LongBowClipBoard;
+
+LONGBOW_TEST_FIXTURE_SETUP(Errors)
+{
+ parcBuffer_LongBowClipBoard *testData = calloc(1, sizeof(parcBuffer_LongBowClipBoard));
+ testData->buffer = parcBuffer_Allocate(10);
+
+ longBowTestCase_SetClipBoardData(testCase, testData);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Errors)
+{
+ parcBuffer_LongBowClipBoard *testData = longBowTestCase_GetClipBoardData(testCase);
+ parcBuffer_Release(&testData->buffer);
+ free(testData);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, parcBuffer_GetByte_Underflow, .event = &LongBowTrapOutOfBounds)
+{
+ parcBuffer_LongBowClipBoard *testData = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = testData->buffer;
+
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ parcBuffer_PutArray(buffer, 1, expected);
+ parcBuffer_Flip(buffer);
+
+ parcBuffer_GetUint8(buffer);
+ parcBuffer_GetUint8(buffer); // this will fail.
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, parcBuffer_Mark_mark_exceeds_position, .event = &LongBowAssertEvent)
+{
+ parcBuffer_LongBowClipBoard *testData = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = testData->buffer;
+
+ size_t expected = 2;
+ parcBuffer_SetPosition(buffer, expected);
+ parcBuffer_Mark(buffer);
+ parcBuffer_SetPosition(buffer, 0);
+ parcBuffer_Reset(buffer);
+}
+
+
+LONGBOW_TEST_FIXTURE(Static)
+{
+ LONGBOW_RUN_TEST_CASE(Static, _digittoint);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Static)
+{
+ _longBowGlobal_Global_outstanding = parcMemory_Outstanding();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Static)
+{
+ LongBowStatus result = LONGBOW_STATUS_SUCCEEDED;
+
+ size_t allocationsLeaked = parcMemory_Outstanding() - _longBowGlobal_Global_outstanding;
+
+ if (allocationsLeaked) {
+ printf("%s leaks memory by %zd allocations\n", longBowTestCase_GetName(testCase), allocationsLeaked);
+ parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ result = LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return result;
+}
+
+LONGBOW_TEST_CASE(Static, _digittoint)
+{
+ char *base10 = "0123456789";
+
+ for (size_t i = 0; i < strlen(base10); i++) {
+ int expected = (int) i;
+ int actual = _digittoint(base10[i]);
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+ }
+
+ char *base16 = "0123456789abcdef";
+
+ for (size_t i = 0; i < strlen(base16); i++) {
+ int expected = (int) i;
+ int actual = _digittoint(base16[i]);
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+ }
+
+ base16 = "0123456789ABCDEF";
+
+ for (size_t i = 0; i < strlen(base16); i++) {
+ int expected = (int) i;
+ int actual = _digittoint(base16[i]);
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+ }
+}
+
+LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, parcBuffer_Create);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ _longBowGlobal_Global_outstanding = parcMemory_Outstanding();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ LongBowStatus result = LONGBOW_STATUS_SUCCEEDED;
+
+ size_t allocationsLeaked = parcMemory_Outstanding() - _longBowGlobal_Global_outstanding;
+
+ if (allocationsLeaked) {
+ printf("%s leaks memory by %zd allocations\n", longBowTestCase_GetName(testCase), allocationsLeaked);
+ parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ result = LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return result;
+}
+
+LONGBOW_TEST_CASE(Performance, parcBuffer_Create)
+{
+ for (size_t i = 0; i < 1000000; i++) {
+ PARCBuffer *buffer = parcBuffer_Allocate(1200);
+ parcBuffer_Release(&buffer);
+ }
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parcBuffer);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}