aboutsummaryrefslogtreecommitdiffstats
path: root/libparc/parc/algol/test
diff options
context:
space:
mode:
Diffstat (limited to 'libparc/parc/algol/test')
-rw-r--r--libparc/parc/algol/test/.gitignore73
-rw-r--r--libparc/parc/algol/test/CMakeLists.txt76
-rw-r--r--libparc/parc/algol/test/_test_parc_URI.h57
-rw-r--r--libparc/parc/algol/test/data.json2614
-rwxr-xr-xlibparc/parc/algol/test/test_parc_ArrayList.c658
-rw-r--r--libparc/parc/algol/test/test_parc_AtomicInteger.c156
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Base64.c414
-rwxr-xr-xlibparc/parc/algol/test/test_parc_BitVector.c438
-rw-r--r--libparc/parc/algol/test/test_parc_Buffer.c1502
-rwxr-xr-xlibparc/parc/algol/test/test_parc_BufferChunker.c336
-rw-r--r--libparc/parc/algol/test/test_parc_BufferComposer.c448
-rwxr-xr-xlibparc/parc/algol/test/test_parc_ByteArray.c499
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Chunker.c271
-rw-r--r--libparc/parc/algol/test/test_parc_Clock.c198
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Deque.c620
-rw-r--r--libparc/parc/algol/test/test_parc_Dictionary.c736
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Display.c85
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Environment.c86
-rw-r--r--libparc/parc/algol/test/test_parc_Event.c243
-rw-r--r--libparc/parc/algol/test/test_parc_EventBuffer.c345
-rw-r--r--libparc/parc/algol/test/test_parc_EventQueue.c402
-rwxr-xr-xlibparc/parc/algol/test/test_parc_EventScheduler.c263
-rw-r--r--libparc/parc/algol/test/test_parc_EventSignal.c167
-rw-r--r--libparc/parc/algol/test/test_parc_EventSocket.c128
-rwxr-xr-xlibparc/parc/algol/test/test_parc_EventTimer.c143
-rw-r--r--libparc/parc/algol/test/test_parc_File.c208
-rwxr-xr-xlibparc/parc/algol/test/test_parc_FileChunker.c431
-rwxr-xr-xlibparc/parc/algol/test/test_parc_FileInputStream.c107
-rwxr-xr-xlibparc/parc/algol/test/test_parc_FileOutputStream.c167
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Hash.c253
-rwxr-xr-xlibparc/parc/algol/test/test_parc_HashCode.c109
-rwxr-xr-xlibparc/parc/algol/test/test_parc_HashCodeTable.c423
-rw-r--r--libparc/parc/algol/test/test_parc_HashMap.c915
-rwxr-xr-xlibparc/parc/algol/test/test_parc_InputStream.c109
-rw-r--r--libparc/parc/algol/test/test_parc_Iterator.c192
-rw-r--r--libparc/parc/algol/test/test_parc_JSON.c690
-rwxr-xr-xlibparc/parc/algol/test/test_parc_JSONArray.c227
-rw-r--r--libparc/parc/algol/test/test_parc_JSONPair.c421
-rwxr-xr-xlibparc/parc/algol/test/test_parc_JSONParser.c310
-rw-r--r--libparc/parc/algol/test/test_parc_JSONValue.c1365
-rwxr-xr-xlibparc/parc/algol/test/test_parc_KeyValue.c386
-rwxr-xr-xlibparc/parc/algol/test/test_parc_KeyedElement.c134
-rw-r--r--libparc/parc/algol/test/test_parc_LinkedList.c1192
-rw-r--r--libparc/parc/algol/test/test_parc_List.c872
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Memory.c220
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Network.c668
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Object.c1580
-rwxr-xr-xlibparc/parc/algol/test/test_parc_PathName.c458
-rw-r--r--libparc/parc/algol/test/test_parc_PriorityQueue.c492
-rw-r--r--libparc/parc/algol/test/test_parc_Properties.c277
-rw-r--r--libparc/parc/algol/test/test_parc_RandomAccessFile.c380
-rw-r--r--libparc/parc/algol/test/test_parc_ReadOnlyBuffer.c689
-rw-r--r--libparc/parc/algol/test/test_parc_SafeMemory.c813
-rw-r--r--libparc/parc/algol/test/test_parc_SortedList.c510
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Stack.c119
-rw-r--r--libparc/parc/algol/test/test_parc_StdlibMemory.c326
-rw-r--r--libparc/parc/algol/test/test_parc_String.c210
-rw-r--r--libparc/parc/algol/test/test_parc_Time.c144
-rwxr-xr-xlibparc/parc/algol/test/test_parc_TreeMap.c1565
-rwxr-xr-xlibparc/parc/algol/test/test_parc_TreeRedBlack.c1461
-rw-r--r--libparc/parc/algol/test/test_parc_URI.c642
-rw-r--r--libparc/parc/algol/test/test_parc_URIAuthority.c267
-rw-r--r--libparc/parc/algol/test/test_parc_URIPath.c406
-rw-r--r--libparc/parc/algol/test/test_parc_URISegment.c315
-rwxr-xr-xlibparc/parc/algol/test/test_parc_Varint.c310
-rw-r--r--libparc/parc/algol/test/test_parc_Vector.c116
66 files changed, 31437 insertions, 0 deletions
diff --git a/libparc/parc/algol/test/.gitignore b/libparc/parc/algol/test/.gitignore
new file mode 100644
index 00000000..b520ab17
--- /dev/null
+++ b/libparc/parc/algol/test/.gitignore
@@ -0,0 +1,73 @@
+test_parc_ArrayList
+test_parc_AtomicInteger
+test_parc_Base64
+test_parc_BitVector
+test_parc_Buffer
+test_parc_BufferComposer
+test_parc_BufferDictionary
+test_parc_ByteArray
+test_parc_ByteBuffer
+test_parc_ByteBufferCodec
+test_parc_ByteBuffer_Codec
+test_parc_Clock
+test_parc_Deque
+test_parc_Dictionary
+test_parc_Digester
+test_parc_Digests
+test_parc_Digests
+test_parc_Display
+test_parc_ElasticBuffer
+test_parc_ElasticString
+test_parc_Environment
+test_parc_Event
+test_parc_EventBuffer
+test_parc_EventQueue
+test_parc_EventScheduler
+test_parc_EventSignal
+test_parc_EventSocket
+test_parc_EventTimer
+test_parc_Extent
+test_parc_ExtentArray
+test_parc_FileOutputStream
+test_parc_Hash
+test_parc_HashCode
+test_parc_HashCodeTable
+test_parc_HashMap
+test_parc_HashMap
+test_parc_HashTable
+test_parc_InputStream
+test_parc_Iterator
+test_parc_JSON
+test_parc_JSONArray
+test_parc_JSONPair
+test_parc_JSONParser
+test_parc_JSONValue
+test_parc_KeyValue
+test_parc_KeyedElement
+test_parc_LinkedList
+test_parc_List
+test_parc_Memory
+test_parc_Network
+test_parc_NewByteBuffer
+test_parc_Object
+test_parc_ObjectImpl
+test_parc_PathName
+test_parc_PointerArray
+test_parc_PriorityQueue
+test_parc_Properties
+test_parc_ReadOnlyBuffer
+test_parc_SafeMemory
+test_parc_SortedList
+test_parc_Stack
+test_parc_StdlibMemory
+test_parc_String
+test_parc_StructArray
+test_parc_Time
+test_parc_Tlv
+test_parc_TreeRedBlack
+test_parc_TreeMap
+test_parc_URI
+test_parc_VarInt
+test_parc_Varint
+test_parc_Vector
+test_parc_VectorArray
diff --git a/libparc/parc/algol/test/CMakeLists.txt b/libparc/parc/algol/test/CMakeLists.txt
new file mode 100644
index 00000000..4199f3de
--- /dev/null
+++ b/libparc/parc/algol/test/CMakeLists.txt
@@ -0,0 +1,76 @@
+# Enable gcov output for the tests
+add_definitions(--coverage)
+set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
+
+configure_file(data.json data.json COPYONLY)
+
+set(TestsExpectedToPass
+ test_parc_ArrayList
+ test_parc_AtomicInteger
+ test_parc_Base64
+ test_parc_BitVector
+ test_parc_Buffer
+ test_parc_BufferChunker
+ test_parc_BufferComposer
+ test_parc_ByteArray
+ test_parc_Clock
+ test_parc_Chunker
+ test_parc_Deque
+ test_parc_Dictionary
+ test_parc_Display
+ test_parc_Environment
+ test_parc_Event
+ test_parc_EventBuffer
+ test_parc_EventQueue
+ test_parc_EventScheduler
+ test_parc_EventSignal
+ test_parc_EventSocket
+ test_parc_EventTimer
+ test_parc_File
+ test_parc_FileChunker
+ test_parc_FileInputStream
+ test_parc_FileOutputStream
+ test_parc_Hash
+ test_parc_HashCode
+ test_parc_HashCodeTable
+ test_parc_HashMap
+ test_parc_InputStream
+ test_parc_Iterator
+ test_parc_JSON
+ test_parc_JSONArray
+ test_parc_JSONPair
+ test_parc_JSONParser
+ test_parc_JSONValue
+ test_parc_KeyValue
+ test_parc_KeyedElement
+ test_parc_LinkedList
+ test_parc_List
+ test_parc_Memory
+ test_parc_Network
+ test_parc_Object
+ test_parc_PathName
+ test_parc_PriorityQueue
+ test_parc_Properties
+ test_parc_RandomAccessFile
+ test_parc_ReadOnlyBuffer
+ test_parc_SafeMemory
+ test_parc_SortedList
+ test_parc_Stack
+ test_parc_StdlibMemory
+ test_parc_String
+ test_parc_Time
+ test_parc_TreeMap
+ test_parc_TreeRedBlack
+ test_parc_URI
+ test_parc_URIAuthority
+ test_parc_URIPath
+ test_parc_URISegment
+ test_parc_Varint
+ test_parc_Vector
+ )
+
+foreach(test ${TestsExpectedToPass})
+ AddTest(${test})
+endforeach()
+
+
diff --git a/libparc/parc/algol/test/_test_parc_URI.h b/libparc/parc/algol/test/_test_parc_URI.h
new file mode 100644
index 00000000..01d3afae
--- /dev/null
+++ b/libparc/parc/algol/test/_test_parc_URI.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+/*
+ * _test_parc_URI.h
+ * PARC Algol
+ */
+
+#ifndef PARC_Algol__test_parc_URI_h
+#define PARC_Algol__test_parc_URI_h
+
+#define URI_SCHEME "lci"
+
+#define URI_AUTHORITY_USERINFO "user:pass"
+#define URI_AUTHORITY_USERINFO_2 "user2:pass2"
+#define URI_AUTHORITY_HOSTNAME "parc.com"
+#define URI_AUTHORITY_HOSTNAME_2 "xerox.com"
+#define URI_AUTHORITY_LITERAL_HOSTNAME "127.0.0.1"
+#define URI_AUTHORITY_LITERAL_HOSTNAME6 "[::0]"
+#define URI_AUTHORITY_LITERAL_HOSTNAME6_2 "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]"
+#define URI_AUTHORITY_PORT_1 "1234"
+#define URI_AUTHORITY_PORT_2 "5678"
+
+#define URI_AUTHORITY URI_AUTHORITY_USERINFO "@" URI_AUTHORITY_HOSTNAME ":" URI_AUTHORITY_PORT_1
+#define URI_AUTHORITY_DIFFERENT_PORT URI_AUTHORITY_USERINFO "@" URI_AUTHORITY_HOSTNAME ":" URI_AUTHORITY_PORT_2
+#define URI_AUTHORITY_DIFFERENT_HOST URI_AUTHORITY_USERINFO "@" URI_AUTHORITY_HOSTNAME_2 ":" URI_AUTHORITY_PORT_1
+#define URI_AUTHORITY_LITERAL_HOST URI_AUTHORITY_USERINFO "@" URI_AUTHORITY_LITERAL_HOSTNAME ":" URI_AUTHORITY_PORT_1
+#define URI_AUTHORITY_LITERAL_HOST6 URI_AUTHORITY_USERINFO "@" URI_AUTHORITY_LITERAL_HOSTNAME6 ":" URI_AUTHORITY_PORT_1
+#define URI_AUTHORITY_LITERAL_HOST6_2 URI_AUTHORITY_USERINFO "@" URI_AUTHORITY_LITERAL_HOSTNAME6_2 ":" URI_AUTHORITY_PORT_1
+#define URI_AUTHORITY_DIFFERENT_USER URI_AUTHORITY_USERINFO_2 "@" URI_AUTHORITY_HOSTNAME ":" URI_AUTHORITY_PORT_1
+
+#define URI_PATH_SEGMENT "%00%01%02-.%03%04_%05%06%07%08%09abcdefghijklmnopqrstuvwxyz"
+#define URI_PATH_SEGMENT_WITH_SLASHES URI_PATH_SEGMENT "//////"
+
+#define URI_PATH "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT
+
+#define URI_QUERY "x=1&y=2&z=3"
+
+#define URI_FRAGMENT "alphabetagamma"
+
+#define URI_FULL URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH "?" URI_QUERY "#" URI_FRAGMENT
+
+char *TEST_URI_SCHEME = URI_SCHEME;
+char *TEST_URI_AUTHORITY = URI_AUTHORITY;
+#endif // PARC_Algol__test_parc_URI_h
diff --git a/libparc/parc/algol/test/data.json b/libparc/parc/algol/test/data.json
new file mode 100644
index 00000000..a146f6ff
--- /dev/null
+++ b/libparc/parc/algol/test/data.json
@@ -0,0 +1,2614 @@
+{
+ "array" : [
+ {
+ "id": 6104546,
+ "name": "-REPONAME",
+ "full_name": "mralexgray/-REPONAME",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/-REPONAME",
+ "description": null,
+ "fork": false,
+ "url": "https://api.github.com/repos/mralexgray/-REPONAME",
+ "forks_url": "https://api.github.com/repos/mralexgray/-REPONAME/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/-REPONAME/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/-REPONAME/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/-REPONAME/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/-REPONAME/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/-REPONAME/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/-REPONAME/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/-REPONAME/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/-REPONAME/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/-REPONAME/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/-REPONAME/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/-REPONAME/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/-REPONAME/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/-REPONAME/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/-REPONAME/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/-REPONAME/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/-REPONAME/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/-REPONAME/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/-REPONAME/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/-REPONAME/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/-REPONAME/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/-REPONAME/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/-REPONAME/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/-REPONAME/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/-REPONAME/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/-REPONAME/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/-REPONAME/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/-REPONAME/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/-REPONAME/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/-REPONAME/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/-REPONAME/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/-REPONAME/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/-REPONAME/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/-REPONAME/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/-REPONAME/releases{/id}",
+ "created_at": "2012-10-06T16:37:39Z",
+ "updated_at": "2013-01-12T13:39:30Z",
+ "pushed_at": "2012-10-06T16:37:39Z",
+ "git_url": "git://github.com/mralexgray/-REPONAME.git",
+ "ssh_url": "git@github.com:mralexgray/-REPONAME.git",
+ "clone_url": "https://github.com/mralexgray/-REPONAME.git",
+ "svn_url": "https://github.com/mralexgray/-REPONAME",
+ "homepage": null,
+ "size": 48,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": null,
+ "has_issues": true,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 13121042,
+ "name": "ace",
+ "full_name": "mralexgray/ace",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/ace",
+ "description": "Ace (Ajax.org Cloud9 Editor)",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/ace",
+ "forks_url": "https://api.github.com/repos/mralexgray/ace/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/ace/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/ace/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/ace/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/ace/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/ace/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/ace/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/ace/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/ace/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/ace/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/ace/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/ace/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/ace/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/ace/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/ace/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/ace/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/ace/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/ace/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/ace/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/ace/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/ace/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/ace/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/ace/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/ace/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/ace/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/ace/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/ace/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/ace/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/ace/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/ace/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/ace/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/ace/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/ace/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/ace/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/ace/releases{/id}",
+ "created_at": "2013-09-26T11:58:10Z",
+ "updated_at": "2013-10-26T12:34:49Z",
+ "pushed_at": "2013-10-26T12:34:48Z",
+ "git_url": "git://github.com/mralexgray/ace.git",
+ "ssh_url": "git@github.com:mralexgray/ace.git",
+ "clone_url": "https://github.com/mralexgray/ace.git",
+ "svn_url": "https://github.com/mralexgray/ace",
+ "homepage": "http://ace.c9.io",
+ "size": 21080,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "JavaScript",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 10791045,
+ "name": "ACEView",
+ "full_name": "mralexgray/ACEView",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/ACEView",
+ "description": "Use the wonderful ACE editor in your Cocoa applications",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/ACEView",
+ "forks_url": "https://api.github.com/repos/mralexgray/ACEView/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/ACEView/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/ACEView/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/ACEView/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/ACEView/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/ACEView/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/ACEView/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/ACEView/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/ACEView/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/ACEView/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/ACEView/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/ACEView/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/ACEView/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/ACEView/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/ACEView/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/ACEView/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/ACEView/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/ACEView/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/ACEView/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/ACEView/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/ACEView/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/ACEView/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/ACEView/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/ACEView/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/ACEView/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/ACEView/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/ACEView/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/ACEView/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/ACEView/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/ACEView/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/ACEView/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/ACEView/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/ACEView/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/ACEView/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/ACEView/releases{/id}",
+ "created_at": "2013-06-19T12:15:04Z",
+ "updated_at": "2013-10-30T12:39:24Z",
+ "pushed_at": "2013-10-30T12:39:18Z",
+ "git_url": "git://github.com/mralexgray/ACEView.git",
+ "ssh_url": "git@github.com:mralexgray/ACEView.git",
+ "clone_url": "https://github.com/mralexgray/ACEView.git",
+ "svn_url": "https://github.com/mralexgray/ACEView",
+ "homepage": null,
+ "size": 1661,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 13623648,
+ "name": "ActiveLog",
+ "full_name": "mralexgray/ActiveLog",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/ActiveLog",
+ "description": "Shut up all logs with active filter.",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/ActiveLog",
+ "forks_url": "https://api.github.com/repos/mralexgray/ActiveLog/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/ActiveLog/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/ActiveLog/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/ActiveLog/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/ActiveLog/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/ActiveLog/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/ActiveLog/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/ActiveLog/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/ActiveLog/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/ActiveLog/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/ActiveLog/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/ActiveLog/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/ActiveLog/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/ActiveLog/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/ActiveLog/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/ActiveLog/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/ActiveLog/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/ActiveLog/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/ActiveLog/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/ActiveLog/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/ActiveLog/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/ActiveLog/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/ActiveLog/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/ActiveLog/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/ActiveLog/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/ActiveLog/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/ActiveLog/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/ActiveLog/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/ActiveLog/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/ActiveLog/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/ActiveLog/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/ActiveLog/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/ActiveLog/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/ActiveLog/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/ActiveLog/releases{/id}",
+ "created_at": "2013-10-16T15:52:37Z",
+ "updated_at": "2013-10-16T15:52:37Z",
+ "pushed_at": "2011-07-03T06:28:59Z",
+ "git_url": "git://github.com/mralexgray/ActiveLog.git",
+ "ssh_url": "git@github.com:mralexgray/ActiveLog.git",
+ "clone_url": "https://github.com/mralexgray/ActiveLog.git",
+ "svn_url": "https://github.com/mralexgray/ActiveLog",
+ "homepage": "http://deepitpro.com/en/articles/ActiveLog/info/",
+ "size": 60,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 9716210,
+ "name": "adium",
+ "full_name": "mralexgray/adium",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/adium",
+ "description": "Official mirror of hg.adium.im",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/adium",
+ "forks_url": "https://api.github.com/repos/mralexgray/adium/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/adium/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/adium/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/adium/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/adium/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/adium/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/adium/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/adium/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/adium/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/adium/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/adium/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/adium/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/adium/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/adium/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/adium/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/adium/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/adium/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/adium/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/adium/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/adium/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/adium/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/adium/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/adium/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/adium/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/adium/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/adium/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/adium/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/adium/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/adium/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/adium/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/adium/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/adium/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/adium/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/adium/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/adium/releases{/id}",
+ "created_at": "2013-04-27T14:59:33Z",
+ "updated_at": "2013-04-27T14:59:33Z",
+ "pushed_at": "2013-04-26T16:43:53Z",
+ "git_url": "git://github.com/mralexgray/adium.git",
+ "ssh_url": "git@github.com:mralexgray/adium.git",
+ "clone_url": "https://github.com/mralexgray/adium.git",
+ "svn_url": "https://github.com/mralexgray/adium",
+ "homepage": null,
+ "size": 277719,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 12752329,
+ "name": "ADLivelyTableView",
+ "full_name": "mralexgray/ADLivelyTableView",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/ADLivelyTableView",
+ "description": "Lively UITableView",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/ADLivelyTableView",
+ "forks_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/ADLivelyTableView/releases{/id}",
+ "created_at": "2013-09-11T09:18:01Z",
+ "updated_at": "2013-09-11T09:18:03Z",
+ "pushed_at": "2012-05-10T10:40:15Z",
+ "git_url": "git://github.com/mralexgray/ADLivelyTableView.git",
+ "ssh_url": "git@github.com:mralexgray/ADLivelyTableView.git",
+ "clone_url": "https://github.com/mralexgray/ADLivelyTableView.git",
+ "svn_url": "https://github.com/mralexgray/ADLivelyTableView",
+ "homepage": "http://applidium.com/en/news/lively_uitableview/",
+ "size": 73,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 5697379,
+ "name": "AFIncrementalStore",
+ "full_name": "mralexgray/AFIncrementalStore",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/AFIncrementalStore",
+ "description": "Core Data Persistence with AFNetworking, Done Right",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/AFIncrementalStore",
+ "forks_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/AFIncrementalStore/releases{/id}",
+ "created_at": "2012-09-06T04:20:33Z",
+ "updated_at": "2013-01-12T03:15:29Z",
+ "pushed_at": "2012-09-01T22:46:25Z",
+ "git_url": "git://github.com/mralexgray/AFIncrementalStore.git",
+ "ssh_url": "git@github.com:mralexgray/AFIncrementalStore.git",
+ "clone_url": "https://github.com/mralexgray/AFIncrementalStore.git",
+ "svn_url": "https://github.com/mralexgray/AFIncrementalStore",
+ "homepage": null,
+ "size": 139,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 6969621,
+ "name": "AFNetworking",
+ "full_name": "mralexgray/AFNetworking",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/AFNetworking",
+ "description": "A delightful iOS and OS X networking framework",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/AFNetworking",
+ "forks_url": "https://api.github.com/repos/mralexgray/AFNetworking/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/AFNetworking/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/AFNetworking/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/AFNetworking/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/AFNetworking/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/AFNetworking/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/AFNetworking/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/AFNetworking/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/AFNetworking/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/AFNetworking/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/AFNetworking/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/AFNetworking/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/AFNetworking/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/AFNetworking/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/AFNetworking/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/AFNetworking/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/AFNetworking/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/AFNetworking/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/AFNetworking/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/AFNetworking/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/AFNetworking/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/AFNetworking/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/AFNetworking/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/AFNetworking/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/AFNetworking/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/AFNetworking/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/AFNetworking/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/AFNetworking/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/AFNetworking/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/AFNetworking/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/AFNetworking/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/AFNetworking/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/AFNetworking/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/AFNetworking/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/AFNetworking/releases{/id}",
+ "created_at": "2012-12-02T17:00:04Z",
+ "updated_at": "2014-01-24T07:14:33Z",
+ "pushed_at": "2014-01-24T07:14:32Z",
+ "git_url": "git://github.com/mralexgray/AFNetworking.git",
+ "ssh_url": "git@github.com:mralexgray/AFNetworking.git",
+ "clone_url": "https://github.com/mralexgray/AFNetworking.git",
+ "svn_url": "https://github.com/mralexgray/AFNetworking",
+ "homepage": "http://afnetworking.com",
+ "size": 4341,
+ "stargazers_count": 1,
+ "watchers_count": 1,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 1,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 9485541,
+ "name": "AGNSSplitView",
+ "full_name": "mralexgray/AGNSSplitView",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/AGNSSplitView",
+ "description": "Simple NSSplitView additions.",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/AGNSSplitView",
+ "forks_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/AGNSSplitView/releases{/id}",
+ "created_at": "2013-04-17T00:10:13Z",
+ "updated_at": "2013-04-17T00:10:13Z",
+ "pushed_at": "2013-02-26T00:32:32Z",
+ "git_url": "git://github.com/mralexgray/AGNSSplitView.git",
+ "ssh_url": "git@github.com:mralexgray/AGNSSplitView.git",
+ "clone_url": "https://github.com/mralexgray/AGNSSplitView.git",
+ "svn_url": "https://github.com/mralexgray/AGNSSplitView",
+ "homepage": null,
+ "size": 68,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 12767784,
+ "name": "AGScopeBar",
+ "full_name": "mralexgray/AGScopeBar",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/AGScopeBar",
+ "description": "Custom scope bar implementation for Cocoa",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/AGScopeBar",
+ "forks_url": "https://api.github.com/repos/mralexgray/AGScopeBar/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/AGScopeBar/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/AGScopeBar/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/AGScopeBar/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/AGScopeBar/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/AGScopeBar/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/AGScopeBar/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/AGScopeBar/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/AGScopeBar/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/AGScopeBar/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/AGScopeBar/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/AGScopeBar/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/AGScopeBar/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/AGScopeBar/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/AGScopeBar/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/AGScopeBar/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/AGScopeBar/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/AGScopeBar/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/AGScopeBar/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/AGScopeBar/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/AGScopeBar/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/AGScopeBar/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/AGScopeBar/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/AGScopeBar/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/AGScopeBar/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/AGScopeBar/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/AGScopeBar/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/AGScopeBar/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/AGScopeBar/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/AGScopeBar/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/AGScopeBar/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/AGScopeBar/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/AGScopeBar/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/AGScopeBar/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/AGScopeBar/releases{/id}",
+ "created_at": "2013-09-11T21:06:54Z",
+ "updated_at": "2013-09-11T21:06:54Z",
+ "pushed_at": "2013-05-07T03:35:29Z",
+ "git_url": "git://github.com/mralexgray/AGScopeBar.git",
+ "ssh_url": "git@github.com:mralexgray/AGScopeBar.git",
+ "clone_url": "https://github.com/mralexgray/AGScopeBar.git",
+ "svn_url": "https://github.com/mralexgray/AGScopeBar",
+ "homepage": null,
+ "size": 64,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 9227846,
+ "name": "AHContentBrowser",
+ "full_name": "mralexgray/AHContentBrowser",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/AHContentBrowser",
+ "description": "A Mac only webview that loads a fast readable version of the website if available.",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/AHContentBrowser",
+ "forks_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/AHContentBrowser/releases{/id}",
+ "created_at": "2013-04-04T20:56:16Z",
+ "updated_at": "2013-04-04T20:56:16Z",
+ "pushed_at": "2013-03-13T17:38:23Z",
+ "git_url": "git://github.com/mralexgray/AHContentBrowser.git",
+ "ssh_url": "git@github.com:mralexgray/AHContentBrowser.git",
+ "clone_url": "https://github.com/mralexgray/AHContentBrowser.git",
+ "svn_url": "https://github.com/mralexgray/AHContentBrowser",
+ "homepage": "",
+ "size": 223,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 9167473,
+ "name": "AHLayout",
+ "full_name": "mralexgray/AHLayout",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/AHLayout",
+ "description": "AHLayout",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/AHLayout",
+ "forks_url": "https://api.github.com/repos/mralexgray/AHLayout/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/AHLayout/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/AHLayout/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/AHLayout/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/AHLayout/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/AHLayout/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/AHLayout/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/AHLayout/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/AHLayout/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/AHLayout/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/AHLayout/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/AHLayout/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/AHLayout/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/AHLayout/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/AHLayout/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/AHLayout/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/AHLayout/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/AHLayout/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/AHLayout/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/AHLayout/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/AHLayout/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/AHLayout/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/AHLayout/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/AHLayout/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/AHLayout/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/AHLayout/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/AHLayout/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/AHLayout/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/AHLayout/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/AHLayout/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/AHLayout/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/AHLayout/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/AHLayout/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/AHLayout/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/AHLayout/releases{/id}",
+ "created_at": "2013-04-02T10:10:30Z",
+ "updated_at": "2013-07-08T02:31:17Z",
+ "pushed_at": "2013-07-08T02:31:14Z",
+ "git_url": "git://github.com/mralexgray/AHLayout.git",
+ "ssh_url": "git@github.com:mralexgray/AHLayout.git",
+ "clone_url": "https://github.com/mralexgray/AHLayout.git",
+ "svn_url": "https://github.com/mralexgray/AHLayout",
+ "homepage": null,
+ "size": 359,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 18450201,
+ "name": "Airmail-Plug-In-Framework",
+ "full_name": "mralexgray/Airmail-Plug-In-Framework",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/Airmail-Plug-In-Framework",
+ "description": "",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework",
+ "forks_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/Airmail-Plug-In-Framework/releases{/id}",
+ "created_at": "2014-04-04T19:33:54Z",
+ "updated_at": "2014-04-04T19:33:54Z",
+ "pushed_at": "2014-03-27T15:42:19Z",
+ "git_url": "git://github.com/mralexgray/Airmail-Plug-In-Framework.git",
+ "ssh_url": "git@github.com:mralexgray/Airmail-Plug-In-Framework.git",
+ "clone_url": "https://github.com/mralexgray/Airmail-Plug-In-Framework.git",
+ "svn_url": "https://github.com/mralexgray/Airmail-Plug-In-Framework",
+ "homepage": null,
+ "size": 888,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": null,
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 5203219,
+ "name": "AJS-iTunes-API",
+ "full_name": "mralexgray/AJS-iTunes-API",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/AJS-iTunes-API",
+ "description": "Cocoa wrapper for the iTunes search API - for iOS and Mac OSX projects",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API",
+ "forks_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/AJS-iTunes-API/releases{/id}",
+ "created_at": "2012-07-27T10:20:58Z",
+ "updated_at": "2013-01-11T11:00:05Z",
+ "pushed_at": "2011-10-30T22:26:48Z",
+ "git_url": "git://github.com/mralexgray/AJS-iTunes-API.git",
+ "ssh_url": "git@github.com:mralexgray/AJS-iTunes-API.git",
+ "clone_url": "https://github.com/mralexgray/AJS-iTunes-API.git",
+ "svn_url": "https://github.com/mralexgray/AJS-iTunes-API",
+ "homepage": "",
+ "size": 103,
+ "stargazers_count": 1,
+ "watchers_count": 1,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 1,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 10093801,
+ "name": "Alcatraz",
+ "full_name": "mralexgray/Alcatraz",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/Alcatraz",
+ "description": "The most awesome (and only) Xcode package manager!",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/Alcatraz",
+ "forks_url": "https://api.github.com/repos/mralexgray/Alcatraz/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/Alcatraz/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/Alcatraz/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/Alcatraz/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/Alcatraz/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/Alcatraz/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/Alcatraz/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/Alcatraz/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/Alcatraz/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/Alcatraz/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/Alcatraz/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/Alcatraz/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/Alcatraz/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/Alcatraz/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/Alcatraz/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/Alcatraz/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/Alcatraz/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/Alcatraz/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/Alcatraz/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/Alcatraz/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/Alcatraz/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/Alcatraz/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/Alcatraz/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/Alcatraz/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/Alcatraz/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/Alcatraz/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/Alcatraz/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/Alcatraz/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/Alcatraz/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/Alcatraz/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/Alcatraz/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/Alcatraz/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/Alcatraz/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/Alcatraz/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/Alcatraz/releases{/id}",
+ "created_at": "2013-05-16T04:41:13Z",
+ "updated_at": "2014-03-19T20:38:35Z",
+ "pushed_at": "2014-03-19T12:50:37Z",
+ "git_url": "git://github.com/mralexgray/Alcatraz.git",
+ "ssh_url": "git@github.com:mralexgray/Alcatraz.git",
+ "clone_url": "https://github.com/mralexgray/Alcatraz.git",
+ "svn_url": "https://github.com/mralexgray/Alcatraz",
+ "homepage": "mneorr.github.com/Alcatraz",
+ "size": 3668,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 12916552,
+ "name": "alcatraz-packages",
+ "full_name": "mralexgray/alcatraz-packages",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/alcatraz-packages",
+ "description": "Package list repository for Alcatraz",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/alcatraz-packages",
+ "forks_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/alcatraz-packages/releases{/id}",
+ "created_at": "2013-09-18T07:15:24Z",
+ "updated_at": "2013-09-18T07:15:25Z",
+ "pushed_at": "2013-09-09T07:51:48Z",
+ "git_url": "git://github.com/mralexgray/alcatraz-packages.git",
+ "ssh_url": "git@github.com:mralexgray/alcatraz-packages.git",
+ "clone_url": "https://github.com/mralexgray/alcatraz-packages.git",
+ "svn_url": "https://github.com/mralexgray/alcatraz-packages",
+ "homepage": "mneorr.github.com/Alcatraz",
+ "size": 482,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Ruby",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 10476467,
+ "name": "Alfred-Google-Translate",
+ "full_name": "mralexgray/Alfred-Google-Translate",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/Alfred-Google-Translate",
+ "description": "Extension for Alfred that will do a Google translate for you",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate",
+ "forks_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/Alfred-Google-Translate/releases{/id}",
+ "created_at": "2013-06-04T10:45:10Z",
+ "updated_at": "2013-06-04T10:45:10Z",
+ "pushed_at": "2013-01-12T19:39:03Z",
+ "git_url": "git://github.com/mralexgray/Alfred-Google-Translate.git",
+ "ssh_url": "git@github.com:mralexgray/Alfred-Google-Translate.git",
+ "clone_url": "https://github.com/mralexgray/Alfred-Google-Translate.git",
+ "svn_url": "https://github.com/mralexgray/Alfred-Google-Translate",
+ "homepage": null,
+ "size": 103,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Shell",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 5524019,
+ "name": "Amber",
+ "full_name": "mralexgray/Amber",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/Amber",
+ "description": "Fork of the difficult-to-deal-with Amber.framework",
+ "fork": false,
+ "url": "https://api.github.com/repos/mralexgray/Amber",
+ "forks_url": "https://api.github.com/repos/mralexgray/Amber/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/Amber/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/Amber/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/Amber/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/Amber/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/Amber/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/Amber/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/Amber/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/Amber/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/Amber/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/Amber/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/Amber/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/Amber/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/Amber/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/Amber/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/Amber/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/Amber/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/Amber/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/Amber/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/Amber/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/Amber/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/Amber/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/Amber/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/Amber/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/Amber/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/Amber/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/Amber/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/Amber/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/Amber/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/Amber/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/Amber/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/Amber/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/Amber/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/Amber/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/Amber/releases{/id}",
+ "created_at": "2012-08-23T10:38:24Z",
+ "updated_at": "2013-01-11T22:25:35Z",
+ "pushed_at": "2012-08-23T10:38:25Z",
+ "git_url": "git://github.com/mralexgray/Amber.git",
+ "ssh_url": "git@github.com:mralexgray/Amber.git",
+ "clone_url": "https://github.com/mralexgray/Amber.git",
+ "svn_url": "https://github.com/mralexgray/Amber",
+ "homepage": null,
+ "size": 48,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": null,
+ "has_issues": true,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 10809060,
+ "name": "Amethyst",
+ "full_name": "mralexgray/Amethyst",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/Amethyst",
+ "description": "Tiling window manager for OS X.",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/Amethyst",
+ "forks_url": "https://api.github.com/repos/mralexgray/Amethyst/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/Amethyst/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/Amethyst/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/Amethyst/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/Amethyst/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/Amethyst/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/Amethyst/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/Amethyst/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/Amethyst/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/Amethyst/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/Amethyst/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/Amethyst/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/Amethyst/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/Amethyst/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/Amethyst/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/Amethyst/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/Amethyst/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/Amethyst/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/Amethyst/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/Amethyst/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/Amethyst/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/Amethyst/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/Amethyst/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/Amethyst/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/Amethyst/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/Amethyst/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/Amethyst/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/Amethyst/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/Amethyst/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/Amethyst/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/Amethyst/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/Amethyst/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/Amethyst/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/Amethyst/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/Amethyst/releases{/id}",
+ "created_at": "2013-06-20T00:34:22Z",
+ "updated_at": "2013-06-20T00:34:22Z",
+ "pushed_at": "2013-06-18T02:54:11Z",
+ "git_url": "git://github.com/mralexgray/Amethyst.git",
+ "ssh_url": "git@github.com:mralexgray/Amethyst.git",
+ "clone_url": "https://github.com/mralexgray/Amethyst.git",
+ "svn_url": "https://github.com/mralexgray/Amethyst",
+ "homepage": "http://ianyh.github.io/Amethyst/",
+ "size": 12623,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 3684286,
+ "name": "Animated-Paths",
+ "full_name": "mralexgray/Animated-Paths",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/Animated-Paths",
+ "description": "Demo project: Animating the drawing of a CGPath with CAShapeLayer.strokeEnd",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/Animated-Paths",
+ "forks_url": "https://api.github.com/repos/mralexgray/Animated-Paths/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/Animated-Paths/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/Animated-Paths/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/Animated-Paths/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/Animated-Paths/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/Animated-Paths/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/Animated-Paths/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/Animated-Paths/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/Animated-Paths/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/Animated-Paths/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/Animated-Paths/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/Animated-Paths/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/Animated-Paths/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/Animated-Paths/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/Animated-Paths/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/Animated-Paths/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/Animated-Paths/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/Animated-Paths/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/Animated-Paths/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/Animated-Paths/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/Animated-Paths/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/Animated-Paths/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/Animated-Paths/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/Animated-Paths/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/Animated-Paths/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/Animated-Paths/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/Animated-Paths/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/Animated-Paths/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/Animated-Paths/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/Animated-Paths/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/Animated-Paths/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/Animated-Paths/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/Animated-Paths/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/Animated-Paths/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/Animated-Paths/releases{/id}",
+ "created_at": "2012-03-11T02:56:38Z",
+ "updated_at": "2013-01-08T04:12:21Z",
+ "pushed_at": "2010-12-30T20:56:51Z",
+ "git_url": "git://github.com/mralexgray/Animated-Paths.git",
+ "ssh_url": "git@github.com:mralexgray/Animated-Paths.git",
+ "clone_url": "https://github.com/mralexgray/Animated-Paths.git",
+ "svn_url": "https://github.com/mralexgray/Animated-Paths",
+ "homepage": "http://oleb.net/blog/2010/12/animating-drawing-of-cgpath-with-cashapelayer/",
+ "size": 411,
+ "stargazers_count": 1,
+ "watchers_count": 1,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 1,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 16662874,
+ "name": "AnsiLove.framework",
+ "full_name": "mralexgray/AnsiLove.framework",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/AnsiLove.framework",
+ "description": "Cocoa Framework for rendering ANSi / ASCII art",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/AnsiLove.framework",
+ "forks_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/AnsiLove.framework/releases{/id}",
+ "created_at": "2014-02-09T08:30:27Z",
+ "updated_at": "2014-02-09T08:30:32Z",
+ "pushed_at": "2013-10-04T14:08:38Z",
+ "git_url": "git://github.com/mralexgray/AnsiLove.framework.git",
+ "ssh_url": "git@github.com:mralexgray/AnsiLove.framework.git",
+ "clone_url": "https://github.com/mralexgray/AnsiLove.framework.git",
+ "svn_url": "https://github.com/mralexgray/AnsiLove.framework",
+ "homepage": "http://byteproject.net",
+ "size": 3780,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "M",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 5189563,
+ "name": "ANTrackBar",
+ "full_name": "mralexgray/ANTrackBar",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/ANTrackBar",
+ "description": "An easy-to-use Cocoa seek bar with a pleasing appearance",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/ANTrackBar",
+ "forks_url": "https://api.github.com/repos/mralexgray/ANTrackBar/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/ANTrackBar/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/ANTrackBar/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/ANTrackBar/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/ANTrackBar/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/ANTrackBar/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/ANTrackBar/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/ANTrackBar/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/ANTrackBar/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/ANTrackBar/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/ANTrackBar/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/ANTrackBar/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/ANTrackBar/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/ANTrackBar/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/ANTrackBar/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/ANTrackBar/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/ANTrackBar/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/ANTrackBar/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/ANTrackBar/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/ANTrackBar/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/ANTrackBar/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/ANTrackBar/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/ANTrackBar/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/ANTrackBar/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/ANTrackBar/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/ANTrackBar/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/ANTrackBar/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/ANTrackBar/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/ANTrackBar/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/ANTrackBar/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/ANTrackBar/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/ANTrackBar/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/ANTrackBar/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/ANTrackBar/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/ANTrackBar/releases{/id}",
+ "created_at": "2012-07-26T08:17:22Z",
+ "updated_at": "2013-01-11T10:29:56Z",
+ "pushed_at": "2012-03-09T01:40:02Z",
+ "git_url": "git://github.com/mralexgray/ANTrackBar.git",
+ "ssh_url": "git@github.com:mralexgray/ANTrackBar.git",
+ "clone_url": "https://github.com/mralexgray/ANTrackBar.git",
+ "svn_url": "https://github.com/mralexgray/ANTrackBar",
+ "homepage": "",
+ "size": 94,
+ "stargazers_count": 1,
+ "watchers_count": 1,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 1,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 16240152,
+ "name": "AOP-in-Objective-C",
+ "full_name": "mralexgray/AOP-in-Objective-C",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/AOP-in-Objective-C",
+ "description": "An NSProxy based library for easily enabling AOP like functionality in Objective-C.",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C",
+ "forks_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/AOP-in-Objective-C/releases{/id}",
+ "created_at": "2014-01-25T21:18:04Z",
+ "updated_at": "2014-02-12T16:23:21Z",
+ "pushed_at": "2014-02-12T16:23:20Z",
+ "git_url": "git://github.com/mralexgray/AOP-in-Objective-C.git",
+ "ssh_url": "git@github.com:mralexgray/AOP-in-Objective-C.git",
+ "clone_url": "https://github.com/mralexgray/AOP-in-Objective-C.git",
+ "svn_url": "https://github.com/mralexgray/AOP-in-Objective-C",
+ "homepage": "http://innoli.hu/en/opensource/",
+ "size": 340,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 1,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 1,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "travis-coveralls",
+ "master_branch": "travis-coveralls"
+ },
+ {
+ "id": 13141936,
+ "name": "Apaxy",
+ "full_name": "mralexgray/Apaxy",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/Apaxy",
+ "description": "A simple, customisable theme for your Apache directory listing.",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/Apaxy",
+ "forks_url": "https://api.github.com/repos/mralexgray/Apaxy/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/Apaxy/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/Apaxy/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/Apaxy/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/Apaxy/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/Apaxy/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/Apaxy/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/Apaxy/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/Apaxy/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/Apaxy/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/Apaxy/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/Apaxy/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/Apaxy/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/Apaxy/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/Apaxy/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/Apaxy/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/Apaxy/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/Apaxy/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/Apaxy/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/Apaxy/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/Apaxy/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/Apaxy/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/Apaxy/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/Apaxy/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/Apaxy/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/Apaxy/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/Apaxy/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/Apaxy/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/Apaxy/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/Apaxy/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/Apaxy/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/Apaxy/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/Apaxy/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/Apaxy/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/Apaxy/releases{/id}",
+ "created_at": "2013-09-27T05:05:35Z",
+ "updated_at": "2013-09-27T05:05:36Z",
+ "pushed_at": "2013-08-02T16:01:32Z",
+ "git_url": "git://github.com/mralexgray/Apaxy.git",
+ "ssh_url": "git@github.com:mralexgray/Apaxy.git",
+ "clone_url": "https://github.com/mralexgray/Apaxy.git",
+ "svn_url": "https://github.com/mralexgray/Apaxy",
+ "homepage": null,
+ "size": 113,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "CSS",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 10048098,
+ "name": "appledoc",
+ "full_name": "mralexgray/appledoc",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/appledoc",
+ "description": "Objective-c code Apple style documentation set generator.",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/appledoc",
+ "forks_url": "https://api.github.com/repos/mralexgray/appledoc/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/appledoc/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/appledoc/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/appledoc/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/appledoc/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/appledoc/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/appledoc/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/appledoc/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/appledoc/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/appledoc/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/appledoc/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/appledoc/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/appledoc/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/appledoc/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/appledoc/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/appledoc/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/appledoc/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/appledoc/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/appledoc/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/appledoc/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/appledoc/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/appledoc/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/appledoc/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/appledoc/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/appledoc/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/appledoc/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/appledoc/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/appledoc/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/appledoc/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/appledoc/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/appledoc/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/appledoc/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/appledoc/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/appledoc/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/appledoc/releases{/id}",
+ "created_at": "2013-05-14T05:45:44Z",
+ "updated_at": "2014-02-09T08:14:42Z",
+ "pushed_at": "2014-02-09T08:14:42Z",
+ "git_url": "git://github.com/mralexgray/appledoc.git",
+ "ssh_url": "git@github.com:mralexgray/appledoc.git",
+ "clone_url": "https://github.com/mralexgray/appledoc.git",
+ "svn_url": "https://github.com/mralexgray/appledoc",
+ "homepage": "http://gentlebytes.com",
+ "size": 10336,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": false,
+ "has_wiki": false,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 16160992,
+ "name": "Appstore-Through-Terminal",
+ "full_name": "mralexgray/Appstore-Through-Terminal",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/Appstore-Through-Terminal",
+ "description": "A simple debian package, made for iPhone, to open the iOS AppStore through terminal. Simple. Slightly usless. My work as a beginner.",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal",
+ "forks_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/Appstore-Through-Terminal/releases{/id}",
+ "created_at": "2014-01-23T03:21:34Z",
+ "updated_at": "2014-01-23T03:21:34Z",
+ "pushed_at": "2011-12-21T06:40:25Z",
+ "git_url": "git://github.com/mralexgray/Appstore-Through-Terminal.git",
+ "ssh_url": "git@github.com:mralexgray/Appstore-Through-Terminal.git",
+ "clone_url": "https://github.com/mralexgray/Appstore-Through-Terminal.git",
+ "svn_url": "https://github.com/mralexgray/Appstore-Through-Terminal",
+ "homepage": "http://getagripon.com/tillie/projects.html",
+ "size": 104,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Shell",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 13709216,
+ "name": "appweb-4",
+ "full_name": "mralexgray/appweb-4",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/appweb-4",
+ "description": "Appweb Embeddable Web Server 4",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/appweb-4",
+ "forks_url": "https://api.github.com/repos/mralexgray/appweb-4/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/appweb-4/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/appweb-4/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/appweb-4/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/appweb-4/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/appweb-4/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/appweb-4/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/appweb-4/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/appweb-4/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/appweb-4/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/appweb-4/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/appweb-4/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/appweb-4/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/appweb-4/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/appweb-4/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/appweb-4/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/appweb-4/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/appweb-4/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/appweb-4/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/appweb-4/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/appweb-4/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/appweb-4/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/appweb-4/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/appweb-4/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/appweb-4/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/appweb-4/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/appweb-4/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/appweb-4/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/appweb-4/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/appweb-4/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/appweb-4/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/appweb-4/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/appweb-4/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/appweb-4/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/appweb-4/releases{/id}",
+ "created_at": "2013-10-19T21:36:10Z",
+ "updated_at": "2013-10-19T21:36:11Z",
+ "pushed_at": "2013-10-19T00:35:06Z",
+ "git_url": "git://github.com/mralexgray/appweb-4.git",
+ "ssh_url": "git@github.com:mralexgray/appweb-4.git",
+ "clone_url": "https://github.com/mralexgray/appweb-4.git",
+ "svn_url": "https://github.com/mralexgray/appweb-4",
+ "homepage": "http://appwebserver.org",
+ "size": 58244,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 12501983,
+ "name": "arbor",
+ "full_name": "mralexgray/arbor",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/arbor",
+ "description": "a graph visualization library using web workers and jQuery",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/arbor",
+ "forks_url": "https://api.github.com/repos/mralexgray/arbor/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/arbor/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/arbor/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/arbor/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/arbor/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/arbor/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/arbor/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/arbor/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/arbor/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/arbor/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/arbor/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/arbor/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/arbor/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/arbor/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/arbor/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/arbor/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/arbor/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/arbor/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/arbor/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/arbor/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/arbor/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/arbor/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/arbor/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/arbor/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/arbor/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/arbor/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/arbor/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/arbor/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/arbor/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/arbor/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/arbor/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/arbor/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/arbor/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/arbor/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/arbor/releases{/id}",
+ "created_at": "2013-08-31T07:07:05Z",
+ "updated_at": "2013-08-31T07:07:06Z",
+ "pushed_at": "2012-05-28T00:47:58Z",
+ "git_url": "git://github.com/mralexgray/arbor.git",
+ "ssh_url": "git@github.com:mralexgray/arbor.git",
+ "clone_url": "https://github.com/mralexgray/arbor.git",
+ "svn_url": "https://github.com/mralexgray/arbor",
+ "homepage": "http://arborjs.org",
+ "size": 237,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "JavaScript",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 13537888,
+ "name": "Archimedes",
+ "full_name": "mralexgray/Archimedes",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/Archimedes",
+ "description": "Geometry functions for Cocoa and Cocoa Touch",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/Archimedes",
+ "forks_url": "https://api.github.com/repos/mralexgray/Archimedes/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/Archimedes/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/Archimedes/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/Archimedes/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/Archimedes/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/Archimedes/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/Archimedes/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/Archimedes/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/Archimedes/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/Archimedes/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/Archimedes/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/Archimedes/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/Archimedes/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/Archimedes/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/Archimedes/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/Archimedes/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/Archimedes/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/Archimedes/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/Archimedes/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/Archimedes/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/Archimedes/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/Archimedes/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/Archimedes/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/Archimedes/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/Archimedes/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/Archimedes/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/Archimedes/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/Archimedes/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/Archimedes/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/Archimedes/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/Archimedes/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/Archimedes/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/Archimedes/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/Archimedes/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/Archimedes/releases{/id}",
+ "created_at": "2013-10-13T11:08:19Z",
+ "updated_at": "2014-04-06T00:41:21Z",
+ "pushed_at": "2014-04-06T00:41:20Z",
+ "git_url": "git://github.com/mralexgray/Archimedes.git",
+ "ssh_url": "git@github.com:mralexgray/Archimedes.git",
+ "clone_url": "https://github.com/mralexgray/Archimedes.git",
+ "svn_url": "https://github.com/mralexgray/Archimedes",
+ "homepage": null,
+ "size": 217,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master",
+ "master_branch": "master"
+ },
+ {
+ "id": 5260205,
+ "name": "arrsync",
+ "full_name": "mralexgray/arrsync",
+ "owner": {
+ "login": "mralexgray",
+ "id": 262517,
+ "avatar_url": "https://avatars.githubusercontent.com/u/262517?",
+ "gravatar_id": "50e7ed4eb2e7af000ea7d161748958f1",
+ "url": "https://api.github.com/users/mralexgray",
+ "html_url": "https://github.com/mralexgray",
+ "followers_url": "https://api.github.com/users/mralexgray/followers",
+ "following_url": "https://api.github.com/users/mralexgray/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mralexgray/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mralexgray/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mralexgray/subscriptions",
+ "organizations_url": "https://api.github.com/users/mralexgray/orgs",
+ "repos_url": "https://api.github.com/users/mralexgray/repos",
+ "events_url": "https://api.github.com/users/mralexgray/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mralexgray/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "private": false,
+ "html_url": "https://github.com/mralexgray/arrsync",
+ "description": "",
+ "fork": true,
+ "url": "https://api.github.com/repos/mralexgray/arrsync",
+ "forks_url": "https://api.github.com/repos/mralexgray/arrsync/forks",
+ "keys_url": "https://api.github.com/repos/mralexgray/arrsync/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/mralexgray/arrsync/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/mralexgray/arrsync/teams",
+ "hooks_url": "https://api.github.com/repos/mralexgray/arrsync/hooks",
+ "issue_events_url": "https://api.github.com/repos/mralexgray/arrsync/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/mralexgray/arrsync/events",
+ "assignees_url": "https://api.github.com/repos/mralexgray/arrsync/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/mralexgray/arrsync/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/mralexgray/arrsync/tags",
+ "blobs_url": "https://api.github.com/repos/mralexgray/arrsync/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/mralexgray/arrsync/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/mralexgray/arrsync/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/mralexgray/arrsync/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/mralexgray/arrsync/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/mralexgray/arrsync/languages",
+ "stargazers_url": "https://api.github.com/repos/mralexgray/arrsync/stargazers",
+ "contributors_url": "https://api.github.com/repos/mralexgray/arrsync/contributors",
+ "subscribers_url": "https://api.github.com/repos/mralexgray/arrsync/subscribers",
+ "subscription_url": "https://api.github.com/repos/mralexgray/arrsync/subscription",
+ "commits_url": "https://api.github.com/repos/mralexgray/arrsync/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/mralexgray/arrsync/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/mralexgray/arrsync/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/mralexgray/arrsync/issues/comments/{number}",
+ "contents_url": "https://api.github.com/repos/mralexgray/arrsync/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/mralexgray/arrsync/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/mralexgray/arrsync/merges",
+ "archive_url": "https://api.github.com/repos/mralexgray/arrsync/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/mralexgray/arrsync/downloads",
+ "issues_url": "https://api.github.com/repos/mralexgray/arrsync/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/mralexgray/arrsync/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/mralexgray/arrsync/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/mralexgray/arrsync/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/mralexgray/arrsync/labels{/name}",
+ "releases_url": "https://api.github.com/repos/mralexgray/arrsync/releases{/id}",
+ "created_at": "2012-08-01T14:21:49Z",
+ "updated_at": "2013-01-11T13:12:21Z",
+ "pushed_at": "2011-05-09T18:56:56Z",
+ "git_url": "git://github.com/mralexgray/arrsync.git",
+ "ssh_url": "git@github.com:mralexgray/arrsync.git",
+ "clone_url": "https://github.com/mralexgray/arrsync.git",
+ "svn_url": "https://github.com/mralexgray/arrsync",
+ "homepage": "",
+ "size": 194,
+ "stargazers_count": 2,
+ "watchers_count": 2,
+ "language": "Objective-C",
+ "has_issues": false,
+ "has_downloads": true,
+ "has_wiki": true,
+ "forks_count": 0,
+ "mirror_url": null,
+ "open_issues_count": 0,
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 2,
+ "default_branch": "master",
+ "master_branch": "master"
+ }
+]
+} \ No newline at end of file
diff --git a/libparc/parc/algol/test/test_parc_ArrayList.c b/libparc/parc/algol/test/test_parc_ArrayList.c
new file mode 100755
index 00000000..9e387a28
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_ArrayList.c
@@ -0,0 +1,658 @@
+/*
+ * 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_ArrayList.c"
+#include <LongBow/unit-test.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+#include <parc/algol/parc_Buffer.h>
+
+LONGBOW_TEST_RUNNER(PARC_ArrayList)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+ LONGBOW_RUN_TEST_FIXTURE(Errors);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(PARC_ArrayList)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(PARC_ArrayList)
+{
+ 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_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_Add);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_AddAll);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_Destroy);
+
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_CustomDestroyer);
+
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_Equals_Contract);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_Equals_Contract_Deep);
+
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_FromInitialCapacity);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_Get);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_New);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_Size);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_Remove_AtIndex_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_Remove_AtIndex);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_Remove_AtIndex_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_RemoveAndDestroy_AtIndex_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_RemoveAndDestroy_AtIndex);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_RemoveAndDestroy_AtIndex_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_InsertAtIndex);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_InsertAtIndex_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_InsertAtIndex_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_InsertAtIndex_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_ArrayList_IsEmpty);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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(Global, PARC_ArrayList_Add)
+{
+ PARCArrayList *array = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+
+ parcArrayList_Add(array, 0);
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(1 == actual, "Expected=%d, actual=%zu", 1, actual);
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_AddAll)
+{
+ PARCArrayList *array = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+
+ void *elements[] = {
+ strdup("a"),
+ strdup("b"),
+ strdup("c"),
+ };
+
+ parcArrayList_AddAll(array, elements, 3);
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(3 == actual, "Expected=%d, actual=%zu", 3, actual);
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Copy)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *copy = parcArrayList_Copy(array);
+ assertTrue(parcArrayList_Equals(array, copy), "Expected arrays to be equal.");
+
+ parcArrayList_Destroy(&copy);
+ parcArrayList_Destroy(&array);
+}
+
+static void
+testCustomDestroyer(void **bufferVoidPtr)
+{
+ PARCBuffer **bufferPtr = (PARCBuffer **) bufferVoidPtr;
+ parcBuffer_Release(bufferPtr);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_CustomDestroyer)
+{
+ size_t before = parcMemory_Outstanding();
+
+ PARCArrayList *array = parcArrayList_Create(testCustomDestroyer);
+ PARCBuffer *buffer = parcBuffer_Allocate(20);
+ parcArrayList_Add(array, parcBuffer_Acquire(buffer));
+ parcBuffer_Release(&buffer);
+ parcArrayList_Destroy(&array);
+
+ size_t after = parcMemory_Outstanding();
+
+ assertTrue(before == after, "Memory imbalance after using custom destroy, expected %zu got %zu", before, after);
+}
+
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Destroy)
+{
+ PARCArrayList *array = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+
+ parcArrayList_Destroy(&array);
+ assertNull(array, "Expected null.");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Equals_Empty)
+{
+ PARCArrayList *a = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+ PARCArrayList *b = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+ assertTrue(parcArrayList_Equals(a, b), "Equal values were expected to be equal");
+
+ parcArrayList_Destroy(&a);
+ parcArrayList_Destroy(&b);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Equals_Same)
+{
+ PARCArrayList *a = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+ assertTrue(parcArrayList_Equals(a, a), "Expected the same array list to be equal to itself.");
+
+ parcArrayList_Destroy(&a);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Equals_Contract)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+ char d[] = "potato";
+
+ PARCArrayList *x = parcArrayList_Create(NULL);
+ parcArrayList_Add(x, a);
+ parcArrayList_Add(x, b);
+ parcArrayList_Add(x, c);
+
+ PARCArrayList *y = parcArrayList_Create(NULL);
+ parcArrayList_Add(y, a);
+ parcArrayList_Add(y, b);
+ parcArrayList_Add(y, c);
+
+ PARCArrayList *z = parcArrayList_Create(NULL);
+ parcArrayList_Add(z, a);
+ parcArrayList_Add(z, b);
+ parcArrayList_Add(z, c);
+
+ PARCArrayList *u1 = parcArrayList_Create(NULL);
+ parcArrayList_Add(u1, a);
+ parcArrayList_Add(u1, b);
+
+ PARCArrayList *u2 = parcArrayList_Create(NULL);
+ parcArrayList_Add(u1, a);
+ parcArrayList_Add(u2, b);
+ parcArrayList_Add(u2, c);
+ parcArrayList_Add(u2, c);
+
+ PARCArrayList *u3 = parcArrayList_Create(NULL);
+ parcArrayList_Add(u3, a);
+ parcArrayList_Add(u3, b);
+ parcArrayList_Add(u3, d);
+
+ parcObjectTesting_AssertEqualsFunction(parcArrayList_Equals, x, y, z, u1, u2, u3);
+
+ parcArrayList_Destroy(&x);
+ parcArrayList_Destroy(&y);
+ parcArrayList_Destroy(&z);
+ parcArrayList_Destroy(&u1);
+ parcArrayList_Destroy(&u2);
+ parcArrayList_Destroy(&u3);
+}
+
+static bool
+stringEquals(void *x, void *y)
+{
+ return strcmp((char *) x, (char *) y) == 0;
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Equals_Contract_Deep)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+ char d[] = "potato";
+
+ PARCArrayList *x = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(x, a);
+ parcArrayList_Add(x, b);
+ parcArrayList_Add(x, c);
+
+ PARCArrayList *y = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(y, a);
+ parcArrayList_Add(y, b);
+ parcArrayList_Add(y, c);
+
+ PARCArrayList *z = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(z, a);
+ parcArrayList_Add(z, b);
+ parcArrayList_Add(z, c);
+
+ PARCArrayList *u1 = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(u1, a);
+ parcArrayList_Add(u1, b);
+
+ PARCArrayList *u2 = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(u2, a);
+ parcArrayList_Add(u2, b);
+ parcArrayList_Add(u2, c);
+ parcArrayList_Add(u2, c);
+
+ PARCArrayList *u3 = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(u3, a);
+ parcArrayList_Add(u3, b);
+ parcArrayList_Add(u3, d);
+
+ parcObjectTesting_AssertEqualsFunction(parcArrayList_Equals, x, y, z, u1, u2, u3);
+
+ parcArrayList_Destroy(&x);
+ parcArrayList_Destroy(&y);
+ parcArrayList_Destroy(&z);
+ parcArrayList_Destroy(&u1);
+ parcArrayList_Destroy(&u2);
+ parcArrayList_Destroy(&u3);
+}
+
+LONGBOW_TEST_CASE(Local, PARC_ArrayList_EnsureRemaining_Empty)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ size_t expected = 4;
+ _ensureRemaining(array, expected);
+
+ size_t actual = _remaining(array);
+
+ assertTrue(actual >= expected, "Expected >= %zd, actual=%zd", expected, actual);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Local, PARC_ArrayList_EnsureRemaining_NonEmpty)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, 0);
+
+ size_t expected = 5;
+ _ensureRemaining(array, expected);
+
+ size_t actual = _remaining(array);
+
+ assertTrue(actual >= expected, "Expected >= %zd, actual=%zd", expected, actual);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_FromInitialCapacity)
+{
+ PARCArrayList *array = parcArrayList_Create_Capacity(NULL, parcArrayList_StdlibFreeFunction, 10);
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(0 == actual, "Expected=%d, actual=%zu", 0, actual);
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Get)
+{
+ PARCArrayList *array = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+
+ char *expected = strdup("Hello World");
+ parcArrayList_Add(array, expected);
+
+ char *actual = parcArrayList_Get(array, 0);
+
+ assertTrue(expected == actual, "Expected=%p, actual=%p", (void *) expected, (void *) actual);
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_New)
+{
+ PARCArrayList *array = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+ size_t size = parcArrayList_Size(array);
+ assertTrue(0 == size, "Expected %d actual=%zu", 0, size);
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Size)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, 0);
+
+ size_t size = parcArrayList_Size(array);
+ assertTrue(1 == size, "Expected %d actual=%zu", 1, size);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_IsEmpty)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ assertTrue(parcArrayList_IsEmpty(array), "Expected a new array to be empty.");
+
+ parcArrayList_Add(array, 0);
+ assertFalse(parcArrayList_IsEmpty(array), "Expected an array with more than zero elements to be empty.");
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_InsertAtIndex)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+
+ parcArrayList_Add(array, (void *) 1);
+ parcArrayList_Add(array, (void *) 2);
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(2 == actual, "Expected=%d, actual=%zu", 2, actual);
+
+ parcArrayList_InsertAtIndex(array, 1, (void *) 3);
+
+ actual = parcArrayList_Size(array);
+ assertTrue(3 == actual, "Expected=%d, actual=%zu", 3, actual);
+
+ void *element0 = parcArrayList_Get(array, 0);
+ assertTrue(element0 == (void *) 1, "Element 1 moved?");
+
+ void *element1 = parcArrayList_Get(array, 1);
+ assertTrue(element1 == (void *) 3, "Element 1 moved?");
+
+ void *element2 = parcArrayList_Get(array, 2);
+ assertTrue(element2 == (void *) 2, "Element 1 moved?");
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_InsertAtIndex_Empty)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+
+ parcArrayList_InsertAtIndex(array, 0, (void *) 3);
+
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(1 == actual, "Expected=%d, actual=%zu", 1, actual);
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_InsertAtIndex_First)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+
+ parcArrayList_Add(array, (void *) 1);
+ parcArrayList_InsertAtIndex(array, 0, (void *) 2);
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(2 == actual, "Expected=%d, actual=%zu", 2, actual);
+
+ void *element0 = parcArrayList_Get(array, 0);
+ assertTrue(element0 == (void *) 2, "Element 1 moved?");
+
+ void *element1 = parcArrayList_Get(array, 1);
+ assertTrue(element1 == (void *) 1, "Element 1 moved?");
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_InsertAtIndex_Last)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+
+ parcArrayList_Add(array, (void *) 1);
+ parcArrayList_Add(array, (void *) 2);
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(2 == actual, "Expected=%d, actual=%zu", 2, actual);
+
+ parcArrayList_InsertAtIndex(array, 2, (void *) 3);
+
+ actual = parcArrayList_Size(array);
+ assertTrue(3 == actual, "Expected=%d, actual=%zu", 3, actual);
+
+ void *element0 = parcArrayList_Get(array, 0);
+ assertTrue(element0 == (void *) 1, "Element 1 moved?");
+
+ void *element1 = parcArrayList_Get(array, 1);
+ assertTrue(element1 == (void *) 2, "Element 1 moved?");
+
+ void *element2 = parcArrayList_Get(array, 2);
+ assertTrue(element2 == (void *) 3, "Element 1 moved?");
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Remove_AtIndex_First)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, b);
+ parcArrayList_Add(expected, c);
+
+ void *removedElement = parcArrayList_RemoveAtIndex(array, 0);
+
+ assertTrue(removedElement == a, "Expected ");
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Remove_AtIndex)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, a);
+ parcArrayList_Add(expected, c);
+
+ void *removedElement = parcArrayList_RemoveAtIndex(array, 1);
+
+ assertTrue(removedElement == b, "Expected ");
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_Remove_AtIndex_Last)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, a);
+ parcArrayList_Add(expected, b);
+
+ void *removedElement = parcArrayList_RemoveAtIndex(array, 2);
+
+ assertTrue(removedElement == c, "Expected ");
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_RemoveAndDestroy_AtIndex_First)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, b);
+ parcArrayList_Add(expected, c);
+
+ parcArrayList_RemoveAndDestroyAtIndex(array, 0);
+
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_RemoveAndDestroy_AtIndex)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, a);
+ parcArrayList_Add(expected, c);
+
+ parcArrayList_RemoveAndDestroyAtIndex(array, 1);
+
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_ArrayList_RemoveAndDestroy_AtIndex_Last)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, a);
+ parcArrayList_Add(expected, b);
+
+ parcArrayList_RemoveAndDestroyAtIndex(array, 2);
+
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, PARC_ArrayList_EnsureRemaining_Empty);
+ LONGBOW_RUN_TEST_CASE(Local, PARC_ArrayList_EnsureRemaining_NonEmpty);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Errors)
+{
+ LONGBOW_RUN_TEST_CASE(Errors, PARC_ArrayList_InsertAtIndex_OutOfCapacity);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Errors)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+
+ longBowTestCase_SetClipBoardData(testCase, array);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Errors)
+{
+ PARCArrayList *array = longBowTestCase_GetClipBoardData(testCase);
+ parcArrayList_Destroy(&array);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, PARC_ArrayList_InsertAtIndex_OutOfCapacity, .event = &LongBowAssertEvent)
+{
+ PARCArrayList *array = longBowTestCase_GetClipBoardData(testCase);
+
+ parcArrayList_Add(array, (void *) 1);
+ parcArrayList_Add(array, (void *) 2);
+
+ parcArrayList_InsertAtIndex(array, 200, (void *) 3);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(PARC_ArrayList);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_AtomicInteger.c b/libparc/parc/algol/test/test_parc_AtomicInteger.c
new file mode 100644
index 00000000..9bd1b99a
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_AtomicInteger.c
@@ -0,0 +1,156 @@
+/*
+ * 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_AtomicInteger.c"
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+
+LONGBOW_TEST_RUNNER(test_parc_AtomicInteger)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Threaded);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(test_parc_AtomicInteger)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(test_parc_AtomicInteger)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicInteger_Uint32Increment);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicInteger_Uint32Decrement);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicInteger_Uint64Increment);
+ LONGBOW_RUN_TEST_CASE(Global, parcAtomicInteger_Uint64Decrement);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicInteger_Uint32Increment)
+{
+ uint32_t value = 0;
+ parcAtomicInteger_Uint32Increment(&value);
+ assertTrue(value == 1, "Expected 1, actual, %u", value);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicInteger_Uint32Decrement)
+{
+ uint32_t value = 0;
+ parcAtomicInteger_Uint32Increment(&value);
+ assertTrue(value == 1, "Expected 1, actual, %u", value);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicInteger_Uint64Increment)
+{
+ uint64_t value = 0;
+ parcAtomicInteger_Uint64Increment(&value);
+ assertTrue(value == 1, "Expected 1, actual, %" PRIu64 "", value);
+}
+
+LONGBOW_TEST_CASE(Global, parcAtomicInteger_Uint64Decrement)
+{
+ uint64_t value = 0;
+ parcAtomicInteger_Uint64Increment(&value);
+ assertTrue(value == 1, "Expected 1, actual, %" PRIu64 "", value);
+}
+
+LONGBOW_TEST_FIXTURE(Threaded)
+{
+ LONGBOW_RUN_TEST_CASE(Threaded, collaborative);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Threaded)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Threaded)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static void *
+collaborator_A(void *data)
+{
+ uint32_t *valuePointer = (uint32_t *) data;
+ uint32_t contribution = 0;
+ while (*valuePointer < 1000000) {
+ parcAtomicInteger_Uint32Increment(valuePointer);
+ contribution++;
+ }
+ printf("A contribution %d\n", contribution);
+ pthread_exit((void *) NULL);
+}
+
+static void *
+collaborator_B(void *data)
+{
+ uint32_t *valuePointer = (uint32_t *) data;
+
+ uint32_t contribution = 0;
+ while (*valuePointer < 1000000) {
+ parcAtomicInteger_Uint32Increment(valuePointer);
+ contribution++;
+ }
+
+ printf("B contribution %d\n", contribution);
+ pthread_exit((void *) NULL);
+}
+
+LONGBOW_TEST_CASE(Threaded, collaborative)
+{
+ uint32_t value = 0;
+
+ pthread_t thread_A;
+ pthread_t thread_B;
+
+ pthread_create(&thread_A, NULL, collaborator_A, &value);
+ pthread_create(&thread_B, NULL, collaborator_B, &value);
+
+ pthread_join(thread_A, NULL);
+ pthread_join(thread_B, NULL);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(test_parc_AtomicInteger);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Base64.c b/libparc/parc/algol/test/test_parc_Base64.c
new file mode 100755
index 00000000..4509ded3
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Base64.c
@@ -0,0 +1,414 @@
+/*
+ * 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 <LongBow/unit-test.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_Base64.c"
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(parc_Base64)
+{
+ // 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_Base64)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Base64)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcBase64_Decode);
+ LONGBOW_RUN_TEST_CASE(Global, parcBase64_Decode_Linefeeds);
+ LONGBOW_RUN_TEST_CASE(Global, parcBase64_Encode);
+ LONGBOW_RUN_TEST_CASE(Global, parcBase64_Encode_Binary);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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;
+}
+
+static struct testvector_s {
+ char *plaintext;
+ char *encoded;
+} testvector[] = {
+ // Test vectors from RFC 4648
+ { .plaintext = "", .encoded = "" },
+ { .plaintext = "f", .encoded = "Zg==" },
+ { .plaintext = "fo", .encoded = "Zm8=" },
+ { .plaintext = "foo", .encoded = "Zm9v" },
+ { .plaintext = "foob", .encoded = "Zm9vYg==" },
+ { .plaintext = "fooba", .encoded = "Zm9vYmE=" },
+ { .plaintext = "foobar", .encoded = "Zm9vYmFy" },
+ { .plaintext = NULL, .encoded = NULL }
+};
+
+LONGBOW_TEST_CASE(Global, parcBase64_Decode)
+{
+ int i = 0;
+ while (testvector[i].plaintext != NULL) {
+ PARCBufferComposer *input = parcBufferComposer_Create();
+ PARCBufferComposer *truth = parcBufferComposer_Create();
+ PARCBufferComposer *output = parcBufferComposer_Create();
+
+ parcBufferComposer_PutString(input, testvector[i].encoded);
+ PARCBuffer *inputBuffer = parcBufferComposer_ProduceBuffer(input);
+ parcBufferComposer_PutString(truth, testvector[i].plaintext);
+ PARCBuffer *truthBuffer = parcBufferComposer_ProduceBuffer(truth);
+
+ parcBase64_Decode(output, parcBufferComposer_GetBuffer(input));
+ PARCBuffer *outputBuffer = parcBufferComposer_ProduceBuffer(output);
+
+ assertTrue(parcBuffer_Equals(truthBuffer, outputBuffer),
+ "encoding, expected '%s' got '%s'",
+ parcBuffer_ToHexString(truthBuffer),
+ parcBuffer_ToHexString(outputBuffer));
+
+ i++;
+
+ parcBuffer_Release(&inputBuffer);
+ parcBuffer_Release(&truthBuffer);
+ parcBuffer_Release(&outputBuffer);
+
+ parcBufferComposer_Release(&input);
+ parcBufferComposer_Release(&output);
+ parcBufferComposer_Release(&truth);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, parcBase64_Decode_Linefeeds)
+{
+ PARCBufferComposer *input = parcBufferComposer_Create();
+ PARCBufferComposer *truth = parcBufferComposer_Create();
+ PARCBufferComposer *output = parcBufferComposer_Create();
+
+ char plaintext[] = "It was a dark and stormy night, and all through the code not bit was stirring.\x0A";
+ char encoded_with_crlf[] = "SXQg" "\x0D\x0A" "d2FzIGEgZGFyayBhbmQgc3Rvcm15IG5pZ2h0LCBhbmQgYWxsIHRocm91Z2gg" "\x0D\x0A" "dGhlIGNvZGUgbm90IGJpdCB3YXMgc3RpcnJpbmcuCg==";
+
+ parcBufferComposer_PutString(input, encoded_with_crlf);
+ PARCBuffer *inputBuffer = parcBufferComposer_ProduceBuffer(input);
+
+ parcBufferComposer_PutString(truth, plaintext);
+ PARCBuffer *truthBuffer = parcBufferComposer_ProduceBuffer(truth);
+
+ parcBase64_Decode(output, parcBufferComposer_GetBuffer(input));
+ PARCBuffer *outputBuffer = parcBufferComposer_ProduceBuffer(output);
+ assertTrue(parcBuffer_Equals(truthBuffer, outputBuffer),
+ "encoding, expected '%s' got '%s'",
+ parcBuffer_ToHexString(truthBuffer),
+ parcBuffer_ToHexString(outputBuffer));
+
+ parcBuffer_Release(&inputBuffer);
+ parcBuffer_Release(&truthBuffer);
+ parcBuffer_Release(&outputBuffer);
+
+ parcBufferComposer_Release(&input);
+ parcBufferComposer_Release(&output);
+ parcBufferComposer_Release(&truth);
+}
+
+
+LONGBOW_TEST_CASE(Global, parcBase64_Encode)
+{
+ int i = 0;
+ while (testvector[i].plaintext != NULL) {
+ PARCBufferComposer *input = parcBufferComposer_Create();
+ PARCBufferComposer *truth = parcBufferComposer_Create();
+ PARCBufferComposer *output = parcBufferComposer_Create();
+
+ parcBufferComposer_PutString(input, testvector[i].plaintext);
+ PARCBuffer *inputBuffer = parcBufferComposer_ProduceBuffer(input);
+ parcBufferComposer_PutString(truth, testvector[i].encoded);
+ PARCBuffer *truthBuffer = parcBufferComposer_ProduceBuffer(truth);
+
+ parcBase64_Encode(output, parcBufferComposer_GetBuffer(input));
+ PARCBuffer *outputBuffer = parcBufferComposer_ProduceBuffer(output);
+ assertTrue(parcBuffer_Equals(truthBuffer, outputBuffer),
+ "encoding, expected '%s' got '%s'",
+ parcBuffer_ToHexString(truthBuffer),
+ parcBuffer_ToHexString(outputBuffer));
+
+ i++;
+
+ parcBuffer_Release(&inputBuffer);
+ parcBuffer_Release(&truthBuffer);
+ parcBuffer_Release(&outputBuffer);
+
+ parcBufferComposer_Release(&input);
+ parcBufferComposer_Release(&output);
+ parcBufferComposer_Release(&truth);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, parcBase64_Encode_Binary)
+{
+ uint8_t zero[] = { 0 };
+
+ // 1 2 3 4 5 6 7
+ char *truthvector[] = { "AA==", "AAA=", "AAAA", "AAAAAA==", "AAAAAAA=", "AAAAAAAA", "AAAAAAAAAA==" };
+
+ for (int i = 0; i < sizeof(truthvector) / sizeof(truthvector[0]); i++) {
+ PARCBufferComposer *input = parcBufferComposer_Create();
+ PARCBufferComposer *truth = parcBufferComposer_Create();
+ PARCBufferComposer *output = parcBufferComposer_Create();
+
+ parcBufferComposer_PutArray(truth, (uint8_t *) truthvector[i], strlen(truthvector[i]));
+ PARCBuffer *truthBuffer = parcBufferComposer_ProduceBuffer(truth);
+
+ // just keep apending a zero to make it longer
+ parcBuffer_SetLimit(parcBufferComposer_GetBuffer(input), parcBuffer_Capacity(parcBufferComposer_GetBuffer(input)));
+ parcBuffer_SetPosition(parcBufferComposer_GetBuffer(input), i);
+ parcBufferComposer_PutArray(input, zero, 1);
+ PARCBuffer *inputBuffer = parcBufferComposer_ProduceBuffer(input);
+
+ parcBase64_Encode(output, parcBufferComposer_GetBuffer(input));
+ PARCBuffer *outputBuffer = parcBufferComposer_ProduceBuffer(output);
+
+ assertTrue(parcBuffer_Equals(truthBuffer, outputBuffer),
+ "encoding, expected '%s' got '%s'",
+ parcBuffer_ToHexString(truthBuffer),
+ parcBuffer_ToHexString(outputBuffer));
+
+ parcBuffer_Release(&inputBuffer);
+ parcBuffer_Release(&truthBuffer);
+ parcBuffer_Release(&outputBuffer);
+
+ parcBufferComposer_Release(&input);
+ parcBufferComposer_Release(&output);
+ parcBufferComposer_Release(&truth);
+ }
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, encodeWithPad_0);
+ LONGBOW_RUN_TEST_CASE(Local, encodeWithPad_1);
+ LONGBOW_RUN_TEST_CASE(Local, encodeWithPad_2);
+ LONGBOW_RUN_TEST_CASE(Local, decode_invalid);
+ LONGBOW_RUN_TEST_CASE(Local, decode_1);
+ LONGBOW_RUN_TEST_CASE(Local, decode_2);
+ LONGBOW_RUN_TEST_CASE(Local, decode_3);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ 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;
+}
+
+/**
+ * This will encode "foo"
+ */
+LONGBOW_TEST_CASE(Local, encodeWithPad_0)
+{
+ PARCBufferComposer *output = parcBufferComposer_Create();
+ uint8_t input[] = "foobar";
+ PARCBufferComposer *truth = parcBufferComposer_Create();
+ parcBufferComposer_PutString(truth, "Zm9v");
+ PARCBuffer *truthBuffer = parcBufferComposer_ProduceBuffer(truth);
+
+ _encodeWithPad(output, input, 0);
+ PARCBuffer *outputBuffer = parcBufferComposer_ProduceBuffer(output);
+ assertTrue(parcBuffer_Equals(truthBuffer, outputBuffer),
+ "Failed 3-byte encode, expected '%s' got '%s'",
+ parcBuffer_ToHexString(truthBuffer),
+ parcBuffer_ToHexString(outputBuffer));
+
+ parcBuffer_Release(&truthBuffer);
+ parcBuffer_Release(&outputBuffer);
+
+ parcBufferComposer_Release(&output);
+ parcBufferComposer_Release(&truth);
+}
+
+/**
+ * This will encode "fo" because we tell it there's 1 pad byte
+ */
+LONGBOW_TEST_CASE(Local, encodeWithPad_1)
+{
+ PARCBufferComposer *output = parcBufferComposer_Create();
+ uint8_t input[] = "foobar";
+ PARCBufferComposer *truth = parcBufferComposer_Create();
+ parcBufferComposer_PutString(truth, "Zm8=");
+ PARCBuffer *truthBuffer = parcBufferComposer_ProduceBuffer(truth);
+
+ _encodeWithPad(output, input, 1);
+ PARCBuffer *outputBuffer = parcBufferComposer_ProduceBuffer(output);
+
+ assertTrue(parcBuffer_Equals(truthBuffer, outputBuffer),
+ "Failed 3-byte encode, expected '%s' got '%s'",
+ parcBuffer_ToHexString(truthBuffer),
+ parcBuffer_ToHexString(outputBuffer));
+
+ parcBuffer_Release(&truthBuffer);
+ parcBuffer_Release(&outputBuffer);
+
+ parcBufferComposer_Release(&output);
+ parcBufferComposer_Release(&truth);
+}
+
+/**
+ * This will encode "f" because we tell it there's 2 pad byte
+ */
+LONGBOW_TEST_CASE(Local, encodeWithPad_2)
+{
+ PARCBufferComposer *output = parcBufferComposer_Create();
+ uint8_t input[] = "foobar";
+ PARCBufferComposer *truth = parcBufferComposer_Create();
+ parcBufferComposer_PutString(truth, "Zg==");
+ PARCBuffer *truthBuffer = parcBufferComposer_ProduceBuffer(truth);
+
+ _encodeWithPad(output, input, 2);
+ PARCBuffer *outputBuffer = parcBufferComposer_ProduceBuffer(output);
+
+ assertTrue(parcBuffer_Equals(truthBuffer, outputBuffer),
+ "Failed 3-byte encode, expected '%s' got '%s'",
+ parcBuffer_ToHexString(truthBuffer),
+ parcBuffer_ToHexString(outputBuffer));
+
+ parcBuffer_Release(&truthBuffer);
+ parcBuffer_Release(&outputBuffer);
+
+ parcBufferComposer_Release(&output);
+ parcBufferComposer_Release(&truth);
+}
+
+
+LONGBOW_TEST_CASE(Local, decode_1)
+{
+ PARCBufferComposer *output = parcBufferComposer_Create();
+ uint8_t input[] = "Zg==";
+ PARCBufferComposer *truth = parcBufferComposer_Create();
+ parcBufferComposer_PutString(truth, "f");
+ PARCBuffer *truthBuffer = parcBufferComposer_ProduceBuffer(truth);
+
+ bool success = _decode(output, input);
+ assertTrue(success, "Valid base64 failed decode");
+
+ PARCBuffer *outputBuffer = parcBufferComposer_ProduceBuffer(output);
+ assertTrue(parcBuffer_Equals(truthBuffer, outputBuffer),
+ "Failed 3-byte encode, expected '%s' got '%s'",
+ parcBuffer_ToHexString(truthBuffer),
+ parcBuffer_ToHexString(outputBuffer));
+
+ parcBuffer_Release(&truthBuffer);
+ parcBuffer_Release(&outputBuffer);
+
+ parcBufferComposer_Release(&output);
+ parcBufferComposer_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Local, decode_2)
+{
+ PARCBufferComposer *output = parcBufferComposer_Create();
+ uint8_t input[] = "Zm8=";
+ PARCBufferComposer *truth = parcBufferComposer_Create();
+ parcBufferComposer_PutString(truth, "fo");
+ PARCBuffer *truthBuffer = parcBufferComposer_ProduceBuffer(truth);
+
+ bool success = _decode(output, input);
+ assertTrue(success, "Valid base64 failed decode");
+
+ PARCBuffer *outputBuffer = parcBufferComposer_ProduceBuffer(output);
+
+ assertTrue(parcBuffer_Equals(truthBuffer, outputBuffer),
+ "Failed 3-byte encode, expected '%s' got '%s'",
+ parcBuffer_ToHexString(truthBuffer),
+ parcBuffer_ToHexString(outputBuffer));
+
+ parcBuffer_Release(&truthBuffer);
+ parcBuffer_Release(&outputBuffer);
+
+ parcBufferComposer_Release(&output);
+ parcBufferComposer_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Local, decode_3)
+{
+ PARCBufferComposer *output = parcBufferComposer_Create();
+ uint8_t input[] = "Zm9v";
+ PARCBufferComposer *truth = parcBufferComposer_Create();
+ parcBufferComposer_PutString(truth, "foo");
+ PARCBuffer *truthBuffer = parcBufferComposer_ProduceBuffer(truth);
+
+ bool success = _decode(output, input);
+ assertTrue(success, "Valid base64 failed decode");
+ PARCBuffer *outputBuffer = parcBufferComposer_ProduceBuffer(output);
+
+ assertTrue(parcBuffer_Equals(truthBuffer, outputBuffer),
+ "Failed 3-byte encode, expected '%s' got '%s'",
+ parcBuffer_ToHexString(truthBuffer),
+ parcBuffer_ToHexString(outputBuffer));
+
+ parcBuffer_Release(&truthBuffer);
+ parcBuffer_Release(&outputBuffer);
+
+ parcBufferComposer_Release(&output);
+ parcBufferComposer_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Local, decode_invalid)
+{
+ PARCBufferComposer *output = parcBufferComposer_Create();
+ uint8_t input[] = "@@@@";
+
+ bool success = _decode(output, input);
+ assertFalse(success, "Invalid base64 somehow decoded");
+
+ parcBufferComposer_Release(&output);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Base64);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_BitVector.c b/libparc/parc/algol/test/test_parc_BitVector.c
new file mode 100755
index 00000000..9a4d0806
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_BitVector.c
@@ -0,0 +1,438 @@
+/*
+ * 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 <LongBow/unit-test.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_BitVector.c"
+
+#include <stdio.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <limits.h>
+
+LONGBOW_TEST_RUNNER(parc_BitVector)
+{
+ // 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_BitVector)
+{
+ 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_BitVector)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_Create_Release);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_SetClear);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_SetVector);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_Reset);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_ClearVector);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_NextBitSet);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_Get);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_ToString);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_Contains);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_Set);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_And);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_Or);
+ LONGBOW_RUN_TEST_CASE(Global, parcBitVector_Shift);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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(Global, parcBitVector_Create_Release)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+ PARCBitVector *reference = parcBitVector;
+ parcBitVector_Acquire(reference);
+ parcBitVector_Release(&parcBitVector);
+ parcBitVector_Release(&reference);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_Set)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 0, "parcBitVector_Create created a non-empty vector");
+
+ parcBitVector_Set(parcBitVector, 0);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 1, "Expect number of bits set to be 1");
+ assertTrue(parcBitVector->firstBitSet == 0, "Expect first bit set to be 0");
+ assertTrue(parcBitVector->bitLength == 8, "Expect the bitLength to be 8");
+ assertTrue(parcBitVector->bitArray[0] == (uint8_t) 1, "Expect the bitArray as a unsigned char to be = 1");
+
+ parcBitVector_Set(parcBitVector, 7);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 2, "Expect number of bits set to be 2");
+ assertTrue(parcBitVector->firstBitSet == 0, "Expect first bit set to be 0");
+ assertTrue(parcBitVector->bitLength == 8, "Expect the bitLength to be 8");
+ assertTrue(parcBitVector->bitArray[0] == (uint8_t) 0x81, "Expect the bitArray as a unsigned char to be = 0x81");
+
+ parcBitVector_Set(parcBitVector, 8);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 3, "Expect number of bits set to be 3");
+ assertTrue(parcBitVector->firstBitSet == 0, "Expect first bit set to be 0");
+ assertTrue(parcBitVector->bitLength == 16, "Expect the bitLength to be 16");
+ assertTrue(parcBitVector->bitArray[0] == (uint8_t) 0x81, "Expect the bitArray as a unsigned char to be = 0x81");
+ assertTrue(parcBitVector->bitArray[1] == (uint8_t) 0x1, "Expect the bitArray as a unsigned char to be = 0x1");
+
+ parcBitVector_Release(&parcBitVector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_And)
+{
+ PARCBitVector *vector1 = parcBitVector_Create();
+ PARCBitVector *vector2 = parcBitVector_Create();
+
+ parcBitVector_Set(vector1, 1);
+ parcBitVector_Set(vector1, 2);
+ parcBitVector_Set(vector1, 10);
+ parcBitVector_Set(vector2, 2);
+ parcBitVector_Set(vector2, 1);
+ parcBitVector_Set(vector2, 20);
+
+ PARCBitVector *result = parcBitVector_And(vector1, vector2);
+
+ assertTrue(parcBitVector_NumberOfBitsSet(result) == 2, "AND vector not equal to expected results");
+ parcBitVector_Release(&result);
+
+ result = parcBitVector_And(vector1, NULL);
+ assertTrue(parcBitVector_NumberOfBitsSet(result) == 0, "AND vector not equal to expected results");
+ parcBitVector_Release(&result);
+
+ result = parcBitVector_And(NULL, vector2);
+ assertTrue(parcBitVector_NumberOfBitsSet(result) == 0, "AND vector not equal to expected results");
+ parcBitVector_Release(&result);
+
+ result = parcBitVector_And(NULL, NULL);
+ assertTrue(parcBitVector_NumberOfBitsSet(result) == 0, "AND vector not equal to expected results");
+ parcBitVector_Release(&result);
+
+ parcBitVector_Release(&vector1);
+ parcBitVector_Release(&vector2);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_Or)
+{
+ PARCBitVector *vector1 = parcBitVector_Create();
+ PARCBitVector *vector2 = parcBitVector_Create();
+
+ parcBitVector_Set(vector1, 1);
+ parcBitVector_Set(vector1, 2);
+ parcBitVector_Set(vector1, 10);
+ parcBitVector_Set(vector2, 2);
+ parcBitVector_Set(vector2, 1);
+ parcBitVector_Set(vector2, 20);
+
+ PARCBitVector *result = parcBitVector_Or(vector1, vector2);
+
+ assertTrue(parcBitVector_Contains(result, vector1), "Vector contents not included in OR operation results");
+ assertTrue(parcBitVector_Contains(result, vector2), "Vector contents not included in OR operation results");
+ assertTrue(parcBitVector_NumberOfBitsSet(result) == 4, "OR vector not equal to expected results");
+ parcBitVector_Release(&result);
+
+ result = parcBitVector_Or(vector1, NULL);
+ assertTrue(parcBitVector_Equals(result, vector1), "OR vector not equal to expected results");
+ parcBitVector_Release(&result);
+
+ result = parcBitVector_Or(NULL, vector2);
+ assertTrue(parcBitVector_Equals(result, vector2), "OR vector not equal to expected results");
+ parcBitVector_Release(&result);
+
+ result = parcBitVector_Or(NULL, NULL);
+ assertTrue(parcBitVector_NumberOfBitsSet(result) == 0, "OR vector not equal to expected results");
+ parcBitVector_Release(&result);
+
+ parcBitVector_Release(&vector1);
+ parcBitVector_Release(&vector2);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_Shift)
+{
+ PARCBitVector *vector = parcBitVector_Create();
+
+ parcBitVector_Set(vector, 0); // should drop off on left shift
+ parcBitVector_Set(vector, 11);
+ parcBitVector_Set(vector, 12);
+ parcBitVector_Set(vector, 13);
+ parcBitVector_Set(vector, 22);
+ parcBitVector_LeftShift(vector, 10);
+ parcBitVector_RightShift(vector, 10);
+ assertTrue(parcBitVector_NextBitSet(vector, 0) == 11, "Shift operations failed");
+ assertTrue(parcBitVector_NextBitSet(vector, 12) == 12, "Shift operations failed");
+ assertTrue(parcBitVector_NextBitSet(vector, 14) == 22, "Shift operations failed");
+ assertTrue(parcBitVector_NumberOfBitsSet(vector) == 4, "Shift operations failed to drop first bit on left shift");
+ parcBitVector_Release(&vector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_SetClear)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 0, "parcBitVector_Create created a non-empty vector");
+
+ parcBitVector_Set(parcBitVector, 10);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 1, "parcBitVector_Set failed");
+
+ parcBitVector_Clear(parcBitVector, 10);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 0, "parcBitVector_Clear failed");
+
+ parcBitVector_Clear(parcBitVector, 20);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 0, "parcBitVector_Clear failed");
+
+ parcBitVector_Release(&parcBitVector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_SetVector)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+ PARCBitVector *setVector = parcBitVector_Create();
+ parcBitVector_Set(parcBitVector, 1);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 1, "parcBitVector_Set failed");
+
+ parcBitVector_Set(setVector, 20);
+ parcBitVector_SetVector(parcBitVector, setVector);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 2, "parcBitVector_SetVector failed");
+ assertTrue(parcBitVector_NextBitSet(parcBitVector, 0) == 1, "parcBitVector_Set failed to set bit 1");
+ assertTrue(parcBitVector_NextBitSet(parcBitVector, 2) == 20, "parcBitVector_SetVector failed to set bit 20");
+
+ parcBitVector_Set(setVector, 10);
+ parcBitVector_SetVector(parcBitVector, setVector);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 3, "parcBitVector_SetVector failed");
+ parcBitVector_Release(&parcBitVector);
+ parcBitVector_Release(&setVector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_Reset)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+
+ // Reset and empty vector test
+ parcBitVector_Reset(parcBitVector);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 0, "parcBitVector_Reset failed");
+
+ parcBitVector_Set(parcBitVector, 1);
+ parcBitVector_Set(parcBitVector, 42);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 2, "parcBitVector_Set failed");
+ assertTrue(parcBitVector->bitLength == 48, "Expected a bitLength of 48");
+
+ parcBitVector_Reset(parcBitVector);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 0, "parcBitVector_Reset failed");
+ assertTrue(parcBitVector->bitLength == 48, "Expected a bitLength of 48");
+
+ parcBitVector_Release(&parcBitVector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_ClearVector)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+
+ PARCBitVector *setVector = parcBitVector_Create();
+ parcBitVector_Set(parcBitVector, 1);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 1, "parcBitVector_Set failed to set bit");
+
+ parcBitVector_Set(setVector, 1);
+ parcBitVector_Set(setVector, 20);
+ parcBitVector_ClearVector(parcBitVector, setVector);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 0, "parcBitVector_ClearVector failed to clear vector");
+
+ parcBitVector_Set(parcBitVector, 12);
+ parcBitVector_Set(parcBitVector, 17);
+ parcBitVector_ClearVector(parcBitVector, parcBitVector);
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 0, "parcBitVector_ClearVector failed to clear vector");
+
+ parcBitVector_Release(&parcBitVector);
+ parcBitVector_Release(&setVector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_NextBitSet)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 0, "parcBitVector_Create created a non-empty vector");
+
+ int nextBit = parcBitVector_NextBitSet(parcBitVector, 0);
+ assertTrue(nextBit == -1, "parcBitVector_NextBitSet should have failed (%d)", nextBit);
+
+ parcBitVector_Set(parcBitVector, 10);
+ nextBit = parcBitVector_NextBitSet(parcBitVector, 0);
+ assertTrue(nextBit == 10, "parcBitVector_NextBitSet failed (%d)", nextBit);
+
+ nextBit = parcBitVector_NextBitSet(parcBitVector, 20);
+ assertTrue(nextBit == -1, "parcBitVector_NextBitSet read past end of vector (%d)", nextBit);
+
+ nextBit = parcBitVector_NextBitSet(parcBitVector, 10);
+ assertTrue(nextBit == 10, "parcBitVector_NextBitSet failed (%d)", nextBit);
+
+ nextBit = parcBitVector_NextBitSet(parcBitVector, 11);
+ assertTrue(nextBit == -1, "parcBitVector_NextBitSet should have failed (%d)", nextBit);
+
+ parcBitVector_Set(parcBitVector, 20);
+ nextBit = parcBitVector_NextBitSet(parcBitVector, 11);
+ assertTrue(nextBit == 20, "parcBitVector_NextBitSet failed (%d)", nextBit);
+ parcBitVector_Release(&parcBitVector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_Get)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+ assertTrue(parcBitVector_NumberOfBitsSet(parcBitVector) == 0, "parcBitVector_Create created a non-empty vector");
+
+ parcBitVector_Set(parcBitVector, 10);
+ int bitValue = parcBitVector_Get(parcBitVector, 10);
+ assertTrue(bitValue == 1, "parcBitVector_Get returned wrong value (%d)", bitValue);
+
+ bitValue = parcBitVector_Get(parcBitVector, 11);
+ assertTrue(bitValue == 0, "parcBitVector_Get returned wrong value (%d)", bitValue);
+
+ bitValue = parcBitVector_Get(parcBitVector, 100);
+ assertTrue(bitValue == -1, "parcBitVector_NextBitSet should have failed (%d)", bitValue);
+
+ parcBitVector_Release(&parcBitVector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_ToString)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+
+ char *string = parcBitVector_ToString(parcBitVector);
+ assertTrue(strcmp(string, "[ ]") == 0, "parcBitVector_ToString returned unexpected representation (%s != [ ])", string);
+ parcMemory_Deallocate(&string);
+
+ parcBitVector_Set(parcBitVector, 10);
+ parcBitVector_Set(parcBitVector, 1);
+ string = parcBitVector_ToString(parcBitVector);
+ assertTrue(strcmp(string, "[ 1 10 ]") == 0, "parcBitVector_ToString returned unexpected representation (%s != [ 1 10 ])", string);
+ parcMemory_Deallocate(&string);
+
+ parcBitVector_Release(&parcBitVector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_Copy)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+
+ parcBitVector_Set(parcBitVector, 10);
+ PARCBitVector *copy = parcBitVector_Copy(parcBitVector);
+ assertTrue(parcBitVector_NumberOfBitsSet(copy) == 1, "parcBitVector_Copy failed to copy set bit");
+ assertTrue(parcBitVector_NextBitSet(copy, 0) == 10, "parcBitVector_Copy failed to copy correct bit");
+
+ parcBitVector_Release(&copy);
+ parcBitVector_Release(&parcBitVector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_Equals)
+{
+ PARCBitVector *parcBitVector = parcBitVector_Create();
+ assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer");
+
+ parcBitVector_Set(parcBitVector, 10);
+ PARCBitVector *copy = parcBitVector_Copy(parcBitVector);
+ assertTrue(parcBitVector_Equals(parcBitVector, copy), "Duplicate vector found unequal");
+
+ parcBitVector_Set(copy, 9);
+ assertFalse(parcBitVector_Equals(parcBitVector, copy), "Unequal vector found equal");
+
+ parcBitVector_Clear(copy, 9);
+ parcBitVector_Set(copy, 29);
+ assertFalse(parcBitVector_Equals(parcBitVector, copy), "Unequal long vector found equal");
+
+ parcBitVector_Clear(copy, 29);
+ assertTrue(parcBitVector_Equals(parcBitVector, copy), "Equal long vector found unequal");
+ assertTrue(parcBitVector_Equals(copy, parcBitVector), "Equal long vector found unequal");
+
+ parcBitVector_Release(&copy);
+ parcBitVector_Release(&parcBitVector);
+}
+
+LONGBOW_TEST_CASE(Global, parcBitVector_Contains)
+{
+ PARCBitVector *supersetVector = parcBitVector_Create();
+
+ parcBitVector_Set(supersetVector, 10);
+ parcBitVector_Set(supersetVector, 11);
+
+ PARCBitVector *testVector = parcBitVector_Create();
+ parcBitVector_Set(testVector, 10);
+ assertTrue(parcBitVector_Contains(supersetVector, testVector), "Expect superset to contain testVector");
+
+ parcBitVector_Set(testVector, 12);
+ assertFalse(parcBitVector_Contains(supersetVector, testVector), "Expect superset to not contain testVector");
+
+ parcBitVector_Release(&supersetVector);
+ parcBitVector_Release(&testVector);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ 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;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_BitVector);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
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);
+}
diff --git a/libparc/parc/algol/test/test_parc_BufferChunker.c b/libparc/parc/algol/test/test_parc_BufferChunker.c
new file mode 100755
index 00000000..8f770968
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_BufferChunker.c
@@ -0,0 +1,336 @@
+/*
+ * 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_BufferChunker.c"
+
+#include <stdio.h>
+
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(parc_BufferChunker)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_BufferChunker)
+{
+ 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_BufferChunker)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_CreateFromBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ForwardIterator_Buffer);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ForwardIterator_BufferPartial);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ForwardIterator_BufferSmall);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ReverseIterator_Buffer);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ReverseIterator_BufferPartial);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ReverseIterator_BufferSmall);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_GetChunkSize);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_CreateFromBuffer)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1024);
+
+ PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+ PARCBufferChunker *copy = parcBufferChunker_Acquire(chunker);
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+ assertNotNull(copy, "Expected non-NULL copy of Chunker");
+ parcBufferChunker_Release(&copy);
+
+ parcBuffer_Release(&buffer);
+ parcBufferChunker_Release(&chunker);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ForwardIterator_Buffer)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1024);
+
+ for (size_t i = 0; i < 32; i++) {
+ for (size_t j = 0; j < 32; j++) {
+ parcBuffer_PutUint8(buffer, i);
+ }
+ }
+ parcBuffer_Flip(buffer);
+
+ PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcBufferChunker_ForwardIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ for (size_t i = 0; i < 32; i++) {
+ assertTrue(contents[i] == count, "Expected %zu at index %zu, got %d", count, i, contents[i]);
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 32, "Expected to iterate over 32 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcBufferChunker_Release(&chunker);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ForwardIterator_BufferPartial)
+{
+ // Allocate something that's not divisible by the chunk size
+ PARCBuffer *buffer = parcBuffer_Allocate(1030);
+
+ for (size_t i = 0; i < 32; i++) {
+ for (size_t j = 0; j < 32; j++) {
+ parcBuffer_PutUint8(buffer, i);
+ }
+ }
+
+ // Special 0xFF to mark the end...
+ for (int i = 0; i < 6; i++) {
+ parcBuffer_PutUint8(buffer, 0xFF);
+ }
+
+ parcBuffer_Flip(buffer);
+
+ PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcBufferChunker_ForwardIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ if (count < 32) {
+ for (size_t i = 0; i < 32; i++) {
+ assertTrue(contents[i] == count, "Expected %zu at index %zu, got %d", count, i, contents[i]);
+ }
+ } else {
+ for (size_t i = 0; i < 6; i++) {
+ assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]);
+ }
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 33, "Expected to iterate over 33 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcBufferChunker_Release(&chunker);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ForwardIterator_BufferSmall)
+{
+ // Allocate something that's not divisible by the chunk size
+ PARCBuffer *buffer = parcBuffer_Allocate(16);
+
+ // Special 0xFF to mark the end...
+ for (int i = 0; i < 16; i++) {
+ parcBuffer_PutUint8(buffer, 0xFF);
+ }
+
+ parcBuffer_Flip(buffer);
+
+ PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcBufferChunker_ForwardIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ for (size_t i = 0; i < 16; i++) {
+ assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]);
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 1, "Expected to iterate over 1 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcBufferChunker_Release(&chunker);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_Buffer)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1024);
+
+ for (size_t i = 0; i < 32; i++) {
+ for (size_t j = 0; j < 32; j++) {
+ parcBuffer_PutUint8(buffer, i);
+ }
+ }
+ parcBuffer_Flip(buffer);
+
+ PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcBufferChunker_ReverseIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ for (size_t i = 0; i < 32; i++) {
+ assertTrue(contents[i] == (31 - count), "Expected %zu at index %zu, got %d", (31 - count), i, contents[i]);
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 32, "Expected to iterate over 32 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcBufferChunker_Release(&chunker);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_BufferPartial)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1030);
+
+ // Special 0xFF to mark the start
+ for (int i = 0; i < 6; i++) {
+ parcBuffer_PutUint8(buffer, 0xFF);
+ }
+
+ for (size_t i = 0; i < 32; i++) {
+ for (size_t j = 0; j < 32; j++) {
+ parcBuffer_PutUint8(buffer, i);
+ }
+ }
+ parcBuffer_Flip(buffer);
+
+ PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcBufferChunker_ReverseIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ if (count < 32) {
+ for (size_t i = 0; i < 32; i++) {
+ assertTrue(contents[i] == (31 - count), "Expected %zu at index %zu, got %d", count, i, contents[i]);
+ }
+ } else {
+ for (size_t i = 0; i < 6; i++) {
+ assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]);
+ }
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 33, "Expected to iterate over 33 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcBufferChunker_Release(&chunker);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_BufferSmall)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(16);
+
+ // Special 0xFF to mark the start
+ for (int i = 0; i < 16; i++) {
+ parcBuffer_PutUint8(buffer, 0xFF);
+ }
+ parcBuffer_Flip(buffer);
+
+ PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcBufferChunker_ReverseIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ for (size_t i = 0; i < 16; i++) {
+ assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]);
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 1, "Expected to iterate over 1 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcBufferChunker_Release(&chunker);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_GetChunkSize)
+{
+ size_t expectedChunkSize = 32;
+ PARCBuffer *buffer = parcBuffer_Allocate(16);
+ PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, expectedChunkSize); // each chunk is 32 bytes
+ size_t actualChunkSize = parcBufferChunker_GetChunkSize(chunker);
+
+ assertTrue(actualChunkSize == expectedChunkSize, "Expected chunk size of %zu, got %zu", expectedChunkSize, actualChunkSize);
+
+ parcBuffer_Release(&buffer);
+ parcBufferChunker_Release(&chunker);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_BufferChunker);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_BufferComposer.c b/libparc/parc/algol/test/test_parc_BufferComposer.c
new file mode 100644
index 00000000..fad9857c
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_BufferComposer.c
@@ -0,0 +1,448 @@
+/*
+ * 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_BufferComposer.c"
+
+#include <inttypes.h>
+#include <LongBow/unit-test.h>
+#include <LongBow/debugging.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+typedef struct {
+ uint32_t setupAllocations;
+ PARCBufferComposer *composer;
+} TestData;
+
+static TestData*
+commonSetup()
+{
+ uint32_t outstanding = parcSafeMemory_Outstanding();
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear of %zu bytes returned NULL.", sizeof(TestData));
+ data->setupAllocations = outstanding;
+ data->composer = parcBufferComposer_Create();
+ return data;
+}
+
+static uint32_t
+commonTearDown(TestData *data)
+{
+ uint32_t setupAllocations = data->setupAllocations;
+
+ // NOTE: The `parcBufferComposer_AssertValid_IncrementSize` invalidates this object, so we must
+ // restore it to a good state in order for all memory to be released correctly.
+ (data->composer)->incrementHeuristic = sizeof(void *);
+
+ parcBufferComposer_Release(&(data->composer));
+ parcMemory_Deallocate((void **) &data);
+ return parcSafeMemory_ReportAllocation(STDOUT_FILENO) - setupAllocations;
+}
+
+LONGBOW_TEST_RUNNER(parc_BufferComposer)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_BufferComposer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_BufferComposer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_Allocate);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_Allocate_SizeMax);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_AssertValid);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_AssertValid_NULL);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_AssertValid_IncrementSize);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_Create);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_PutArray);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_PutBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_PutUint16);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_PutUint32);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_PutUint64);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_PutUint8);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_PutString);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_PutStrings);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_Format);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_PutChar);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_GetBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_CreateBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_ProduceBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_PutString_Extend);
+ LONGBOW_RUN_TEST_CASE(Global, parcBufferComposer_ToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ TestData *data = commonSetup();
+ longBowTestCase_SetClipBoardData(testCase, data);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint32_t outstandingAllocations = commonTearDown(data);
+
+ 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(Global, parcBufferComposer_Acquire)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ PARCBufferComposer *handle = parcBufferComposer_Acquire(composer);
+
+ assertNotNull(handle, "Acquired PARCBufferComposer handle should be non-NULL.");
+ assertTrue(parcBufferComposer_Equals(composer, handle), "PARCBufferComposer instances should be equal");
+
+ parcBufferComposer_Release(&handle);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_Allocate)
+{
+ size_t size = 10;
+ PARCBufferComposer *composer = parcBufferComposer_Allocate(size);
+ PARCBuffer *buffer = parcBufferComposer_GetBuffer(composer);
+
+ assertNotNull(composer, "PARCBufferComposer instance should be non-NULL.");
+ assertTrue(parcBuffer_Limit(buffer) == size,
+ "PARCBufferComposer instance's internal PARCBuffer limit must be %zu: %zu", size, parcBuffer_Limit(buffer));
+
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_Allocate_SizeMax)
+{
+ size_t size = SIZE_MAX;
+ PARCBufferComposer *composer = parcBufferComposer_Allocate(size);
+
+ assertNull(composer, "PARCBufferComposer instance should be NULL.");
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_AssertValid)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ assertNotNull(composer, "PARCBufferComposer instance should be non-NULL.");
+ parcBufferComposer_AssertValid(composer);
+
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, parcBufferComposer_AssertValid_NULL, .event = &LongBowTrapIllegalValue)
+{
+ parcBufferComposer_AssertValid(NULL);
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, parcBufferComposer_AssertValid_IncrementSize, .event = &LongBowTrapIllegalValue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ (data->composer)->incrementHeuristic = 0; // must be >= sizeof(void *)
+ parcBufferComposer_AssertValid(data->composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_Create)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ assertNotNull(composer, "PARCBufferComposer instance should be non-NULL.");
+
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_Equals)
+{
+ PARCBufferComposer *x = parcBufferComposer_Create();
+ PARCBufferComposer *y = parcBufferComposer_Create();
+ PARCBufferComposer *z = parcBufferComposer_Create();
+ PARCBufferComposer *u = parcBufferComposer_Allocate(10);
+
+ parcObjectTesting_AssertEqualsFunction(parcBufferComposer_Equals, x, y, z, u);
+
+ u->incrementHeuristic = 0;
+ assertFalse(parcBufferComposer_Equals(x, u), "PARCBufferComposer instances should be unequal due to size increments.");
+ assertFalse(parcBufferComposer_Equals(x, NULL), "Equals should return false since the second parameter is NULL.");
+ u->incrementHeuristic = sizeof(void *);
+
+ parcBufferComposer_Release(&x);
+ parcBufferComposer_Release(&y);
+ parcBufferComposer_Release(&z);
+ parcBufferComposer_Release(&u);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_ToString)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_Format(composer, "hello %s", "world");
+
+ char *string = parcBufferComposer_ToString(composer);
+
+ assertNotNull(string, "Expected non-NULL result from parcBufferComposer_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_GetBuffer)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ PARCBuffer *buffer = parcBufferComposer_GetBuffer(composer);
+
+ assertNotNull(composer, "PARCBufferComposer instance should be non-NULL.");
+ assertNotNull(buffer, "PARCBufferComposer instance's internal PARCBuffer should not be NULL");
+
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_PutArray)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ uint8_t string[6] = { 'h', 'e', 'l', 'l', 'o', '\0' };
+ parcBufferComposer_PutArray(composer, string, 6);
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+
+ char expected[5] = "hello";
+ char *actual = parcBuffer_ToString(buffer);
+ assertTrue(strncmp(expected, actual, 5) == 0, "Expected strings to match. Got %s, expected %s", actual, expected);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_PutBuffer)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ PARCBuffer *insertee = parcBuffer_WrapCString("hello world");
+ parcBufferComposer_PutBuffer(composer, insertee);
+ parcBuffer_Release(&insertee);
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+
+ char expected[11] = "hello world";
+ char *actual = parcBuffer_ToString(buffer);
+ assertTrue(strncmp(expected, actual, 11) == 0, "Expected strings to match. Got %s, expected %s", actual, expected);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_PutUint16)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ uint16_t val = 0x0101;
+ parcBufferComposer_PutUint16(composer, val);
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+ assertTrue(parcBuffer_GetUint16(buffer) == val, "Expected inserted uint16_t to be equal to %x, got %x", val, parcBuffer_GetUint16(buffer));
+
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_PutUint32)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ uint32_t val = 0x0101FFFF;
+ parcBufferComposer_PutUint32(composer, val);
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+ assertTrue(parcBuffer_GetUint32(buffer) == val, "Expected inserted uint32_t to be equal to %x, got %x", val, parcBuffer_GetUint32(buffer));
+
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_PutUint64)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ uint64_t val = 0x0101FFFFABCD0123;
+ parcBufferComposer_PutUint64(composer, val);
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+ assertTrue(parcBuffer_GetUint64(buffer) == val,
+ "Expected inserted uint64_t to be equal to %" PRIu64 ", got %" PRIu64 "", val, parcBuffer_GetUint64(buffer));
+
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_PutUint8)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ uint8_t byte = 0x01;
+ parcBufferComposer_PutUint8(composer, byte);
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+ assertTrue(parcBuffer_GetUint8(buffer) == byte, "Expected inserted byte to be equal to %x, got %x", byte, parcBuffer_GetUint8(buffer));
+
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_PutString)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ char string[14] = "Hello, World!";
+ parcBufferComposer_PutString(composer, string);
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(buffer);
+ assertTrue(strncmp(actual, string, strlen(string)) == 0,
+ "Expected inserted string to be equal to %s, got %s", string, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_PutStrings)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ char string[14] = "Hello, World!";
+ parcBufferComposer_PutStrings(composer, "Hello", ", ", "World!", NULL);
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(buffer);
+ assertTrue(strncmp(actual, string, strlen(string)) == 0, "Expected inserted string to be equal to %s, got %s", string, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_Format)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_Format(composer, "hello %s", "world");
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+
+ char expected[11] = "hello world";
+ char *actual = parcBuffer_ToString(buffer);
+ assertTrue(strncmp(expected, actual, 11) == 0, "Expected strings to match. Got %s, expected %s", actual, expected);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_PutChar)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ char byte = 'a';
+ parcBufferComposer_PutChar(composer, byte);
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+ assertTrue(parcBuffer_GetUint8(buffer) == byte, "Expected inserted char to be equal to %c, got %c", byte, parcBuffer_GetUint8(buffer));
+
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_CreateBuffer)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_PutString(composer, "hello world");
+
+ PARCBuffer *buffer = parcBufferComposer_CreateBuffer(composer);
+ parcBuffer_Flip(buffer); // flip the buffer since it was returned in write mode
+
+ char expected[11] = "hello world";
+ char *actual = parcBuffer_ToString(buffer);
+ assertTrue(strncmp(expected, actual, 11) == 0, "Expected strings to match. Got %s, expected %s", actual, expected);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_ProduceBuffer)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_PutString(composer, "hello world");
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+
+ char expected[11] = "hello world";
+ char *actual = parcBuffer_ToString(buffer);
+ assertTrue(strncmp(expected, actual, 11) == 0, "Expected strings to match. Got %s, expected %s", actual, expected);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcBufferComposer_PutString_Extend)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Allocate(4);
+ parcBufferComposer_PutString(composer, "hello world");
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+
+ char expected[11] = "hello world";
+ char *actual = parcBuffer_ToString(buffer);
+ assertTrue(strncmp(expected, actual, 11) == 0, "Expected strings to match. Got %s, expected %s", actual, expected);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_BufferComposer);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_ByteArray.c b/libparc/parc/algol/test/test_parc_ByteArray.c
new file mode 100755
index 00000000..971d79dd
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_ByteArray.c
@@ -0,0 +1,499 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file test_parc_ByteArray.c
+ *
+ */
+#include "../parc_ByteArray.c"
+#include <stdio.h>
+
+#include <LongBow/unit-test.h>
+#include <LongBow/debugging.h>
+#include <stdio.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(PARCByteArray)
+{
+ // 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(Errors);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(PARCByteArray)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(PARCByteArray)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Acquire_destroyoriginal);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Allocate);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Allocate_ZeroLength);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Wrap_NULL);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Wrap_ZeroLength);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Wrap);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Array);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_AddressOfIndex);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Capacity);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Copy_Allocated);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Copy_Wrapped);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Compare);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_PutBytes);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_CopyOut);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_CopyInByteArray);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Get);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Put);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Release);
+ LONGBOW_RUN_TEST_CASE(Global, parcByteArray_Display);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Allocate)
+{
+ PARCByteArray *actual = parcByteArray_Allocate(10);
+
+ parcByteArray_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Allocate_ZeroLength)
+{
+ PARCByteArray *actual = parcByteArray_Allocate(0);
+ assertNotNull(actual, "parcByteArray_Allocate(0) must not return NULL.");
+ assertTrue(parcByteArray_Capacity(actual) == 0, "Expected capacity to be 0");
+
+ parcByteArray_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Wrap)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *actual = parcByteArray_Wrap(10, buffer);
+
+ parcByteArray_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Wrap_NULL)
+{
+ PARCByteArray *actual = parcByteArray_Wrap(10, NULL);
+
+ assertNull(actual, "Expected NULL return value from parcByteArray_Wrap()");
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Wrap_ZeroLength)
+{
+ PARCByteArray *actual = parcByteArray_Wrap(0, (uint8_t[1]) { 0 });
+
+ assertNotNull(actual, "Expected non-NULL return value from parcByteArray_Wrap()");
+ assertTrue(parcByteArray_Capacity(actual) == 0, "Expected capacity to be zero.");
+ parcByteArray_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Array)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *actual = parcByteArray_Wrap(10, buffer);
+ assertTrue(buffer == parcByteArray_Array(actual), "Expected the array to be the wrapped array.");
+
+ parcByteArray_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_AddressOfIndex)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *actual = parcByteArray_Wrap(10, buffer);
+ uint8_t *address = parcByteArray_AddressOfIndex(actual, 3);
+
+ assertTrue(buffer[3] == *address,
+ "Expected %d, actual %d", buffer[3], *address);
+
+ parcByteArray_Release(&actual);
+}
+
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Release)
+{
+ PARCByteArray *actual = parcByteArray_Allocate(10);
+
+ parcByteArray_Release(&actual);
+ assertNull(actual, "Expected the pointer to be NULL after parcByteArray_Release");
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Copy_Allocated)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *original = parcByteArray_Allocate(sizeof(buffer));
+ parcByteArray_PutBytes(original, 0, sizeof(buffer), buffer);
+
+ PARCByteArray *clone = parcByteArray_Copy(original);
+
+ assertTrue(original != clone, "Expected clone to be a different instance that original.");
+
+ assertTrue(parcByteArray_Equals(original, clone), "Expected the clone to be equal to the original.");
+
+ parcByteArray_Release(&original);
+ parcByteArray_Release(&clone);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Copy_Wrapped)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *original = parcByteArray_Wrap(sizeof(buffer), buffer);
+
+ PARCByteArray *clone = parcByteArray_Copy(original);
+
+ assertTrue(original != clone, "Expected clone to be a different instance that original.");
+
+ assertTrue(parcByteArray_Equals(original, clone), "Expected the clone to be equal to the original.");
+
+ parcByteArray_Release(&original);
+ parcByteArray_Release(&clone);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Compare)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *x = parcByteArray_Wrap(sizeof(buffer), buffer);
+
+ PARCByteArray **equivalents = (PARCByteArray *[]) {
+ parcByteArray_Wrap(sizeof(buffer), buffer),
+ NULL
+ };
+ PARCByteArray **lessers = (PARCByteArray *[]) {
+ parcByteArray_Wrap(sizeof(buffer) - 1, buffer),
+ parcByteArray_Wrap(sizeof(buffer) - 1, (uint8_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8 }),
+ NULL
+ };
+ PARCByteArray **greaters = (PARCByteArray *[]) {
+ parcByteArray_Wrap(11, (uint8_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }),
+ parcByteArray_Wrap(10, (uint8_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10 }),
+ NULL
+ };
+ /*
+ * (a - b)
+ */
+ parcObjectTesting_AssertCompareTo(parcByteArray_Compare, x, equivalents, lessers, greaters);
+
+ parcByteArray_Release(&x);
+
+ for (int i = 0; equivalents[i] != NULL; i++) {
+ parcByteArray_Release(&equivalents[i]);
+ }
+ for (int i = 0; lessers[i] != NULL; i++) {
+ parcByteArray_Release(&lessers[i]);
+ }
+ for (int i = 0; greaters[i] != NULL; i++) {
+ parcByteArray_Release(&greaters[i]);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Equals)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *x = parcByteArray_Wrap(10, buffer);
+ PARCByteArray *y = parcByteArray_Wrap(10, buffer);
+ PARCByteArray *z = parcByteArray_Wrap(10, buffer);
+ PARCByteArray *u1 = parcByteArray_Wrap(5, buffer);
+ PARCByteArray *u2 = parcByteArray_Allocate(5);
+
+ parcObjectTesting_AssertEqualsFunction(parcByteArray_Equals, x, y, z, u1, u2, NULL);
+
+ parcByteArray_Release(&x);
+ parcByteArray_Release(&y);
+ parcByteArray_Release(&z);
+ parcByteArray_Release(&u1);
+ parcByteArray_Release(&u2);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Capacity)
+{
+ size_t expected = 10;
+
+ PARCByteArray *actual = parcByteArray_Allocate(expected);
+ assertTrue(expected == parcByteArray_Capacity(actual), "Expected %zd, actual %zd", expected, parcByteArray_Capacity(actual));
+
+ parcByteArray_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_CopyOut)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ uint8_t actual[10];
+
+ PARCByteArray *original = parcByteArray_Wrap(10, expected);
+ parcByteArray_GetBytes(original, 0, sizeof(actual), actual);
+
+ assertTrue(memcmp(expected, actual, sizeof(actual)) == 0,
+ "Expected parcByteArray_CopyOut to copy the orginal data");
+
+ parcByteArray_Release(&original);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_PutBytes)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ uint8_t actual[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ PARCByteArray *original = parcByteArray_Wrap(10, expected);
+ parcByteArray_PutBytes(original, 0, 10, actual);
+
+ assertTrue(memcmp(expected, actual, 10) == 0,
+ "Expected parcByteArray_CopyOut to copy the orginal data");
+
+ parcByteArray_Release(&original);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_CopyInByteArray)
+{
+ uint8_t array1[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ uint8_t array2[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ uint8_t expected[10] = { 0, 1, 2, 0, 0, 0, 6, 7, 8, 9 };
+
+ PARCByteArray *a1 = parcByteArray_Wrap(10, array1);
+ PARCByteArray *a2 = parcByteArray_Wrap(10, array2);
+ parcByteArray_ArrayCopy(a1, 3, a2, 0, 3);
+
+ assertTrue(memcmp(expected, parcByteArray_Array(a1), 10) == 0,
+ "Expected parcByteArray_CopyOut to copy the orginal data");
+
+ parcByteArray_Release(&a1);
+ parcByteArray_Release(&a2);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Get)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *original = parcByteArray_Wrap(10, buffer);
+
+ for (uint8_t index = 0; index < 10; index++) {
+ uint8_t actual = parcByteArray_GetByte(original, index);
+ assertTrue(index == actual, "Expected %d, actual %d", index, actual);
+ }
+ parcByteArray_Release(&original);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Put)
+{
+ uint8_t buffer[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ PARCByteArray *original = parcByteArray_Wrap(10, buffer);
+
+ for (uint8_t index = 0; index < 10; index++) {
+ parcByteArray_PutByte(original, index, index);
+ }
+
+ for (uint8_t index = 0; index < 10; index++) {
+ uint8_t actual = parcByteArray_GetByte(original, index);
+ assertTrue(index == actual, "Expected %d, actual %d", index, actual);
+ }
+
+ parcByteArray_Release(&original);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Acquire)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *actual = parcByteArray_Wrap(10, buffer);
+ PARCByteArray *reference = parcByteArray_Acquire(actual);
+
+ assertTrue(reference == actual, "Expected the new reference to be equal to the original.");
+
+ PARCByteArray *new1 = parcByteArray_Acquire(actual);
+ assertTrue(new1 == actual, "Expected new to be the same as actual");
+
+ PARCByteArray *new2 = parcByteArray_Acquire(actual);
+ assertTrue(new2 == actual, "Expected new to be the same as actual");
+
+ parcByteArray_Release(&new1);
+ assertNull(new1, "Expected destroy to null the pointer");
+ assertNotNull(actual, "Expected destroy to NOT null the original pointer");
+
+ parcByteArray_Release(&new2);
+ assertNull(new1, "Expected destroy to null the pointer");
+ assertNotNull(actual, "Expected destroy to NOT null the original pointer");
+
+ parcByteArray_Release(&reference);
+ parcByteArray_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Acquire_destroyoriginal)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *original = parcByteArray_Wrap(10, buffer);
+
+ PARCByteArray *ref1 = parcByteArray_Acquire(original);
+ assertTrue(ref1 == original, "Expected new to be the same as original");
+
+ parcByteArray_Release(&original);
+ assertNull(original, "Expected destroy to null the pointer");
+ assertNotNull(ref1, "Expected destroy to NOT null the new reference");
+
+ parcByteArray_Release(&ref1);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_HashCode)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCByteArray *x = parcByteArray_Wrap(10, buffer);
+ PARCByteArray *y = parcByteArray_Wrap(10, buffer);
+
+ PARCHashCode hashX = parcByteArray_HashCode(x);
+ PARCHashCode hashY = parcByteArray_HashCode(y);
+
+ assertTrue(hashX == hashY,
+ "Expected %" PRIPARCHashCode ", actual %" PRIPARCHashCode, hashX, hashY);
+
+ parcByteArray_Release(&x);
+ parcByteArray_Release(&y);
+}
+
+LONGBOW_TEST_CASE(Global, parcByteArray_Display)
+{
+ uint8_t buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
+
+ PARCByteArray *x = parcByteArray_Wrap(sizeof(buffer), buffer);
+
+ parcByteArray_Display(x, 0);
+
+ parcByteArray_Release(&x);
+}
+
+LONGBOW_TEST_FIXTURE(Errors)
+{
+ LONGBOW_RUN_TEST_CASE(Errors, parcByteArray_Put_overrun);
+ LONGBOW_RUN_TEST_CASE(Errors, parcByteArray_Get_overrun);
+ LONGBOW_RUN_TEST_CASE(Errors, parcByteArray_CopyIn_overrun);
+ LONGBOW_RUN_TEST_CASE(Errors, parcByteArray_CopyOut_overrun);
+}
+
+typedef struct parc_byte_array_longbow_clipboard {
+ PARCByteArray *byteArray;
+} parcByteArray_LongBowClipBoard;
+
+LONGBOW_TEST_FIXTURE_SETUP(Errors)
+{
+ parcByteArray_LongBowClipBoard *clipboardData = calloc(1, sizeof(parcByteArray_LongBowClipBoard));
+ clipboardData->byteArray = parcByteArray_Allocate(10);
+
+ longBowTestCase_SetClipBoardData(testCase, clipboardData);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Errors)
+{
+ parcByteArray_LongBowClipBoard *clipboardData = longBowTestCase_GetClipBoardData(testCase);
+ parcByteArray_Release(&clipboardData->byteArray);
+ free(clipboardData);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, parcByteArray_Put_overrun, .event = &LongBowTrapOutOfBounds)
+{
+ parcByteArray_LongBowClipBoard *testData = longBowTestCase_GetClipBoardData(testCase);
+ PARCByteArray *original = testData->byteArray;
+
+ for (uint8_t index = 0; index < 10 + 1; index++) {
+ parcByteArray_PutByte(original, index, index); // This will fail.
+ }
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, parcByteArray_CopyIn_overrun, .event = &LongBowTrapOutOfBounds)
+{
+ uint8_t actual[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ parcByteArray_LongBowClipBoard *testData = longBowTestCase_GetClipBoardData(testCase);
+ PARCByteArray *original = testData->byteArray;
+ parcByteArray_GetBytes(original, 1, 10, actual); // This will fail.
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, parcByteArray_CopyOut_overrun, .event = &LongBowTrapOutOfBounds)
+{
+ uint8_t actual[10];
+
+ parcByteArray_LongBowClipBoard *testData = longBowTestCase_GetClipBoardData(testCase);
+ PARCByteArray *original = testData->byteArray;
+ parcByteArray_GetBytes(original, 1, 10, actual); // This will fail.
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, parcByteArray_Get_overrun, .event = &LongBowTrapOutOfBounds)
+{
+ uint8_t buffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ parcByteArray_LongBowClipBoard *testData = longBowTestCase_GetClipBoardData(testCase);
+ PARCByteArray *original = testData->byteArray;
+ parcByteArray_PutBytes(original, 0, 10, buffer);
+
+ for (uint8_t index = 0; index < 10 + 1; index++) {
+ uint8_t actual = parcByteArray_GetByte(original, index); // this will fail.
+ assertTrue(index == actual, "Expected %d, actual %d", index, actual);
+ }
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(PARCByteArray);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Chunker.c b/libparc/parc/algol/test/test_parc_Chunker.c
new file mode 100755
index 00000000..945e6bab
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Chunker.c
@@ -0,0 +1,271 @@
+/*
+ * 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_Chunker.c"
+
+#include <stdio.h>
+
+#include <parc/algol/parc_Object.h>
+
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+typedef struct {
+ int val;
+ int dir;
+ bool atEnd;
+} _DummyChunkerState;
+
+typedef struct {
+ int start;
+ int end;
+ bool released;
+ size_t chunkSize;
+} _DummyChunker;
+
+static void *
+_InitForward(_DummyChunker *chunker)
+{
+ _DummyChunkerState *state = parcMemory_Allocate(sizeof(_DummyChunkerState));
+
+ state->val = 0;
+ state->dir = 1;
+ state->atEnd = false;
+
+ return state;
+}
+
+static bool
+_hasNext(_DummyChunker *chunker, void *voidstate)
+{
+ _DummyChunkerState *state = (_DummyChunkerState *) voidstate;
+ return !state->atEnd;
+}
+
+static void *
+_next(_DummyChunker *chunker, void *voidstate)
+{
+ _DummyChunkerState *state = (_DummyChunkerState *) voidstate;
+ state->val++;
+
+ if (state->val == chunker->end) {
+ state->atEnd = true;
+ }
+
+ return state;
+}
+
+static void *
+_get(_DummyChunker *chunker, void *voidstate)
+{
+ _DummyChunkerState *state = (_DummyChunkerState *) voidstate;
+ return &(state->val);
+}
+
+static void
+_finish(_DummyChunker *chunker, void *state)
+{
+ _DummyChunkerState *thestate = (_DummyChunkerState *) state;
+ parcMemory_Deallocate(&thestate);
+}
+
+static PARCIterator *
+_mock_ForwardIterator(const void *chunker)
+{
+ PARCIterator *iterator = parcIterator_Create((void *) chunker,
+ (void *(*)(PARCObject *))_InitForward,
+ (bool (*)(PARCObject *, void *))_hasNext,
+ (void *(*)(PARCObject *, void *))_next,
+ NULL,
+ (void *(*)(PARCObject *, void *))_get,
+ (void (*)(void *, void *))_finish,
+ NULL);
+
+ return iterator;
+}
+
+static PARCIterator *
+_mock_ReverseIterator(const void *chunker)
+{
+ PARCIterator *iterator = parcIterator_Create((void *) chunker,
+ (void *(*)(PARCObject *))_InitForward,
+ (bool (*)(PARCObject *, void *))_hasNext,
+ (void *(*)(PARCObject *, void *))_next,
+ NULL,
+ (void *(*)(PARCObject *, void *))_get,
+ (void (*)(void *, void *))_finish,
+ NULL);
+
+ return iterator;
+}
+
+static size_t
+_mock_GetChunkSize(const void *chunker)
+{
+ _DummyChunker *dummy = (_DummyChunker *) chunker;
+ return dummy->chunkSize;
+}
+
+static void
+_dummyDestroy(_DummyChunker **chunkerP)
+{
+ // pass...
+}
+
+PARCChunkerInterface *_MockChunker = &(PARCChunkerInterface) {
+ .ForwardIterator = (void *(*)(const void *))_mock_ForwardIterator,
+ .ReverseIterator = (void *(*)(const void *))_mock_ReverseIterator,
+ .GetChunkSize = (size_t (*)(const void *))_mock_GetChunkSize
+};
+
+parcObject_ExtendPARCObject(_DummyChunker, _dummyDestroy, NULL, NULL, NULL, NULL, NULL, NULL);
+parcObject_ImplementAcquire(_dummy, _DummyChunker);
+parcObject_ImplementRelease(_dummy, _DummyChunker);
+
+static _DummyChunker *
+_dummy_Create(int val)
+{
+ _DummyChunker *chunker = (_DummyChunker *) parcObject_CreateAndClearInstance(_DummyChunker);
+ chunker->start = 0;
+ chunker->end = val;
+ chunker->released = false;
+ chunker->chunkSize = val;
+ return chunker;
+}
+
+LONGBOW_TEST_RUNNER(parc_Chunker)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Chunker)
+{
+ 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_Chunker)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_Create);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ForwardIterator);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ReverseIterator);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_GetChunkSize);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_Create)
+{
+ _DummyChunker *dummy = _dummy_Create(10);
+ PARCChunker *chunker = parcChunker_Create(dummy, _MockChunker);
+ _dummy_Release(&dummy);
+
+ assertNotNull(chunker, "Expected non-NULL PARCChunker to be created from the dummy MockChunker");
+ PARCChunker *copy = parcChunker_Acquire(chunker);
+ assertNotNull(copy, "Expected non-NULL copy of the PARCChunker");
+
+ parcChunker_Release(&chunker);
+ parcChunker_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ForwardIterator)
+{
+ int n = 10;
+
+ _DummyChunker *dummy = _dummy_Create(n);
+ PARCChunker *chunker = parcChunker_Create(dummy, _MockChunker);
+ _dummy_Release(&dummy);
+ PARCIterator *itr = parcChunker_ForwardIterator(chunker);
+
+ int targetSum = (n * (n + 1)) / 2;
+ int sum = 0;
+ while (parcIterator_HasNext(itr)) {
+ int *val = parcIterator_Next(itr);
+ sum += *val;
+ }
+ assertTrue(targetSum == sum, "Expected the iterator to walk the chunker as needed\n");
+
+ parcIterator_Release(&itr);
+ parcChunker_Release(&chunker);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator)
+{
+ int n = 10;
+
+ _DummyChunker *dummy = _dummy_Create(n);
+ PARCChunker *chunker = parcChunker_Create(dummy, _MockChunker);
+ _dummy_Release(&dummy);
+ PARCIterator *itr = parcChunker_ReverseIterator(chunker);
+
+ int targetSum = (n * (n + 1)) / 2;
+ int sum = 0;
+ while (parcIterator_HasNext(itr)) {
+ int *val = parcIterator_Next(itr);
+ sum += *val;
+ }
+ assertTrue(targetSum == sum, "Expected the iterator to walk the chunker as needed\n");
+
+ parcIterator_Release(&itr);
+ parcChunker_Release(&chunker);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_GetChunkSize)
+{
+ int n = 10;
+
+ _DummyChunker *dummy = _dummy_Create(n);
+ PARCChunker *chunker = parcChunker_Create(dummy, _MockChunker);
+ _dummy_Release(&dummy);
+
+ size_t chunkSize = parcChunker_GetChunkSize(chunker);
+ assertTrue(chunkSize == n, "Expected the chunk size to be %d, got %zu\n", n, chunkSize);
+
+ parcChunker_Release(&chunker);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Chunker);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Clock.c b/libparc/parc/algol/test/test_parc_Clock.c
new file mode 100644
index 00000000..0adf813e
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Clock.c
@@ -0,0 +1,198 @@
+/*
+ * 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_Clock.c"
+#include <stdio.h>
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(parc_Clock)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Clock)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Clock)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ==========================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcClock_Wallclock);
+ LONGBOW_RUN_TEST_CASE(Global, parcClock_Wallclock_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, parcClock_Wallclock_GetTime);
+ LONGBOW_RUN_TEST_CASE(Global, parcClock_Wallclock_GetTimeval);
+ LONGBOW_RUN_TEST_CASE(Global, parcClock_Montonic);
+ LONGBOW_RUN_TEST_CASE(Global, parcClock_Monotonic_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, parcClock_Monotonic_GetTime);
+ LONGBOW_RUN_TEST_CASE(Global, parcClock_Monotonic_GetTimeval);
+
+ LONGBOW_RUN_TEST_CASE(Global, counterClock_Create);
+ LONGBOW_RUN_TEST_CASE(Global, counterClock_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, counterClock_GetTime);
+ LONGBOW_RUN_TEST_CASE(Global, counterClock_GetTime_Twice);
+ LONGBOW_RUN_TEST_CASE(Global, counterClock_GetTimeval);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcClock_Wallclock)
+{
+ PARCClock *clock = parcClock_Wallclock();
+ assertNotNull(clock, "Got null wall clock");
+ parcClock_Release(&clock);
+}
+
+LONGBOW_TEST_CASE(Global, parcClock_Wallclock_Acquire)
+{
+ PARCClock *clock = parcClock_Wallclock();
+ PARCClock *copy = parcClock_Acquire(clock);
+ assertNotNull(copy, "Got null wall clock");
+ parcClock_Release(&copy);
+ parcClock_Release(&clock);
+}
+
+LONGBOW_TEST_CASE(Global, parcClock_Wallclock_GetTime)
+{
+ PARCClock *clock = parcClock_Wallclock();
+ uint64_t t = parcClock_GetTime(clock);
+ parcClock_Release(&clock);
+ assertTrue(t > 0, "got 0 time");
+}
+
+LONGBOW_TEST_CASE(Global, parcClock_Wallclock_GetTimeval)
+{
+ PARCClock *clock = parcClock_Wallclock();
+ struct timeval tv = { 0, 0 };
+ parcClock_GetTimeval(clock, &tv);
+ parcClock_Release(&clock);
+ assertTrue(tv.tv_sec > 0, "Got 0 seconds");
+}
+
+// -----
+
+LONGBOW_TEST_CASE(Global, parcClock_Montonic)
+{
+ PARCClock *clock = parcClock_Monotonic();
+ assertNotNull(clock, "Got null wall clock");
+ parcClock_Release(&clock);
+}
+
+LONGBOW_TEST_CASE(Global, parcClock_Monotonic_Acquire)
+{
+ PARCClock *clock = parcClock_Monotonic();
+ PARCClock *copy = parcClock_Acquire(clock);
+ assertNotNull(copy, "Got null wall clock");
+}
+
+LONGBOW_TEST_CASE(Global, parcClock_Monotonic_GetTime)
+{
+ PARCClock *clock = parcClock_Monotonic();
+ uint64_t t = parcClock_GetTime(clock);
+ parcClock_Release(&clock);
+ assertTrue(t > 0, "got 0 time");
+}
+
+LONGBOW_TEST_CASE(Global, parcClock_Monotonic_GetTimeval)
+{
+ PARCClock *clock = parcClock_Monotonic();
+ struct timeval tv = { 0, 0 };
+ parcClock_GetTimeval(clock, &tv);
+ parcClock_Release(&clock);
+ assertTrue(tv.tv_sec > 0, "Got 0 seconds");
+}
+
+// -----
+
+LONGBOW_TEST_CASE(Global, counterClock_Create)
+{
+ PARCClock *clock = parcClock_Counter();
+ assertNotNull(clock, "Got null wall clock");
+ parcClock_Release(&clock);
+}
+
+LONGBOW_TEST_CASE(Global, counterClock_Acquire)
+{
+ PARCClock *clock = parcClock_Counter();
+ PARCClock *copy = parcClock_Acquire(clock);
+ assertNotNull(copy, "Got null wall clock");
+ parcClock_Release(&copy);
+ parcClock_Release(&clock);
+}
+
+LONGBOW_TEST_CASE(Global, counterClock_GetTime)
+{
+ PARCClock *clock = parcClock_Counter();
+ uint64_t t = parcClock_GetTime(clock);
+ parcClock_Release(&clock);
+ assertTrue(t == 1, "On first call should have gotten 1");
+}
+
+LONGBOW_TEST_CASE(Global, counterClock_GetTime_Twice)
+{
+ PARCClock *clock = parcClock_Counter();
+ parcClock_GetTime(clock);
+ uint64_t t2 = parcClock_GetTime(clock);
+ parcClock_Release(&clock);
+ assertTrue(t2 == 2, "On second call should have gotten 2");
+}
+
+LONGBOW_TEST_CASE(Global, counterClock_GetTimeval)
+{
+ PARCClock *clock = parcClock_Counter();
+ struct timeval tv = { 0, 0 };
+ parcClock_GetTimeval(clock, &tv);
+ parcClock_Release(&clock);
+ assertTrue(tv.tv_usec == 1, "On first call should have gotten 1 usec");
+}
+
+
+// ==========================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Clock);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
+
diff --git a/libparc/parc/algol/test/test_parc_Deque.c b/libparc/parc/algol/test/test_parc_Deque.c
new file mode 100755
index 00000000..02884b4a
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Deque.c
@@ -0,0 +1,620 @@
+/*
+ * 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_Deque.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_StdlibMemory.h>
+
+#include <parc/testing/parc_ObjectTesting.h>
+#include <parc/testing/parc_MemoryTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_Deque)
+{
+ // 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);
+ LONGBOW_RUN_TEST_FIXTURE(AcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+// LONGBOW_RUN_TEST_FIXTURE(Errors);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Deque)
+{
+ 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_Deque)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(AcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcDeque_CreateRelease);
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcDeque_CreateRelease_WithEquals);
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcDeque_AcquireRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(AcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(AcquireRelease)
+{
+ bool leaked = parcMemoryTesting_ExpectedOutstanding(0, "%s leaks memory \n", longBowTestCase_GetName(testCase)) != true;
+ if (leaked) {
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ printf("bailing\n");
+ exit(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcDeque_CreateRelease)
+{
+ PARCDeque *deque = parcDeque_Create();
+ assertNotNull(deque, "Expected non-null result from parcDeque_Create()");
+
+ parcDeque_Release(&deque);
+ assertNull(deque, "Expected parcDeque_Release to null the pointer");
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcDeque_CreateRelease_WithEquals)
+{
+ PARCDeque *deque = parcDeque_CreateCustom(NULL, NULL);
+ assertNotNull(deque, "Expected non-null result from parcDeque_Create()");
+
+ parcDeque_Release(&deque);
+ assertNull(deque, "Expected parcDeque_Release to null the pointer");
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcDeque_AcquireRelease)
+{
+ PARCDeque *original = parcDeque_Create();
+ assertNotNull(original, "Expected non-null result from parcDeque_Create()");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcDeque_Acquire, original);
+
+ PARCDeque *reference = parcDeque_Acquire(original);
+ assertTrue(original == reference, "Expected the reference to be equal to the original.");
+
+ parcDeque_Release(&original);
+ assertNull(original, "Expected parcDeque_Release to null the pointer");
+
+ parcDeque_Append(reference, (void *) 1);
+ size_t expected = 1;
+ size_t actual = parcDeque_Size(reference);
+ assertTrue(expected == actual,
+ "Expected size %zd, actual %zd", expected, actual);
+ parcDeque_Release(&reference);
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Append_One);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Append_Two);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_CreateDestroy);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_PeekFirst);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_PeekLast);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Prepend_One);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Prepend_Two);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Prepend_Three);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_IsEmpty);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_GetAtIndex);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_RemoveFirst);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_RemoveFirst_SingleElement);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_RemoveLast);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Size);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Display);
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Display_NULL);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcDeque_Iterator);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ bool leaked = parcMemoryTesting_ExpectedOutstanding(0, "%s leaks memory \n", longBowTestCase_GetName(testCase)) != true;
+ if (leaked) {
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Append_One)
+{
+ PARCDeque *deque = parcDeque_Create();
+ PARCDeque *actual = parcDeque_Append(deque, "element 1");
+
+ assertTrue(deque == actual, "Expected parcDeque_Append to return its argument.");
+ assertTrue(parcDeque_Size(deque) == 1, "Expected size of 1, actual %zd", parcDeque_Size(deque));
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Append_Two)
+{
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Append(deque, "element 1");
+ PARCDeque *actual = parcDeque_Append(deque, "element 2");
+
+ assertTrue(deque == actual, "Expected parcDeque_Append to return its argument.");
+ assertTrue(parcDeque_Size(deque) == 2, "Expected size of 2, actual %zd", parcDeque_Size(deque));
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_CreateDestroy)
+{
+ PARCDeque *deque = parcDeque_Create();
+ assertNotNull(deque, "Expected non-null result from parcDeque_Create()");
+
+ parcDeque_Release(&deque);
+ assertNull(deque, "Expected parcDeque_Destroy to null the pointer");
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_PeekFirst)
+{
+ char *expected = "element 2";
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Append(deque, expected);
+ parcDeque_Append(deque, "element 2");
+ parcDeque_Append(deque, "element 3");
+
+ char *actual = parcDeque_PeekFirst(deque);
+ assertTrue(strcmp(expected, actual) == 0, "Expected '%s' actual '%s'", expected, actual);
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_PeekLast)
+{
+ char *expected = "element 2";
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Append(deque, "element 1");
+ parcDeque_Append(deque, "element 2");
+ parcDeque_Append(deque, expected);
+
+ char *actual = parcDeque_PeekLast(deque);
+ assertTrue(strcmp(expected, actual) == 0, "Expected '%s' actual '%s'", expected, actual);
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Prepend_One)
+{
+ PARCDeque *deque = parcDeque_Create();
+ PARCDeque *actual = parcDeque_Prepend(deque, "element 1");
+
+ assertTrue(deque == actual, "Expected parcDeque_Append to return its argument.");
+ assertTrue(parcDeque_Size(deque) == 1, "Expected size of 1, actual %zd", parcDeque_Size(deque));
+ assertTrue(deque->head != NULL, "Expected head to be not null.");
+ assertTrue(deque->head == deque->tail, "Expected head to be equal to the tail.");
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Prepend_Two)
+{
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Prepend(deque, "element 2");
+ PARCDeque *actual = parcDeque_Prepend(deque, "element 1");
+
+ assertTrue(deque == actual, "Expected parcDeque_Prepend to return its argument.");
+ assertTrue(parcDeque_Size(deque) == 2, "Expected size of 2, actual %zd", parcDeque_Size(deque));
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Prepend_Three)
+{
+ char *expectedFirst = "expected first";
+ char *expectedLast = "expected last";
+
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Prepend(deque, expectedLast);
+ parcDeque_Prepend(deque, "element 2");
+ PARCDeque *actual = parcDeque_Prepend(deque, expectedFirst);
+
+ assertTrue(deque == actual, "Expected parcDeque_Prepend to return its argument.");
+ assertTrue(parcDeque_Size(deque) == 3, "Expected size of 3, actual %zd", parcDeque_Size(deque));
+
+ char *peek = parcDeque_PeekFirst(deque);
+ assertTrue(strcmp(expectedFirst, peek) == 0, "Expected '%s' actual '%s'", expectedFirst, peek);
+
+ peek = parcDeque_PeekLast(deque);
+ assertTrue(strcmp(expectedLast, peek) == 0, "Expected '%s' actual '%s'", expectedLast, peek);
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_RemoveFirst)
+{
+ char *expectedFirst = "expected 1st";
+ char *expectedLast = "expected last";
+
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Prepend(deque, expectedLast);
+ parcDeque_Prepend(deque, "element 2");
+ parcDeque_Prepend(deque, expectedFirst);
+
+ char *peek = parcDeque_RemoveFirst(deque);
+ assertTrue(strcmp(expectedFirst, peek) == 0, "Expected '%s' actual '%s'", expectedFirst, peek);
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_RemoveFirst_SingleElement)
+{
+ char *expectedFirst = "expected 1st";
+
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Prepend(deque, expectedFirst);
+
+ char *peek = parcDeque_RemoveFirst(deque);
+ assertTrue(strcmp(expectedFirst, peek) == 0,
+ "Expected '%s' actual '%s'", expectedFirst, peek);
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_RemoveLast)
+{
+ char *expectedFirst = "expected 1st";
+ char *expectedLast = "expected last";
+
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Prepend(deque, expectedLast);
+ parcDeque_Prepend(deque, "element 2");
+ parcDeque_Prepend(deque, expectedFirst);
+
+ char *peek = parcDeque_RemoveLast(deque);
+ assertTrue(strcmp(expectedLast, peek) == 0,
+ "Expected '%s' actual '%s'", expectedLast, peek);
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_RemoveLast_SingleElement)
+{
+ char *expectedFirst = "expected 1st";
+
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Prepend(deque, expectedFirst);
+
+ char *peek = parcDeque_RemoveLast(deque);
+ assertTrue(strcmp(expectedFirst, peek) == 0,
+ "Expected '%s' actual '%s'", expectedFirst, peek);
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Size)
+{
+ char *expectedFirst = "expected 1st";
+ char *expectedLast = "expected last";
+
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Prepend(deque, expectedLast);
+ parcDeque_Prepend(deque, "element 2");
+ parcDeque_Prepend(deque, expectedFirst);
+
+ assertTrue(parcDeque_Size(deque) == 3,
+ "Expected 3, actual %zd", parcDeque_Size(deque));
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_IsEmpty)
+{
+ char *expectedLast = "expected last";
+
+ PARCDeque *deque = parcDeque_Create();
+
+ assertTrue(parcDeque_IsEmpty(deque), "Expected true.");
+ parcDeque_Prepend(deque, expectedLast);
+ assertFalse(parcDeque_IsEmpty(deque), "Expected false.");
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_GetAtIndex)
+{
+ char *expected0 = "expected 1";
+ char *expected1 = "expected 2";
+ char *expected2 = "expected 3";
+
+ PARCDeque *deque = parcDeque_Create();
+ parcDeque_Append(deque, expected0);
+ parcDeque_Append(deque, expected1);
+ parcDeque_Append(deque, expected2);
+
+ char *actual;
+ actual = parcDeque_GetAtIndex(deque, 0);
+ assertTrue(strcmp(actual, expected0) == 0, "Expected '%s', actual '%s", expected0, actual);
+ actual = parcDeque_GetAtIndex(deque, 1);
+ assertTrue(strcmp(actual, expected1) == 0, "Expected '%s', actual '%s", expected1, actual);
+ actual = parcDeque_GetAtIndex(deque, 2);
+ assertTrue(strcmp(actual, expected2) == 0, "Expected '%s', actual '%s", expected2, actual);
+
+ parcDeque_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Equals)
+{
+ PARCDeque *x = parcDeque_Create();
+ parcDeque_Append(x, (void *) 0);
+ parcDeque_Append(x, (void *) 1);
+ parcDeque_Append(x, (void *) 2);
+ parcDeque_Append(x, (void *) 3);
+ parcDeque_Append(x, (void *) 4);
+ parcDeque_Append(x, (void *) 5);
+ PARCDeque *y = parcDeque_Create();
+ parcDeque_Append(y, (void *) 0);
+ parcDeque_Append(y, (void *) 1);
+ parcDeque_Append(y, (void *) 2);
+ parcDeque_Append(y, (void *) 3);
+ parcDeque_Append(y, (void *) 4);
+ parcDeque_Append(y, (void *) 5);
+ PARCDeque *z = parcDeque_Create();
+ parcDeque_Append(z, (void *) 0);
+ parcDeque_Append(z, (void *) 1);
+ parcDeque_Append(z, (void *) 2);
+ parcDeque_Append(z, (void *) 3);
+ parcDeque_Append(z, (void *) 4);
+ parcDeque_Append(z, (void *) 5);
+ PARCDeque *u1 = parcDeque_Create();
+ parcDeque_Append(u1, (void *) 0);
+ parcDeque_Append(u1, (void *) 1);
+ parcDeque_Append(u1, (void *) 2);
+ parcDeque_Append(u1, (void *) 3);
+ parcDeque_Append(u1, (void *) 4);
+ PARCDeque *u2 = parcDeque_Create();
+ parcDeque_Append(u2, (void *) 0);
+ parcDeque_Append(u2, (void *) 1);
+ parcDeque_Append(u2, (void *) 2);
+ parcDeque_Append(u2, (void *) 3);
+ parcDeque_Append(u2, (void *) 4);
+ parcDeque_Append(u2, (void *) 4);
+
+ parcObjectTesting_AssertEqualsFunction(parcDeque_Equals, x, y, z, u1, u2, NULL);
+
+ parcDeque_Release(&x);
+ parcDeque_Release(&y);
+ parcDeque_Release(&z);
+ parcDeque_Release(&u1);
+ parcDeque_Release(&u2);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Copy)
+{
+ PARCDeque *x = parcDeque_Create();
+ parcDeque_Append(x, (void *) 0);
+ parcDeque_Append(x, (void *) 1);
+ parcDeque_Append(x, (void *) 2);
+ parcDeque_Append(x, (void *) 3);
+ parcDeque_Append(x, (void *) 4);
+ parcDeque_Append(x, (void *) 5);
+
+ PARCDeque *y = parcDeque_Copy(x);
+
+ assertTrue(parcDeque_Equals(x, y), "Expected the copy to be equal to the original.");
+
+ parcDeque_Release(&y);
+ parcDeque_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Display)
+{
+ PARCDeque *x = parcDeque_Create();
+ parcDeque_Append(x, (void *) 0);
+ parcDeque_Append(x, (void *) 1);
+ parcDeque_Append(x, (void *) 2);
+ parcDeque_Append(x, (void *) 3);
+ parcDeque_Append(x, (void *) 4);
+ parcDeque_Append(x, (void *) 5);
+
+ parcDeque_Display(x, 0);
+
+ parcDeque_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Display_NULL)
+{
+ parcDeque_Display(NULL, 0);
+}
+
+LONGBOW_TEST_CASE(Global, parcDeque_Iterator)
+{
+ PARCDeque *x = parcDeque_Create();
+ for (size_t i = 0; i < 100; i++) {
+ parcDeque_Append(x, (void *) i);
+ }
+
+ PARCIterator *iterator = parcDeque_Iterator(x);
+ size_t expected = 0;
+ while (parcIterator_HasNext(iterator)) {
+ size_t actual = (size_t) parcIterator_Next(iterator);
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+ expected++;
+ }
+ parcIterator_Release(&iterator);
+
+ parcDeque_Release(&x);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _parcDequeNode_Create);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ bool leaked = parcMemoryTesting_ExpectedOutstanding(0, "%s leaks memory \n", longBowTestCase_GetName(testCase)) != true;
+ if (leaked) {
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Local, _parcDequeNode_Create)
+{
+ void *element = "element";
+ struct parc_deque_node *previous = NULL;
+ struct parc_deque_node *next = NULL;
+
+ struct parc_deque_node *actual = _parcDequeNode_Create(element, previous, next);
+ _parcDequeNode_Destroy(NULL, &actual);
+}
+
+LONGBOW_TEST_FIXTURE(Errors)
+{
+ LONGBOW_RUN_TEST_CASE(Errors, parcDeque_GetAtIndex_OutOfBounds);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Errors)
+{
+ PARCDeque *deque = parcDeque_Create();
+ longBowTestCase_SetClipBoardData(testCase, deque);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Errors)
+{
+ PARCDeque *deque = longBowTestCase_GetClipBoardData(testCase);
+ parcDeque_Release(&deque);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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, parcDeque_GetAtIndex_OutOfBounds, .event = &LongBowTrapOutOfBounds)
+{
+ char *expected0 = "expected 1";
+ char *expected1 = "expected 2";
+ char *expected2 = "expected 3";
+
+ PARCDeque *deque = longBowTestCase_GetClipBoardData(testCase);
+ parcDeque_Append(deque, expected0);
+ parcDeque_Append(deque, expected1);
+ parcDeque_Append(deque, expected2);
+
+ parcDeque_GetAtIndex(deque, 3);
+}
+
+LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, parcQueue_Append);
+ LONGBOW_RUN_TEST_CASE(Performance, parcQueue_N2);
+ LONGBOW_RUN_TEST_CASE(Performance, parcQueue_Iterator);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ parcMemory_SetInterface(&PARCStdlibMemoryAsPARCMemory);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Performance, parcQueue_Append)
+{
+ PARCDeque *x = parcDeque_Create();
+
+ for (size_t i = 0; i < 100000; i++) {
+ parcDeque_Append(x, (void *) i);
+ }
+
+ parcDeque_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Performance, parcQueue_N2)
+{
+ PARCDeque *x = parcDeque_Create();
+ for (size_t i = 0; i < 100000; i++) {
+ parcDeque_Append(x, (void *) i);
+ }
+
+ for (size_t expected = 0; expected < parcDeque_Size(x); expected++) {
+ size_t actual = (size_t) parcDeque_GetAtIndex(x, expected);
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+ }
+
+ parcDeque_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Performance, parcQueue_Iterator)
+{
+ PARCDeque *x = parcDeque_Create();
+ for (size_t i = 0; i < 100000; i++) {
+ parcDeque_Append(x, (void *) i);
+ }
+
+ PARCIterator *iterator = parcDeque_Iterator(x);
+ size_t expected = 0;
+ while (parcIterator_HasNext(iterator)) {
+ size_t actual = (size_t) parcIterator_Next(iterator);
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+ expected++;
+ }
+ parcIterator_Release(&iterator);
+
+ parcDeque_Release(&x);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Deque);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Dictionary.c b/libparc/parc/algol/test/test_parc_Dictionary.c
new file mode 100644
index 00000000..095f3c98
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Dictionary.c
@@ -0,0 +1,736 @@
+/*
+ * 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 <stdio.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include "../parc_Dictionary.c"
+
+static int *
+_keyNewInt(int key)
+{
+ int *newKey = parcMemory_Allocate(sizeof(int));
+ assertNotNull(newKey, "parcMemory_Allocate(%zu) returned NULL",
+ sizeof(int));
+ *newKey = key;
+ return newKey;
+}
+
+static int *
+_valueNewInt(int value)
+{
+ int *newValue = parcMemory_Allocate(sizeof(int));
+ assertNotNull(newValue, "parcMemory_Allocate(%zu) returned NULL", sizeof(int));
+ *newValue = value;
+ return newValue;
+}
+
+static bool
+_valueEquals(const void *value1, const void *value2)
+{
+ return *(int *) value1 == *(int *) value2;
+}
+
+static int
+_intKeyComp(const void *key1, const void *key2)
+{
+ if (*(int *) key1 < *(int *) key2) {
+ return -1;
+ }
+ if (*(int *) key1 == *(int *) key2) {
+ return 0;
+ }
+ return 1;
+}
+
+static uint32_t
+_intKeyHash(const void *key1)
+{
+ return *(int *) key1;
+}
+
+
+static void
+_keyFree(void **value)
+{
+ parcMemory_Deallocate((void **) value);
+ *value = NULL;
+}
+
+static void
+_valueFree(void **key)
+{
+ parcMemory_Deallocate((void **) key);
+ *key = NULL;
+}
+
+
+
+
+LONGBOW_TEST_RUNNER(PARC_Dictionary)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(PARC_Dictionary)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(PARC_Dictionary)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(-1);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Create);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_SetValue_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Size_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Size);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Size_AfterDelete);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Size_AfterOverwrite);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Get_EmptyTree);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Get_NonExistent);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Get_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Get);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Get_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Remove_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Remove);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Remove_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_RemoveAndDestroy_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_RemoveAndDestroy);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_RemoveAndDestroy_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Keys);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Values);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Equals_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Equals_Not_Values);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_Dictionary_Equals_Not_Keys);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Create)
+{
+ PARCDictionary *dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, NULL, NULL, NULL);
+
+ parcDictionary_Destroy(&dictionary);
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_SetValue_Destroy)
+{
+ PARCDictionary *dictionary;
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(1), (void *) _valueNewInt(11));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(2), (void *) _valueNewInt(12));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(3), (void *) _valueNewInt(13));
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Size_Empty)
+{
+ PARCDictionary *dictionary;
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ assertTrue(0 == parcDictionary_Size(dictionary), "Wrong size of dictionary - empty, start");
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Size)
+{
+ PARCDictionary *dictionary;
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(4), (void *) _valueNewInt(1004));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(3), (void *) _valueNewInt(1003));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(2), (void *) _valueNewInt(1002));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(8), (void *) _valueNewInt(1008));
+
+ assertTrue(4 == parcDictionary_Size(dictionary), "Wrong size of dictionary after add 3");
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Size_AfterDelete)
+{
+ PARCDictionary *dictionary;
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(4), (void *) _valueNewInt(1004));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(3), (void *) _valueNewInt(1003));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(2), (void *) _valueNewInt(1002));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(8), (void *) _valueNewInt(1008));
+
+ int searchKey = 2;
+
+ parcDictionary_RemoveAndDestroyValue(dictionary, &searchKey);
+
+ size_t size = parcDictionary_Size(dictionary);
+
+ assertTrue(3 == size, "Wrong size of dictionary after 1 delete (%zu instead of 3)", size);
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Size_AfterOverwrite)
+{
+ PARCDictionary *dictionary;
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(4), (void *) _valueNewInt(1004));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(3), (void *) _valueNewInt(1003));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(2), (void *) _valueNewInt(1002));
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(8), (void *) _valueNewInt(1008));
+
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(3), (void *) _valueNewInt(1010));
+
+ size_t size = parcDictionary_Size(dictionary);
+
+ assertTrue(4 == size, "Wrong size of dictionary after 1 delete (%zu instead of 4)", size);
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Get_EmptyTree)
+{
+ PARCDictionary *dictionary;
+
+ int key = 100;
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ void *value = parcDictionary_GetValue(dictionary, &key);
+
+ assertTrue(NULL == value, "Object did not exist, must return NULL");
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Get_NonExistent)
+{
+ PARCDictionary *dictionary;
+ int key = 100;
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 1; i < 10; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ void *value = parcDictionary_GetValue(dictionary, &key);
+
+ assertTrue(NULL == value, "Object did not exist, must return NULL");
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Get_First)
+{
+ PARCDictionary *dictionary;
+ int key = 1;
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 1; i < 10; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ int *value = parcDictionary_GetValue(dictionary, &key);
+
+ assertNotNull(value, "NULL value returned");
+ assertTrue(*value == (1 << 8), "Wrong object returned or not found");
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Get)
+{
+ PARCDictionary *dictionary;
+ int key = 5;
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 1; i < 10; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ int *value = parcDictionary_GetValue(dictionary, &key);
+
+ assertNotNull(value, "NULL value returned");
+ assertTrue(*value == (5 << 8), "Wrong object returned or not found");
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Get_Last)
+{
+ PARCDictionary *dictionary;
+ int key = 9;
+
+ dictionary = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 1; i < 10; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ int *value = parcDictionary_GetValue(dictionary, &key);
+
+ assertNotNull(value, "NULL value returned");
+ assertTrue(*value == (9 << 8), "Wrong object returned or not found");
+
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Remove_First)
+{
+ PARCDictionary *dictionary1;
+ PARCDictionary *dictionary2;
+
+ dictionary1 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+ dictionary2 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(1), (void *) _valueNewInt(1 << 8));
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ int searchKey = 1;
+
+ void *data = parcDictionary_RemoveValue(dictionary1, &searchKey);
+
+ _valueFree(&data);
+
+ assertTrue(parcDictionary_Equals(dictionary1, dictionary2), "Trees dont match after remove");
+
+ parcDictionary_Destroy(&dictionary1);
+ parcDictionary_Destroy(&dictionary2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Remove)
+{
+ PARCDictionary *dictionary1;
+ PARCDictionary *dictionary2;
+
+ dictionary1 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+ dictionary2 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 31; i < 40; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(30), (void *) _valueNewInt(31 << 8));
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ int searchKey = 30;
+
+ void *data = parcDictionary_RemoveValue(dictionary1, &searchKey);
+
+ _valueFree(&data);
+
+ assertTrue(parcDictionary_Equals(dictionary1, dictionary2), "Trees dont match after remove");
+
+ parcDictionary_Destroy(&dictionary1);
+ parcDictionary_Destroy(&dictionary2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Remove_Last)
+{
+ PARCDictionary *dictionary1;
+ PARCDictionary *dictionary2;
+
+ dictionary1 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+ dictionary2 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(100), (void *) _valueNewInt(100 << 8));
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ int searchKey = 100;
+
+ void *data = parcDictionary_RemoveValue(dictionary1, &searchKey);
+
+ _valueFree(&data);
+
+ assertTrue(parcDictionary_Equals(dictionary1, dictionary2), "Trees dont match after remove");
+
+ parcDictionary_Destroy(&dictionary1);
+ parcDictionary_Destroy(&dictionary2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_RemoveAndDestroy_First)
+{
+ PARCDictionary *dictionary1 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+ PARCDictionary *dictionary2 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(1), (void *) _valueNewInt(1 << 8));
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ int searchKey = 1;
+
+ parcDictionary_RemoveAndDestroyValue(dictionary1, &searchKey);
+
+ assertTrue(parcDictionary_Equals(dictionary1, dictionary2), "Trees dont match after remove");
+
+ parcDictionary_Destroy(&dictionary1);
+ parcDictionary_Destroy(&dictionary2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_RemoveAndDestroy)
+{
+ PARCDictionary *dictionary1;
+ PARCDictionary *dictionary2;
+
+ dictionary1 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+ dictionary2 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 31; i < 40; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(30), (void *) _valueNewInt(31 << 8));
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ int searchKey = 30;
+
+ parcDictionary_RemoveAndDestroyValue(dictionary1, &searchKey);
+
+ assertTrue(parcDictionary_Equals(dictionary1, dictionary2), "Trees dont match after remove");
+
+ parcDictionary_Destroy(&dictionary1);
+ parcDictionary_Destroy(&dictionary2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_RemoveAndDestroy_Last)
+{
+ PARCDictionary *dictionary1;
+ PARCDictionary *dictionary2;
+
+ dictionary1 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+ dictionary2 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(100), (void *) _valueNewInt(100 << 8));
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary1, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ int searchKey = 100;
+
+ parcDictionary_RemoveAndDestroyValue(dictionary1, &searchKey);
+
+ assertTrue(parcDictionary_Equals(dictionary1, dictionary2), "Trees dont match after remove");
+
+ parcDictionary_Destroy(&dictionary1);
+ parcDictionary_Destroy(&dictionary2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Keys)
+{
+ PARCDictionary *dictionary =
+ parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 0; i < 9; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ PARCArrayList *keys = parcDictionary_Keys(dictionary);
+
+ assertNotNull(keys,
+ "parcDictionary_Keys returned NULL, expected non-NULL.");
+
+ assertTrue(parcArrayList_Size(keys) == parcDictionary_Size(dictionary),
+ "Expected parcDictionary_Keys size %zu, actual %zd, ",
+ parcDictionary_Size(dictionary), parcArrayList_Size(keys));
+
+ for (int i = 0; i < 9; i++) {
+ bool found = false;
+ int *keyToFind = _keyNewInt(i);
+ for (int j = 0; j < parcArrayList_Size(keys); j++) {
+ int *keyToTest = parcArrayList_Get(keys, j);
+ if (*keyToTest == *keyToFind) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue(found, "Expected to find Key %d, not found", *keyToFind);
+ parcMemory_Deallocate((void **) &keyToFind);
+ }
+ parcArrayList_Destroy(&keys);
+ parcDictionary_Destroy(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Values)
+{
+ PARCDictionary *dictionary =
+ parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 0; i < 9; i++) {
+ // Add some elements to the dictionary
+ parcDictionary_SetValue(dictionary, (void *) _keyNewInt(i), (void *) _valueNewInt(i << 8));
+ }
+
+ PARCArrayList *values = parcDictionary_Values(dictionary);
+
+ assertNotNull(values,
+ "parcDictionary_Values returned NULL, expected not NULL");
+
+ assertTrue(parcArrayList_Size(values) == parcDictionary_Size(dictionary),
+ "parcDictionary_Values size %zd not equal not parcDictionary_Size, %zd",
+ parcArrayList_Size(values), parcDictionary_Size(dictionary));
+
+ for (int i = 0; i < 9; i++) {
+ bool found = false;
+ int *keyToFind = _keyNewInt(i);
+ int *valueToFind = parcDictionary_GetValue(dictionary, keyToFind);
+ for (int j = 0; j < parcArrayList_Size(values); j++) {
+ int *valueToTest = parcArrayList_Get(values, j);
+ if (valueToFind == valueToTest) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue(found,
+ "Expected to find value %d, not found", *valueToFind);
+ parcMemory_Deallocate((void **) &keyToFind);
+ }
+ parcArrayList_Destroy(&values);
+ parcDictionary_Destroy(&dictionary);
+}
+
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Equals_Empty)
+{
+ PARCDictionary *dictionary1;
+ PARCDictionary *dictionary2;
+
+ dictionary1 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+ dictionary2 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ assertTrue(parcDictionary_Equals(dictionary1, dictionary2), "Empty lists are not equal");
+
+ parcDictionary_Destroy(&dictionary1);
+ parcDictionary_Destroy(&dictionary2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Equals_Not_Values)
+{
+ PARCDictionary *dictionary1;
+ PARCDictionary *dictionary2;
+
+ int compareSetValues = 100;
+
+ dictionary1 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+ dictionary2 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ printf("Testing dictionary equals...\n");
+
+ for (int i = 1; i < compareSetValues; i++) {
+ parcDictionary_SetValue(dictionary1,
+ (void *) _keyNewInt(i),
+ (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2,
+ (void *) _keyNewInt(compareSetValues - i),
+ (void *) _valueNewInt((compareSetValues + i) << 8));
+ }
+
+ assertFalse(parcDictionary_Equals(dictionary1, dictionary2), "Dictionaries are equal and they shouldn't be!");
+
+ parcDictionary_Destroy(&dictionary1);
+ parcDictionary_Destroy(&dictionary2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Equals_Not_Keys)
+{
+ PARCDictionary *dictionary1;
+ PARCDictionary *dictionary2;
+
+ int compareSetValues = 100;
+
+ dictionary1 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+ dictionary2 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 1; i < compareSetValues; i++) {
+ parcDictionary_SetValue(dictionary1,
+ (void *) _keyNewInt(i),
+ (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2,
+ (void *) _keyNewInt(compareSetValues + i),
+ (void *) _valueNewInt((compareSetValues - i) << 8));
+ }
+
+ assertFalse(parcDictionary_Equals(dictionary1, dictionary2), "Lists are equal");
+
+ parcDictionary_Destroy(&dictionary1);
+ parcDictionary_Destroy(&dictionary2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_Dictionary_Equals)
+{
+ PARCDictionary *dictionary1;
+ PARCDictionary *dictionary2;
+
+ int compareSetValues = 100;
+
+ dictionary1 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+ dictionary2 = parcDictionary_Create(_intKeyComp, _intKeyHash, _keyFree, _valueEquals, _valueFree);
+
+ for (int i = 1; i < compareSetValues; i++) {
+ parcDictionary_SetValue(dictionary1,
+ (void *) _keyNewInt(i),
+ (void *) _valueNewInt(i << 8));
+ parcDictionary_SetValue(dictionary2,
+ (void *) _keyNewInt(compareSetValues - i),
+ (void *) _valueNewInt((compareSetValues - i) << 8));
+ }
+
+ assertTrue(parcDictionary_Equals(dictionary1, dictionary2), "Dictionaries are not equal");
+
+ parcDictionary_Destroy(&dictionary1);
+ parcDictionary_Destroy(&dictionary2);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(PARC_Dictionary);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Display.c b/libparc/parc/algol/test/test_parc_Display.c
new file mode 100755
index 00000000..29b9fdf2
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Display.c
@@ -0,0 +1,85 @@
+/*
+ * 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_DisplayIndented.c"
+
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(parc_Display)
+{
+ // 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_Display)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Display)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcDisplay_PrintLine);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcDisplay_PrintLine)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Display);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Environment.c b/libparc/parc/algol/test/test_parc_Environment.c
new file mode 100755
index 00000000..e4513b31
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Environment.c
@@ -0,0 +1,86 @@
+/*
+ * 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_Environment.c"
+
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(parc_Environment)
+{
+ // 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_Environment)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Environment)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcEnvironment_GetHomeDirectory);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcEnvironment_GetHomeDirectory)
+{
+ const char *homeDirectory = parcEnvironment_GetHomeDirectory();
+ assertNotNull(homeDirectory, "Cannot get the current home directory.");
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Environment);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Event.c b/libparc/parc/algol/test/test_parc_Event.c
new file mode 100644
index 00000000..261cd079
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Event.c
@@ -0,0 +1,243 @@
+/*
+ * 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 <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.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_Event.c"
+
+LONGBOW_TEST_RUNNER(parc_Event)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Event)
+{
+ parcEvent_EnableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Event)
+{
+ parcEvent_DisableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parc_Event_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Event_Start);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Event_Stop);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Event_Poll);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Event_SetPriority);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static int _test_event_called = 0;
+
+static void
+_test_event(int fd, PARCEventType flags, void *data)
+{
+ _test_event_called++;
+}
+
+LONGBOW_TEST_CASE(Global, parc_Event_Create_Destroy)
+{
+ int fds[2];
+ int result = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+ assertFalse(result, "Socketpair creation failed.\n");
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+ PARCEvent *parcEvent = parcEvent_Create(parcEventScheduler, fds[0], PARCEventType_Write, _test_event, NULL);
+ assertNotNull(parcEvent, "parcEvent_Create returned a null reference");
+ parcEvent_Destroy(&parcEvent);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+
+ close(fds[0]);
+ close(fds[1]);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Event_Start)
+{
+ int fds[2];
+ int result = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+ assertFalse(result, "Socketpair creation failed.\n");
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+ PARCEvent *parcEvent = parcEvent_Create(parcEventScheduler, fds[0], PARCEventType_Read | PARCEventType_Write, _test_event, NULL);
+ assertNotNull(parcEvent, "parcEvent_Create returned a null reference");
+
+ _test_event_called = 0;
+ parcEvent_Start(parcEvent);
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_Blocking);
+ assertTrue(_test_event_called == 1, "Event never called.");
+
+ parcEvent_Destroy(&parcEvent);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ close(fds[0]);
+ close(fds[1]);
+}
+
+static int _test_stop_event_called = 0;
+
+static void
+_test_stop_event(int fd, PARCEventType flags, void *data)
+{
+ PARCEvent **parcEvent = (PARCEvent **) data;
+ _test_stop_event_called++;
+ parcEvent_Stop(*parcEvent);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Event_Stop)
+{
+ int fds[2];
+ int result = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+ assertFalse(result, "Socketpair creation failed.\n");
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+ PARCEvent *parcEvent = parcEvent_Create(parcEventScheduler, fds[0], PARCEventType_Write | PARCEventType_Persist, _test_stop_event, &parcEvent);
+ assertNotNull(parcEvent, "parcEvent_Create returned a null reference");
+
+ parcEvent_Start(parcEvent);
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_Blocking);
+ assertTrue(_test_stop_event_called > 0, "Event never called.");
+ assertFalse(_test_stop_event_called != 1, "Event called more than once.");
+
+ parcEvent_Destroy(&parcEvent);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ close(fds[0]);
+ close(fds[1]);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Event_Poll)
+{
+ int fds[2];
+ int result = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+ assertFalse(result, "Socketpair creation failed.\n");
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+ PARCEvent *parcEvent = parcEvent_Create(parcEventScheduler, fds[0], PARCEventType_Write, _test_event, NULL);
+ assertNotNull(parcEvent, "parcEvent_Create returned a null reference");
+
+ result = parcEvent_Poll(parcEvent, PARCEventType_Read);
+ // should be no outstanding events
+ assertTrue(result == 0, "parcEvent_Poll returned %d\n", result);
+
+ parcEvent_Destroy(&parcEvent);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ close(fds[0]);
+ close(fds[1]);
+}
+
+static int _test_writeMaxPriority_event_called = 0;
+
+static void
+_test_writeMaxPriority_event(int fd, PARCEventType flags, void *data)
+{
+ PARCEvent *parcEvent = *((PARCEvent **) data);
+ parcEvent_Stop(parcEvent);
+ _test_writeMaxPriority_event_called++;
+}
+
+static int _test_writeMinPriority_event_called = 0;
+
+static void
+_test_writeMinPriority_event(int fd, PARCEventType flags, void *data)
+{
+ PARCEvent *parcEvent = *((PARCEvent **) data);
+ parcEvent_Stop(parcEvent);
+ _test_writeMinPriority_event_called++;
+}
+
+LONGBOW_TEST_CASE(Global, parc_Event_SetPriority)
+{
+ int fds[2];
+ int result = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+ assertFalse(result, "Socketpair creation failed.\n");
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ //
+ // First event to be called back disables its partner's event
+ //
+ PARCEvent *parcEventWriteMax, *parcEventWriteMin;
+ parcEventWriteMax = parcEvent_Create(parcEventScheduler, fds[0],
+ PARCEventType_Write,
+ _test_writeMaxPriority_event,
+ (void *) &parcEventWriteMin);
+ assertNotNull(parcEventWriteMax, "parcEvent_Create returned a null reference");
+ parcEventWriteMin = parcEvent_Create(parcEventScheduler, fds[1],
+ PARCEventType_Write,
+ _test_writeMinPriority_event,
+ (void *) &parcEventWriteMax);
+ assertNotNull(parcEventWriteMin, "parcEvent_Create returned a null reference");
+
+ result = parcEvent_SetPriority(parcEventWriteMin, PARCEventPriority_Minimum);
+ assertTrue(result == 0, "parcEvent_SetPriority write returned %d\n", result);
+ result = parcEvent_SetPriority(parcEventWriteMax, PARCEventPriority_Maximum);
+ assertTrue(result == 0, "parcEvent_SetPriority read returned %d\n", result);
+
+ parcEvent_Start(parcEventWriteMin);
+ parcEvent_Start(parcEventWriteMax);
+
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_NonBlocking);
+
+ assertTrue(_test_writeMaxPriority_event_called == 1, "Read event called before priority write event handled");
+ assertTrue(_test_writeMinPriority_event_called == 0, "Write event never triggered");
+
+ parcEvent_Destroy(&parcEventWriteMax);
+ parcEvent_Destroy(&parcEventWriteMin);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ close(fds[0]);
+ close(fds[1]);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Event);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_EventBuffer.c b/libparc/parc/algol/test/test_parc_EventBuffer.c
new file mode 100644
index 00000000..c0b8d8c9
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_EventBuffer.c
@@ -0,0 +1,345 @@
+/*
+ * 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 <stdio.h>
+#include <pthread.h>
+
+#include <arpa/inet.h>
+
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_EventBuffer.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_EventBuffer.c"
+
+LONGBOW_TEST_RUNNER(parc_EventBuffer)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_EventBuffer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_EventBuffer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventBuffer_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventBuffer_GetLength_Append);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventBuffer_Prepend_Pullup);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventBuffer_ReadIntoBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventBuffer_AppendBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventBuffer_Read);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventBuffer_WriteToFileDescriptor);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventBuffer_ReadFromFileDescriptor);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventBuffer_ReadLine_FreeLine);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventBuffer_GetQueueBuffer);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventBuffer_Create_Destroy)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ parcEventBuffer_EnableDebug(parcEventScheduler_GetLogger(parcEventScheduler));
+
+ PARCEventBuffer *parcEventBuffer = parcEventBuffer_Create();
+ assertNotNull(parcEventBuffer, "parcEventBuffer_Create returned a null reference");
+
+ parcEventBuffer_Destroy(&parcEventBuffer);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ parcEventBuffer_DisableDebug();
+}
+
+static int _dataLength = 8192;
+
+LONGBOW_TEST_CASE(Global, parc_EventBuffer_GetLength_Append)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ parcEventBuffer_EnableDebug(parcEventScheduler_GetLogger(parcEventScheduler));
+
+ PARCEventBuffer *parcEventBuffer = parcEventBuffer_Create();
+ assertNotNull(parcEventBuffer, "parcEventBuffer_Create returned a null reference");
+
+ char data[_dataLength];
+ parcEventBuffer_Append(parcEventBuffer, data, _dataLength);
+ assertTrue(parcEventBuffer_GetLength(parcEventBuffer) == _dataLength, "Buffer length does not match length of appended data");
+
+ parcEventBuffer_Destroy(&parcEventBuffer);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+static uint8_t prependedDataValue = '1';
+
+LONGBOW_TEST_CASE(Global, parc_EventBuffer_Prepend_Pullup)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ parcEventBuffer_EnableDebug(parcEventScheduler_GetLogger(parcEventScheduler));
+
+ PARCEventBuffer *parcEventBuffer = parcEventBuffer_Create();
+ assertNotNull(parcEventBuffer, "parcEventBuffer_Create returned a null reference");
+
+ char data[_dataLength];
+ data[0] = 2;
+ parcEventBuffer_Append(parcEventBuffer, data, _dataLength);
+ assertTrue(parcEventBuffer_GetLength(parcEventBuffer) == _dataLength, "Buffer length does not match length of appended data");
+
+ uint8_t prependedData[1];
+ prependedData[0] = prependedDataValue;
+ parcEventBuffer_Prepend(parcEventBuffer, prependedData, sizeof(uint8_t));
+ size_t bufferSize = parcEventBuffer_GetLength(parcEventBuffer);
+ assertTrue(bufferSize == (_dataLength + 1), "Buffer length does not match length plus prepended data length");
+
+ uint8_t *completeBuffer = parcEventBuffer_Pullup(parcEventBuffer, -1);
+ assertTrue(completeBuffer[0] == prependedDataValue, "Prepended data doesn't match %d != %d", completeBuffer[0], prependedDataValue);
+ assertTrue(completeBuffer[1] == 2, "Consolidated data doesn't match %d != %d", completeBuffer[1], 2);
+
+ parcEventBuffer_Destroy(&parcEventBuffer);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventBuffer_ReadIntoBuffer)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ parcEventBuffer_EnableDebug(parcEventScheduler_GetLogger(parcEventScheduler));
+
+ PARCEventBuffer *parcEventBufferSource = parcEventBuffer_Create();
+ assertNotNull(parcEventBufferSource, "parcEventBuffer_Create returned a null reference");
+ char sourceData[_dataLength];
+ parcEventBuffer_Append(parcEventBufferSource, sourceData, _dataLength);
+
+ PARCEventBuffer *parcEventBufferDestination = parcEventBuffer_Create();
+ assertNotNull(parcEventBufferDestination, "parcEventBuffer_Create returned a null reference");
+ char destinationData[_dataLength];
+ parcEventBuffer_Append(parcEventBufferDestination, destinationData, _dataLength);
+
+ parcEventBuffer_ReadIntoBuffer(parcEventBufferSource, parcEventBufferDestination, -1);
+ size_t bufferSize = parcEventBuffer_GetLength(parcEventBufferDestination);
+ assertTrue(bufferSize == (_dataLength * 2), "Destination buffer size doesn't match expected length");
+
+ parcEventBuffer_Destroy(&parcEventBufferSource);
+ parcEventBuffer_Destroy(&parcEventBufferDestination);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventBuffer_AppendBuffer)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ parcEventBuffer_EnableDebug(parcEventScheduler_GetLogger(parcEventScheduler));
+
+ PARCEventBuffer *parcEventBufferSource = parcEventBuffer_Create();
+ assertNotNull(parcEventBufferSource, "parcEventBuffer_Create returned a null reference");
+ char sourceData[_dataLength];
+ parcEventBuffer_Append(parcEventBufferSource, sourceData, _dataLength);
+
+ PARCEventBuffer *parcEventBufferDestination = parcEventBuffer_Create();
+ assertNotNull(parcEventBufferDestination, "parcEventBuffer_Create returned a null reference");
+ char destinationData[_dataLength];
+ parcEventBuffer_Append(parcEventBufferDestination, destinationData, _dataLength);
+
+ parcEventBuffer_AppendBuffer(parcEventBufferSource, parcEventBufferDestination);
+ size_t bufferSize = parcEventBuffer_GetLength(parcEventBufferDestination);
+ assertTrue(bufferSize == (_dataLength * 2), "Destination buffer size doesn't match expected length, %zu != %d", bufferSize, _dataLength * 2);
+
+ parcEventBuffer_Destroy(&parcEventBufferSource);
+ parcEventBuffer_Destroy(&parcEventBufferDestination);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventBuffer_Read)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ parcEventBuffer_EnableDebug(parcEventScheduler_GetLogger(parcEventScheduler));
+
+ PARCEventBuffer *parcEventBuffer = parcEventBuffer_Create();
+ assertNotNull(parcEventBuffer, "parcEventBuffer_Create returned a null reference");
+
+ char sourceData[64] = "This is a test";
+ parcEventBuffer_Append(parcEventBuffer, sourceData, 64);
+
+ char readDataBuffer[64];
+ int length = parcEventBuffer_Read(parcEventBuffer, readDataBuffer, 32);
+
+ assertTrue(strncmp(sourceData, readDataBuffer, 32) == 0,
+ "Buffer contents written do not match contents read");
+ assertTrue(length == 32, "parcEventBuffer_Read length unexpected %d != 32\n", length);
+
+ length = parcEventBuffer_Read(parcEventBuffer, NULL, 64);
+ assertTrue(length == 0, "Drain of parcEventBuffer returned %d", length);
+
+ parcEventBuffer_Destroy(&parcEventBuffer);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventBuffer_WriteToFileDescriptor)
+{
+ int fds[2];
+ int result = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+ assertFalse(result, "Socketpair creation failed.\n");
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ parcEventBuffer_EnableDebug(parcEventScheduler_GetLogger(parcEventScheduler));
+
+ PARCEventBuffer *parcEventBuffer = parcEventBuffer_Create();
+ assertNotNull(parcEventBuffer, "parcEventBuffer_Create returned a null reference");
+
+ char sourceData[100] = "This is a test";
+ parcEventBuffer_Append(parcEventBuffer, sourceData, 64);
+ size_t written = parcEventBuffer_WriteToFileDescriptor(parcEventBuffer, fds[0], 64);
+
+ assertTrue(written == 64, "Length written does not match buffer length.");
+ assertTrue(read(fds[1], sourceData, 100) == 64, "Length read does not match length written.");
+
+ parcEventBuffer_Destroy(&parcEventBuffer);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ close(fds[0]);
+ close(fds[1]);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventBuffer_ReadFromFileDescriptor)
+{
+ int fds[2];
+ int result = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+ assertFalse(result, "Socketpair creation failed.\n");
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ parcEventBuffer_EnableDebug(parcEventScheduler_GetLogger(parcEventScheduler));
+
+ PARCEventBuffer *parcEventBuffer = parcEventBuffer_Create();
+ assertNotNull(parcEventBuffer, "parcEventBuffer_Create returned a null reference");
+
+ char sourceData[64] = "This is a test";
+ parcEventBuffer_Append(parcEventBuffer, sourceData, 64);
+
+ size_t written = parcEventBuffer_WriteToFileDescriptor(parcEventBuffer, fds[0], 64);
+ assertTrue(written == 64, "Length written does not match buffer length.");
+ size_t read = parcEventBuffer_ReadFromFileDescriptor(parcEventBuffer, fds[1], -1);
+
+ assertTrue(read == 64, "Length read does not match amount written.");
+
+ parcEventBuffer_Destroy(&parcEventBuffer);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ close(fds[0]);
+ close(fds[1]);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventBuffer_ReadLine_FreeLine)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ parcEventBuffer_EnableDebug(parcEventScheduler_GetLogger(parcEventScheduler));
+
+ PARCEventBuffer *parcEventBuffer = parcEventBuffer_Create();
+ assertNotNull(parcEventBuffer, "parcEventBuffer_Create returned a null reference");
+
+ char sourceData[64] = "This is a test\n";
+ parcEventBuffer_Append(parcEventBuffer, sourceData, 64);
+ assertTrue(parcEventBuffer_GetLength(parcEventBuffer) == 64, "parcEventBuffer has wrong length %zu.", parcEventBuffer_GetLength(parcEventBuffer));
+
+ size_t bytesRead;
+ char *lineRead = parcEventBuffer_ReadLine(parcEventBuffer, &bytesRead);
+ // read up to newline and terminate, so we read the newline but don't return it in the result
+ assertTrue(parcEventBuffer_GetLength(parcEventBuffer) == (64 - (bytesRead + 1)),
+ "parcEventBuffer has wrong length %zu != %zu.",
+ (64 - (bytesRead + 1)), parcEventBuffer_GetLength(parcEventBuffer));
+ assertTrue(strncmp(sourceData, lineRead, bytesRead) == 0, "Line read doesn't match %s != %s", sourceData, lineRead);
+ assertTrue((strlen(sourceData) - strlen(lineRead)) == 1, "Line length doesn't match %zu != %zu", strlen(sourceData), strlen(lineRead));
+
+ parcEventBuffer_FreeLine(parcEventBuffer, &lineRead);
+
+ parcEventBuffer_Destroy(&parcEventBuffer);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventBuffer_GetQueueBuffer)
+{
+ int fds[2];
+ int result = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+ assertFalse(result, "Socketpair creation failed.\n");
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ parcEventBuffer_EnableDebug(parcEventScheduler_GetLogger(parcEventScheduler));
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, fds[0], 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ PARCEventBuffer *parcEventBuffer_Output = parcEventBuffer_GetQueueBufferOutput(parcEventQueue);
+ assertNotNull(parcEventBuffer_Output, "Received null output buffer from queue");
+
+ PARCEventBuffer *parcEventBuffer_Input = parcEventBuffer_GetQueueBufferInput(parcEventQueue);
+ assertNotNull(parcEventBuffer_Input, "Received null input buffer from queue");
+
+ parcEventBuffer_Destroy(&parcEventBuffer_Output);
+ parcEventBuffer_Destroy(&parcEventBuffer_Input);
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ close(fds[0]);
+ close(fds[1]);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_EventBuffer);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_EventQueue.c b/libparc/parc/algol/test/test_parc_EventQueue.c
new file mode 100644
index 00000000..862cb61d
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_EventQueue.c
@@ -0,0 +1,402 @@
+/*
+ * 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 <stdio.h>
+#include <pthread.h>
+
+#include <arpa/inet.h>
+
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_EventQueue.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_EventQueue.c"
+
+LONGBOW_TEST_RUNNER(parc_EventQueue)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_EventQueue)
+{
+ parcEventQueue_EnableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_EventQueue)
+{
+ parcEventQueue_DisableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_SetFileDescriptor_GetFileDecriptor);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_Get_Enable_Disable);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_SetCallbacks);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_Flush);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_Finished);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_SetWatermark);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_ReadWrite);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_SetPriority);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_Printf);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_GetEvBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_ConnectSocket);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_Create_Destroy_Pair);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventQueue_GetUpDownQueue);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_Create_Destroy)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, 0, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ assertNull(parcEventQueue, "parcEventQueue_Destroy did not clear reference");
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ assertNull(parcEventScheduler, "parcEventScheduler_Destroy did not clear reference");
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_Get_Enable_Disable)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, 0, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ PARCEventType defaultEvents = parcEventQueue_GetEnabled(parcEventQueue);
+
+ parcEventQueue_Enable(parcEventQueue, PARCEventType_Read);
+ PARCEventType newEvents = parcEventQueue_GetEnabled(parcEventQueue);
+ assertTrue(newEvents == (defaultEvents | PARCEventType_Read),
+ "parcEventQueue_GetEnabled returned incorrect event set 0x%x != 0x%x",
+ newEvents, defaultEvents | PARCEventType_Read);
+
+ parcEventQueue_Disable(parcEventQueue, PARCEventType_Read);
+
+ newEvents = parcEventQueue_GetEnabled(parcEventQueue);
+ assertTrue(defaultEvents == newEvents, "parcEventQueue_GetEnabled returned incorrect event set 0x%x != 0x%x", newEvents, defaultEvents);
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_SetFileDescriptor_GetFileDecriptor)
+{
+ int fds[2];
+ int result = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+ assertFalse(result, "Socketpair creation failed.\n");
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, 0, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned null");
+
+ result = parcEventQueue_SetFileDescriptor(parcEventQueue, fds[0]);
+ assertTrue(result == 0, " parcEventQueue_SetFileDescriptor call failed");
+
+ result = parcEventQueue_GetFileDescriptor(parcEventQueue);
+ assertTrue(result == fds[0], "parcEventQueue_GetFileDescriptor failed");
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ close(fds[0]);
+ close(fds[1]);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_Create_Destroy_Pair)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned null");
+
+ PARCEventQueuePair *parcEventQueuePair = parcEventQueue_CreateConnectedPair(parcEventScheduler);
+ assertNotNull(parcEventQueuePair, "parcEventQueue_CreateConnectedPair returned a null pair");
+
+ parcEventQueue_DestroyConnectedPair(&parcEventQueuePair);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_GetUpDownQueue)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+
+ PARCEventQueuePair *parcEventQueuePair = parcEventQueue_CreateConnectedPair(parcEventScheduler);
+
+ assertNotNull(parcEventQueue_GetConnectedUpQueue(parcEventQueuePair), "parcEventQueue_GetUpQueue returned null");
+ assertNotNull(parcEventQueue_GetConnectedDownQueue(parcEventQueuePair), "parcEventQueue_GetDownQueue returned null");
+
+ parcEventQueue_DestroyConnectedPair(&parcEventQueuePair);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+static int _queue_callback_count = 0;
+
+static void
+_queue_callback(PARCEventQueue *event, PARCEventType type, void *data)
+{
+ _queue_callback_count++;
+}
+
+static int _queue_event_callback_count = 0;
+
+static void
+_queue_event_callback(PARCEventQueue *event, PARCEventQueueEventType type, void *data)
+{
+ _queue_event_callback_count++;
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_SetCallbacks)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, 0, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ parcEventQueue_SetCallbacks(parcEventQueue,
+ _queue_callback,
+ _queue_callback,
+ _queue_event_callback,
+ NULL);
+
+ _parc_queue_read_callback(NULL, parcEventQueue);
+ assertTrue(_queue_callback_count == 1, "Callback count expected 1 got %d", _queue_callback_count);
+
+ _parc_queue_write_callback(NULL, parcEventQueue);
+ assertTrue(_queue_callback_count == 2, "Callback count expected 2 got %d", _queue_callback_count);
+
+ _parc_queue_event_callback(NULL, PARCEventQueueEventType_EOF, parcEventQueue);
+ assertTrue(_queue_event_callback_count == 1, "Callback event count expected 1 got %d", _queue_event_callback_count);
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_Flush)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, 0, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ int result = parcEventQueue_Flush(parcEventQueue, PARCEventType_Read);
+ assertTrue(result == 0, "parcEventQueue_Flush failed with %d", result);
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_Finished)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, 0, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ int result = parcEventQueue_Finished(parcEventQueue, PARCEventType_Read);
+ assertTrue(result == 0, "parcEventQueue_Finished failed with %d", result);
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_SetWatermark)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, 0, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ parcEventQueue_SetWatermark(parcEventQueue, PARCEventType_Read, 0, 0);
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_ReadWrite)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, 0, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ char *data = "Hello World\n";
+ int length = strlen(data);
+ int result = parcEventQueue_Write(parcEventQueue, data, length);
+ assertTrue(result == 0, "parcEventQueue_Write failed.");
+
+ char buffer[64];
+ result = parcEventQueue_Read(parcEventQueue, buffer, 64);
+ assertTrue(result == 0, "parcEventQueue_Read failed.");
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+static int _test_writeMaxPriority_event_called = 0;
+static void
+_test_writeMaxPriority_callback(PARCEventQueue *parcEventQueue, PARCEventType event, void *data)
+{
+ PARCEventQueue *parcEventQueuePartner = *((PARCEventQueue **) data);
+ parcEventQueue_Disable(parcEventQueuePartner, event);
+ _test_writeMaxPriority_event_called++;
+}
+
+static int _test_writeMinPriority_event_called = 0;
+static void
+_test_writeMinPriority_callback(PARCEventQueue *parcEventQueue, PARCEventType event, void *data)
+{
+ PARCEventQueue *parcEventQueuePartner = *((PARCEventQueue **) data);
+ parcEventQueue_Disable(parcEventQueuePartner, event);
+ _test_writeMinPriority_event_called++;
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_SetPriority)
+{
+ int fds[2];
+ int result = socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds);
+ assertFalse(result, "Socketpair creation failed.\n");
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ //
+ // First queue to be called back disables its partner's queue
+ //
+ PARCEventQueue *parcEventQueueMin, *parcEventQueueMax;
+ parcEventQueueMin = parcEventQueue_Create(parcEventScheduler, fds[0], PARCEventQueueOption_CloseOnFree);
+ assertNotNull(parcEventQueueMin, "parcEventQueue_Create returned a null reference");
+ parcEventQueue_SetCallbacks(parcEventQueueMin, NULL, _test_writeMinPriority_callback, NULL, (void *) &parcEventQueueMax);
+
+ parcEventQueueMax = parcEventQueue_Create(parcEventScheduler, fds[0], PARCEventQueueOption_CloseOnFree);
+ assertNotNull(parcEventQueueMax, "parcEventQueue_Create returned a null reference");
+ parcEventQueue_SetCallbacks(parcEventQueueMax, NULL, _test_writeMaxPriority_callback, NULL, (void *) &parcEventQueueMin);
+
+ result = parcEventQueue_SetPriority(parcEventQueueMin, PARCEventPriority_Minimum);
+ assertTrue(result == 0, "parcEventQueue_SetPriority Minimum priority failed.");
+ result = parcEventQueue_SetPriority(parcEventQueueMax, PARCEventPriority_Maximum);
+ assertTrue(result == 0, "parcEventQueue_SetPriority Maximum priority failed.");
+
+ parcEventQueue_Enable(parcEventQueueMin, PARCEventType_Write);
+ parcEventQueue_Enable(parcEventQueueMax, PARCEventType_Write);
+
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_NonBlocking);
+
+ assertTrue(_test_writeMaxPriority_event_called == 1, "Read event called before priority write event handled");
+ assertTrue(_test_writeMinPriority_event_called == 0, "Write event never triggered");
+
+ parcEventQueue_Destroy(&parcEventQueueMin);
+ parcEventQueue_Destroy(&parcEventQueueMax);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ close(fds[0]);
+ close(fds[1]);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_Printf)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, 0, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ int result = parcEventQueue_Printf(parcEventQueue, "%s %s\n", "Hello", "World");
+ assertTrue(result == 12, "parcEventQueue_Printf didn't write expected length %d != %d", result, 12);
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_GetEvBuffer)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, 0, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ struct evbuffer *result = internal_parcEventQueue_GetEvInputBuffer(parcEventQueue);
+ assertTrue(result != NULL, "parcEventQueue_GetEvInputBuffer failed.");
+
+ result = internal_parcEventQueue_GetEvOutputBuffer(parcEventQueue);
+ assertTrue(result != NULL, "parcEventQueue_GetEvOutputBuffer failed.");
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventQueue_ConnectSocket)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventQueue *parcEventQueue = parcEventQueue_Create(parcEventScheduler, -1, 0);
+ assertNotNull(parcEventQueue, "parcEventQueue_Create returned a null reference");
+
+ struct sockaddr_in address;
+ int addressLength = sizeof(address);
+ memset(&address, 0, addressLength);
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
+ address.sin_port = htons(8080); /* Port 8080 */
+
+ int result = parcEventQueue_ConnectSocket(parcEventQueue, (struct sockaddr *) &address, addressLength);
+ assertTrue(result == 0, "parcEventQueue_ConnectSocket returned %d", result);
+
+ parcEventQueue_Destroy(&parcEventQueue);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_EventQueue);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_EventScheduler.c b/libparc/parc/algol/test/test_parc_EventScheduler.c
new file mode 100755
index 00000000..8195bd2e
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_EventScheduler.c
@@ -0,0 +1,263 @@
+/*
+ * 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 <stdio.h>
+
+#include <pthread.h>
+
+#include <LongBow/unit-test.h>
+
+#include "../internal_parc_Event.h"
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_EventScheduler.h>
+#include <parc/algol/parc_EventTimer.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_EventScheduler.c"
+
+LONGBOW_TEST_RUNNER(parc_EventScheduler)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_EventScheduler)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_EventScheduler)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventScheduler_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventScheduler_Run);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventScheduler_Dispatch);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventScheduler_Stop);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventScheduler_Abort);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventScheduler_Memory);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventScheduler_GetEvBase);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventScheduler_GetLogger);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ parcEventScheduler_EnableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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;
+ }
+
+ parcEventScheduler_DisableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventScheduler_Create_Destroy)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+ parcEventScheduler_Destroy(&parcEventScheduler);
+ assertNull(parcEventScheduler, "parcEventScheduler_Destroy failed to null reference");
+}
+
+static void
+_event_callback(int fd, PARCEventType flags, void *data)
+{
+ (*(unsigned *) data)++;
+}
+
+static int _callback_event_called = 0;
+
+LONGBOW_TEST_CASE(Global, parc_EventScheduler_Run)
+{
+ _callback_event_called = 0;
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+ PARCEventTimer *parcEvent = parcEventTimer_Create(parcEventScheduler, 0, _event_callback, (void *) &_callback_event_called);
+ assertNotNull(parcEvent, "parcEventTimer_Create returned a null reference");
+
+ struct timeval fs = { 0, 1 };
+ parcEventTimer_Start(parcEvent, &fs);
+
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_Blocking);
+ assertTrue(_callback_event_called == 1, "Timer event never called back");
+
+ parcEventTimer_Destroy(&parcEvent);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventScheduler_Dispatch)
+{
+ _callback_event_called = 0;
+
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+ PARCEventTimer *parcEvent = parcEventTimer_Create(parcEventScheduler, 0, _event_callback, (void *) &_callback_event_called);
+ assertNotNull(parcEvent, "parcEventTimer_Create returned a null reference");
+
+ struct timeval fs = { 0, 1 };
+ parcEventTimer_Start(parcEvent, &fs);
+
+ // This will block until the event is processed
+ parcEventScheduler_DispatchBlocking(parcEventScheduler);
+ assertTrue(_callback_event_called == 1, "Timer event never called back");
+
+ // Start the timer
+ struct timeval longerfs = { 1, 0 }; // 1s
+ parcEventTimer_Start(parcEvent, &longerfs);
+ parcEventScheduler_DispatchNonBlocking(parcEventScheduler);
+ assertTrue(_callback_event_called == 1, "Timer event called again prematurely");
+ usleep(2000000); // 2s
+ parcEventScheduler_DispatchNonBlocking(parcEventScheduler);
+ assertTrue(_callback_event_called == 2, "Timer event never called back");
+
+ parcEventTimer_Destroy(&parcEvent);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+static void
+_stop_callback(int fd, PARCEventType flags, void *data)
+{
+ PARCEventScheduler *parcEventScheduler = (PARCEventScheduler *) data;
+ struct timeval fs = { 0, 0 };
+ parcEventScheduler_Stop(parcEventScheduler, &fs);
+ _callback_event_called++;
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventScheduler_Stop)
+{
+ _callback_event_called = 0;
+
+ // Create a new scheduler
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ // Create a persistent event which will repeat until stopped
+ PARCEventTimer *parcEvent = parcEventTimer_Create(parcEventScheduler, PARCEventType_Persist, _stop_callback, parcEventScheduler);
+ assertNotNull(parcEvent, "parcEventTimer_Create returned a null reference");
+
+ struct timeval fs = { 1, 0 };
+ parcEventTimer_Start(parcEvent, &fs);
+
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_Blocking);
+ assertTrue(_callback_event_called == 1, "Timer event never called back");
+
+ parcEventTimer_Destroy(&parcEvent);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+static void
+_abort_callback(int fd, PARCEventType flags, void *data)
+{
+ PARCEventScheduler *parcEventScheduler = (PARCEventScheduler *) data;
+ parcEventScheduler_Abort(parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventScheduler_Abort)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+ PARCEventTimer *parcEvent = parcEventTimer_Create(parcEventScheduler, PARCEventType_Persist, _abort_callback, parcEventScheduler);
+ assertNotNull(parcEvent, "parcEventTimer_Create returned a null reference");
+
+ struct timeval fs = { 1, 0 };
+ parcEventTimer_Start(parcEvent, &fs);
+
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_Blocking);
+
+ parcEventTimer_Destroy(&parcEvent);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+static void
+_test_memory_event(int fd, short flags, void *data)
+{
+}
+
+/**
+ * Ensure that the scheduler is using parc memory inside libevent
+ */
+LONGBOW_TEST_CASE(Global, parc_EventScheduler_Memory)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ size_t baseline = parcMemory_Outstanding();
+
+ struct event *testEvent = event_new(parcEventScheduler_GetEvBase(parcEventScheduler), -1, 0, _test_memory_event, NULL);
+
+ assertTrue(parcMemory_Outstanding() > baseline,
+ "event_new() did not increase parcMemory_Outstanding: baseline %zu now %u",
+ baseline,
+ parcMemory_Outstanding());
+
+ event_free(testEvent);
+
+ assertTrue(parcMemory_Outstanding() == baseline,
+ "event_free() did reduce to baseline: baseline %zu now %u",
+ baseline,
+ parcMemory_Outstanding());
+
+ parcEventScheduler_Destroy(&parcEventScheduler);
+
+ assertTrue(parcSafeMemory_ReportAllocation(STDOUT_FILENO) == 0, "Memory imbalance on create/destroy: %u", parcMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventScheduler_GetEvBase)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ assertNotNull(parcEventScheduler_GetEvBase(parcEventScheduler), "Expected a non-null EV pointer.");
+
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventScheduler_GetLogger)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ assertNotNull(parcEventScheduler_GetLogger(parcEventScheduler), "Expected a non-null logger.");
+
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_EventScheduler);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_EventSignal.c b/libparc/parc/algol/test/test_parc_EventSignal.c
new file mode 100644
index 00000000..fcb86333
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_EventSignal.c
@@ -0,0 +1,167 @@
+/*
+ * 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 <stdio.h>
+#include <pthread.h>
+
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_EventSignal.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_EventSignal.c"
+
+LONGBOW_TEST_RUNNER(parc_EventSignal)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_EventSignal)
+{
+ parcEventSignal_EnableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_EventSignal)
+{
+ parcEventSignal_DisableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventSignal_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventSignal_Start_Stop);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static int _empty_event_called = 0;
+
+static void
+_empty_event(int fd, PARCEventType flags, void *data)
+{
+ _empty_event_called++;
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventSignal_Create_Destroy)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventSignal *parcEventSignal = parcEventSignal_Create(parcEventScheduler, SIGUSR1, PARCEventType_Signal | PARCEventType_Persist, _empty_event, NULL);
+ assertNotNull(parcEventSignal, "parcEventSignal_Create returned a null reference");
+
+ _parc_event_signal_callback(0, 0, (void *) parcEventSignal);
+ assertTrue(_empty_event_called == 1, "Event handler never called.");
+ parcEventSignal_Destroy(&parcEventSignal);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+#include <pthread.h>
+
+static void *
+_run_scheduler(void *data)
+{
+ PARCEventScheduler *parcEventScheduler = (PARCEventScheduler *) data;
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_Blocking);
+ return NULL;
+}
+
+static int _test_event_called = 0;
+
+static void
+_signal_event(int fd, PARCEventType flags, void *data)
+{
+ PARCEventSignal **parcEventSignal = (PARCEventSignal **) data;
+ _test_event_called++;
+ parcEventSignal_Stop(*parcEventSignal);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventSignal_Start_Stop)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+ PARCEventSignal *parcEventSignal = parcEventSignal_Create(parcEventScheduler, SIGUSR1, PARCEventType_Signal | PARCEventType_Persist, _signal_event, &parcEventSignal);
+ assertNotNull(parcEventSignal, "parcEventSignal_Create returned a null reference");
+
+ parcEventSignal_Start(parcEventSignal);
+
+ pthread_t thread;
+ pthread_create(&thread, NULL, _run_scheduler, parcEventScheduler);
+
+ kill(getpid(), SIGUSR1);
+ pthread_join(thread, NULL);
+ assertTrue(_test_event_called == 1, "Event never called.");
+
+ parcEventSignal_Destroy(&parcEventSignal);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+static void
+_test_stop_event(int fd, PARCEventType flags, void *data)
+{
+ PARCEventSignal **parcEventSignal = (PARCEventSignal **) data;
+ _test_event_called++;
+ parcEventSignal_Stop(*parcEventSignal);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventSignal_Stop)
+{
+ _test_event_called = 0;
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+ PARCEventSignal *parcEventSignal = parcEventSignal_Create(parcEventScheduler, SIGUSR1, PARCEventType_Signal | PARCEventType_Persist, _test_stop_event, &parcEventSignal);
+ assertNotNull(parcEventSignal, "parcEventSignal_Create returned a null reference");
+
+ parcEventSignal_Start(parcEventSignal);
+ kill(getpid(), SIGUSR1);
+
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_Blocking);
+ assertTrue(_test_event_called == 1, "Event never called.");
+
+ parcEventSignal_Destroy(&parcEventSignal);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_EventSignal);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_EventSocket.c b/libparc/parc/algol/test/test_parc_EventSocket.c
new file mode 100644
index 00000000..dbe8892b
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_EventSocket.c
@@ -0,0 +1,128 @@
+/*
+ * 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 <stdio.h>
+#include <pthread.h>
+
+#include <arpa/inet.h>
+
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_EventSocket.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_EventSocket.c"
+
+LONGBOW_TEST_RUNNER(parc_EventSocket)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_EventSocket)
+{
+ parcEventSocket_EnableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_EventSocket)
+{
+ parcEventSocket_DisableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventSocket_Create_Destroy);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static int _test_event_called = 0;
+
+static void
+listener_callback(int fd, struct sockaddr *sa, int socklen, void *user_data)
+{
+ _test_event_called++;
+}
+
+static int _test_error_event_called = 0;
+
+static void
+listener_error_callback(PARCEventScheduler *base, int error, char *errorString, void *addr_unix)
+{
+ _test_error_event_called++;
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventSocket_Create_Destroy)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(49009);
+ inet_pton(AF_INET, "127.0.0.1", &(addr.sin_addr));
+
+ PARCEventSocket *parcEventSocket = parcEventSocket_Create(parcEventScheduler,
+ listener_callback,
+ listener_error_callback,
+ NULL, NULL, 0);
+ assertNull(parcEventSocket, "parcEventSocket_Create didn't return an error when expected");
+
+ parcEventSocket = parcEventSocket_Create(parcEventScheduler,
+ listener_callback,
+ listener_error_callback,
+ NULL, (struct sockaddr *) &addr, sizeof(addr));
+ assertNotNull(parcEventSocket, "parcEventSocket_Create returned a null reference");
+
+ _parc_evconn_callback(NULL, 0, (struct sockaddr *) &addr, sizeof(addr), parcEventSocket);
+ assertTrue(_test_event_called == 1, "Listener callback wasn't triggered");
+ _parc_evconn_error_callback(NULL, parcEventSocket);
+ assertTrue(_test_error_event_called == 1, "Listener error callback wasn't triggered");
+
+ parcEventSocket_Destroy(&parcEventSocket);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_EventSocket);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_EventTimer.c b/libparc/parc/algol/test/test_parc_EventTimer.c
new file mode 100755
index 00000000..f6b9917e
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_EventTimer.c
@@ -0,0 +1,143 @@
+/*
+ * 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 <stdio.h>
+#include <pthread.h>
+
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_EventTimer.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_EventTimer.c"
+
+LONGBOW_TEST_RUNNER(parc_EventTimer)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_EventTimer)
+{
+ parcEventTimer_EnableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_EventTimer)
+{
+ parcEventTimer_DisableDebug();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventTimer_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventTimer_Start);
+ LONGBOW_RUN_TEST_CASE(Global, parc_EventTimer_Stop);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static int _test_event_called = 0;
+
+static void
+_test_event(int fd, PARCEventType flags, void *data)
+{
+ _test_event_called++;
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventTimer_Create_Destroy)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventTimer *parcEventTimer = parcEventTimer_Create(parcEventScheduler, PARCEventType_None, _test_event, NULL);
+ assertNotNull(parcEventTimer, "parcEventTimer_Create returned a null reference");
+
+ parcEventTimer_Destroy(&parcEventTimer);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventTimer_Start)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventTimer *parcEventTimer = parcEventTimer_Create(parcEventScheduler, PARCEventType_None, _test_event, NULL);
+ assertNotNull(parcEventTimer, "parcEventTimer_Create returned a null reference");
+
+ struct timeval timeout = { 1, 0 };
+ parcEventTimer_Start(parcEventTimer, &timeout);
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_Blocking);
+ assertTrue(_test_event_called == 1, "Event never called.");
+
+ parcEventTimer_Destroy(&parcEventTimer);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+static void
+_test_stop_event(int fd, PARCEventType flags, void *data)
+{
+ PARCEventTimer **parcEventTimer = (PARCEventTimer **) data;
+ _test_event_called++;
+ parcEventTimer_Stop(*parcEventTimer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_EventTimer_Stop)
+{
+ PARCEventScheduler *parcEventScheduler = parcEventScheduler_Create();
+ assertNotNull(parcEventScheduler, "parcEventScheduler_Create returned a null reference");
+
+ PARCEventTimer *parcEventTimer = parcEventTimer_Create(parcEventScheduler, PARCEventType_None | PARCEventType_Persist, _test_stop_event, &parcEventTimer);
+ assertNotNull(parcEventTimer, "parcEventTimer_Create returned a null reference");
+
+ _test_event_called = 0;
+ struct timeval timeout = { 1, 0 };
+ parcEventTimer_Start(parcEventTimer, &timeout);
+ parcEventScheduler_Start(parcEventScheduler, PARCEventSchedulerDispatchType_Blocking);
+ assertTrue(_test_event_called == 1, "Event never called.");
+
+ parcEventTimer_Destroy(&parcEventTimer);
+ parcEventScheduler_Destroy(&parcEventScheduler);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_EventTimer);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_File.c b/libparc/parc/algol/test/test_parc_File.c
new file mode 100644
index 00000000..eccef210
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_File.c
@@ -0,0 +1,208 @@
+/*
+ * 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 <LongBow/unit-test.h>
+#include <fcntl.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_SafeMemory.h"
+#include "../parc_File.c"
+
+#define PATH_SEGMENT "A"
+
+LONGBOW_TEST_RUNNER(parc_File)
+{
+ // 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);
+ LONGBOW_RUN_TEST_FIXTURE(AcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_File)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_File)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(AcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcFile_AcquireRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(AcquireRelease)
+{
+ longBowClipBoard_SetInt(testClipBoard, "initalAllocations", parcMemory_Outstanding());
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(AcquireRelease)
+{
+ uint64_t initialAllocations = longBowClipBoard_GetAsInt(testClipBoard, "initalAllocations");
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (initialAllocations < outstandingAllocations) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcFile_AcquireRelease)
+{
+ char *root = "/tmp/test_parc_File";
+
+ PARCFile *file = parcFile_Create(root);
+
+ PARCFile *reference = parcFile_Acquire(file);
+
+ parcFile_Release(&reference);
+
+ parcFile_AssertValid(file);
+
+ parcFile_Release(&file);
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcFile_CreateChild);
+ LONGBOW_RUN_TEST_CASE(Global, parcFile_CreateDeleteNewFile);
+ LONGBOW_RUN_TEST_CASE(Global, parcFile_CreateDelete_Directory);
+ LONGBOW_RUN_TEST_CASE(Global, parcFile_Exists);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ longBowClipBoard_SetInt(testClipBoard, "initalAllocations", parcMemory_Outstanding());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint64_t initialAllocations = longBowClipBoard_GetAsInt(testClipBoard, "initalAllocations");
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (initialAllocations < outstandingAllocations) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcFile_Exists)
+{
+ char *root = "/tmp";
+
+ PARCFile *parent = parcFile_Create(root);
+
+ char *child = "foo";
+ PARCFile *file = parcFile_CreateChild(parent, child);
+
+ parcFile_CreateNewFile(file);
+
+ bool actual = parcFile_Exists(file);
+
+ assertTrue(actual, "Expected the file to exist.");
+
+ parcFile_Release(&file);
+ parcFile_Release(&parent);
+}
+
+LONGBOW_TEST_CASE(Global, parcFile_CreateChild)
+{
+ char *root = "/tmp";
+
+ PARCFile *parent = parcFile_Create(root);
+
+ char *child = "foo";
+ PARCFile *file = parcFile_CreateChild(parent, child);
+
+ char *actual = parcFile_ToString(file);
+
+ assertTrue(strcmp("/tmp/foo", actual) == 0,
+ "Expected %s, actual %s", "/tmp/foo", actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcFile_Release(&file);
+ parcFile_Release(&parent);
+}
+
+LONGBOW_TEST_CASE(Global, parcFile_CreateDeleteNewFile)
+{
+ char *name = "/tmp/test_parc_File";
+
+ PARCFile *file = parcFile_Create(name);
+
+ parcFile_CreateNewFile(file);
+
+ bool actual = parcFile_Delete(file);
+ assertTrue(actual, "Expected parcFile_Delete to return true.");
+
+ parcFile_Release(&file);
+}
+
+LONGBOW_TEST_CASE(Global, parcFile_CreateDelete_Directory)
+{
+ char *name = "/tmp/test_parc_File_directory";
+
+ PARCFile *directory = parcFile_Create(name);
+
+ parcFile_Mkdir(directory);
+
+ char *fileName = "foo";
+ PARCFile *file = parcFile_CreateChild(directory, fileName);
+
+ bool success = parcFile_CreateNewFile(file);
+ assertTrue(success, "Expected parcFile_CreateNewFile success");
+
+ bool actual = parcFile_Delete(directory);
+ assertTrue(actual, "Expected parcFile_Delete to return true.");
+
+ parcFile_Release(&file);
+ parcFile_Release(&directory);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_File);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_FileChunker.c b/libparc/parc/algol/test/test_parc_FileChunker.c
new file mode 100755
index 00000000..6060cff6
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_FileChunker.c
@@ -0,0 +1,431 @@
+/*
+ * 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_FileChunker.c"
+
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_BufferChunker.h>
+
+LONGBOW_TEST_RUNNER(parc_FileChunker)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_FileChunker)
+{
+ 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_FileChunker)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_CreateFromFile);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ForwardIterator_File);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ForwardIterator_FilePartial);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ForwardIterator_FileSmall);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ReverseIterator_File);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ReverseIterator_FilePartial);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_ReverseIterator_FileSmall);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Chunker_GetChunkSize);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static void
+_createFile(char *fname, PARCBuffer *buffer)
+{
+ PARCFile *file = parcFile_Create(fname);
+ if (!parcFile_Exists(file)) {
+ parcFile_CreateNewFile(file);
+ }
+ PARCRandomAccessFile *fhandle = parcRandomAccessFile_Open(file);
+ parcFile_Release(&file);
+
+ parcRandomAccessFile_Write(fhandle, buffer);
+ parcRandomAccessFile_Close(fhandle);
+ parcRandomAccessFile_Release(&fhandle);
+}
+
+static void
+_deleteFile(char *fname)
+{
+ PARCFile *file = parcFile_Create(fname);
+ parcFile_Delete(file);
+ parcFile_Release(&file);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_CreateFromFile)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1024);
+
+ for (size_t i = 0; i < 32; i++) {
+ for (size_t j = 0; j < 32; j++) {
+ parcBuffer_PutUint8(buffer, i);
+ }
+ }
+ parcBuffer_Flip(buffer);
+
+ _createFile("/tmp/file_chunker.tmp", buffer);
+
+ PARCFile *file = parcFile_Create("/tmp/file_chunker.tmp");
+
+ PARCFileChunker *chunker = parcFileChunker_Create(file, 32); // each chunk is 32 bytes
+ PARCFileChunker *copy = parcFileChunker_Acquire(chunker);
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+ assertNotNull(copy, "Expected non-NULL copy of Chunker");
+ parcFileChunker_Release(&copy);
+
+ parcFile_Release(&file);
+ parcFileChunker_Release(&chunker);
+
+ _deleteFile("/tmp/file_chunker.tmp");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ForwardIterator_File)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1024);
+
+ for (size_t i = 0; i < 32; i++) {
+ for (size_t j = 0; j < 32; j++) {
+ parcBuffer_PutUint8(buffer, i);
+ }
+ }
+ parcBuffer_Flip(buffer);
+
+ _createFile("/tmp/file_chunker.tmp", buffer);
+
+ PARCFile *file = parcFile_Create("/tmp/file_chunker.tmp");
+
+ PARCFileChunker *chunker = parcFileChunker_Create(file, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcFileChunker_ForwardIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ for (size_t i = 0; i < 32; i++) {
+ assertTrue(contents[i] == count, "Expected %zu at index %zu, got %d", count, i, contents[i]);
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 32, "Expected to iterate over 32 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcFile_Release(&file);
+ parcFileChunker_Release(&chunker);
+
+ _deleteFile("/tmp/file_chunker.tmp");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ForwardIterator_FilePartial)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1030);
+
+ for (size_t i = 0; i < 32; i++) {
+ for (size_t j = 0; j < 32; j++) {
+ parcBuffer_PutUint8(buffer, i);
+ }
+ }
+
+ // Special 0xFF to mark the end...
+ for (int i = 0; i < 6; i++) {
+ parcBuffer_PutUint8(buffer, 0xFF);
+ }
+ parcBuffer_Flip(buffer);
+
+ _createFile("/tmp/file_chunker.tmp", buffer);
+
+ PARCFile *file = parcFile_Create("/tmp/file_chunker.tmp");
+
+ PARCFileChunker *chunker = parcFileChunker_Create(file, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcFileChunker_ForwardIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ if (count < 32) {
+ for (size_t i = 0; i < 32; i++) {
+ assertTrue(contents[i] == count, "Expected %zu at index %zu, got %d", count, i, contents[i]);
+ }
+ } else {
+ for (size_t i = 0; i < 6; i++) {
+ assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]);
+ }
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 33, "Expected to iterate over 33 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcFile_Release(&file);
+ parcFileChunker_Release(&chunker);
+
+ _deleteFile("/tmp/file_chunker.tmp");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ForwardIterator_FileSmall)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(16);
+
+ // Special 0xFF to mark the end...
+ for (int i = 0; i < 16; i++) {
+ parcBuffer_PutUint8(buffer, 0xFF);
+ }
+ parcBuffer_Flip(buffer);
+
+ _createFile("/tmp/file_chunker.tmp", buffer);
+
+ PARCFile *file = parcFile_Create("/tmp/file_chunker.tmp");
+
+ PARCFileChunker *chunker = parcFileChunker_Create(file, 4096); // each chunk is 1024 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcFileChunker_ForwardIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ for (size_t i = 0; i < 16; i++) {
+ assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]);
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 1, "Expected to iterate over 1 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcFile_Release(&file);
+ parcFileChunker_Release(&chunker);
+
+ _deleteFile("/tmp/file_chunker.tmp");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_File)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1024);
+
+ for (size_t i = 0; i < 32; i++) {
+ for (size_t j = 0; j < 32; j++) {
+ parcBuffer_PutUint8(buffer, i);
+ }
+ }
+ parcBuffer_Flip(buffer);
+
+ _createFile("/tmp/file_chunker.tmp", buffer);
+
+ PARCFile *file = parcFile_Create("/tmp/file_chunker.tmp");
+
+ PARCFileChunker *chunker = parcFileChunker_Create(file, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcFileChunker_ReverseIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ for (size_t i = 0; i < 32; i++) {
+ assertTrue(contents[i] == (31 - count), "Expected %zu at index %zu, got %d", count, i, contents[i]);
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 32, "Expected to iterate over 32 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcFile_Release(&file);
+ parcFileChunker_Release(&chunker);
+
+ _deleteFile("/tmp/file_chunker.tmp");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_FilePartial)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1030);
+
+ // Special 0xFF to mark the start...
+ for (int i = 0; i < 6; i++) {
+ parcBuffer_PutUint8(buffer, 0xFF);
+ }
+
+ for (size_t i = 0; i < 32; i++) {
+ for (size_t j = 0; j < 32; j++) {
+ parcBuffer_PutUint8(buffer, i);
+ }
+ }
+ parcBuffer_Flip(buffer);
+
+ _createFile("/tmp/file_chunker.tmp", buffer);
+
+ PARCFile *file = parcFile_Create("/tmp/file_chunker.tmp");
+
+ PARCFileChunker *chunker = parcFileChunker_Create(file, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcFileChunker_ReverseIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ if (count < 32) {
+ for (size_t i = 0; i < 32; i++) {
+ assertTrue(contents[i] == (31 - count), "Expected %zu at index %zu, got %d", (31 - count), i, contents[i]);
+ }
+ } else {
+ for (size_t i = 0; i < 6; i++) {
+ assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]);
+ }
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 33, "Expected to iterate over 33 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcFile_Release(&file);
+ parcFileChunker_Release(&chunker);
+
+ _deleteFile("/tmp/file_chunker.tmp");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_FileSmall)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1030);
+
+ // Special 0xFF to mark the start...
+ for (int i = 0; i < 6; i++) {
+ parcBuffer_PutUint8(buffer, 0xFF);
+ }
+ parcBuffer_Flip(buffer);
+
+ _createFile("/tmp/file_chunker.tmp", buffer);
+
+ PARCFile *file = parcFile_Create("/tmp/file_chunker.tmp");
+
+ PARCFileChunker *chunker = parcFileChunker_Create(file, 32); // each chunk is 32 bytes
+ assertNotNull(chunker, "Expected non-NULL Chunker");
+
+ PARCIterator *itr = parcFileChunker_ReverseIterator(chunker);
+ size_t count = 0;
+ while (parcIterator_HasNext(itr)) {
+ PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
+
+ uint8_t *contents = parcBuffer_Overlay(payload, 0);
+ for (size_t i = 0; i < 6; i++) {
+ assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]);
+ }
+ count++;
+
+ parcBuffer_Release(&payload);
+ }
+ assertTrue(count == 1, "Expected to iterate over 1 content objects from the chunker, but for %zu", count);
+ parcIterator_Release(&itr);
+
+ parcFile_Release(&file);
+ parcFileChunker_Release(&chunker);
+
+ _deleteFile("/tmp/file_chunker.tmp");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parc_Chunker_GetChunkSize)
+{
+ size_t expectedChunkSize = 32;
+ PARCBuffer *buffer = parcBuffer_Allocate(1030);
+
+ // Special 0xFF to mark the start...
+ for (int i = 0; i < 6; i++) {
+ parcBuffer_PutUint8(buffer, 0xFF);
+ }
+ parcBuffer_Flip(buffer);
+
+ _createFile("/tmp/file_chunker.tmp", buffer);
+
+ PARCFile *file = parcFile_Create("/tmp/file_chunker.tmp");
+ PARCFileChunker *chunker = parcFileChunker_Create(file, expectedChunkSize); // each chunk is 32 bytes
+
+ size_t actualChunkSize = parcBufferChunker_GetChunkSize(chunker);
+
+ assertTrue(actualChunkSize == expectedChunkSize, "Expected chunk size of %zu, got %zu", expectedChunkSize, actualChunkSize);
+
+ parcFile_Release(&file);
+ parcFileChunker_Release(&chunker);
+
+ _deleteFile("/tmp/file_chunker.tmp");
+
+ parcBuffer_Release(&buffer);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_FileChunker);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_FileInputStream.c b/libparc/parc/algol/test/test_parc_FileInputStream.c
new file mode 100755
index 00000000..49032050
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_FileInputStream.c
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+/**
+ * @header <#Headline Name#>
+ * @abstract <#Abstract#>
+ * @discussion
+ * <#Discussion#>
+ *
+ */
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../parc_FileInputStream.c"
+
+#include <LongBow/unit-test.h>
+#include <LongBow/debugging.h>
+
+#include <parc/algol/parc_File.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(test_parc_FileInputStream)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(test_parc_FileInputStream)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(test_parc_FileInputStream)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcFileInputStream_Open);
+ LONGBOW_RUN_TEST_CASE(Global, parcFileInputStream_ReadFile);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Global, parcFileInputStream_Open)
+{
+ PARCFile *file = parcFile_Create("test_parc_FileInputStream");
+ PARCFileInputStream *stream = parcFileInputStream_Open(file);
+
+ parcFileInputStream_Release(&stream);
+ parcFile_Release(&file);
+}
+
+LONGBOW_TEST_CASE(Global, parcFileInputStream_ReadFile)
+{
+ PARCFile *file = parcFile_Create("test_parc_FileInputStream");
+ PARCFileInputStream *stream = parcFileInputStream_Open(file);
+
+ PARCBuffer *actual = parcFileInputStream_ReadFile(stream);
+ assertNotNull(actual, "Expected non-null result from parcFileInputStream_ReadFile");
+
+ parcBuffer_Flip(actual);
+
+ assertTrue(parcBuffer_HasRemaining(actual), "Expected the buffer to contain data.");
+
+ parcBuffer_Release(&actual);
+ parcFileInputStream_Release(&stream);
+ parcFile_Release(&file);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(test_parc_FileInputStream);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_FileOutputStream.c b/libparc/parc/algol/test/test_parc_FileOutputStream.c
new file mode 100755
index 00000000..aa4236ae
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_FileOutputStream.c
@@ -0,0 +1,167 @@
+/*
+ * 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 <LongBow/unit-test.h>
+#include <fcntl.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_SafeMemory.h"
+#include "../parc_FileOutputStream.c"
+
+#define PATH_SEGMENT "A"
+
+LONGBOW_TEST_RUNNER(parc_FileOutputStream)
+{
+ // 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);
+ LONGBOW_RUN_TEST_FIXTURE(AcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_FileOutputStream)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_FileOutputStream)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(AcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcFileOutputStream_Create);
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcFileOutputStream_Release);
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcFileOutputStream_AcquireRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(AcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(AcquireRelease)
+{
+ unlink("/tmp/test_parc_FileOutputStream");
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(AcquireRelease, parcFileOutputStream_Create)
+{
+ PARCFileOutputStream *stream = parcFileOutputStream_Create(open("/tmp/test_parc_FileOutputStream", O_CREAT | O_WRONLY | O_TRUNC, 0600));
+ assertNotNull(stream, "Expected a non-null pointer");
+
+ parcFileOutputStream_Release(&stream);
+ assertNull(stream, "Expected parcFileOutputStream_Release to null the pointer");
+ unlink("/tmp/test_parc_FileOutputStream");
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcFileOutputStream_Release)
+{
+ PARCFileOutputStream *stream = parcFileOutputStream_Create(open("/tmp/test_parc_FileOutputStream", O_CREAT | O_WRONLY | O_TRUNC, 0600));
+ assertNotNull(stream, "Expected a non-null pointer");
+
+ parcFileOutputStream_Release(&stream);
+ assertNull(stream, "Expected parcFileOutputStream_Release to null the pointer");
+ unlink("/tmp/test_parc_FileOutputStream");
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcFileOutputStream_AcquireRelease)
+{
+ PARCFileOutputStream *stream = parcFileOutputStream_Create(open("/tmp/test_parc_FileOutputStream", O_CREAT | O_WRONLY | O_TRUNC, 0600));
+ assertNotNull(stream, "Expected a non-null pointer");
+
+ PARCFileOutputStream *reference = parcFileOutputStream_Acquire(stream);
+ assertTrue(stream == reference, "Expected the reference to be equal to the original.");
+
+ parcFileOutputStream_Release(&stream);
+ assertNull(stream, "Expected parcFileOutputStream_Release to null the pointer");
+
+ parcFileOutputStream_Release(&reference);
+ unlink("/tmp/test_parc_FileOutputStream");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcFileOutputStream_Write);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ unlink("/tmp/test_parc_FileOutputStream");
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Global, parcFileOutputStream_Write)
+{
+ PARCFileOutputStream *stream =
+ parcFileOutputStream_Create(open("/tmp/test_parc_FileOutputStream", O_CREAT | O_WRONLY | O_TRUNC, 0600));
+
+ PARCBuffer *buffer = parcBuffer_Allocate(16 * 1024 * 1024);
+
+ parcFileOutputStream_Write(stream, buffer);
+
+ assertFalse(parcBuffer_HasRemaining(buffer), "Expected the buffer to be emtpy");
+
+ parcBuffer_Release(&buffer);
+
+ parcFileOutputStream_Release(&stream);
+ unlink("/tmp/test_parc_FileOutputStream");
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_FileOutputStream);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Hash.c b/libparc/parc/algol/test/test_parc_Hash.c
new file mode 100755
index 00000000..cc92a867
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Hash.c
@@ -0,0 +1,253 @@
+/*
+ * 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_Hash.c"
+
+#include <LongBow/testing.h>
+#include <stdio.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(parc_Hash)
+{
+ // 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_Hash)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Hash)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcHash32Bit_Create);
+ LONGBOW_RUN_TEST_CASE(Global, parcHash32Bit_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, parcHash32Bit_Release);
+ LONGBOW_RUN_TEST_CASE(Global, parcHash32Bit_Update);
+ LONGBOW_RUN_TEST_CASE(Global, parcHash32Bit_UpdateUint32);
+ LONGBOW_RUN_TEST_CASE(Global, parcHash32Bit_Hash);
+
+ LONGBOW_RUN_TEST_CASE(Global, parc_Hash32_Data);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Hash32_Int32);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Hash32_Int64);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Hash64_Data);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Hash64_Int32);
+ LONGBOW_RUN_TEST_CASE(Global, parc_Hash64_Int64);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Global, parcHash32Bit_Create)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcHash32Bit_Acquire)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcHash32Bit_Release)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcHash32Bit_Update)
+{
+ PARCHash32Bits *hash = parcHash32Bits_Create();
+ parcHash32Bits_Update(hash, "123", 3);
+ uint32_t value = parcHash32Bits_Hash(hash);
+ assertTrue(value != 0, "Expected a non-zero (non-initial) value");
+
+ parcHash32Bits_Release(&hash);
+}
+
+LONGBOW_TEST_CASE(Global, parcHash32Bit_UpdateUint32)
+{
+ PARCHash32Bits *hash = parcHash32Bits_Create();
+ parcHash32Bits_UpdateUint32(hash, 123);
+ uint32_t value = parcHash32Bits_Hash(hash);
+ assertTrue(value != 0, "Expected a non-zero (non-initial) value");
+
+ parcHash32Bits_Release(&hash);
+}
+
+LONGBOW_TEST_CASE(Global, parcHash32Bit_Hash)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parc_Hash32_Data)
+{
+ char *data1 = "Hello World";
+ char *data2 = "Hello World1";
+ char *data3 = "Hello World2";
+
+ char data4[20];
+ strncpy(data4, data1, sizeof(data4));
+
+ uint32_t hash1 = parcHash32_Data(data1, strlen(data1));
+ uint32_t hash2 = parcHash32_Data(data2, strlen(data2));
+ uint32_t hash3 = parcHash32_Data(data3, strlen(data3));
+ uint32_t hash4 = parcHash32_Data(data4, strlen(data4));
+
+ assertTrue(hash1 != 0, "Hash is 0, unlikely");
+ assertTrue(hash2 != 0, "Hash is 0, unlikely");
+ assertTrue(hash3 != 0, "Hash is 0, unlikely");
+ assertTrue(hash4 != 0, "Hash is 0, unlikely");
+ assertTrue(hash1 != hash2, "Hash collision, unlikely");
+ assertTrue(hash3 != hash2, "Hash collision, unlikely");
+ assertTrue(hash3 != hash1, "Hash collision, unlikely");
+ assertTrue(hash1 == hash4, "Hash different for same content");
+}
+
+LONGBOW_TEST_CASE(Global, parc_Hash32_Int32)
+{
+ uint32_t data1 = 12345;
+ uint32_t data2 = 12346;
+ uint32_t data3 = 12345;
+
+ uint32_t hash1 = parcHash32_Int32(data1);
+ uint32_t hash2 = parcHash32_Int32(data2);
+ uint32_t hash3 = parcHash32_Int32(data3);
+
+ assertTrue(hash1 != 0, "Hash is 0, unlikely");
+ assertTrue(hash2 != 0, "Hash is 0, unlikely");
+ assertTrue(hash3 != 0, "Hash is 0, unlikely");
+ assertTrue(hash1 != hash2, "Hash collision, unlikely");
+ assertTrue(hash1 == hash3, "Hash different for same content");
+}
+
+LONGBOW_TEST_CASE(Global, parc_Hash32_Int64)
+{
+ uint64_t data1 = 10010010012345;
+ uint64_t data2 = 10010010012346;
+ uint64_t data3 = 10010010012345;
+
+ uint32_t hash1 = parcHash32_Int64(data1);
+ uint32_t hash2 = parcHash32_Int64(data2);
+ uint32_t hash3 = parcHash32_Int64(data3);
+
+ assertTrue(hash1 != 0, "Hash is 0, unlikely");
+ assertTrue(hash2 != 0, "Hash is 0, unlikely");
+ assertTrue(hash3 != 0, "Hash is 0, unlikely");
+ assertTrue(hash1 != hash2, "Hash collision, unlikely");
+ assertTrue(hash1 == hash3, "Hash different for same content");
+}
+
+LONGBOW_TEST_CASE(Global, parc_Hash64_Data)
+{
+ char *data1 = "Hello World";
+ char *data2 = "Hello World1";
+ char *data3 = "Hello World2";
+
+ char data4[20];
+ strncpy(data4, data1, sizeof(data4));
+
+ uint64_t hash1 = parcHash64_Data(data1, strlen(data1));
+ uint64_t hash2 = parcHash64_Data(data2, strlen(data2));
+ uint64_t hash3 = parcHash64_Data(data3, strlen(data3));
+ uint64_t hash4 = parcHash64_Data(data4, strlen(data4));
+
+ assertTrue(hash1 != 0, "Hash is 0, unlikely");
+ assertTrue(hash2 != 0, "Hash is 0, unlikely");
+ assertTrue(hash3 != 0, "Hash is 0, unlikely");
+ assertTrue(hash4 != 0, "Hash is 0, unlikely");
+ assertTrue(hash1 != hash2, "Hash collision, unlikely");
+ assertTrue(hash3 != hash2, "Hash collision, unlikely");
+ assertTrue(hash3 != hash1, "Hash collision, unlikely");
+ assertTrue(hash1 == hash4, "Hash different for same content");
+}
+
+LONGBOW_TEST_CASE(Global, parc_Hash64_Int32)
+{
+ uint32_t data1 = 12345;
+ uint32_t data2 = 12346;
+ uint32_t data3 = 12345;
+
+ uint64_t hash1 = parcHash64_Int32(data1);
+ uint64_t hash2 = parcHash64_Int32(data2);
+ uint64_t hash3 = parcHash64_Int32(data3);
+
+ assertTrue(hash1 != 0, "Hash is 0, unlikely");
+ assertTrue(hash2 != 0, "Hash is 0, unlikely");
+ assertTrue(hash3 != 0, "Hash is 0, unlikely");
+ assertTrue(hash1 != hash2, "Hash collision, unlikely");
+ assertTrue(hash1 == hash3, "Hash different for same content");
+}
+
+LONGBOW_TEST_CASE(Global, parc_Hash64_Int64)
+{
+ uint64_t data1 = 10010010012345;
+ uint64_t data2 = 10010010012346;
+ uint64_t data3 = 10010010012345;
+
+ uint64_t hash1 = parcHash64_Int64(data1);
+ uint64_t hash2 = parcHash64_Int64(data2);
+ uint64_t hash3 = parcHash64_Int64(data3);
+
+ assertTrue(hash1 != 0, "Hash is 0, unlikely");
+ assertTrue(hash2 != 0, "Hash is 0, unlikely");
+ assertTrue(hash3 != 0, "Hash is 0, unlikely");
+ assertTrue(hash1 != hash2, "Hash collision, unlikely");
+ assertTrue(hash1 == hash3, "Hash different for same content");
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Hash);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_HashCode.c b/libparc/parc/algol/test/test_parc_HashCode.c
new file mode 100755
index 00000000..a5b21137
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_HashCode.c
@@ -0,0 +1,109 @@
+/*
+ * 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_HashCode.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+
+LONGBOW_TEST_RUNNER(test_parc_HashCode)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(test_parc_HashCode)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(test_parc_HashCode)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcHashCode_HashImpl);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashCode_HashHashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashCode_Hash);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcHashCode_HashImpl)
+{
+ PARCHashCode lastValue = 0;
+ uint8_t *memory = (uint8_t *) "1234";
+ size_t length = 4;
+
+ PARCHashCode expected = 3316911679945239212ULL;
+ PARCHashCode actual = parcHashCode_HashImpl(memory, length, lastValue);
+
+ assertTrue(expected == actual, "Expected %" PRIPARCHashCode " actual %" PRIPARCHashCode, expected, actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashCode_HashHashCode)
+{
+ PARCHashCode lastValue = 0;
+ uint8_t *memory = (uint8_t *) "1234";
+ size_t length = 4;
+
+ PARCHashCode lastHash = parcHashCode_HashImpl(memory, length, lastValue);
+
+ PARCHashCode hashedHash = parcHashCode_HashHashCode(lastHash, 123456);
+
+ assertTrue(lastHash != 0, "Expected a non zero hash value for lastHash");
+ assertTrue(hashedHash != 0, "Expected a non zero hash value for hashedHash");
+ assertTrue(lastHash != hashedHash, "Expected different hash values for hashedHash and lastHash");
+}
+
+LONGBOW_TEST_CASE(Global, parcHashCode_Hash)
+{
+ char *testString1 = "this is some test data";
+ char *testString2 = "this is different test data";
+
+ PARCHashCode hash1 = parcHashCode_Hash((uint8_t *) testString1, strlen(testString1));
+ PARCHashCode hash2 = parcHashCode_Hash((uint8_t *) testString2, strlen(testString2));
+
+ assertTrue(hash1 != 0, "Expected a non zero hash value for testString1");
+ assertTrue(hash2 != 0, "Expected a non zero hash value for testString2");
+ assertTrue(hash1 != hash2, "Expected different hash values for testString1 and testString2");
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(test_parc_HashCode);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_HashCodeTable.c b/libparc/parc/algol/test/test_parc_HashCodeTable.c
new file mode 100755
index 00000000..c2adf9d2
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_HashCodeTable.c
@@ -0,0 +1,423 @@
+/*
+ * 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 <config.h>
+
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/time.h>
+
+#include <LongBow/unit-test.h>
+
+#include "../parc_HashCodeTable.c"
+
+#include <parc/algol/parc_SafeMemory.h>
+
+// ==============================
+// The objects to put in the hash table. We have a separate key class and data class
+
+typedef struct test_key_class {
+ unsigned key_value;
+ unsigned hash_value;
+} TestKeyClass;
+
+typedef struct test_data_class {
+ unsigned data_value;
+} TestDataClass;
+
+static bool
+TestKeyClass_Equals(const void *a, const void *b)
+{
+ return ((TestKeyClass *) a)->key_value == ((TestKeyClass *) b)->key_value;
+}
+
+static HashCodeType
+TestKeyClass_Hash(const void *a)
+{
+ return ((TestKeyClass *) a)->hash_value;
+}
+
+static void
+TestKeyClassDestroy(void **aPtr)
+{
+ parcMemory_Deallocate((void **) aPtr);
+ aPtr = NULL;
+}
+
+static void
+TestDataClassDestroy(void **aPtr)
+{
+ parcMemory_Deallocate((void **) aPtr);
+ aPtr = NULL;
+}
+
+typedef struct truth_table_entry {
+ unsigned key_value;
+ unsigned hash_code;
+ unsigned data_value;
+} TruthTableEntry;
+
+// ==============================
+
+
+LONGBOW_TEST_RUNNER(parc_HashCodeTable)
+{
+ // 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_HashCodeTable)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_HashCodeTable)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcHashCodeTable_Add_Get);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashCodeTable_Create);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashCodeTable_Create_Size);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashCodeTable_Del);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcHashCodeTable_Add_DuplicateHashes);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashCodeTable_Add_DuplicateValues);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcHashCodeTable_BigTable);
+}
+
+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;
+}
+
+LONGBOW_TEST_CASE(Global, parcHashCodeTable_Add_Get)
+{
+ const int testsize = 4096;
+ PARCHashCodeTable *table = parcHashCodeTable_Create(TestKeyClass_Equals, TestKeyClass_Hash, TestKeyClassDestroy, TestDataClassDestroy);
+ TruthTableEntry *truthtable = parcMemory_Allocate(sizeof(TruthTableEntry) * testsize);
+ assertNotNull(truthtable, "parcMemory_Allocate(%zu) returned NULL", sizeof(TruthTableEntry) * testsize);
+ int i;
+ int fd = open("/dev/urandom", O_RDONLY);
+
+ if (fd == -1) {
+ assertFalse(fd == -1, "Error opening random number generator: %s", strerror(errno));
+ }
+
+ ssize_t nread = read(fd, truthtable, sizeof(TruthTableEntry) * testsize);
+ assertTrue(nread > 0, "Error using read");
+ close(fd);
+
+ for (i = 0; i < testsize; i++) {
+ TestKeyClass *key = parcMemory_AllocateAndClear(sizeof(TestKeyClass));
+ assertNotNull(key, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestKeyClass));
+ TestDataClass *data = parcMemory_AllocateAndClear(sizeof(TestDataClass));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestDataClass));
+
+ key->key_value = truthtable[i].key_value;
+ key->hash_value = truthtable[i].hash_code;
+ data->data_value = truthtable[i].data_value;
+
+ bool success = parcHashCodeTable_Add(table, key, data);
+ assertTrue(success, "Failed inserting value");
+ }
+
+ // now retrieve them
+ for (i = 0; i < testsize; i++) {
+ TestKeyClass lookupkey;
+ lookupkey.key_value = truthtable[i].key_value;
+ lookupkey.hash_value = truthtable[i].hash_code;
+
+ TestDataClass *data = parcHashCodeTable_Get(table, &lookupkey);
+ assertTrue(data->data_value == truthtable[i].data_value, "Data value incorrect");
+ }
+
+ parcHashCodeTable_Destroy(&table);
+ parcMemory_Deallocate((void **) &truthtable);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashCodeTable_Create)
+{
+ PARCHashCodeTable *table = parcHashCodeTable_Create(TestKeyClass_Equals, TestKeyClass_Hash, TestKeyClassDestroy, TestDataClassDestroy);
+
+ assertNotNull(table, "table came back as null");
+ assertTrue(table->hashtable.tableSize == 0, "Hash table initialized to wrong size");
+ assertTrue(table->hashtable.tableLimit == MIN_SIZE, "Initial table limit size is wrong");
+ assertTrue(table->keyEqualsFunc == TestKeyClass_Equals, "KeyEqualsFunc wrong");
+ assertTrue(table->keyHashCodeFunc == TestKeyClass_Hash, "KeyHashFunc wrong");
+ assertTrue(table->keyDestroyer == TestKeyClassDestroy, "KeyDestroyer wrong");
+ assertTrue(table->dataDestroyer == TestDataClassDestroy, "DataDestroyer wrong");
+
+ parcHashCodeTable_Destroy(&table);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashCodeTable_Create_Size)
+{
+ PARCHashCodeTable *table = parcHashCodeTable_Create_Size(TestKeyClass_Equals, TestKeyClass_Hash, TestKeyClassDestroy, TestDataClassDestroy, 16);
+
+ assertNotNull(table, "table came back as null");
+ assertTrue(table->hashtable.tableLimit == 16, "Initial table limit size is wrong");
+ parcHashCodeTable_Destroy(&table);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashCodeTable_Del)
+{
+ const int testsize = 6;
+ PARCHashCodeTable *table = parcHashCodeTable_Create(TestKeyClass_Equals, TestKeyClass_Hash, TestKeyClassDestroy, TestDataClassDestroy);
+ TruthTableEntry *truthtable = parcMemory_Allocate(sizeof(TruthTableEntry) * testsize);
+ assertNotNull(truthtable, "parcMemory_Allocate(%zu) returned NULL", sizeof(TruthTableEntry) * testsize);
+ int i;
+ int fd = open("/dev/urandom", O_RDONLY);
+
+ if (fd == -1) {
+ assertFalse(fd == -1, "Error opening random number generator: %s", strerror(errno));
+ }
+
+ ssize_t nread = read(fd, truthtable, sizeof(TruthTableEntry) * testsize);
+ assertTrue(nread > 0, "Error using read");
+ close(fd);
+
+ for (i = 0; i < testsize; i++) {
+ TestKeyClass *key = parcMemory_AllocateAndClear(sizeof(TestKeyClass));
+ assertNotNull(key, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestKeyClass));
+ TestDataClass *data = parcMemory_AllocateAndClear(sizeof(TestDataClass));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestDataClass));
+
+ key->key_value = truthtable[i].key_value;
+ key->hash_value = truthtable[i].hash_code;
+ data->data_value = truthtable[i].data_value;
+
+ bool success = parcHashCodeTable_Add(table, key, data);
+ assertTrue(success, "Failed inserting value");
+ }
+
+ // delete the last one
+ {
+ TestKeyClass lookupkey;
+
+ lookupkey.key_value = truthtable[testsize - 1].key_value;
+ lookupkey.hash_value = truthtable[testsize - 1].hash_code;
+
+ parcHashCodeTable_Del(table, &lookupkey);
+ assertTrue(table->hashtable.tableSize == testsize - 1, "tableSize wrong");
+ }
+
+ for (i = 0; i < testsize - 1; i++) {
+ TestKeyClass lookupkey;
+ lookupkey.key_value = truthtable[i].key_value;
+ lookupkey.hash_value = truthtable[i].hash_code;
+
+ TestDataClass *data = parcHashCodeTable_Get(table, &lookupkey);
+ assertTrue(data->data_value == truthtable[i].data_value, "Data value incorrect");
+ }
+
+ for (i = testsize - 1; i < testsize; i++) {
+ TestKeyClass lookupkey;
+ lookupkey.key_value = truthtable[i].key_value;
+ lookupkey.hash_value = truthtable[i].hash_code;
+
+ TestDataClass *data = parcHashCodeTable_Get(table, &lookupkey);
+ assertNull(data, "Should not have returned deleted value");
+ }
+ parcHashCodeTable_Destroy(&table);
+ parcMemory_Deallocate((void **) &truthtable);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashCodeTable_Add_DuplicateHashes)
+{
+ PARCHashCodeTable *table = parcHashCodeTable_Create(TestKeyClass_Equals, TestKeyClass_Hash, TestKeyClassDestroy, TestDataClassDestroy);
+
+ TestKeyClass *key1 = parcMemory_AllocateAndClear(sizeof(TestKeyClass));
+ assertNotNull(key1, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestKeyClass));
+ TestKeyClass *key2 = parcMemory_AllocateAndClear(sizeof(TestKeyClass));
+ assertNotNull(key2, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestKeyClass));
+ TestDataClass *data1 = parcMemory_AllocateAndClear(sizeof(TestDataClass));
+ assertNotNull(data1, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestDataClass));
+ TestDataClass *data2 = parcMemory_AllocateAndClear(sizeof(TestDataClass));
+ assertNotNull(data2, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestDataClass));
+ TestDataClass *test;
+ bool success;
+
+ *key1 = (TestKeyClass) { .key_value = 1, .hash_value = 2 };
+ *key2 = (TestKeyClass) { .key_value = 3, .hash_value = 2 };
+ data1->data_value = 11;
+ data2->data_value = 22;
+
+ success = parcHashCodeTable_Add(table, key1, data1);
+ assertTrue(success, "Failed to add value");
+
+ success = parcHashCodeTable_Add(table, key2, data2);
+ assertTrue(success, "Failed to add value");
+
+ // value 3 should be in position 3
+ test = parcHashCodeTable_Get(table, key1);
+ assertNotNull(test, "returned null on get");
+ assertTrue(test->data_value == 11, "Got wrong value back for key1");
+
+ test = parcHashCodeTable_Get(table, key2);
+ assertNotNull(test, "returned null on get");
+ assertTrue(test->data_value == 22, "Got wrong value back for key1");
+
+ parcHashCodeTable_Destroy(&table);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashCodeTable_Add_DuplicateValues)
+{
+ PARCHashCodeTable *table = parcHashCodeTable_Create(TestKeyClass_Equals, TestKeyClass_Hash, TestKeyClassDestroy, TestDataClassDestroy);
+
+ TestKeyClass *key1 = parcMemory_AllocateAndClear(sizeof(TestKeyClass));
+ assertNotNull(key1, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestKeyClass));
+ TestKeyClass *key2 = parcMemory_AllocateAndClear(sizeof(TestKeyClass));
+ assertNotNull(key2, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestKeyClass));
+ TestDataClass *data1 = parcMemory_AllocateAndClear(sizeof(TestDataClass));
+ assertNotNull(data1, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestDataClass));
+ TestDataClass *data2 = parcMemory_AllocateAndClear(sizeof(TestDataClass));
+ assertNotNull(data2, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestDataClass));
+ TestDataClass *test;
+ bool success;
+
+ *key1 = (TestKeyClass) { .key_value = 1, .hash_value = 2 };
+ *key2 = (TestKeyClass) { .key_value = 1, .hash_value = 2 };
+ data1->data_value = 11;
+ data2->data_value = 22;
+
+ success = parcHashCodeTable_Add(table, key1, data1);
+ assertTrue(success, "Failed to add value");
+
+ success = parcHashCodeTable_Add(table, key2, data2);
+ assertFalse(success, "Second add should have failed on duplicate key");
+
+ // value 3 should be in position 3
+ test = parcHashCodeTable_Get(table, key1);
+ assertNotNull(test, "returned null on get");
+ assertTrue(test->data_value == 11, "Got wrong value back for key1");
+
+ parcHashCodeTable_Destroy(&table);
+ parcMemory_Deallocate((void **) &key2);
+ parcMemory_Deallocate((void **) &data2);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashCodeTable_BigTable)
+{
+ PARCHashCodeTable *table = parcHashCodeTable_Create(TestKeyClass_Equals, TestKeyClass_Hash, TestKeyClassDestroy, TestDataClassDestroy);
+
+ struct timeval t0, t1;
+
+ gettimeofday(&t0, NULL);
+
+ int loops = 1000;
+ for (int i = 0; i < loops; i++) {
+ TestKeyClass *key = parcMemory_AllocateAndClear(sizeof(TestKeyClass));
+ assertNotNull(key, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestKeyClass));
+ TestDataClass *data = parcMemory_AllocateAndClear(sizeof(TestDataClass));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestDataClass));
+
+ *key = (TestKeyClass) { .key_value = i, .hash_value = i };
+ data->data_value = i;
+
+ bool success = parcHashCodeTable_Add(table, key, data);
+ assertTrue(success, "Failed to add value");
+ }
+ gettimeofday(&t1, NULL);
+
+ timersub(&t1, &t0, &t1);
+ double sec = t1.tv_sec + t1.tv_usec * 1E-6;
+ printf("expand count %u, sec = %.3f, sec/add = %.9f\n", table->expandCount, sec, sec / loops);
+
+ gettimeofday(&t0, NULL);
+ parcHashCodeTable_Destroy(&table);
+ gettimeofday(&t1, NULL);
+
+ timersub(&t1, &t0, &t1);
+ sec = t1.tv_sec + t1.tv_usec * 1E-6;
+ printf("destroy sec = %.3f, sec/add = %.9f\n", sec, sec / loops);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _findIndex);
+}
+
+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, _findIndex)
+{
+ PARCHashCodeTable *table = parcHashCodeTable_Create(TestKeyClass_Equals, TestKeyClass_Hash, TestKeyClassDestroy, TestDataClassDestroy);
+
+ // stick a data element in the middle of the table
+ TestKeyClass *key = parcMemory_AllocateAndClear(sizeof(TestKeyClass));
+ assertNotNull(key, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestKeyClass));
+ TestDataClass *data = parcMemory_AllocateAndClear(sizeof(TestDataClass));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestDataClass));
+
+ key->key_value = 1;
+ key->hash_value = 37;
+ data->data_value = 7;
+
+ table->hashtable.entries[37].key = key;
+ table->hashtable.entries[37].hashcode = key->hash_value;
+ table->hashtable.entries[37].data = data;
+
+ size_t index;
+ bool success = _findIndex(table, key, &index);
+ assertTrue(success, "FindIndex did not find known value");
+ assertTrue(index == 37, "FindIndex returned wrong value");
+
+
+ parcHashCodeTable_Destroy(&table);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_HashCodeTable);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_HashMap.c b/libparc/parc/algol/test/test_parc_HashMap.c
new file mode 100644
index 00000000..1b071f44
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_HashMap.c
@@ -0,0 +1,915 @@
+/*
+ * 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_HashMap.c"
+
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_StdlibMemory.h>
+
+#include <parc/testing/parc_ObjectTesting.h>
+#include <parc/testing/parc_MemoryTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_HashMap)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Static);
+ LONGBOW_RUN_TEST_FIXTURE(CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(ObjectContract);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_HashMap)
+{
+ 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_HashMap)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateCapacity0);
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateCapacityNominal);
+}
+
+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)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+ assertNotNull(instance, "Expeced non-null result from parcHashMap_Create();");
+ parcObjectTesting_AssertAcquireReleaseContract(parcHashMap_Acquire, instance);
+
+ parcHashMap_Release(&instance);
+ assertNull(instance, "Expeced null result from parcHashMap_Release();");
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateCapacity0)
+{
+ const size_t CAPACITY = 0;
+ PARCHashMap *instance = parcHashMap_CreateCapacity(CAPACITY);
+ assertNotNull(instance, "Expeced non-null result from parcHashMap_Create();");
+ parcObjectTesting_AssertAcquireReleaseContract(parcHashMap_Acquire, instance);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateCapacityNominal)
+{
+ const size_t CAPACITY = 10000;
+ PARCHashMap *instance = parcHashMap_CreateCapacity(CAPACITY);
+ assertNotNull(instance, "Expeced non-null result from parcHashMap_Create();");
+ parcObjectTesting_AssertAcquireReleaseContract(parcHashMap_Acquire, instance);
+ assertTrue(instance->capacity == CAPACITY, "Expect capacity to be %zu", CAPACITY);
+ assertTrue(instance->size == 0, "Expect size to be 0");
+
+ //Make sure all the buckets exist
+ for (size_t i = 0; i < CAPACITY; ++i) {
+ assertNull(instance->buckets[i], "Expect the hashmap to be clear");
+ }
+
+ parcHashMap_Release(&instance);
+ assertNull(instance, "Expeced null result from parcHashMap_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(ObjectContract)
+{
+ LONGBOW_RUN_TEST_CASE(ObjectContract, parcHashMap_Copy);
+ LONGBOW_RUN_TEST_CASE(ObjectContract, parcHashMap_Display);
+ LONGBOW_RUN_TEST_CASE(ObjectContract, parcHashMap_Equals);
+ LONGBOW_RUN_TEST_CASE(ObjectContract, parcHashMap_HashCode_Empty);
+ LONGBOW_RUN_TEST_CASE(ObjectContract, parcHashMap_HashCode_NonEmpty);
+ LONGBOW_RUN_TEST_CASE(ObjectContract, parcHashMap_IsValid);
+ LONGBOW_RUN_TEST_CASE(ObjectContract, parcHashMap_AssertValid);
+ LONGBOW_RUN_TEST_CASE(ObjectContract, parcHashMap_ToJSON);
+ LONGBOW_RUN_TEST_CASE(ObjectContract, parcHashMap_ToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(ObjectContract)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(ObjectContract)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(1);
+
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(ObjectContract, parcHashMap_Copy)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+ PARCHashMap *copy = parcHashMap_Copy(instance);
+
+ assertTrue(parcHashMap_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcHashMap_Release(&instance);
+ parcHashMap_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(ObjectContract, parcHashMap_Display)
+{
+ PARCHashMap *x = parcHashMap_Create();
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+ parcHashMap_Put(x, key, value);
+ parcHashMap_Display(x, 0);
+
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ parcHashMap_Release(&x);
+}
+
+LONGBOW_TEST_CASE(ObjectContract, parcHashMap_Equals)
+{
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+
+ PARCHashMap *x = parcHashMap_Create();
+ parcHashMap_Put(x, key, value);
+ PARCHashMap *y = parcHashMap_Create();
+ parcHashMap_Put(y, key, value);
+ PARCHashMap *z = parcHashMap_Create();
+ parcHashMap_Put(z, key, value);
+
+ PARCHashMap *u1 = parcHashMap_Create();
+
+ PARCHashMap *u2 = parcHashMap_Create();
+ parcHashMap_Put(u2, key, value);
+
+ parcObjectTesting_AssertEquals(x, y, z, u1, NULL);
+
+ parcHashMap_Release(&x);
+ parcHashMap_Release(&y);
+ parcHashMap_Release(&z);
+ parcHashMap_Release(&u1);
+ parcHashMap_Release(&u2);
+
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+}
+
+LONGBOW_TEST_CASE(ObjectContract, parcHashMap_HashCode_Empty)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCHashCode code = parcHashMap_HashCode(instance);
+
+ assertTrue(code == 0, "Expected 0, actual %" PRIPARCHashCode, code);
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(ObjectContract, parcHashMap_HashCode_NonEmpty)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+ parcHashMap_Put(instance, key, value);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ PARCHashCode code = parcHashMap_HashCode(instance);
+ assertTrue(code != 0, "Expected a non-zero hash code, actual %" PRIPARCHashCode, code);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(ObjectContract, parcHashMap_IsValid)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+ parcHashMap_Put(instance, key, value);
+ assertTrue(parcHashMap_IsValid(instance), "Expected parcHashMap_Create to result in a valid instance.");
+
+ parcHashMap_Release(&instance);
+ assertFalse(parcHashMap_IsValid(instance), "Expected parcHashMap_Create to result in an invalid instance.");
+
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+}
+
+LONGBOW_TEST_CASE(ObjectContract, parcHashMap_AssertValid)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+ parcHashMap_Put(instance, key, value);
+ parcHashMap_AssertValid(instance);
+
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(ObjectContract, parcHashMap_ToJSON)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+ parcHashMap_Put(instance, key, value);
+
+ PARCJSON *json = parcHashMap_ToJSON(instance);
+
+ parcJSON_Release(&json);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(ObjectContract, parcHashMap_ToString)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+ parcHashMap_Put(instance, key, value);
+
+ char *string = parcHashMap_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcHashMap_ToString");
+
+ parcMemory_Deallocate(&string);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_Put);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_PutN);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_Put_Replace);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_Get_NoValue);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_Contains_True);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_Contains_False);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_Remove);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_Remove_False);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_Resize);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_GetClusteringNumber);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_CreateValueIterator);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_CreateValueIterator_HasNext);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_CreateValueIterator_Next);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_KeyIterator);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_KeyIterator_HasNext);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_KeyIterator_Next);
+ LONGBOW_RUN_TEST_CASE(Global, parcHashMap_KeyIterator_Remove);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_Put)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+
+ //size_t keyReferences = parcObject_GetReferenceCount(key);
+ size_t valueReferences = parcObject_GetReferenceCount(value);
+
+ parcHashMap_Put(instance, key, value);
+ //M.S. Put() now results in a copy of the key.
+ //assertTrue(keyReferences + 1 == parcObject_GetReferenceCount(key), "Expected key reference to be incremented by 1.");
+ assertTrue(valueReferences + 1 == parcObject_GetReferenceCount(value), "Expected value reference to be incremented by 1.");
+
+ PARCBuffer *actual = (PARCBuffer *) parcHashMap_Get(instance, key);
+
+ assertTrue(parcBuffer_Equals(value, actual), "Expected value was not returned from Get");
+
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ parcHashMap_Release(&instance);
+}
+
+typedef struct {
+ int64_t number;
+} _Int;
+
+static char *
+_int_toString(const _Int *anInt)
+{
+ char *result = parcMemory_AllocateAndClear(22);
+ sprintf(result, "%" PRIi64 "", anInt->number);
+ return result;
+}
+
+static PARCHashCode
+_int_hashCode(const _Int *anInt)
+{
+ PARCHashCode result = anInt->number;
+
+ return result;
+}
+
+parcObject_ExtendPARCObject(_Int, NULL, NULL, _int_toString, NULL, NULL, _int_hashCode, NULL);
+
+parcObject_ImplementRelease(_int, _Int);
+
+static _Int *
+_int_Create(int64_t anInt)
+{
+ _Int *_int = parcObject_CreateInstance(_Int);
+
+ if (_int != NULL) {
+ _int->number = anInt;
+ }
+
+ return _int;
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_GetClusteringNumber)
+{
+ size_t minimumSize = 100;
+ PARCHashMap *instance = parcHashMap_CreateCapacity(minimumSize);
+
+ double maxLoadFactor = instance->maxLoadFactor;
+
+ // Load a hash map up to its load-factor
+ size_t testRunSize = minimumSize * maxLoadFactor - 20;
+ srand(time(NULL));
+ for (int i = 0; i < testRunSize; ++i) {
+ _Int *key = _int_Create(rand());
+ PARCBuffer *value = parcBuffer_Allocate(sizeof(uint32_t));
+ parcBuffer_PutUint32(value, 1000 + i);
+ parcHashMap_Put(instance, key, value);
+ parcBuffer_Release(&value);
+ _int_Release(&key);
+ }
+
+ double currentClusteringNumber = parcHashMap_GetClusteringNumber(instance);
+
+ if (currentClusteringNumber < 0.5) {
+ testWarn("Oddly low clustering number detected.");
+ }
+
+ if (currentClusteringNumber > 1.5) {
+ testWarn("Oddly high clustering number detected.");
+ }
+
+ // This will load up one bucket
+ for (int i = 0; i < 20; ++i) {
+ _Int *key = _int_Create(1 + (100 * i));
+ PARCBuffer *value = parcBuffer_Allocate(sizeof(uint32_t));
+ parcBuffer_PutUint32(value, 10 + i);
+ parcHashMap_Put(instance, key, value);
+ parcBuffer_Release(&value);
+ _int_Release(&key);
+ }
+
+ currentClusteringNumber = parcHashMap_GetClusteringNumber(instance);
+
+ parcHashMap_Release(&instance);
+
+ if (currentClusteringNumber < 2.9) {
+ testWarn("Oddly low clustering number detected.");
+ }
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_Resize)
+{
+ size_t initialSize = 8;
+ PARCHashMap *instance = parcHashMap_CreateCapacity(initialSize);
+
+ PARCBuffer *key = parcBuffer_Allocate(sizeof(uint32_t));
+ PARCBuffer *value42 = parcBuffer_WrapCString("value42");
+ double maxLoadFactor = instance->maxLoadFactor;
+
+ // Load a hash map up to its load-factor
+ size_t testRunSize = initialSize * maxLoadFactor;
+ for (uint32_t i = 0; i < testRunSize; ++i) {
+ parcBuffer_PutUint32(key, i);
+ PARCBuffer *value = parcBuffer_Allocate(sizeof(uint32_t));
+ parcBuffer_PutUint32(value, 1000 + i);
+ parcHashMap_Put(instance, parcBuffer_Flip(key), value);
+ parcBuffer_Release(&value);
+ }
+ assertTrue(parcHashMap_Size(instance) == testRunSize, "Expect the size to be %zu", testRunSize);
+ assertTrue(instance->capacity == initialSize, "Expect to have the original capacity");
+
+ // Test for expected values
+ for (uint32_t i = 0; i < testRunSize; ++i) {
+ parcBuffer_PutUint32(key, i);
+ PARCBuffer *value = parcBuffer_Allocate(sizeof(uint32_t));
+ parcBuffer_PutUint32(value, 1000 + i);
+ const PARCBuffer *storedValue = parcHashMap_Get(instance, parcBuffer_Flip(key));
+ assertTrue(parcBuffer_Equals(value, storedValue), "Expect looked up values to match");
+ parcBuffer_Release(&value);
+ }
+
+ // Add one more item to the the hash map, this should trigger an expansion
+ parcBuffer_PutUint32(key, 42);
+ parcHashMap_Put(instance, parcBuffer_Flip(key), value42);
+ assertTrue(parcHashMap_Size(instance) == testRunSize + 1, "Expect the size to be %zu", testRunSize);
+ assertTrue(instance->capacity == 2 * initialSize, "Expect to have the original capacity");
+
+ // Re-test value look ups to make sure the new hash map still maps correctly
+ for (uint32_t i = 0; i < testRunSize; ++i) {
+ parcBuffer_PutUint32(key, i);
+ PARCBuffer *value = parcBuffer_Allocate(sizeof(uint32_t));
+ parcBuffer_PutUint32(value, 1000 + i);
+ const PARCBuffer *storedValue = parcHashMap_Get(instance, parcBuffer_Flip(key));
+ assertTrue(parcBuffer_Equals(value, storedValue), "Expect looked up values to match");
+ parcBuffer_Release(&value);
+ }
+ double averageBucketSize = parcHashMap_GetClusteringNumber(instance);
+ parcBuffer_PutUint32(key, 42);
+ const PARCBuffer *storedValue = parcHashMap_Get(instance, parcBuffer_Flip(key));
+ assertTrue(parcBuffer_Equals(value42, storedValue), "Expect to get back value42");
+ parcBuffer_Release(&value42);
+ assertTrue(parcHashMap_GetClusteringNumber(instance) <= averageBucketSize,
+ "Expect the average bucket size to be less then it was");
+
+ // Now test multiple expansions to make sure they happened are result in a valid hash map
+ size_t testCapacity = 1024;
+ // If we load up to (maxLoadFactor * testCapacity) + 1, the capacity should expand to 2 * testCapacity
+ testRunSize = (testCapacity * maxLoadFactor) + 1;
+ for (uint32_t i = 0; i < testRunSize; ++i) {
+ parcBuffer_PutUint32(key, i);
+ PARCBuffer *value = parcBuffer_Allocate(sizeof(uint32_t));
+ parcBuffer_PutUint32(value, 1000 + i);
+ parcHashMap_Put(instance, parcBuffer_Flip(key), value);
+ parcBuffer_Release(&value);
+ if (i == (testRunSize - 2)) {
+ averageBucketSize = parcHashMap_GetClusteringNumber(instance);
+ }
+ }
+ assertTrue(instance->capacity == (2 * testCapacity),
+ "Expect capacity to be %zu got %zu", (2 * testCapacity), instance->capacity);
+ assertTrue(parcHashMap_GetClusteringNumber(instance) < averageBucketSize,
+ "Expect the average bucket size to be less then it was");
+
+ // Now test multiple contractions.
+ // If we remove all elements from index "smallSize" (eg. 8) up we will be left with a map of size smallSize,
+ // the map capacity should be contracting and, because the minimum load factor is 0.25 and the contraction
+ // is a divide by 2, the last contraction should be from capacity of "smallSize * 4" (32) to one
+ // of "smallSize * 2" (16) when size goes from "smallSize +1" (9) to "smallSize" (8).
+ //
+ size_t smallSize = 8;
+ for (uint32_t i = smallSize; i < testRunSize; ++i) {
+ parcBuffer_PutUint32(key, i);
+ parcBuffer_Flip(key);
+ PARCBuffer *value = parcBuffer_Allocate(sizeof(uint32_t));
+ parcBuffer_PutUint32(value, 1000 + i);
+ const PARCBuffer *storedValue = parcHashMap_Get(instance, key);
+ assertTrue(parcBuffer_Equals(value, storedValue), "Expect looked up values to match");
+ parcBuffer_Release(&value);
+
+ assertTrue(parcHashMap_Remove(instance, key), "Expect Remove to succeed");
+ }
+ assertTrue(instance->size == smallSize,
+ "Expect the hash map to have size %zu, got %zu", smallSize, instance->size)
+ assertTrue(instance->capacity == (smallSize * 2),
+ "Expect capacity to be %zu, got %zu", (smallSize * 2), instance->capacity);
+
+ // Re-test value look ups to make sure the new hash map still maps correctly
+ for (uint32_t i = 0; i < smallSize; ++i) {
+ parcBuffer_PutUint32(key, i);
+ PARCBuffer *value = parcBuffer_Allocate(sizeof(uint32_t));
+ parcBuffer_PutUint32(value, 1000 + i);
+ const PARCBuffer *storedValue = parcHashMap_Get(instance, parcBuffer_Flip(key));
+ assertTrue(parcBuffer_Equals(value, storedValue), "Expect looked up values to match");
+ parcBuffer_Release(&value);
+ }
+
+ parcBuffer_Release(&key);
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_PutN)
+{
+ size_t testRunSize = 100;
+
+ PARCHashMap *instance = parcHashMap_CreateCapacity(testRunSize);
+
+ PARCBuffer *key = parcBuffer_Allocate(sizeof(uint32_t));
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+ PARCBuffer *value42 = parcBuffer_WrapCString("value42");
+ for (uint32_t i = 0; i < testRunSize * 2; ++i) {
+ parcBuffer_PutUint32(key, i);
+ parcHashMap_Put(instance, parcBuffer_Flip(key), value);
+ if (i == 42) {
+ parcHashMap_Put(instance, key, value42);
+ }
+ }
+
+ parcBuffer_PutUint32(key, 42);
+ PARCBuffer *actual = (PARCBuffer *) parcHashMap_Get(instance, parcBuffer_Flip(key));
+ assertTrue(parcBuffer_Equals(value42, actual), "Expect to get back value42");
+
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+ parcBuffer_Release(&value42);
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_Put_Replace)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value1 = parcBuffer_WrapCString("value1");
+ PARCBuffer *value2 = parcBuffer_WrapCString("value2");
+
+ parcHashMap_Put(instance, key, value1);
+
+ parcHashMap_Put(instance, key, value2);
+
+ PARCBuffer *actual = (PARCBuffer *) parcHashMap_Get(instance, key);
+
+ assertTrue(parcBuffer_Equals(value2, actual), "Expected value was not returned from Get");
+
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value1);
+ parcBuffer_Release(&value2);
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_Get_NoValue)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+
+ PARCBuffer *actual = (PARCBuffer *) parcHashMap_Get(instance, key);
+
+ assertNull(actual, "Expected parcHashMap_Get to return NULL for non-existent key.");
+
+ parcBuffer_Release(&key);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_Contains_True)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+
+ parcHashMap_Put(instance, key, value);
+
+ bool actual = parcHashMap_Contains(instance, key);
+
+ assertTrue(actual, "Expected parcHashMap_Contains to return true");
+
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_Contains_False)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+
+ bool actual = parcHashMap_Contains(instance, key);
+
+ assertFalse(actual, "Expected parcHashMap_Contains to return NULL for non-existent key.");
+
+ parcBuffer_Release(&key);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_Remove)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+
+ parcHashMap_Put(instance, key, value);
+
+ bool actual = parcHashMap_Remove(instance, key);
+
+ assertTrue(actual, "Expected parcHashMap_Remove to return true.");
+
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_Remove_False)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *key2 = parcBuffer_WrapCString("key2");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+
+ parcHashMap_Put(instance, key, value);
+
+ bool actual = parcHashMap_Remove(instance, key2);
+
+ assertFalse(actual, "Expected parcHashMap_Remove to return false.");
+
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&key2);
+ parcBuffer_Release(&value);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_CreateValueIterator)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+
+ parcHashMap_Put(instance, key, value);
+
+ PARCIterator *iterator = parcHashMap_CreateValueIterator(instance);
+
+ assertNotNull(iterator, "Expected parcHashMap_ValueIterator to return non-null result");
+
+ parcIterator_Release(&iterator);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_CreateValueIterator_HasNext)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+
+ parcHashMap_Put(instance, key, value);
+
+ PARCIterator *iterator = parcHashMap_CreateValueIterator(instance);
+
+ assertTrue(parcIterator_HasNext(iterator), "Expected parcIterator_HasNext to return true");
+
+ parcIterator_Release(&iterator);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_CreateValueIterator_Next)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key1 = parcBuffer_WrapCString("key1");
+ PARCBuffer *value1 = parcBuffer_WrapCString("1");
+ PARCBuffer *key2 = parcBuffer_WrapCString("key2");
+ PARCBuffer *value2 = parcBuffer_WrapCString("2");
+ PARCBuffer *key3 = parcBuffer_WrapCString("key3");
+ PARCBuffer *value3 = parcBuffer_WrapCString("3");
+ PARCBuffer *key4 = parcBuffer_WrapCString("key4");
+ PARCBuffer *value4 = parcBuffer_WrapCString("4");
+
+ parcHashMap_Put(instance, key1, value1);
+ parcHashMap_Put(instance, key2, value2);
+ parcHashMap_Put(instance, key3, value3);
+ parcHashMap_Put(instance, key4, value4);
+
+ PARCIterator *iterator = parcHashMap_CreateValueIterator(instance);
+
+ while (parcIterator_HasNext(iterator)) {
+ PARCBuffer *actual = parcIterator_Next(iterator);
+ assertNotNull(actual, "Expected parcIterator_Next to return non-null");
+ assertTrue(parcBuffer_Remaining(actual) > 0, "The same value appeared more than once in the iteration");
+ parcBuffer_SetPosition(actual, parcBuffer_Limit(actual));
+ }
+ parcIterator_Release(&iterator);
+
+ parcBuffer_Release(&key1);
+ parcBuffer_Release(&value1);
+ parcBuffer_Release(&key2);
+ parcBuffer_Release(&value2);
+ parcBuffer_Release(&key3);
+ parcBuffer_Release(&value3);
+ parcBuffer_Release(&key4);
+ parcBuffer_Release(&value4);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_KeyIterator)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+
+ parcHashMap_Put(instance, key, value);
+
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(instance);
+
+ assertNotNull(iterator, "Expected parcHashMap_KeyIterator to return non-null result");
+
+ parcIterator_Release(&iterator);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_KeyIterator_HasNext)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+
+ parcHashMap_Put(instance, key, value);
+
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(instance);
+
+ assertTrue(parcIterator_HasNext(iterator), "Expected parcIterator_HasNext to return true");
+
+ parcIterator_Release(&iterator);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_KeyIterator_Next)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key1 = parcBuffer_WrapCString("key1");
+ PARCBuffer *value1 = parcBuffer_WrapCString("1");
+ PARCBuffer *key2 = parcBuffer_WrapCString("key2");
+ PARCBuffer *value2 = parcBuffer_WrapCString("2");
+ PARCBuffer *key3 = parcBuffer_WrapCString("key3");
+ PARCBuffer *value3 = parcBuffer_WrapCString("3");
+ PARCBuffer *key4 = parcBuffer_WrapCString("key4");
+ PARCBuffer *value4 = parcBuffer_WrapCString("4");
+
+ parcHashMap_Put(instance, key1, value1);
+ parcHashMap_Put(instance, key2, value2);
+ parcHashMap_Put(instance, key3, value3);
+ parcHashMap_Put(instance, key4, value4);
+
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(instance);
+
+ while (parcIterator_HasNext(iterator)) {
+ PARCBuffer *actual = parcIterator_Next(iterator);
+ assertNotNull(actual, "Expected parcIterator_Next to return non-null");
+ assertTrue(parcBuffer_Remaining(actual) > 0, "The same value appeared more than once in the iteration");
+ parcBuffer_SetPosition(actual, parcBuffer_Limit(actual));
+ }
+ parcIterator_Release(&iterator);
+
+ parcBuffer_Release(&key1);
+ parcBuffer_Release(&value1);
+ parcBuffer_Release(&key2);
+ parcBuffer_Release(&value2);
+ parcBuffer_Release(&key3);
+ parcBuffer_Release(&value3);
+ parcBuffer_Release(&key4);
+ parcBuffer_Release(&value4);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcHashMap_KeyIterator_Remove)
+{
+ PARCHashMap *instance = parcHashMap_Create();
+
+ PARCBuffer *key1 = parcBuffer_WrapCString("key1");
+ PARCBuffer *value1 = parcBuffer_WrapCString("1");
+ PARCBuffer *key2 = parcBuffer_WrapCString("key2");
+ PARCBuffer *value2 = parcBuffer_WrapCString("2");
+ PARCBuffer *key3 = parcBuffer_WrapCString("key3");
+ PARCBuffer *value3 = parcBuffer_WrapCString("3");
+ PARCBuffer *key4 = parcBuffer_WrapCString("key4");
+ PARCBuffer *value4 = parcBuffer_WrapCString("4");
+
+ parcHashMap_Put(instance, key1, value1);
+ parcHashMap_Put(instance, key2, value2);
+ parcHashMap_Put(instance, key3, value3);
+ parcHashMap_Put(instance, key4, value4);
+
+ assertTrue(parcHashMap_Size(instance) == 4, "Expected 4, actual %zd", parcHashMap_Size(instance));
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(instance);
+
+ while (parcIterator_HasNext(iterator)) {
+ PARCBuffer *key = parcBuffer_Acquire(parcIterator_Next(iterator));
+ parcIterator_Remove(iterator);
+ assertNull(parcHashMap_Get(instance, key), "Expected deleted entry to not be gettable.");
+ parcBuffer_Release(&key);
+ }
+ parcIterator_Release(&iterator);
+
+ assertTrue(parcHashMap_Size(instance) == 0, "Expected 0, actual %zd", parcHashMap_Size(instance));
+ parcBuffer_Release(&key1);
+ parcBuffer_Release(&value1);
+ parcBuffer_Release(&key2);
+ parcBuffer_Release(&value2);
+ parcBuffer_Release(&key3);
+ parcBuffer_Release(&value3);
+ parcBuffer_Release(&key4);
+ parcBuffer_Release(&value4);
+
+ parcHashMap_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Static)
+{
+ LONGBOW_RUN_TEST_CASE(Static, parcHashMapEntry);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Static)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Static, parcHashMapEntry)
+{
+ PARCBuffer *key = parcBuffer_WrapCString("key1");
+ PARCBuffer *value = parcBuffer_WrapCString("value1");
+
+ _PARCHashMapEntry *instance = _parcHashMapEntry_Create(key, value);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ _parcHashMapEntry_Release(&instance);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_HashMap);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_InputStream.c b/libparc/parc/algol/test/test_parc_InputStream.c
new file mode 100755
index 00000000..46d47862
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_InputStream.c
@@ -0,0 +1,109 @@
+/*
+ * 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_InputStream.c"
+
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(parc_InputStream)
+{
+ // 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_InputStream)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_InputStream)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcInputStream);
+ LONGBOW_RUN_TEST_CASE(Global, parcInputStream_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, parcInputStream_Read);
+ LONGBOW_RUN_TEST_CASE(Global, parcInputStream_Release);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcInputStream)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcInputStream_Acquire)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcInputStream_Read)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcInputStream_Release)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, parcInputStream_Finalize);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Local, parcInputStream_Finalize)
+{
+ testUnimplemented("");
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_InputStream);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Iterator.c b/libparc/parc/algol/test/test_parc_Iterator.c
new file mode 100644
index 00000000..d5778721
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Iterator.c
@@ -0,0 +1,192 @@
+/*
+ * 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_Iterator.c"
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <parc/algol/parc_Buffer.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+#include <parc/testing/parc_MemoryTesting.h>
+
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(parc_Iterator)
+{
+ // 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_Iterator)
+{
+ 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_Iterator)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, parcIterator_CreateAcquireRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s", longBowTestCase_GetName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static uint64_t _state;
+
+static void *
+init(PARCObject *object __attribute__((unused)))
+{
+ _state = 0;
+ return &_state;
+}
+
+static bool
+hasNext(PARCObject *object __attribute__((unused)), void *state)
+{
+ uint64_t *value = (uint64_t *) state;
+ return (*value < 5);
+}
+
+static void *
+next(PARCObject *object __attribute__((unused)), void *state)
+{
+ uint64_t *value = (uint64_t *) state;
+
+ (*value)++;
+ return state;
+}
+
+static void
+removex(PARCObject *object __attribute__((unused)), void **state)
+{
+}
+
+static void *
+getElement(PARCObject *object __attribute__((unused)), void *state)
+{
+ uint64_t *value = (uint64_t *) state;
+ return (void *) *value;
+}
+
+static void
+fini(PARCObject *object __attribute__((unused)), void *state __attribute__((unused)))
+{
+}
+
+static void
+assertValid(const void *state __attribute__((unused)))
+{
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, parcIterator_CreateAcquireRelease)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+
+ PARCIterator *iterator = parcIterator_Create(buffer, init, hasNext, next, removex, getElement, fini, assertValid);
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcIterator_Acquire, iterator);
+ parcBuffer_Release(&buffer);
+ parcIterator_Release(&iterator);
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcIterator_HasNext);
+ LONGBOW_RUN_TEST_CASE(Global, parcIterator_Next);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ bool leaked = parcMemoryTesting_ExpectedOutstanding(0, "%s leaks memory \n", longBowTestCase_GetName(testCase)) != true;
+ if (leaked) {
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcIterator_HasNext)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+
+ PARCIterator *iterator = parcIterator_Create(buffer, init, hasNext, next, removex, getElement, fini, assertValid);
+
+ while (parcIterator_HasNext(iterator)) {
+ uint64_t value = (uint64_t) parcIterator_Next(iterator);
+ printf("%" PRIu64 "\n", value);
+ }
+ parcBuffer_Release(&buffer);
+ parcIterator_Release(&iterator);
+}
+
+LONGBOW_TEST_CASE(Global, parcIterator_Next)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+
+ PARCIterator *iterator = parcIterator_Create(buffer, init, hasNext, next, removex, getElement, fini, assertValid);
+
+ while (parcIterator_HasNext(iterator)) {
+ uint64_t value = (uint64_t) parcIterator_Next(iterator);
+ printf("%" PRIu64 "\n", value);
+ }
+ parcBuffer_Release(&buffer);
+ parcIterator_Release(&iterator);
+}
+
+LONGBOW_TEST_CASE(Local, _finalize)
+{
+ testUnimplemented("");
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Iterator);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_JSON.c b/libparc/parc/algol/test/test_parc_JSON.c
new file mode 100644
index 00000000..d1825319
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_JSON.c
@@ -0,0 +1,690 @@
+/*
+ * 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_JSON.c"
+#include "../parc_JSONPair.c"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include <LongBow/unit-test.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_List.h"
+#include "../parc_ArrayList.h"
+#include "../parc_SafeMemory.h"
+#include "../parc_Memory.h"
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_JSON)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Static);
+ LONGBOW_RUN_TEST_FIXTURE(JSON);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_JSON)
+{
+ 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_JSON)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(JSON)
+{
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_CreateRelease);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_Equals);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_HashCode);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_Copy);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_Add);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_GetMembers);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_GetPairByName);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_GetValueByName);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_GetPairByIndex);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_GetValueByIndex);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_BuildString);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_ToString);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_ToCompactString);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_GetByPath);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_GetByPath_BadArrayIndex);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_GetByPath_DeadEndPath);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_ParseString);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_ParseBuffer_WithExcess);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_Display);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_AddString);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_AddObject);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_AddInteger);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_AddBoolean);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_AddArray);
+ LONGBOW_RUN_TEST_CASE(JSON, parcJSON_AddValue);
+}
+
+typedef struct {
+ PARCJSON *json;
+ char *expected;
+ char *compactExpected;
+} TestData;
+
+LONGBOW_TEST_FIXTURE_SETUP(JSON)
+{
+ TestData *data = parcMemory_Allocate(sizeof(TestData));
+
+ char *temp = "{ \"string\" : \"foo\\/bar\", \"null\" : null, \"true\" : true, \"false\" : false, \"integer\" : 31415, \"float\" : 3.141500, \"json\" : { \"string\" : \"foo\\/bar\" }, \"array\" : [ null, false, true, 31415, \"string\", [ null, false, true, 31415, \"string\" ], { } ] }";
+ data->expected = parcMemory_StringDuplicate(temp, strlen(temp));
+
+ temp = "{\"string\":\"foo/bar\",\"null\":null,\"true\":true,\"false\":false,\"integer\":31415,\"float\":3.141500,\"json\":{\"string\":\"foo/bar\"},\"array\":[null,false,true,31415,\"string\",[null,false,true,31415,\"string\"],{}]}";
+ data->compactExpected = parcMemory_StringDuplicate(temp, strlen(temp));
+
+ data->json = parcJSON_ParseString(temp);
+
+ longBowTestCase_SetClipBoardData(testCase, data);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(JSON)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ parcJSON_Release(&data->json);
+ parcMemory_Deallocate(&data->expected);
+ parcMemory_Deallocate(&data->compactExpected);
+
+ parcMemory_Deallocate(&data);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+
+LONGBOW_TEST_CASE(JSON, parcJSON_CreateRelease)
+{
+ PARCJSON *json = parcJSON_Create();
+
+ parcJSON_Release(&json);
+ assertNull(json, "Expected the NULL pointer side-effect of Release.");
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_Copy)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCJSON *copy = parcJSON_Copy(data->json);
+
+ assertTrue(parcJSON_Equals(data->json, copy), "Expect copy to equal original");
+
+ parcJSON_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_HashCode)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCHashCode expected = parcHashCode_Hash((uint8_t *) data->compactExpected, strlen(data->compactExpected));
+
+ PARCHashCode hashCode = parcJSON_HashCode(data->json);
+
+ assertTrue(hashCode == expected, "Expect correct hash code");
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_Add)
+{
+ PARCJSON *json = parcJSON_Create();
+ {
+ PARCBuffer *string = parcBuffer_WrapCString("string");
+ PARCJSONValue *stringValue = parcJSONValue_CreateFromString(string);
+ PARCBuffer *stringName = parcBuffer_WrapCString("string");
+ PARCJSONPair *pair = parcJSONPair_Create(stringName, stringValue);
+ parcJSON_AddPair(json, pair);
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&stringName);
+ parcJSONValue_Release(&stringValue);
+ parcBuffer_Release(&string);
+ }
+ {
+ PARCBuffer *name = parcBuffer_WrapCString("null");
+ PARCJSONValue *value = parcJSONValue_CreateFromNULL();
+ PARCJSONPair *pair = parcJSONPair_Create(name, value);
+ parcJSON_AddPair(json, pair);
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&name);
+ parcJSONValue_Release(&value);
+ }
+ {
+ PARCBuffer *name = parcBuffer_WrapCString("true");
+ PARCJSONValue *value = parcJSONValue_CreateFromBoolean(true);
+ PARCJSONPair *pair = parcJSONPair_Create(name, value);
+ parcJSON_AddPair(json, pair);
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&name);
+ parcJSONValue_Release(&value);
+ }
+ {
+ PARCBuffer *name = parcBuffer_WrapCString("false");
+ PARCJSONValue *value = parcJSONValue_CreateFromBoolean(false);
+ PARCJSONPair *pair = parcJSONPair_Create(name, value);
+ parcJSON_AddPair(json, pair);
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&name);
+ parcJSONValue_Release(&value);
+ }
+ {
+ PARCBuffer *name = parcBuffer_WrapCString("integer");
+ PARCJSONValue *value = parcJSONValue_CreateFromInteger(31415);
+ PARCJSONPair *pair = parcJSONPair_Create(name, value);
+ parcJSON_AddPair(json, pair);
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&name);
+ parcJSONValue_Release(&value);
+ }
+ {
+ PARCBuffer *name = parcBuffer_WrapCString("float");
+ PARCJSONValue *value = parcJSONValue_CreateFromFloat(3.1415);
+ PARCJSONPair *pair = parcJSONPair_Create(name, value);
+ parcJSON_AddPair(json, pair);
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&name);
+ parcJSONValue_Release(&value);
+ }
+
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_GetMembers)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ char *s = parcJSON_ToString(data->json);
+ parcMemory_Deallocate((void **) &s);
+
+ PARCList *members = parcJSON_GetMembers(data->json);
+ assertTrue(parcList_Size(members) == 8, "Expected 8, actual %zd", parcList_Size(members));
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_GetPairByName)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ int expected = 31415;
+ const PARCJSONPair *pair = parcJSON_GetPairByName(data->json, "integer");
+
+ PARCBuffer *name = parcJSONPair_GetName(pair);
+ PARCJSONValue *value = parcJSONPair_GetValue(pair);
+
+ int64_t actual = parcJSONValue_GetInteger(value);
+
+ PARCBuffer *expectedName = parcBuffer_WrapCString("integer");
+
+ assertTrue(parcBuffer_Equals(expectedName, name),
+ "Expected 'integer', actual '%s'", (char *) parcBuffer_ToString(name));
+
+ assertTrue(expected == actual, "Expected %d, actual %" PRIi64 "", expected, actual);
+
+ parcBuffer_Release(&expectedName);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_GetValueByName)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ int expected = 31415;
+ const PARCJSONValue *value = parcJSON_GetValueByName(data->json, "integer");
+
+ int64_t actual = parcJSONValue_GetInteger(value);
+
+ PARCBuffer *expectedName = parcBuffer_WrapCString("integer");
+
+ assertTrue(expected == actual, "Expected %d, actual %" PRIi64 "", expected, actual);
+
+ parcBuffer_Release(&expectedName);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_GetPairByIndex)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCJSONPair *pair = parcJSON_GetPairByIndex(data->json, 0);
+ PARCBuffer *name = parcJSONPair_GetName(pair);
+ PARCBuffer *expectedName = parcBuffer_WrapCString("string");
+ assertTrue(parcBuffer_Equals(expectedName, name),
+ "Expected 'string', actual '%s'", (char *) parcBuffer_ToString(name));
+ parcBuffer_Release(&expectedName);
+
+ pair = parcJSON_GetPairByIndex(data->json, 1);
+ name = parcJSONPair_GetName(pair);
+ expectedName = parcBuffer_WrapCString("null");
+ assertTrue(parcBuffer_Equals(expectedName, name),
+ "Expected 'null', actual '%s'", (char *) parcBuffer_ToString(name));
+ parcBuffer_Release(&expectedName);
+
+ pair = parcJSON_GetPairByIndex(data->json, 2);
+ name = parcJSONPair_GetName(pair);
+ expectedName = parcBuffer_WrapCString("true");
+ assertTrue(parcBuffer_Equals(expectedName, name),
+ "Expected 'true', actual '%s'", (char *) parcBuffer_ToString(name));
+ parcBuffer_Release(&expectedName);
+
+ pair = parcJSON_GetPairByIndex(data->json, 3);
+ name = parcJSONPair_GetName(pair);
+ expectedName = parcBuffer_WrapCString("false");
+ assertTrue(parcBuffer_Equals(expectedName, name),
+ "Expected 'false', actual '%s'", (char *) parcBuffer_ToString(name));
+ parcBuffer_Release(&expectedName);
+
+ pair = parcJSON_GetPairByIndex(data->json, 4);
+ name = parcJSONPair_GetName(pair);
+ expectedName = parcBuffer_WrapCString("integer");
+ assertTrue(parcBuffer_Equals(expectedName, name),
+ "Expected 'integer', actual '%s'", (char *) parcBuffer_ToString(name));
+ parcBuffer_Release(&expectedName);
+
+ pair = parcJSON_GetPairByIndex(data->json, 5);
+ name = parcJSONPair_GetName(pair);
+ expectedName = parcBuffer_WrapCString("float");
+ assertTrue(parcBuffer_Equals(expectedName, name),
+ "Expected 'float', actual '%s'", (char *) parcBuffer_ToString(name));
+ parcBuffer_Release(&expectedName);
+
+ pair = parcJSON_GetPairByIndex(data->json, 6);
+ name = parcJSONPair_GetName(pair);
+ expectedName = parcBuffer_WrapCString("json");
+ assertTrue(parcBuffer_Equals(expectedName, name),
+ "Expected 'json', actual '%s'", (char *) parcBuffer_ToString(name));
+ parcBuffer_Release(&expectedName);
+
+ pair = parcJSON_GetPairByIndex(data->json, 7);
+ name = parcJSONPair_GetName(pair);
+ expectedName = parcBuffer_WrapCString("array");
+ assertTrue(parcBuffer_Equals(expectedName, name),
+ "Expected 'array', actual '%s'", (char *) parcBuffer_ToString(name));
+ parcBuffer_Release(&expectedName);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_GetValueByIndex)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCJSONValue *value = parcJSON_GetValueByIndex(data->json, 0);
+ assertTrue(parcJSONValue_IsString(value),
+ "Expected value to be type string");
+
+ value = parcJSON_GetValueByIndex(data->json, 1);
+ assertTrue(parcJSONValue_IsNull(value),
+ "Expected value to be type string");
+
+ value = parcJSON_GetValueByIndex(data->json, 2);
+ assertTrue(parcJSONValue_IsBoolean(value),
+ "Expected value to be type string");
+
+ value = parcJSON_GetValueByIndex(data->json, 3);
+ assertTrue(parcJSONValue_IsBoolean(value),
+ "Expected value to be type string");
+
+ value = parcJSON_GetValueByIndex(data->json, 4);
+ assertTrue(parcJSONValue_IsNumber(value),
+ "Expected value to be type string");
+
+ value = parcJSON_GetValueByIndex(data->json, 5);
+ assertTrue(parcJSONValue_IsNumber(value),
+ "Expected value to be type string");
+
+ value = parcJSON_GetValueByIndex(data->json, 6);
+ assertTrue(parcJSONValue_IsJSON(value),
+ "Expected value to be type string");
+
+ value = parcJSON_GetValueByIndex(data->json, 7);
+ assertTrue(parcJSONValue_IsArray(value),
+ "Expected value to be type string");
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_BuildString)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcJSON_BuildString(data->json, composer, false);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+
+ assertTrue(strcmp(data->expected, actual) == 0, "Expected %s, actual %s", data->expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+
+ composer = parcBufferComposer_Create();
+ parcJSON_BuildString(data->json, composer, true);
+
+ tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+
+ assertTrue(strcmp(data->compactExpected, actual) == 0, "Expected %s, actual %s", data->compactExpected, actual);
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_ToString)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ char *actual = parcJSON_ToString(data->json);
+ assertTrue(strcmp(data->expected, actual) == 0, "Expected %s, actual %s", data->expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_ToCompactString)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ char *actual = parcJSON_ToCompactString(data->json);
+ assertTrue(strcmp(data->compactExpected, actual) == 0, "Expected %s, actual %s", data->expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_GetByPath)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCJSON *json = data->json;
+
+ char *s = parcJSON_ToString(json);
+ printf("%s\n", s);
+ parcMemory_Deallocate((void **) &s);
+
+ const PARCJSONValue *value = parcJSON_GetByPath(json, "/string");
+ assertTrue(parcJSONValue_IsString(value), "Expected /string to be a string type.");
+ value = parcJSON_GetByPath(json, "/null");
+ assertTrue(parcJSONValue_IsNull(value), "Expected /null to be a null type.");
+ value = parcJSON_GetByPath(json, "/true");
+ assertTrue(parcJSONValue_IsBoolean(value), "Expected /true to be a boolean type.");
+ value = parcJSON_GetByPath(json, "/integer");
+ assertTrue(parcJSONValue_IsNumber(value), "Expected /integer to be a number type.");
+ value = parcJSON_GetByPath(json, "/float");
+ assertTrue(parcJSONValue_IsNumber(value), "Expected /float to be a number type.");
+ value = parcJSON_GetByPath(json, "/array");
+ assertTrue(parcJSONValue_IsArray(value), "Expected /array to be an array type.");
+ value = parcJSON_GetByPath(json, "/nonexistent");
+ assertNull(value, "Expected /nonexistent to be NULL");
+
+ value = parcJSON_GetByPath(json, "/array/1");
+ assertTrue(parcJSONValue_IsBoolean(value), "Expected /array/0 to be a boolean type.");
+
+ value = parcJSON_GetByPath(json, "/array/5");
+ assertTrue(parcJSONValue_IsArray(value), "Expected /array/5 to be an array type.");
+
+ assertNotNull(value, "Expected non-null pair");
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_GetByPath_BadArrayIndex)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ const PARCJSONValue *value = parcJSON_GetByPath(data->json, "/array/100");
+ assertNull(value, "Expected null value return from parcJSON_GetByPath");
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_GetByPath_DeadEndPath)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ const PARCJSONValue *value = parcJSON_GetByPath(data->json, "/string/foo");
+ assertNull(value, "Expected null value return from parcJSON_GetByPath");
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_Equals)
+{
+ PARCJSON *x = parcJSON_ParseString("{ \"string\" : \"xyzzy\" }");
+ PARCJSON *y = parcJSON_ParseString("{ \"string\" : \"xyzzy\" }");
+ PARCJSON *z = parcJSON_ParseString("{ \"string\" : \"xyzzy\" }");
+
+ PARCJSON *notEqual1 = parcJSON_ParseString("{ \"string\" : \"string\" }");
+
+ PARCJSON *notEqual2 = parcJSON_ParseString("{ \"string\" : \"xyzzy\", \"integer\" : 1 }");
+
+ parcObjectTesting_AssertEqualsFunction(parcJSON_Equals, x, y, z, notEqual1, notEqual2);
+
+ parcJSON_Release(&x);
+ parcJSON_Release(&y);
+ parcJSON_Release(&z);
+ parcJSON_Release(&notEqual1);
+ parcJSON_Release(&notEqual2);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_Display)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ parcJSON_Display(data->json, 0);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_ParseString)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCJSON *json = parcJSON_ParseString(data->expected);
+
+ char *actual = parcJSON_ToString(json);
+
+ assertTrue(strcmp(data->expected, actual) == 0, "Expected %s, actual %s", data->expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_ParseBuffer_WithExcess)
+{
+ char *string = "{ \"string\" : \"string\", \"null\" : null, \"true\" : true, \"false\" : false, \"integer\" : 31415, \"float\" : 3.141500, \"array\" : [ null, false, true, 31415, \"string\", [ null, false, true, 31415, \"string\" ], { } ] }Xhowdy";
+ PARCBuffer *buffer = parcBuffer_WrapCString((char *) string);
+
+ PARCJSON *json = parcJSON_ParseBuffer(buffer);
+
+ char actual = parcBuffer_GetUint8(buffer);
+ assertTrue(actual == 'X', "Expected buffer position to point to X, actual %x", actual);
+
+ parcBuffer_Release(&buffer);
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_AddString)
+{
+ PARCJSON *json = parcJSON_Create();
+
+ char *expectedName = "string";
+ char *expectedValue = "value";
+
+ parcJSON_AddString(json, expectedName, expectedValue);
+
+ const PARCJSONPair *pair = parcJSON_GetPairByName(json, "string");
+ PARCBuffer *actualName = parcJSONPair_GetName(pair);
+ PARCJSONValue *actualValue = parcJSONPair_GetValue(pair);
+
+ assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0,
+ "Expected name %s, actual %s",
+ expectedName,
+ parcBuffer_ToString(actualName));
+ assertTrue(strcmp(expectedValue, parcBuffer_Overlay(parcJSONValue_GetString(actualValue), 0)) == 0,
+ "Expected value %s, actual %s",
+ expectedValue,
+ parcJSONValue_ToString(actualValue));
+
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_AddObject)
+{
+ PARCJSON *json = parcJSON_Create();
+
+ PARCJSON *expectedValue = parcJSON_ParseString("{ \"string\" : \"xyzzy\" }");
+ parcJSON_AddObject(json, "object", expectedValue);
+
+ char *expectedName = "object";
+ const PARCJSONPair *pair = parcJSON_GetPairByName(json, expectedName);
+
+ PARCBuffer *actualName = parcJSONPair_GetName(pair);
+ PARCJSONValue *actualValue = parcJSONPair_GetValue(pair);
+
+ assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0,
+ "Expected name %s, actual %s", expectedName, (char *) parcBuffer_ToString(actualName));
+
+ assertTrue(parcJSON_Equals(expectedValue, parcJSONValue_GetJSON(actualValue)),
+ "Expected value did not match the actual value.");
+
+ parcJSON_Release(&expectedValue);
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_AddInteger)
+{
+ PARCJSON *json = parcJSON_Create();
+
+ char *expectedName = "integer";
+ uint64_t expectedValue = 12345;
+
+ parcJSON_AddInteger(json, expectedName, expectedValue);
+
+ const PARCJSONPair *pair = parcJSON_GetPairByName(json, expectedName);
+
+ PARCBuffer *actualName = parcJSONPair_GetName(pair);
+ PARCJSONValue *actualValue = parcJSONPair_GetValue(pair);
+
+ assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0,
+ "Expected name %s, actual %s", expectedName, (char *) parcBuffer_ToString(actualName));
+
+ assertTrue(expectedValue == parcJSONValue_GetInteger(actualValue),
+ "Expected %" PRIi64 "d actual %" PRIi64 "d", expectedValue, parcJSONValue_GetInteger(actualValue));
+
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_AddBoolean)
+{
+ PARCJSON *json = parcJSON_Create();
+
+ char *expectedName = "boolean";
+ bool expectedValue = true;
+
+ parcJSON_AddBoolean(json, expectedName, expectedValue);
+
+ const PARCJSONPair *pair = parcJSON_GetPairByName(json, expectedName);
+
+ PARCBuffer *actualName = parcJSONPair_GetName(pair);
+ PARCJSONValue *actualValue = parcJSONPair_GetValue(pair);
+
+ assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0,
+ "Expected name %s, actual %s", expectedName, (char *) parcBuffer_ToString(actualName));
+
+ assertTrue(expectedValue == parcJSONValue_GetBoolean(actualValue),
+ "Expected %d actual %d", expectedValue, parcJSONValue_GetBoolean(actualValue));
+
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_AddArray)
+{
+ PARCJSON *json = parcJSON_Create();
+
+ char *expectedName = "array";
+
+ PARCJSONArray *array = parcJSONArray_Create();
+ PARCJSONValue *value = parcJSONValue_CreateFromCString("Some Pig");
+ parcJSONArray_AddValue(array, value);
+
+ parcJSON_AddArray(json, expectedName, array);
+ parcJSONArray_Release(&array);
+
+ const PARCJSONPair *pair = parcJSON_GetPairByName(json, expectedName);
+
+ PARCBuffer *actualName = parcJSONPair_GetName(pair);
+ PARCJSONValue *actualValue = parcJSONPair_GetValue(pair);
+ assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0,
+ "Expected name %s, actual %s", expectedName, (char *) parcBuffer_ToString(actualName));
+ assertTrue(parcJSONValue_IsArray(actualValue), "Expect value to be type PARCJSONArray");
+ array = parcJSONValue_GetArray(actualValue);
+ PARCJSONValue *result = parcJSONArray_GetValue(array, 0);
+ assertTrue(parcBuffer_Equals(parcJSONValue_GetString(result), parcJSONValue_GetString(value)),
+ "Expected %s actual %s",
+ parcJSONValue_ToString(value),
+ parcJSONValue_ToString(result));
+
+ parcJSONValue_Release(&value);
+
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSON, parcJSON_AddValue)
+{
+ PARCJSON *json = parcJSON_Create();
+
+ char *expectedName = "value";
+
+ PARCJSONValue *value = parcJSONValue_CreateFromCString("Some Pig");
+
+ parcJSON_AddValue(json, expectedName, value);
+
+ const PARCJSONPair *pair = parcJSON_GetPairByName(json, expectedName);
+
+ PARCBuffer *actualName = parcJSONPair_GetName(pair);
+ PARCJSONValue *actualValue = parcJSONPair_GetValue(pair);
+ assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0,
+ "Expected name %s, actual %s", expectedName, (char *) parcBuffer_ToString(actualName));
+ assertTrue(parcJSONValue_IsString(actualValue), "Expect value to be type PARCJSONArray");
+ assertTrue(parcBuffer_Equals(parcJSONValue_GetString(actualValue), parcJSONValue_GetString(value)),
+ "Expected %s actual %s",
+ parcJSONValue_ToString(value),
+ parcJSONValue_ToString(actualValue));
+
+ parcJSONValue_Release(&value);
+
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_FIXTURE(Static)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_JSON);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_JSONArray.c b/libparc/parc/algol/test/test_parc_JSONArray.c
new file mode 100755
index 00000000..d0ad9ec5
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_JSONArray.c
@@ -0,0 +1,227 @@
+/*
+ * 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_JSONArray.c"
+
+#include <LongBow/unit-test.h>
+#include <stdio.h>
+
+#include "../parc_List.h"
+#include "../parc_ArrayList.h"
+#include "../parc_SafeMemory.h"
+#include "../parc_Memory.h"
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_JSONArray)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Static);
+ LONGBOW_RUN_TEST_FIXTURE(parc_JSONArray);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_JSONArray)
+{
+ 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_JSONArray)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(parc_JSONArray)
+{
+ LONGBOW_RUN_TEST_CASE(parc_JSONArray, parcJSONArray_CreateRelease);
+ LONGBOW_RUN_TEST_CASE(parc_JSONArray, parcJSONArray_Equals);
+ LONGBOW_RUN_TEST_CASE(parc_JSONArray, parcJSONArray_AddValue);
+ LONGBOW_RUN_TEST_CASE(parc_JSONArray, parcJSONArray_GetLength);
+ LONGBOW_RUN_TEST_CASE(parc_JSONArray, parcJSONArray_GetValue);
+ LONGBOW_RUN_TEST_CASE(parc_JSONArray, parcJSONArray_BuildString);
+ LONGBOW_RUN_TEST_CASE(parc_JSONArray, parcJSONArray_ToString);
+ LONGBOW_RUN_TEST_CASE(parc_JSONArray, parcJSONArray_Display);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(parc_JSONArray)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(parc_JSONArray)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(parc_JSONArray, parcJSONArray_CreateRelease)
+{
+ PARCJSONArray *expected = parcJSONArray_Create();
+ parcJSONArray_AssertValid(expected);
+ assertNotNull(expected, "Expected non-null return value from parcJSONArray_Create");
+
+ PARCJSONArray *actual = parcJSONArray_Acquire(expected);
+ parcJSONArray_AssertValid(actual);
+
+ parcJSONArray_Release(&actual);
+ assertNull(actual, "Expected null value set by parcJSONArray_Release");
+ parcJSONArray_AssertValid(expected);
+
+ parcJSONArray_Release(&expected);
+ assertNull(expected, "Expected null value set by parcJSONArray_Release");
+}
+
+LONGBOW_TEST_CASE(parc_JSONArray, parcJSONArray_Equals)
+{
+ PARCJSONArray *x = parcJSONArray_Create();
+ PARCJSONArray *y = parcJSONArray_Create();
+ PARCJSONArray *z = parcJSONArray_Create();
+
+ PARCJSONArray *notEqual1 = parcJSONArray_Create();
+ PARCJSONValue *value = parcJSONValue_CreateFromCString("Hello");
+ parcJSONArray_AddValue(notEqual1, value);
+ parcJSONValue_Release(&value);
+
+ parcObjectTesting_AssertEqualsFunction(parcJSONArray_Equals, x, y, z, notEqual1);
+
+ parcJSONArray_Release(&x);
+ parcJSONArray_Release(&y);
+ parcJSONArray_Release(&z);
+ parcJSONArray_Release(&notEqual1);
+}
+
+LONGBOW_TEST_CASE(parc_JSONArray, parcJSONArray_AddValue)
+{
+ PARCJSONArray *expected = parcJSONArray_Create();
+ PARCJSONValue *value = parcJSONValue_CreateFromInteger(10);
+ parcJSONArray_AddValue(expected, value);
+ parcJSONValue_Release(&value);
+
+ parcJSONArray_Release(&expected);
+}
+
+LONGBOW_TEST_CASE(parc_JSONArray, parcJSONArray_GetLength)
+{
+ PARCJSONArray *expected = parcJSONArray_Create();
+ PARCJSONValue *value = parcJSONValue_CreateFromInteger(10);
+ parcJSONArray_AddValue(expected, value);
+ parcJSONValue_Release(&value);
+ assertTrue(parcJSONArray_GetLength(expected) == 1, "Expected a length of 1");
+
+ parcJSONArray_Release(&expected);
+}
+
+LONGBOW_TEST_CASE(parc_JSONArray, parcJSONArray_GetValue)
+{
+ PARCJSONArray *array = parcJSONArray_Create();
+ PARCJSONValue *expected = parcJSONValue_CreateFromInteger(10);
+ parcJSONArray_AddValue(array, expected);
+
+ PARCJSONValue *actual = parcJSONArray_GetValue(array, 0);
+
+ assertTrue(expected == actual, "Expected different value");
+
+ parcJSONValue_Release(&expected);
+ parcJSONArray_Release(&array);
+}
+
+LONGBOW_TEST_CASE(parc_JSONArray, parcJSONArray_BuildString)
+{
+ PARCJSONArray *array = parcJSONArray_Create();
+ PARCJSONValue *expected = parcJSONValue_CreateFromInteger(10);
+ parcJSONArray_AddValue(array, expected);
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcJSONArray_BuildString(array, composer, false);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ parcBufferComposer_Release(&composer);
+ char *result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ assertTrue(strlen(result) > 0, "Expected non-empty string result");
+
+ parcMemory_Deallocate((void **) &result);
+
+ composer = parcBufferComposer_Create();
+ parcJSONArray_BuildString(array, composer, true);
+ tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ parcBufferComposer_Release(&composer);
+ result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ assertTrue(strlen(result) > 0, "Expected non-empty string result");
+
+ parcMemory_Deallocate((void **) &result);
+
+ parcJSONValue_Release(&expected);
+ parcJSONArray_Release(&array);
+}
+
+LONGBOW_TEST_CASE(parc_JSONArray, parcJSONArray_ToString)
+{
+ PARCJSONArray *array = parcJSONArray_Create();
+ PARCJSONValue *expected = parcJSONValue_CreateFromInteger(10);
+ parcJSONArray_AddValue(array, expected);
+ parcJSONValue_Release(&expected);
+
+ const char *string = parcJSONArray_ToString(array);
+
+ parcMemory_Deallocate((void **) &string);
+
+ parcJSONArray_Release(&array);
+}
+
+LONGBOW_TEST_CASE(parc_JSONArray, parcJSONArray_Display)
+{
+ PARCJSONArray *array = parcJSONArray_Create();
+ PARCJSONValue *expected = parcJSONValue_CreateFromInteger(10);
+ parcJSONArray_AddValue(array, expected);
+ parcJSONValue_Release(&expected);
+
+ parcJSONArray_Display(array, 0);
+
+ parcJSONArray_Release(&array);
+}
+
+LONGBOW_TEST_FIXTURE(Static)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_JSONArray);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_JSONPair.c b/libparc/parc/algol/test/test_parc_JSONPair.c
new file mode 100644
index 00000000..b8c0c3f9
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_JSONPair.c
@@ -0,0 +1,421 @@
+/*
+ * 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_JSONPair.c"
+#include <LongBow/unit-test.h>
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include "../parc_List.h"
+#include "../parc_ArrayList.h"
+#include "../parc_SafeMemory.h"
+#include "../parc_Memory.h"
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_JSONPair)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Static);
+ LONGBOW_RUN_TEST_FIXTURE(JSONPair);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_JSONPair)
+{
+ 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_JSONPair)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(JSONPair)
+{
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_CreateAcquireRelease);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_BuildString);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_ToString);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_Display);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_Equals);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_Parser);
+
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_CreateNULL);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_CreateValue);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_CreateString);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_CreateFromBoolean);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_CreateFromInteger);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_CreateFromFloat);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_CreateFromJSONArray);
+ LONGBOW_RUN_TEST_CASE(JSONPair, parcJSONPair_CreateFromJSON);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(JSONPair)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(JSONPair)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_CreateAcquireRelease)
+{
+ PARCBuffer *name = parcBuffer_WrapCString("name");
+
+ PARCBuffer *stringValue = parcBuffer_WrapCString("foo");
+ PARCJSONValue *value = parcJSONValue_CreateFromString(stringValue);
+ parcBuffer_Release(&stringValue);
+
+ PARCJSONPair *pair = parcJSONPair_Create(name, value);
+
+ assertTrue(parcBuffer_Equals(name, pair->name),
+ "Expected '%s' actual '%s'", parcBuffer_ToString(name), parcBuffer_ToString(pair->name));
+ assertTrue(value == pair->value,
+ "Expected %p' actual %p", (void *) value, (void *) pair->value);
+
+ PARCJSONPair *reference = parcJSONPair_Acquire(pair);
+
+ assertTrue(reference == pair,
+ "Expected parcJSONPair_Acquire to return the same pointer as the original.");
+
+ parcBuffer_Release(&name);
+ parcJSONValue_Release(&value);
+ parcJSONPair_Release(&reference);
+ parcJSONPair_Release(&pair);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_Display)
+{
+ PARCBuffer *name = parcBuffer_WrapCString("name");
+ PARCBuffer *value = parcBuffer_WrapCString("foo");
+
+ PARCJSONValue *jsonValue = parcJSONValue_CreateFromString(value);
+ parcBuffer_Release(&value);
+ PARCJSONPair *pair = parcJSONPair_Create(name, jsonValue);
+ parcBuffer_Release(&name);
+ parcJSONValue_Release(&jsonValue);
+
+ parcJSONPair_Display(pair, 0);
+
+ parcJSONPair_Release(&pair);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_BuildString)
+{
+ PARCBuffer *name = parcBuffer_WrapCString("name");
+ PARCBuffer *value = parcBuffer_WrapCString("foo/bar");
+
+ PARCJSONValue *jsonValue = parcJSONValue_CreateFromString(value);
+ parcBuffer_Release(&value);
+ PARCJSONPair *pair = parcJSONPair_Create(name, jsonValue);
+ parcBuffer_Release(&name);
+ parcJSONValue_Release(&jsonValue);
+
+ // umcompressed
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcJSONPair_BuildString(pair, composer, false);
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+
+ char *expected = "\"name\" : \"foo\\/bar\"";
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s' actual '%s'", expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+
+ // compressed
+ composer = parcBufferComposer_Create();
+ parcJSONPair_BuildString(pair, composer, true);
+ tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+
+ expected = "\"name\":\"foo/bar\"";
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s' actual '%s'", expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+
+ parcJSONPair_Release(&pair);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_ToString)
+{
+ PARCBuffer *name = parcBuffer_WrapCString("name");
+ PARCBuffer *value = parcBuffer_WrapCString("foo");
+
+ PARCJSONValue *jsonValue = parcJSONValue_CreateFromString(value);
+ parcBuffer_Release(&value);
+ PARCJSONPair *pair = parcJSONPair_Create(name, jsonValue);
+ parcBuffer_Release(&name);
+ parcJSONValue_Release(&jsonValue);
+
+ char *expected = "\"name\" : \"foo\"";
+ char *actual = parcJSONPair_ToString(pair);
+
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s' actual '%s'", expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+
+ parcJSONPair_Release(&pair);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_CreateNULL)
+{
+ char *name = "MyNull";
+ PARCBuffer *expectedName = parcBuffer_AllocateCString(name);
+
+ PARCJSONPair *pair = parcJSONPair_CreateFromNULL(name);
+
+ assertTrue(parcBuffer_Equals(expectedName, parcJSONPair_GetName(pair)),
+ "Expected name '%s', got '%s'", name, parcBuffer_ToString(parcJSONPair_GetName(pair)));
+
+ assertTrue(parcJSONValue_IsNull(parcJSONPair_GetValue(pair)),
+ "Expected a JSON Null value.");
+
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&expectedName);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_CreateValue)
+{
+ char *name = "MyNull";
+ PARCBuffer *expectedName = parcBuffer_AllocateCString(name);
+ PARCJSONValue *value = parcJSONValue_CreateFromCString("Some Pig");
+
+ PARCJSONPair *pair = parcJSONPair_CreateFromJSONValue(name, value);
+
+ assertTrue(parcBuffer_Equals(expectedName, parcJSONPair_GetName(pair)),
+ "Expected name '%s', got '%s'", name, parcBuffer_ToString(parcJSONPair_GetName(pair)));
+
+ assertTrue(parcJSONValue_IsString(parcJSONPair_GetValue(pair)),
+ "Expected a String value.");
+
+ assertTrue(parcJSONPair_GetValue(pair) == value, "Expect values to be equal");
+
+ parcJSONValue_Release(&value);
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&expectedName);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_CreateString)
+{
+ char *name = "MyNull";
+ char *value = "value";
+ PARCBuffer *expectedName = parcBuffer_AllocateCString(name);
+ PARCJSONValue *expectedValue = parcJSONValue_CreateFromCString(value);
+
+ PARCJSONPair *pair = parcJSONPair_CreateFromString(name, value);
+
+ assertTrue(parcBuffer_Equals(expectedName, parcJSONPair_GetName(pair)),
+ "Expected name '%s', got '%s'", name, parcBuffer_ToString(parcJSONPair_GetName(pair)));
+ assertTrue(parcJSONValue_Equals(expectedValue, parcJSONPair_GetValue(pair)),
+ "Expected value '%s', Got '%s'", value, parcBuffer_ToString(parcJSONValue_GetString(parcJSONPair_GetValue(pair))));
+ assertTrue(parcJSONValue_IsString(parcJSONPair_GetValue(pair)),
+ "Expected a JSON String value.");
+
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&expectedName);
+ parcJSONValue_Release(&expectedValue);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_CreateFromBoolean)
+{
+ char *name = "MyNull";
+ bool value = true;
+ PARCBuffer *expectedName = parcBuffer_AllocateCString(name);
+ PARCJSONValue *expectedValue = parcJSONValue_CreateFromBoolean(value);
+
+ PARCJSONPair *pair = parcJSONPair_CreateFromBoolean(name, value);
+
+ assertTrue(parcBuffer_Equals(expectedName, parcJSONPair_GetName(pair)),
+ "Expected name '%s', got '%s'", name, parcBuffer_ToString(parcJSONPair_GetName(pair)));
+ assertTrue(parcJSONValue_Equals(expectedValue, parcJSONPair_GetValue(pair)),
+ "Expected value '%d', Got '%d'", value, parcJSONValue_GetBoolean(parcJSONPair_GetValue(pair)));
+
+ assertTrue(parcJSONValue_IsBoolean(parcJSONPair_GetValue(pair)),
+ "Expected a JSON Boolean value.");
+
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&expectedName);
+ parcJSONValue_Release(&expectedValue);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_CreateFromInteger)
+{
+ char *name = "MyNull";
+ int value = 31415;
+ PARCBuffer *expectedName = parcBuffer_AllocateCString(name);
+ PARCJSONValue *expectedValue = parcJSONValue_CreateFromInteger(value);
+
+ PARCJSONPair *pair = parcJSONPair_CreateFromInteger(name, value);
+
+ assertTrue(parcBuffer_Equals(expectedName, parcJSONPair_GetName(pair)),
+ "Expected name '%s', got '%s'", name, parcBuffer_ToString(parcJSONPair_GetName(pair)));
+ assertTrue(parcJSONValue_Equals(expectedValue, parcJSONPair_GetValue(pair)),
+ "Expected value '%d', Got '%" PRIi64 "'", value, parcJSONValue_GetInteger(parcJSONPair_GetValue(pair)));
+
+ assertTrue(parcJSONValue_IsNumber(parcJSONPair_GetValue(pair)),
+ "Expected a JSON Integer value.");
+
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&expectedName);
+ parcJSONValue_Release(&expectedValue);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_CreateFromFloat)
+{
+ char *name = "MyNull";
+ double value = 3.1;
+ PARCBuffer *expectedName = parcBuffer_AllocateCString(name);
+ PARCJSONValue *expectedValue = parcJSONValue_CreateFromFloat(value);
+
+ PARCJSONPair *pair = parcJSONPair_CreateFromDouble(name, value);
+
+ assertTrue(parcBuffer_Equals(expectedName, parcJSONPair_GetName(pair)),
+ "Expected name '%s', got '%s'", name, parcBuffer_ToString(parcJSONPair_GetName(pair)));
+ assertTrue(parcJSONValue_Equals(expectedValue, parcJSONPair_GetValue(pair)),
+ "Expected %g, got %Lg", value, parcJSONValue_GetFloat(parcJSONPair_GetValue(pair)));
+
+ assertTrue(parcJSONValue_IsNumber(parcJSONPair_GetValue(pair)),
+ "Expected a JSON number value.");
+
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&expectedName);
+ parcJSONValue_Release(&expectedValue);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_CreateFromJSONArray)
+{
+ char *name = "MyNull";
+ PARCJSONArray *array = parcJSONArray_Create();
+
+ PARCBuffer *expectedName = parcBuffer_AllocateCString(name);
+ PARCJSONValue *expectedValue = parcJSONValue_CreateFromJSONArray(array);
+
+ PARCJSONPair *pair = parcJSONPair_CreateFromJSONArray(name, array);
+ parcJSONArray_Release(&array);
+
+ assertTrue(parcBuffer_Equals(expectedName, parcJSONPair_GetName(pair)),
+ "Expected name '%s', got '%s'", name, parcBuffer_ToString(parcJSONPair_GetName(pair)));
+ assertTrue(parcJSONValue_Equals(expectedValue, parcJSONPair_GetValue(pair)),
+ "Expected the value to be equal the same array provided");
+
+ assertTrue(parcJSONValue_IsArray(parcJSONPair_GetValue(pair)),
+ "Expected a JSON Array value.");
+
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&expectedName);
+ parcJSONValue_Release(&expectedValue);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_CreateFromJSON)
+{
+ char *name = "MyNull";
+ PARCJSON *value = parcJSON_Create();
+
+ PARCBuffer *expectedName = parcBuffer_AllocateCString(name);
+ PARCJSONValue *expectedValue = parcJSONValue_CreateFromJSON(value);
+
+ PARCJSONPair *pair = parcJSONPair_CreateFromJSON(name, value);
+
+ assertTrue(parcBuffer_Equals(expectedName, parcJSONPair_GetName(pair)),
+ "Expected name '%s', got '%s'", name, parcBuffer_ToString(parcJSONPair_GetName(pair)));
+ assertTrue(parcJSONValue_Equals(expectedValue, parcJSONPair_GetValue(pair)),
+ "Expected %s", parcJSON_ToString(value));
+
+ assertTrue(parcJSONValue_IsJSON(parcJSONPair_GetValue(pair)),
+ "Expected a JSON Object value.");
+
+ parcJSONPair_Release(&pair);
+ parcBuffer_Release(&expectedName);
+ parcJSONValue_Release(&expectedValue);
+ parcJSON_Release(&value);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_Equals)
+{
+ char *name = "MyNull";
+ char *unequalName = "foo";
+ int value = 31415;
+ int unequalValue = 141;
+
+ PARCJSONPair *pair = parcJSONPair_CreateFromInteger(name, value);
+ PARCJSONPair *y = parcJSONPair_CreateFromInteger(name, value);
+ PARCJSONPair *z = parcJSONPair_CreateFromInteger(name, value);
+ PARCJSONPair *unequal1 = parcJSONPair_CreateFromInteger(name, unequalValue);
+ PARCJSONPair *unequal2 = parcJSONPair_CreateFromInteger(unequalName, unequalValue);
+
+ parcObjectTesting_AssertEqualsFunction(parcJSONPair_Equals, pair, y, z, unequal1, unequal2);
+
+ parcJSONPair_Release(&pair);
+ parcJSONPair_Release(&y);
+ parcJSONPair_Release(&z);
+ parcJSONPair_Release(&unequal1);
+ parcJSONPair_Release(&unequal2);
+}
+
+LONGBOW_TEST_CASE(JSONPair, parcJSONPair_Parser)
+{
+ PARCBuffer *buffer = parcBuffer_AllocateCString("\"name\" : \"value\"");
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONPair *pair = parcJSONPair_Parser(parser);
+
+ assertTrue(parcBuffer_Position(parcJSONPair_GetName(pair)) == 0, "Expected the JSONPair name buffer to be 'reset'");
+
+ parcJSONPair_Release(&pair);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_FIXTURE(Static)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_JSONPair);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_JSONParser.c b/libparc/parc/algol/test/test_parc_JSONParser.c
new file mode 100755
index 00000000..63bcea8d
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_JSONParser.c
@@ -0,0 +1,310 @@
+/*
+ * 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 <LongBow/unit-test.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <math.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_JSONParser.c"
+
+#include <parc/algol/parc_JSONValue.h>
+
+#include <parc/algol/parc_List.h>
+#include <parc/algol/parc_ArrayList.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_StdlibMemory.h>
+#include <parc/algol/parc_Memory.h>
+
+LONGBOW_TEST_RUNNER(parc_JSONParser)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Static);
+ LONGBOW_RUN_TEST_FIXTURE(JSONParse_CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(JSONParse);
+// LONGBOW_RUN_TEST_FIXTURE(Performance);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_JSONParser)
+{
+ 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_JSONParser)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+
+LONGBOW_TEST_FIXTURE(JSONParse_CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(JSONParse_CreateAcquireRelease, parcJSONParser_Create);
+ LONGBOW_RUN_TEST_CASE(JSONParse_CreateAcquireRelease, parcJSONParser_AcquireRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(JSONParse_CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(JSONParse_CreateAcquireRelease)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(JSONParse_CreateAcquireRelease, parcJSONParser_Create)
+{
+ char *string = "\"string\"";
+
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+ assertNull(parser,
+ "Expected parcJSONParser_Release to set the reference pointer to NULL");
+}
+
+LONGBOW_TEST_CASE(JSONParse_CreateAcquireRelease, parcJSONParser_AcquireRelease)
+{
+ char *string = "\"string\"";
+
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *expected = parcJSONParser_Create(buffer);
+
+ PARCJSONParser *actual = parcJSONParser_Acquire(expected);
+ assertTrue(actual == expected,
+ "Expected the acquired reference to be the same as the original instance.");
+
+ parcJSONParser_Release(&actual);
+ assertNull(actual,
+ "Expected parcJSONParser_Release to set the reference pointer to NULL");
+
+ parcJSONParser_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_FIXTURE(JSONParse)
+{
+ LONGBOW_RUN_TEST_CASE(JSONParse, parcJSONString_Parser);
+ LONGBOW_RUN_TEST_CASE(JSONParse, parcJSONParser_RequireString_Fail);
+ LONGBOW_RUN_TEST_CASE(JSONParse, parcJSONString_Parser_Quoted);
+ LONGBOW_RUN_TEST_CASE(JSONParse, parcJSON_Parse);
+
+ LONGBOW_RUN_TEST_CASE(JSONParse, parcJSON_ParseFile);
+ LONGBOW_RUN_TEST_CASE(JSONParse, parcJSON_ParseFileToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(JSONParse)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(JSONParse)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(JSONParse, parcJSONString_Parser)
+{
+ char *string = "\"\\\" \\\\ \\b \\f \\n \\r \\t \\/\"";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+
+ PARCBuffer *expected = parcBuffer_AllocateCString("\" \\ \b \f \n \r \t /");
+ PARCBuffer *actual = parcJSONParser_ParseString(parser);
+
+ assertTrue(parcBuffer_Equals(expected, actual), "Expected string");
+
+ parcBuffer_Release(&actual);
+ parcBuffer_Release(&expected);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONParse, parcJSONParser_RequireString_Fail)
+{
+ char *string = "\"string\"";
+ char *requiredString = "foo";
+
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+
+ bool actual = parcJSONParser_RequireString(parser, requiredString);
+
+ assertFalse(actual, "Expected parcJSONParser_RequireString to fail");
+
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONParse, parcJSONString_Parser_Quoted)
+{
+ char *string = "\"str\\\"ing\"";
+
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+
+ PARCBuffer *expected = parcBuffer_WrapCString("str\"ing");
+ PARCBuffer *actual = parcJSONParser_ParseString(parser);
+
+ assertTrue(parcBuffer_Equals(expected, actual), "Expected string");
+
+ parcBuffer_Release(&actual);
+ parcBuffer_Release(&expected);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONParse, parcJSON_Parse)
+{
+ char *expected = "{ \"string\" : \"string\", \"null\" : null, \"true\" : true, \"false\" : false, \"integer\" : 31415, \"float\" : 3.141500, \"array\" : [ null, false, true, 31415, \"string\", [ null, false, true, 31415, \"string\" ], { } ] }";
+
+ expected = "{ \"integer\" : 31415 }";
+
+ expected = "{ \"string\" : \"string\", \"null\" : null, \"true\" : true, \"false\" : false, \"integer\" : 31415, \"array\" : [ null, false, true, 31415, \"string\", [ null, false, true, 31415, \"string\" ], { \"string\" : \"string\" } ] }";
+
+ PARCJSON *json = parcJSON_ParseString(expected);
+ assertNotNull(json, "Parse error for %s", expected);
+
+ char *actual = parcJSON_ToString(json);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected %s, actual %s", expected, actual);
+
+ printf("%s\n", actual);
+ parcMemory_Deallocate((void **) &actual);
+
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSONParse, parcJSON_ParseFile)
+{
+ char *string = NULL;
+ size_t nread = longBowDebug_ReadFile("data.json", &string);
+ assertTrue(nread != -1, "Cannot read '%s'", "data.json");
+
+ PARCJSON *json = parcJSON_ParseString(string);
+
+ assertNotNull(json, "parcJSON_ParseString failed");
+
+ // assertTrue(longBowDebug_WriteFile("/tmp/test_parc_JSON.json", actual, strlen(actual)) != 0,
+ // "Can't write file");
+
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSONParse, parcJSON_ParseFileToString)
+{
+ char *string = NULL;
+ size_t nread = longBowDebug_ReadFile("data.json", &string);
+ assertTrue(nread != -1, "Cannot read '%s'", "data.json");
+
+ PARCJSON *json = parcJSON_ParseString(string);
+
+ assertNotNull(json, "parcJSON_ParseString failed");
+
+ char *actual = parcJSON_ToString(json);
+
+ // assertTrue(longBowDebug_WriteFile("/tmp/test_parc_JSON.json", actual, strlen(actual)) != 0,
+ // "Can't write file");
+
+ parcMemory_Deallocate((void **) &actual);
+
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_FIXTURE(Static)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Performance)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, parcJSON_ParseFileToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ parcMemory_SetInterface(&PARCStdlibMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Performance, parcJSON_ParseFileToString)
+{
+ char *string = NULL;
+ size_t nread = longBowDebug_ReadFile("citylots.json", &string);
+ assertTrue(nread != -1, "Cannot read '%s'", "citylots.json");
+
+ PARCJSON *json = parcJSON_ParseString(string);
+
+ assertNotNull(json, "parcJSON_ParseString failed");
+
+ char *actual = parcJSON_ToString(json);
+
+ // assertTrue(longBowDebug_WriteFile("/tmp/test_parc_JSON.json", actual, strlen(actual)) != 0,
+ // "Can't write file");
+
+ parcMemory_Deallocate((void **) &actual);
+
+ parcJSON_Release(&json);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_JSONParser);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_JSONValue.c b/libparc/parc/algol/test/test_parc_JSONValue.c
new file mode 100644
index 00000000..804eb690
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_JSONValue.c
@@ -0,0 +1,1365 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+
+#include "../parc_JSONValue.c"
+#include <LongBow/unit-test.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include "../parc_List.h"
+#include "../parc_ArrayList.h"
+#include "../parc_SafeMemory.h"
+#include "../parc_Memory.h"
+
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_JSONValue)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Static);
+ LONGBOW_RUN_TEST_FIXTURE(JSONValue_CreateAcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(JSONValue);
+ LONGBOW_RUN_TEST_FIXTURE(JSONValueParsing);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_JSONValue)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_JSONValue)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(JSONValue_CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(JSONValue_CreateAcquireRelease, _createValue);
+ LONGBOW_RUN_TEST_CASE(JSONValue_CreateAcquireRelease, parcJSONValue_AcquireRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(JSONValue_CreateAcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(JSONValue_CreateAcquireRelease)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(JSONValue_CreateAcquireRelease, _createValue)
+{
+ PARCJSONValue *result = parcJSONValue_CreateFromNULL();
+
+ assertNotNull(result, "Expected non-null return value from _createValue");
+ assertTrue(parcJSONValue_IsNull(result),
+ "Expected PARCJSONValueType_Null");
+
+ parcJSONValue_Release(&result);
+ assertNull(result, "Expected parcJSONValue_Release to NULL the instance pointer.");
+}
+
+
+LONGBOW_TEST_CASE(JSONValue_CreateAcquireRelease, parcJSONValue_AcquireRelease)
+{
+ PARCJSONValue *result = parcJSONValue_CreateFromNULL();
+
+ assertNotNull(result, "Expected non-null return value from _createValue");
+ assertTrue(parcJSONValue_IsNull(result),
+ "Expected PARCJSONValueType_Null");
+
+ PARCJSONValue *actual = parcJSONValue_Acquire(result);
+ assertTrue(result == actual, "Expected parcJSONValue_Acquire return value to be same as the original.");
+
+ parcJSONValue_Release(&actual);
+ parcJSONValue_Release(&result);
+ assertNull(result, "Expected parcJSONValue_Release to NULL the instance pointer.");
+}
+
+
+LONGBOW_TEST_FIXTURE(JSONValue)
+{
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_NULL);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Boolean);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Float);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Integer);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_String);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_JSON);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Array);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Timespec);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Create_Timeval);
+
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_IsValid);
+
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Display);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_BuildString);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_NULL);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_Array);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_Boolean);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_Float);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_Integer);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_String);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_CreateCString);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_ToString_JSON);
+
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_NULL);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_Boolean);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_Integer);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_Float);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_String);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_Object);
+ LONGBOW_RUN_TEST_CASE(JSONValue, parcJSONValue_Equals_Array);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(JSONValue)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(JSONValue)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_IsValid)
+{
+ bool actual = parcJSONValue_IsValid(NULL);
+ assertFalse(actual, "Expected a NULL value to be invalid");
+
+ PARCJSONValue *value = parcJSONValue_CreateFromNULL();
+
+ actual = parcJSONValue_IsValid(value);
+ parcJSONValue_Release(&value);
+ assertTrue(actual, "Expected a NULL value to be invalid");
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_JSON)
+{
+ PARCJSON *json = parcJSON_Create();
+ PARCJSONValue *value = parcJSONValue_CreateFromJSON(json);
+
+ assertTrue(parcJSONValue_IsJSON(value),
+ "Expected PARCJSONValueType_JSON");
+
+ assertTrue(parcJSONValue_GetJSON(value) == json,
+ "Expected parcJSONValue_GetJSON to return the original instance pointer.");
+ parcJSONValue_Release(&value);
+ assertNull(value, "Expected NULL pointer.");
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Timeval)
+{
+ struct timeval timeval = { .tv_sec = 42, .tv_usec = 23 };
+ PARCJSONValue *value = parcJSONValue_CreateFromTimeval(&timeval);
+
+ assertTrue(parcJSONValue_IsJSON(value),
+ "Expected PARCJSONValueType_JSON");
+
+ struct timeval actual;
+ parcJSONValue_GetTimeval(value, &actual);
+ assertTrue(timeval.tv_sec == actual.tv_sec, "Expected seconds to be equal.");
+ assertTrue(timeval.tv_usec == actual.tv_usec, "Expected seconds to be equal.");
+
+ parcJSONValue_Release(&value);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Timespec)
+{
+ struct timespec timespec = { .tv_sec = 42, .tv_nsec = 23 };
+ PARCJSONValue *value = parcJSONValue_CreateFromTimespec(&timespec);
+
+ assertTrue(parcJSONValue_IsJSON(value),
+ "Expected PARCJSONValueType_JSON");
+
+ struct timespec testTS;
+ parcJSONValue_GetTimespec(value, &testTS);
+ assertTrue(memcmp(&timespec, &testTS, sizeof(struct timespec)) == 0,
+ "Expected parcJSONValue_GetTimespec to return the original instance pointer.");
+ parcJSONValue_Release(&value);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_NULL)
+{
+ PARCJSONValue *value = parcJSONValue_CreateFromNULL();
+
+ assertTrue(value->type == PARCJSONValueType_Null,
+ "Expected PARCJSONValueType_Null, actual %d", value->type);
+ assertTrue(parcJSONValue_IsNull(value),
+ "Expected PARCJSONValueType_Null");
+ parcJSONValue_Release(&value);
+ assertNull(value, "Expected NULL pointer.");
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Boolean)
+{
+ bool expected = true;
+ PARCJSONValue *value = parcJSONValue_CreateFromBoolean(expected);
+
+ assertTrue(value->type == PARCJSONValueType_Boolean,
+ "Expected PARCJSONValueType_BooleanON_VALUE_BOOLEAN, actual %d", value->type);
+ assertTrue(value->value.boolean == expected, "Expected %d actual %d", expected, value->value.boolean);
+
+ assertTrue(parcJSONValue_IsBoolean(value),
+ "Expected PARCJSONValueType_Boolean");
+ assertTrue(parcJSONValue_GetBoolean(value), "Expected value to be true");
+ parcJSONValue_Release(&value);
+ assertNull(value, "Expected NULL pointer.");
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Float)
+{
+ double expected = 3.1415;
+ PARCJSONValue *value = parcJSONValue_CreateFromFloat(expected);
+
+ assertTrue(parcJSONValue_IsNumber(value),
+ "Expected parcJSONValue_IsNumber to be true.");
+ assertTrue(parcJSONValue_GetFloat(value) == expected,
+ "Expected %g, actual %Lg", expected, parcJSONValue_GetFloat(value));
+
+ char *expectedString = "3.141500";
+ char *actualString = parcJSONValue_ToString(value);
+ assertTrue(strcmp(expectedString, actualString) == 0, "Exepcted %s, actual %s", expectedString, actualString);
+ parcMemory_Deallocate((void **) &actualString);
+
+ parcJSONValue_Release(&value);
+ assertNull(value, "Expected NULL pointer.");
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Integer)
+{
+ int expected = 31415;
+ PARCJSONValue *value = parcJSONValue_CreateFromInteger(expected);
+
+ assertTrue(parcJSONValue_IsNumber(value),
+ "Expected parcJSONValue_IsNumber");
+ int64_t actual = parcJSONValue_GetInteger(value);
+ assertTrue(expected == actual, "Expected %d, actual %" PRIi64 "", expected, actual);
+ parcJSONValue_Release(&value);
+ assertNull(value, "Expected NULL pointer.");
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_String)
+{
+ PARCBuffer *expected = parcBuffer_WrapCString("31415");
+ PARCJSONValue *value = parcJSONValue_CreateFromString(expected);
+
+ assertTrue(value->type == PARCJSONValueType_String,
+ "Expected parcJSONValueType.String, actual %d", value->type);
+ assertTrue(parcBuffer_Equals(value->value.string, expected),
+ "Expected %s actual %s", parcBuffer_ToString(expected), parcBuffer_ToString(value->value.string));
+ assertTrue(parcJSONValue_IsString(value),
+ "Expected PARCJSONValueType_String");
+
+ assertTrue(parcBuffer_Equals(parcJSONValue_GetString(value), expected), "Expected value did not match actual value");
+ parcJSONValue_Release(&value);
+ assertNull(value, "Expected NULL pointer.");
+ parcBuffer_Release(&expected);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_CreateCString)
+{
+ PARCBuffer *expected = parcBuffer_WrapCString("31415");
+
+ PARCJSONValue *value = parcJSONValue_CreateFromCString("31415");
+
+ assertTrue(value->type == PARCJSONValueType_String,
+ "Expected parcJSONValueType.String, actual %d", value->type);
+
+ assertTrue(parcBuffer_Equals(parcJSONValue_GetString(value), expected), "Assert:")
+ {
+ char *expectedString = parcBuffer_ToString(expected);
+ char *actualString = parcBuffer_ToString(parcJSONValue_GetString(value));
+ printf("Expected '%s', actual '%s'", expectedString, actualString);
+ parcMemory_Deallocate((void **) &expectedString);
+ parcMemory_Deallocate((void **) &actualString);
+ }
+
+ parcJSONValue_Release(&value);
+ assertNull(value, "Expected NULL pointer.");
+ parcBuffer_Release(&expected);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Create_Array)
+{
+ PARCJSONArray *array = parcJSONArray_Create();
+
+ PARCJSONValue *value = parcJSONValue_CreateFromNULL();
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromJSONArray(array);
+
+ parcJSONValue_Release(&value);
+
+ parcJSONArray_Release(&array);
+ assertNull(value, "Expected NULL pointer.");
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_BuildString)
+{
+ PARCJSONArray *array = parcJSONArray_Create();
+
+ PARCJSONValue *value = parcJSONValue_CreateFromNULL();
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromBoolean(false);
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromBoolean(true);
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromInteger(31415);
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+
+ PARCBuffer *stringValue = parcBuffer_WrapCString("stringA/stringB");
+ value = parcJSONValue_CreateFromString(stringValue);
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+ parcBuffer_Release(&stringValue);
+
+ value = parcJSONValue_CreateFromJSONArray(array);
+ parcJSONArray_Release(&array);
+
+ // Uncompacted
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcJSONValue_BuildString(value, composer, false);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+
+ char *expected = "[ null, false, true, 31415, \"stringA\\/stringB\" ]";
+
+ assertTrue(strcmp(actual, expected) == 0,
+ "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+
+ // Compacted
+ composer = parcBufferComposer_Create();
+ parcJSONValue_BuildString(value, composer, true);
+
+ tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+
+ expected = "[null,false,true,31415,\"stringA/stringB\"]";
+
+ assertTrue(strcmp(actual, expected) == 0,
+ "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+
+
+ parcJSONValue_Release(&value);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_Array)
+{
+ PARCJSONArray *array = parcJSONArray_Create();
+
+ PARCJSONValue *value = parcJSONValue_CreateFromNULL();
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromBoolean(false);
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromBoolean(true);
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromInteger(31415);
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+
+ PARCBuffer *stringValue = parcBuffer_WrapCString("stringA/stringB");
+ value = parcJSONValue_CreateFromString(stringValue);
+ parcJSONArray_AddValue(array, value);
+ parcJSONValue_Release(&value);
+ parcBuffer_Release(&stringValue);
+
+ value = parcJSONValue_CreateFromJSONArray(array);
+ parcJSONArray_Release(&array);
+
+ char *expected = "[ null, false, true, 31415, \"stringA\\/stringB\" ]";
+ char *actual = parcJSONValue_ToString(value);
+
+ assertTrue(strcmp(actual, expected) == 0,
+ "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcJSONValue_Release(&value);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Display)
+{
+ PARCJSONValue *value = parcJSONValue_CreateFromNULL();
+ parcJSONValue_Display(value, 0);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromBoolean(true);
+ parcJSONValue_Display(value, 0);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromCString("hello");
+ parcJSONValue_Display(value, 0);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromFloat(3.14);
+ parcJSONValue_Display(value, 0);
+ parcJSONValue_Release(&value);
+
+ value = parcJSONValue_CreateFromInteger(314);
+ parcJSONValue_Display(value, 0);
+ parcJSONValue_Release(&value);
+
+ PARCJSONArray *array = parcJSONArray_Create();
+ value = parcJSONValue_CreateFromJSONArray(array);
+ parcJSONValue_Display(value, 0);
+ parcJSONValue_Release(&value);
+ parcJSONArray_Release(&array);
+
+ PARCJSON *json = parcJSON_Create();
+ value = parcJSONValue_CreateFromJSON(json);
+ parcJSONValue_Display(value, 0);
+ parcJSONValue_Release(&value);
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_NULL)
+{
+ char *expected = "null";
+ PARCJSONValue *value = parcJSONValue_CreateFromNULL();
+
+ char *actual = parcJSONValue_ToString(value);
+ assertTrue(strcmp(actual, expected) == 0, "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcJSONValue_Release(&value);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_Boolean)
+{
+ char *expected = "true";
+ PARCJSONValue *value = parcJSONValue_CreateFromBoolean(expected);
+
+ char *actual = parcJSONValue_ToString(value);
+ assertTrue(strcmp(actual, expected) == 0, "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcJSONValue_Release(&value);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_Float)
+{
+ struct test_values {
+ char *string;
+ long double value;
+ long double error;
+ } successful[] = {
+ { "-0.0415e-12", -0.0415e-12, 0.00001e-12 },
+ { "-0.0415e12", -0.0415e12, 0.00001e12 },
+ { "-0.0415", -0.0415, 0.00001 },
+ { "-3.0415", -3.0415, 0.00001 },
+ { "123.456", 123.456, 0.0001 },
+ { "123.456e78", 123.456e78, 0.0001e78 },
+ { "123.456e-78", 123.456e-78, 0.0001e-78 },
+ { "123.456e-78", 123.456e-78, 0.0001e-78 },
+ { "4e1", 40.0, 0.0001e-78 },
+ { NULL },
+ };
+
+ for (int i = 0; successful[i].string != NULL; i++) {
+ PARCBuffer *buffer = parcBuffer_WrapCString(successful[i].string);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ PARCJSONValue *expected = _parcJSONValue_NumberParser(parser);
+
+ char *string = parcJSONValue_ToString(expected);
+ assertTrue(strcmp(successful[i].string, string) == 0,
+ "Expected %s, actual %s", successful[i].string, string);
+ parcMemory_Deallocate((void **) &string);
+
+ parcJSONValue_Release(&expected);
+ parcJSONParser_Release(&parser);
+ }
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_Integer)
+{
+ char *expected = "31415";
+ PARCJSONValue *value = parcJSONValue_CreateFromInteger(31415);
+
+ char *actual = parcJSONValue_ToString(value);
+ assertTrue(strcmp(actual, expected) == 0,
+ "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcJSONValue_Release(&value);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_String)
+{
+ char *input = "31415\b";
+ char *expected = "\"31415\\b\"";
+
+ PARCBuffer *stringValue = parcBuffer_WrapCString(input);
+ PARCJSONValue *value = parcJSONValue_CreateFromString(stringValue);
+ parcBuffer_Release(&stringValue);
+
+ char *actual = parcJSONValue_ToString(value);
+ assertTrue(strcmp(actual, expected) == 0, "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcJSONValue_Release(&value);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_ToString_JSON)
+{
+ char *expected = "{ }";
+ PARCJSON *json = parcJSON_Create();
+ PARCJSONValue *value = parcJSONValue_CreateFromJSON(json);
+ parcJSON_Release(&json);
+
+ char *actual = parcJSONValue_ToString(value);
+ assertTrue(strcmp(actual, expected) == 0, "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcJSONValue_Release(&value);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_NULL)
+{
+ PARCJSONValue *example = parcJSONValue_CreateFromNULL();
+
+ PARCJSONValue *equal1 = parcJSONValue_CreateFromNULL();
+ PARCJSONValue *equal2 = parcJSONValue_CreateFromNULL();
+
+ PARCBuffer *stringBuffer = parcBuffer_AllocateCString("Hello");
+ PARCJSONValue *string = parcJSONValue_CreateFromString(stringBuffer);
+ parcBuffer_Release(&stringBuffer);
+
+ parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, example, equal1, equal2, string);
+
+ parcJSONValue_Release(&string);
+ parcJSONValue_Release(&equal2);
+ parcJSONValue_Release(&equal1);
+ parcJSONValue_Release(&example);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_Boolean)
+{
+ PARCJSONValue *example = parcJSONValue_CreateFromBoolean(true);
+
+ PARCJSONValue *equal1 = parcJSONValue_CreateFromBoolean(true);
+ PARCJSONValue *equal2 = parcJSONValue_CreateFromBoolean(true);
+
+ PARCJSONValue *unequal1 = parcJSONValue_CreateFromBoolean(false);
+
+ PARCBuffer *stringBuffer = parcBuffer_AllocateCString("Hello");
+ PARCJSONValue *string = parcJSONValue_CreateFromString(stringBuffer);
+ parcBuffer_Release(&stringBuffer);
+
+ parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, example, equal1, equal2, unequal1, string);
+
+ parcJSONValue_Release(&string);
+ parcJSONValue_Release(&unequal1);
+ parcJSONValue_Release(&equal2);
+ parcJSONValue_Release(&equal1);
+ parcJSONValue_Release(&example);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_Integer)
+{
+ PARCJSONValue *example = parcJSONValue_CreateFromInteger(31415);
+
+ PARCJSONValue *equal1 = parcJSONValue_CreateFromInteger(31415);
+ PARCJSONValue *equal2 = parcJSONValue_CreateFromInteger(31415);
+
+ PARCJSONValue *unequal1 = parcJSONValue_CreateFromInteger(4);
+
+ PARCBuffer *stringBuffer = parcBuffer_AllocateCString("Hello");
+ PARCJSONValue *string = parcJSONValue_CreateFromString(stringBuffer);
+ parcBuffer_Release(&stringBuffer);
+
+ parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, example, equal1, equal2, unequal1, string);
+
+ parcJSONValue_Release(&string);
+ parcJSONValue_Release(&unequal1);
+ parcJSONValue_Release(&equal2);
+ parcJSONValue_Release(&equal1);
+ parcJSONValue_Release(&example);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_Float)
+{
+ PARCJSONValue *example = parcJSONValue_CreateFromFloat(3.1415);
+
+ PARCJSONValue *equal1 = parcJSONValue_CreateFromFloat(3.1415);
+ PARCJSONValue *equal2 = parcJSONValue_CreateFromFloat(3.1415);
+
+ PARCJSONValue *unequal1 = parcJSONValue_CreateFromFloat(4.0);
+
+ PARCBuffer *stringBuffer = parcBuffer_AllocateCString("Hello");
+ PARCJSONValue *string = parcJSONValue_CreateFromString(stringBuffer);
+ parcBuffer_Release(&stringBuffer);
+
+ parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, example, equal1, equal2, unequal1, string);
+
+ parcJSONValue_Release(&string);
+ parcJSONValue_Release(&unequal1);
+ parcJSONValue_Release(&equal2);
+ parcJSONValue_Release(&equal1);
+ parcJSONValue_Release(&example);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_String)
+{
+ PARCBuffer *stringBuffer = parcBuffer_AllocateCString("Hello");
+ PARCJSONValue *example = parcJSONValue_CreateFromString(stringBuffer);
+ parcBuffer_Release(&stringBuffer);
+
+ stringBuffer = parcBuffer_AllocateCString("Hello");
+ PARCJSONValue *equal1 = parcJSONValue_CreateFromString(stringBuffer);
+ parcBuffer_Release(&stringBuffer);
+
+ stringBuffer = parcBuffer_AllocateCString("Hello");
+ PARCJSONValue *equal2 = parcJSONValue_CreateFromString(stringBuffer);
+ parcBuffer_Release(&stringBuffer);
+
+ PARCJSONValue *unequal1 = parcJSONValue_CreateFromFloat(4.0);
+
+ stringBuffer = parcBuffer_AllocateCString("World");
+ PARCJSONValue *string = parcJSONValue_CreateFromString(stringBuffer);
+ parcBuffer_Release(&stringBuffer);
+
+ parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, example, equal1, equal2, unequal1, string);
+
+ parcJSONValue_Release(&string);
+ parcJSONValue_Release(&unequal1);
+ parcJSONValue_Release(&equal2);
+ parcJSONValue_Release(&equal1);
+ parcJSONValue_Release(&example);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_Object)
+{
+ char *string = "{ \"name\" : 1, \"name2\" : 2 }";
+
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ PARCJSONValue *x = parcJSONValue_ObjectParser(parser);
+ parcJSONParser_Release(&parser);
+
+ assertTrue(parcJSONValue_IsJSON(x), "Expected a JSON Object value.");
+
+ buffer = parcBuffer_WrapCString(string);
+ parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ PARCJSONValue *y = parcJSONValue_ObjectParser(parser);
+ parcJSONParser_Release(&parser);
+
+ buffer = parcBuffer_WrapCString(string);
+ parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ PARCJSONValue *z = parcJSONValue_ObjectParser(parser);
+ parcJSONParser_Release(&parser);
+
+ PARCJSONValue *unequal1 = parcJSONValue_CreateFromFloat(4.0);
+
+ PARCJSON *json = parcJSON_Create();
+ PARCJSONValue *unequal2 = parcJSONValue_CreateFromJSON(json);
+ parcJSON_Release(&json);
+
+ parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, x, y, z, unequal1, unequal2);
+
+ parcJSONValue_Release(&x);
+ parcJSONValue_Release(&y);
+ parcJSONValue_Release(&z);
+ parcJSONValue_Release(&unequal1);
+ parcJSONValue_Release(&unequal2);
+}
+
+LONGBOW_TEST_CASE(JSONValue, parcJSONValue_Equals_Array)
+{
+ char *string = "[ \"name\", 1, true, false, null, [ ], { } ]";
+
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ PARCJSONValue *x = _parcJSONValue_ArrayParser(parser);
+ parcJSONParser_Release(&parser);
+
+ assertTrue(parcJSONValue_IsArray(x), "Expected a JSON Array value.");
+
+ buffer = parcBuffer_WrapCString(string);
+ parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ PARCJSONValue *y = _parcJSONValue_ArrayParser(parser);
+ parcJSONParser_Release(&parser);
+
+ buffer = parcBuffer_WrapCString(string);
+ parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ PARCJSONValue *z = _parcJSONValue_ArrayParser(parser);
+ parcJSONParser_Release(&parser);
+
+ PARCJSONValue *unequal1 = parcJSONValue_CreateFromFloat(4.0);
+
+ PARCJSONArray *array = parcJSONArray_Create();
+ PARCJSONValue *unequal2 = parcJSONValue_CreateFromJSONArray(array);
+ parcJSONArray_Release(&array);
+
+ parcObjectTesting_AssertEqualsFunction(parcJSONValue_Equals, x, y, z, unequal1, unequal2);
+
+ parcJSONValue_Release(&x);
+ parcJSONValue_Release(&y);
+ parcJSONValue_Release(&z);
+ parcJSONValue_Release(&unequal1);
+ parcJSONValue_Release(&unequal2);
+}
+
+LONGBOW_TEST_FIXTURE(JSONValueParsing)
+{
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_NullParser);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_NullParser_Bad);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_TrueParser);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_TrueParser_Bad);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_FalseParser);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_FalseParser_Bad);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_StringParser);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser_Bad_Pair);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser_Bad_Pair2);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_ArrayParser);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, _parcJSONValue_StringParser_BAD);
+
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_NumberParser_BatchedFloat);
+
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Comma);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_CloseBracket);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Null);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_True);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_False);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_String);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Array);
+ LONGBOW_RUN_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Object);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(JSONValueParsing)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(JSONValueParsing)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_NullParser)
+{
+ char *string = "null";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = _parcJSONValue_NullParser(parser);
+
+ assertTrue(parcJSONValue_IsNull(actual), "Expected a JSON Null value.");
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_NullParser_Bad)
+{
+ char *string = "nulx";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = _parcJSONValue_NullParser(parser);
+
+ assertNull(actual, "Expected a NULL return value");
+
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_TrueParser)
+{
+ char *string = "true";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = _parcJSONValue_TrueParser(parser);
+
+ assertTrue(parcJSONValue_IsBoolean(actual), "Expected a JSON Boolean value.");
+ assertTrue(parcJSONValue_GetBoolean(actual), "Expected true.");
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_TrueParser_Bad)
+{
+ char *string = "trux";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = _parcJSONValue_TrueParser(parser);
+
+ assertNull(actual, "Expected a NULL return value");
+
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_FalseParser)
+{
+ char *string = "false";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = _parcJSONValue_FalseParser(parser);
+
+ assertTrue(parcJSONValue_IsBoolean(actual), "Expected a JSON Boolean value.");
+ assertFalse(parcJSONValue_GetBoolean(actual), "Expected false.");
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_FalseParser_Bad)
+{
+ char *string = "falsx";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = _parcJSONValue_FalseParser(parser);
+
+ assertNull(actual, "Expected a NULL return value");
+
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_StringParser)
+{
+ char *parserInput = "\"\\\" \\\\ \\b \\f \\n \\r \\t \\/\"";
+ PARCBuffer *buffer = parcBuffer_WrapCString(parserInput);
+ PARCBuffer *expected = parcBuffer_AllocateCString("\" \\ \b \f \n \r \t /");
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = _parcJSONValue_StringParser(parser);
+
+ assertTrue(parcJSONValue_IsString(actual),
+ "Expected a JSON String value.");
+
+ assertTrue(parcBuffer_Equals(expected, actual->value.string),
+ "Expected '%s' actual '%s'", parcBuffer_ToString(expected), parcBuffer_ToString(actual->value.string))
+ {
+ parcBuffer_Display(expected, 0);
+ parcBuffer_Display(actual->value.string, 0);
+ }
+
+ char *string = parcJSONValue_ToString(actual);
+ assertTrue(strcmp(parserInput, string) == 0,
+ "Expected %s, actual %s", parserInput, string);
+
+ parcMemory_Deallocate((void **) &string);
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, _parcJSONValue_StringParser_BAD)
+{
+ char *bad[] = {
+ "\"\t\"",
+ "\"",
+ NULL
+ };
+
+ for (int i = 0; bad[i] != NULL; i++) {
+ char *parserInput = bad[i];
+ PARCBuffer *buffer = parcBuffer_WrapCString(parserInput);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = _parcJSONValue_StringParser(parser);
+
+ assertNull(actual, "Expected failure");
+ parcBuffer_Release(&buffer);
+ parcJSONParser_Release(&parser);
+ }
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser)
+{
+ char *string = "{ \"name\" : 1, \"name2\" : 2 }";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = parcJSONValue_ObjectParser(parser);
+
+ assertTrue(parcJSONValue_IsJSON(actual), "Expected a JSON Object value.");
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser_Bad_Pair)
+{
+ char *string = "{ \"name\" , \"name2\" : 2 }";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = parcJSONValue_ObjectParser(parser);
+
+ assertNull(actual, "Expected parcJSONValue_ObjectParser to return NULL indicating failure");
+
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_ObjectParser_Bad_Pair2)
+{
+ char *string = "{ 2 }";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = parcJSONValue_ObjectParser(parser);
+
+ assertNull(actual, "Expected parcJSONValue_ObjectParser to return NULL indicating failure");
+
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_ArrayParser)
+{
+ char *string = "[ \"name\", 1, true, false, null, [ ], { } ]";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = _parcJSONValue_ArrayParser(parser);
+
+ assertTrue(parcJSONValue_IsArray(actual), "Expected a JSON Array value.");
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_NumberParser_BatchedFloat)
+{
+ struct test_values {
+ char *string;
+ char *expectedString;
+ long double floatValue;
+ int64_t integerValue;
+ long double floatTolerance;
+ } successful[] = {
+ { "0", "0", 0.0, 0, 0 },
+ { " 1", "1", 1.0, 1, 0 },
+ { "-1", "-1", -1.0, -1, 0 },
+ { "1e1", "1e1", 1.0e1, 10, 0 },
+ { "-2e1", "-2e1", -2.0e1, -2e1, 0 },
+ { "-2e+1", "-2e1", -2.0e+1, -2e+1, 0 },
+ { " 1.0", "1", 1.0, 1, 0 },
+ { "3e-1", "3e-1", 3e-1, 0, 0.01e-1 },
+ { "100e-2", "100e-2", 100e-2, 100e-2, 0.0001 },
+ { "123.456e11", "123.456e11", 123.456e11, 12345600000000, 0.0001e11 },
+ { "-0.0415e-12", "-0.0415e-12", -0.0415e-12, 0, 0.00001e-12 },
+ { "-0.0415e12", "-0.0415e12", -0.0415e12, -41500000000, 0.00001e12 },
+ { "-0.0415", "-0.0415", -0.0415, 0, 0.00001 },
+ { "-3.0415", "-3.0415", -3.0415, -3, 0.00001 },
+ { "123.456", "123.456", 123.456, 123, 0.0001 },
+ { "123.456e+11", "123.456e11", 123.456e+11, 12345600000000, 0.0001e+11 },
+ { "123.456e-11", "123.456e-11", 123.456e-11, 0, 0.0001e-11 },
+ { "1e-1", "1e-1", 1e-1, 0, 0.1e-1 },
+ { NULL },
+ };
+
+ for (int i = 0; successful[i].string != NULL; i++) {
+ PARCBuffer *buffer = parcBuffer_WrapCString(successful[i].string);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ PARCJSONValue *expected = _parcJSONValue_NumberParser(parser);
+ assertNotNull(expected, "_parcJSONValue_NumberParser returned NULL");
+
+ long double floatValue = parcJSONValue_GetFloat(expected);
+
+ assertTrue(fabsl(floatValue - successful[i].floatValue) <= successful[i].floatTolerance,
+ "Expected %Lf actual %Lf", successful[i].floatValue, floatValue);
+
+ char *string = parcJSONValue_ToString(expected);
+ assertTrue(strcmp(successful[i].expectedString, string) == 0,
+ "Expected %s actual %s", successful[i].expectedString, string);
+ parcMemory_Deallocate((void **) &string);
+
+ int64_t integerValue = parcJSONValue_GetInteger(expected);
+ assertTrue(integerValue == (int64_t) successful[i].integerValue,
+ "Expected %" PRIi64 " actual %" PRIi64 "", (int64_t) successful[i].integerValue, integerValue);
+
+ parcJSONValue_Release(&expected);
+ parcJSONParser_Release(&parser);
+ }
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Comma)
+{
+ char *string = ", null";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = parcJSONValue_Parser(parser);
+
+ assertNull(actual, "Expected parcJSONValue_Parser to return NULL when encountering a comma");
+
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_CloseBracket)
+{
+ char *string = "], null";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = parcJSONValue_Parser(parser);
+
+ assertNull(actual, "Expected parcJSONValue_Parser to return NULL when encountering a ]");
+
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Null)
+{
+ char *string = " null";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = parcJSONValue_Parser(parser);
+
+ assertTrue(parcJSONValue_IsNull(actual),
+ "Expected parcJSONValue_Parser to return a Null JSON value when encountering 'null'");
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_True)
+{
+ char *string = " true";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = parcJSONValue_Parser(parser);
+
+ assertTrue(parcJSONValue_IsBoolean(actual),
+ "Expected parcJSONValue_Parser to return a boolean JSON value when encountering 'true'");
+ assertTrue(parcJSONValue_GetBoolean(actual),
+ "Expected true");
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_False)
+{
+ char *string = " false";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = parcJSONValue_Parser(parser);
+
+ assertTrue(parcJSONValue_IsBoolean(actual),
+ "Expected parcJSONValue_Parser to return a boolean JSON value when encountering 'false'");
+ assertFalse(parcJSONValue_GetBoolean(actual),
+ "Expected true");
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_String)
+{
+ char *string = " \"string\"";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = parcJSONValue_Parser(parser);
+
+ assertTrue(parcJSONValue_IsString(actual),
+ "Expected parcJSONValue_Parser to return a string JSON value");
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Array)
+{
+ char *string = " [ ]";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *value = parcJSONValue_Parser(parser);
+
+ assertTrue(parcJSONValue_IsArray(value),
+ "Expected parcJSONValue_Parser to return a array JSON value");
+
+ PARCJSONArray *array = parcJSONValue_GetArray(value);
+ assertNotNull(array, "Expected a non-null pointer to a PARCJSONArray");
+
+ parcJSONValue_Release(&value);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(JSONValueParsing, parcJSONValue_Parser_Object)
+{
+ char *string = " { }";
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ PARCJSONValue *actual = parcJSONValue_Parser(parser);
+
+ assertTrue(parcJSONValue_IsJSON(actual),
+ "Expected parcJSONValue_Parser to return a JSON object value");
+
+ parcJSONValue_Release(&actual);
+ parcJSONParser_Release(&parser);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_FIXTURE(Static)
+{
+ LONGBOW_RUN_TEST_CASE(Static, _parseSign_Negative);
+ LONGBOW_RUN_TEST_CASE(Static, _parseSign_NotASign);
+ LONGBOW_RUN_TEST_CASE(Static, _parseSign_Nil);
+
+ LONGBOW_RUN_TEST_CASE(Static, _parseWholeNumber);
+ LONGBOW_RUN_TEST_CASE(Static, _parseOptionalFraction);
+ LONGBOW_RUN_TEST_CASE(Static, _parseOptionalExponent);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Static, _parseSign_Negative)
+{
+ char *string = "-";
+
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+ int sign;
+ bool result = _parseSign(parser, &sign);
+
+ assertTrue(result, "Expected true from _parseSign()");
+
+ parcJSONParser_Release(&parser);
+}
+
+LONGBOW_TEST_CASE(Static, _parseSign_NotASign)
+{
+ char *string = "asd";
+
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+ int sign;
+ bool result = _parseSign(parser, &sign);
+
+ assertFalse(result, "Expected true from _parseSign()");
+
+ parcJSONParser_Release(&parser);
+}
+
+LONGBOW_TEST_CASE(Static, _parseSign_Nil)
+{
+ char *string = "";
+
+ PARCBuffer *buffer = parcBuffer_WrapCString(string);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+ int sign;
+ bool result = _parseSign(parser, &sign);
+
+ assertTrue(result, "Expected true from _parseSign()");
+
+ parcJSONParser_Release(&parser);
+}
+
+LONGBOW_TEST_CASE(Static, _parseWholeNumber)
+{
+ struct test_values {
+ char *string;
+ long double value;
+ } successful[] = {
+ { "0", 0 },
+ { "1", 1 },
+ { "123", 123 },
+ { NULL },
+ };
+
+ for (int i = 0; successful[i].string != NULL; i++) {
+ PARCBuffer *buffer = parcBuffer_WrapCString(successful[i].string);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ int64_t value = 0;
+
+ bool actual = _parseWholeNumber(parser, &value);
+
+ assertTrue(actual, "Expected true from _parseNumber()");
+ assertTrue(value == successful[i].value,
+ "Expected %Lf actual %" PRIi64 "", successful[i].value, value);
+ parcJSONParser_Release(&parser);
+ }
+}
+
+LONGBOW_TEST_CASE(Static, _parseOptionalFraction)
+{
+ struct test_values {
+ char *string;
+ long double value;
+ bool correct;
+ } successful[] = {
+ { ".0", 0, true },
+ { ".", 0, false },
+ { ".1", 1, true },
+ { "crap", 0, false },
+ { "}", 0, true },
+ { NULL },
+ };
+
+ for (int i = 0; successful[i].string != NULL; i++) {
+ PARCBuffer *buffer = parcBuffer_WrapCString(successful[i].string);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ int64_t value = 0;
+ int log10OfFraction;
+
+ bool actual = _parseOptionalFraction(parser, &value, &log10OfFraction);
+
+ assertTrue(actual == successful[i].correct, "Expected true from _parseNumber()");
+ assertTrue(value == successful[i].value,
+ "Expected %Lf actual %" PRIi64 "", successful[i].value, value);
+ parcJSONParser_Release(&parser);
+ }
+}
+
+LONGBOW_TEST_CASE(Static, _parseOptionalExponent)
+{
+ struct test_values {
+ char *string;
+ long double value;
+ bool correct;
+ } successful[] = {
+ { "e", 0, false },
+ { "ex", 0, false },
+ { "e-1", -1, true },
+ { "e1", 1, true },
+ { "e+1", 1, true },
+ { "x", 0, false },
+ { NULL },
+ };
+
+ for (int i = 0; successful[i].string != NULL; i++) {
+ PARCBuffer *buffer = parcBuffer_WrapCString(successful[i].string);
+ PARCJSONParser *parser = parcJSONParser_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ int64_t value = 0;
+
+ bool actual = _parseOptionalExponent(parser, &value);
+
+ assertTrue(actual == successful[i].correct, "Expected true from _parseNumber()");
+ assertTrue(value == successful[i].value,
+ "Expected %Lf actual %" PRIi64 "", successful[i].value, value);
+ parcJSONParser_Release(&parser);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_JSONValue);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_KeyValue.c b/libparc/parc/algol/test/test_parc_KeyValue.c
new file mode 100755
index 00000000..f9440602
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_KeyValue.c
@@ -0,0 +1,386 @@
+/*
+ * 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 <LongBow/unit-test.h>
+
+#include <stdio.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_KeyValue.c"
+
+
+LONGBOW_TEST_RUNNER(parc_KeyValue)
+{
+ // 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(PARCKeyValueAsPARCObject);
+ 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_KeyValue)
+{
+ 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_KeyValue)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_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_FIXTURE(PARCKeyValueAsPARCObject)
+{
+ LONGBOW_RUN_TEST_CASE(PARCKeyValueAsPARCObject, parcObject_Conformance);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(PARCKeyValueAsPARCObject)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(PARCKeyValueAsPARCObject)
+{
+ 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(PARCKeyValueAsPARCObject, parcObject_Conformance)
+{
+ PARCBuffer *key = parcBuffer_WrapCString("Key_1");
+ PARCBuffer *value = parcBuffer_WrapCString("Value");
+ PARCKeyValue *inst1 = parcKeyValue_Create(key, value);
+ PARCKeyValue *inst2 = parcKeyValue_Create(key, value);
+ PARCKeyValue *inst3 = parcKeyValue_Create(key, value);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ key = parcBuffer_WrapCString("Key_0");
+ value = parcBuffer_WrapCString("Value");
+ PARCKeyValue *lesser = parcKeyValue_Create(key, value);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ key = parcBuffer_WrapCString("Key_2");
+ value = parcBuffer_WrapCString("Value");
+ PARCKeyValue *greater = parcKeyValue_Create(key, value);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&value);
+
+ parcObjectTesting_AssertObjectConformance(inst1, inst2, inst3, lesser, greater);
+
+ parcKeyValue_Release(&inst1);
+ parcKeyValue_Release(&inst2);
+ parcKeyValue_Release(&inst3);
+ parcKeyValue_Release(&lesser);
+ parcKeyValue_Release(&greater);
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_Create);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_Compare);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_GetKey);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_GetValue);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_EqualKeys);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_SetKey);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyValue_SetValue);
+}
+
+typedef struct {
+ PARCKeyValue *testKV1;
+ PARCKeyValue *testKV2;
+ PARCKeyValue *nullValue;
+ PARCBuffer *key1;
+ PARCBuffer *value1;
+ PARCBuffer *key2;
+ PARCBuffer *value2;
+} TestData;
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ data->key1 = parcBuffer_WrapCString("This is key 1");
+ data->value1 = parcBuffer_WrapCString("This is value 1");
+ data->key2 = parcBuffer_WrapCString("This is key 2");
+ data->value2 = parcBuffer_WrapCString("This is value 2");
+
+ data->testKV1 = parcKeyValue_Create(data->key1, data->value1);
+ data->testKV2 = parcKeyValue_Create(data->key2, data->value2);
+
+ PARCBuffer *nullKey = parcBuffer_WrapCString("NULL KEY");
+ data->nullValue = parcKeyValue_Create(nullKey, NULL);
+ parcBuffer_Release(&nullKey);
+
+ longBowTestCase_SetClipBoardData(testCase, data);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ parcBuffer_Release(&data->key1);
+ parcBuffer_Release(&data->value1);
+ parcBuffer_Release(&data->key2);
+ parcBuffer_Release(&data->value2);
+
+ parcKeyValue_Release(&data->testKV1);
+ parcKeyValue_Release(&data->testKV2);
+ parcKeyValue_Release(&data->nullValue);
+
+ parcMemory_Deallocate((void **) &data);
+
+ 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(Global, parcKeyValue_Create)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ assertNotNull(data->testKV1, "Expect a non-NULL key value");
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyValue_Acquire)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ assertNotNull(data->testKV1, "Expect a non-NULL key value");
+
+ PARCKeyValue *kv = parcKeyValue_Acquire(data->testKV1);
+ parcKeyValue_Release(&kv);
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyValue_GetKey)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ assertTrue(parcBuffer_Equals(parcKeyValue_GetKey(data->testKV1), data->key1),
+ "The key returned is not the key provided");
+
+ assertNotNull(parcKeyValue_GetKey(data->nullValue), "Expect Non-NULL key from NULL value kv");
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyValue_GetValue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ assertTrue(parcBuffer_Equals(parcKeyValue_GetValue(data->testKV1), data->value1),
+ "The key returned is not the key provided");
+
+ assertNull(parcKeyValue_GetValue(data->nullValue), "Expect NULL from GetValue");
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyValue_Equals)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ bool isEqual = parcKeyValue_Equals(data->testKV1, data->testKV2);
+ assertFalse(isEqual, "Expect test key-values to not be equal");
+
+ PARCKeyValue *kv = parcKeyValue_Create(data->key1, data->value2);
+ isEqual = parcKeyValue_Equals(kv, data->testKV1) || parcKeyValue_Equals(kv, data->testKV2);
+ parcKeyValue_Release(&kv);
+ assertFalse(isEqual, "Expect test key-values to not be equal");
+
+ kv = parcKeyValue_Create(data->key1, data->value1);
+ isEqual = parcKeyValue_Equals(kv, data->testKV1) && !parcKeyValue_Equals(kv, data->testKV2);
+ parcKeyValue_Release(&kv);
+
+ assertTrue(isEqual, "Expect test key-values to be equal");
+
+ // NULL values
+ isEqual = parcKeyValue_Equals(data->testKV1, data->nullValue);
+ assertFalse(isEqual, "Expect NULL key-valuet to not be equal");
+
+ kv = parcKeyValue_Copy(data->nullValue);
+ isEqual = parcKeyValue_Equals(kv, data->nullValue);
+ assertTrue(isEqual, "Expect NULL key-valuet to not be equal");
+ parcKeyValue_Release(&kv);
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyValue_Compare)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ assertTrue(parcKeyValue_Compare(NULL, NULL) == 0, "Expect 0 from comparing NULLs");
+ assertTrue(parcKeyValue_Compare(data->testKV1, NULL) > 0, "Expect result > 0 from comparing non-NULL to NULL");
+ assertTrue(parcKeyValue_Compare(NULL, data->testKV1) < 0, "Expect result < 0 from comparing NULL to non-NULL");
+
+ int result = parcKeyValue_Compare(data->testKV1, data->testKV2);
+ assertTrue(result < 0, "Expect compareison to be < 0");
+
+ result = parcKeyValue_Compare(data->testKV2, data->testKV1);
+ assertTrue(result > 0, "Expect compareison to be > 0");
+
+ // Mixed keys & values
+ PARCKeyValue *kv = parcKeyValue_Create(data->key1, data->value2);
+ result = parcKeyValue_Compare(kv, data->testKV1);
+ assertTrue(result == 0, "Expect comparison to be 0");
+
+ result = parcKeyValue_Compare(kv, data->testKV2);
+ assertTrue(result < 0, "Expect comparison to be < 0");
+
+ parcKeyValue_Release(&kv);
+
+ // NULL value
+ result = parcKeyValue_Compare(data->testKV1, data->nullValue);
+ assertTrue(result > 0, "Expect NULL key-value be > 0");
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyValue_HashCode)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCHashCode hash1 = parcKeyValue_HashCode(data->testKV1);
+ PARCHashCode hash2 = parcKeyValue_HashCode(data->testKV2);
+ assertFalse(hash1 == hash2, "Expect hash codes to be different");
+
+ PARCKeyValue *kv = parcKeyValue_Create(data->key1, data->value1);
+ hash2 = parcKeyValue_HashCode(kv);
+ assertTrue(hash1 == hash2, "Expect hash codes to be equal");
+ parcKeyValue_Release(&kv);
+
+ // Mixed keys & values
+ kv = parcKeyValue_Create(data->key1, data->value2);
+ hash2 = parcKeyValue_HashCode(kv);
+ assertTrue(hash1 == hash2, "Expect hash codes to be equal");
+ parcKeyValue_Release(&kv);
+
+ // NULL value
+ PARCHashCode hash = parcKeyValue_HashCode(data->nullValue);
+ assertTrue(hash != 0, "Expect NULL key-value hash to != 0");
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyValue_EqualKeys)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ assertFalse(parcKeyValue_EqualKeys(data->testKV1, data->testKV2), "Expect keys to be different");
+
+ PARCKeyValue *kv = parcKeyValue_Create(data->key1, data->value2);
+
+ assertTrue(parcKeyValue_EqualKeys(data->testKV1, kv), "Expect keys to be equal");
+
+ parcKeyValue_Release(&kv);
+
+ // NULL value
+ assertFalse(parcKeyValue_EqualKeys(data->nullValue, data->testKV1), "Expect NULL key-value hash to != 0");
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyValue_SetKey)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ parcKeyValue_SetKey(data->testKV2, data->key1);
+
+ assertTrue(parcKeyValue_EqualKeys(data->testKV1, data->testKV2),
+ "Expect kv keys to be equal after SetKey");
+
+ // NULL value
+ parcKeyValue_SetKey(data->nullValue, data->key1);
+ assertTrue(parcKeyValue_EqualKeys(data->testKV1, data->nullValue),
+ "Expect kv keys to be equal after SetKey");
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyValue_SetValue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ parcKeyValue_SetValue(data->testKV2, data->value1);
+
+ assertTrue(parcBuffer_Equals(parcKeyValue_GetValue(data->testKV1),
+ parcKeyValue_GetValue(data->testKV2)),
+ "Expect kv values to be equal after SetValue");
+
+ // NULL value
+ parcKeyValue_SetValue(data->testKV2, NULL);
+ assertNull(parcKeyValue_GetValue(data->testKV2),
+ "Expect NULL for testKV2 after SetValue");
+
+ parcKeyValue_SetValue(data->nullValue, data->value1);
+ assertTrue(parcBuffer_Equals(parcKeyValue_GetValue(data->testKV1),
+ parcKeyValue_GetValue(data->nullValue)),
+ "Expect kv values to be equal after SetValue");
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyValue_Copy)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCKeyValue *kv = parcKeyValue_Copy(data->testKV1);
+ assertTrue(parcKeyValue_Equals(kv, data->testKV1),
+ "Expect key-value copy to be equal to original key-value");
+
+ parcKeyValue_Release(&kv);
+
+ // NULL value
+ kv = parcKeyValue_Copy(data->nullValue);
+ assertTrue(parcKeyValue_Equals(kv, data->nullValue),
+ "Expect key-value copy to be equal to original key-value");
+
+ parcKeyValue_Release(&kv);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_KeyValue);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_KeyedElement.c b/libparc/parc/algol/test/test_parc_KeyedElement.c
new file mode 100755
index 00000000..a6866437
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_KeyedElement.c
@@ -0,0 +1,134 @@
+/*
+ * 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_KeyedElement.c"
+
+#include <LongBow/unit-test.h>
+#include <stdio.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(parc_KeyedElement)
+{
+ // 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_KeyedElement)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_KeyedElement)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyedElement_CreateDestroy);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyedElement_GetData);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyedElement_GetKey);
+ LONGBOW_RUN_TEST_CASE(Global, parcKeyedElement_SetData);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyedElement_CreateDestroy)
+{
+ char *key1 = "key001";
+ size_t keylen1 = 7;
+ PARCKeyedElement *keyedElement = parcKeyedElement_Create("Some data", key1, keylen1);
+ parcKeyedElement_Destroy(&keyedElement);
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyedElement_GetData)
+{
+ char *initial_data = "some data here";
+ char *key1 = "key001";
+ size_t keylen1 = 7;
+ PARCKeyedElement *keyedElement = parcKeyedElement_Create(initial_data, key1, keylen1);
+ char *data = parcKeyedElement_GetData(keyedElement);
+ assertTrue(initial_data == data, "We got different data from element");
+ parcKeyedElement_Destroy(&keyedElement);
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyedElement_GetKey)
+{
+ char *initial_data = "some data here";
+ char *key1 = "key001";
+ size_t keylen1 = 7;
+ PARCKeyedElement *keyedElement = parcKeyedElement_Create(initial_data, key1, keylen1);
+ char *thekey = parcKeyedElement_GetKey(keyedElement);
+ size_t thekeylen = parcKeyedElement_GetKeyLen(keyedElement);
+ assertTrue(keylen1 == thekeylen, "We got different key size?");
+ assertTrue(memcmp(key1, thekey, keylen1) == 0, "We got different keys?");
+ parcKeyedElement_Destroy(&keyedElement);
+}
+
+LONGBOW_TEST_CASE(Global, parcKeyedElement_SetData)
+{
+ char *key1 = "key001";
+ size_t keylen1 = 7;
+ char *initial_data = "some data here";
+
+ PARCKeyedElement *keyedElement = parcKeyedElement_Create("Hello World", key1, keylen1);
+
+ parcKeyedElement_SetData(keyedElement, initial_data);
+ char *data = parcKeyedElement_GetData(keyedElement);
+ assertTrue(initial_data == data, "We got different data from element");
+ parcKeyedElement_Destroy(&keyedElement);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_KeyedElement);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_LinkedList.c b/libparc/parc/algol/test/test_parc_LinkedList.c
new file mode 100644
index 00000000..294f2ea2
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_LinkedList.c
@@ -0,0 +1,1192 @@
+/*
+ * 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_LinkedList.c"
+
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_StdlibMemory.h>
+
+#include <parc/testing/parc_ObjectTesting.h>
+#include <parc/testing/parc_MemoryTesting.h>
+
+LONGBOW_TEST_RUNNER(PARCLinkedList)
+{
+ // 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);
+ LONGBOW_RUN_TEST_FIXTURE(AcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(PARCLinkedList)
+{
+ 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(PARCLinkedList)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(AcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcLinkedList_CreateRelease);
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcLinkedList_AcquireRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(AcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(AcquireRelease)
+{
+ bool leaked = parcMemoryTesting_ExpectedOutstanding(0, "%s leaks memory \n", longBowTestCase_GetName(testCase)) != true;
+ if (leaked) {
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcLinkedList_CreateRelease)
+{
+ PARCLinkedList *deque = parcLinkedList_Create();
+ assertNotNull(deque, "Expected non-null result from parcLinkedList_Create()");
+
+ assertTrue(parcLinkedList_IsValid(deque), "Expected created PARCLinkedList to be valid.");
+
+ parcLinkedList_Release(&deque);
+ assertNull(deque, "Expected parcLinkedList_Release to null the pointer");
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcLinkedList_AcquireRelease)
+{
+ PARCLinkedList *original = parcLinkedList_Create();
+ assertNotNull(original, "Expected non-null result from parcLinkedList_Create()");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcLinkedList_Acquire, original);
+
+ PARCLinkedList *reference = parcLinkedList_Acquire(original);
+ assertTrue(original == reference, "Expected the reference to be equal to the original.");
+
+ parcLinkedList_Release(&original);
+ assertNull(original, "Expected parcLinkedList_Release to null the pointer");
+
+ PARCBuffer *object = parcBuffer_Allocate(11);
+ parcLinkedList_Append(reference, object);
+ parcBuffer_Release(&object);
+
+ size_t expected = 1;
+ size_t actual = parcLinkedList_Size(reference);
+ assertTrue(expected == actual,
+ "Expected size %zd, actual %zd", expected, actual);
+ parcLinkedList_Release(&reference);
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_AssertValid);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Append_One);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Append_Two);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_AppendAll);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_AppendAll_None);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_CreateDestroy);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_GetFirst);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_GetLast);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_SetAtIndex);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Prepend_One);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Prepend_Two);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Prepend_Three);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_IsEmpty);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_GetAtIndex);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Contains_True);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Contains_False);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_RemoveFirst);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_RemoveFirst_SingleElement);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_RemoveLast);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Remove);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_RemoveNotFound);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_RemoveAtIndex);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Size);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_InsertAtIndex_Head);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_InsertAtIndex_HeadEmptyList);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_InsertAtIndex_Tail);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_InsertAtIndex_Middle);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Display);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_Display_NULL);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_CreateIterator);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_CreateIterator_Remove);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_CreateIterator_RemoveHead);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_CreateIterator_RemoveMiddle);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_CreateIterator_RemoveTail);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_SetEquals_True);
+ LONGBOW_RUN_TEST_CASE(Global, parcLinkedList_SetEquals_False);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ bool leaked = parcMemoryTesting_ExpectedOutstanding(0, "%s leaks memory \n", longBowTestCase_GetName(testCase)) != true;
+ if (leaked) {
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_AssertValid)
+{
+ PARCLinkedList *list = parcLinkedList_Create();
+
+ parcLinkedList_AssertValid(list);
+ parcLinkedList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Append_One)
+{
+ PARCLinkedList *list = parcLinkedList_Create();
+
+ PARCBuffer *object = parcBuffer_Allocate(11);
+ PARCLinkedList *actual = parcLinkedList_Append(list, object);
+ parcBuffer_Release(&object);
+
+ assertTrue(parcLinkedList_IsValid(list), "PARCLinkedList is invalid.");
+
+ assertTrue(list == actual, "Expected parcLinkedList_Append to return its argument.");
+ assertTrue(parcLinkedList_Size(list) == 1, "Expected size of 1, actual %zd", parcLinkedList_Size(list));
+
+ parcLinkedList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Append_Two)
+{
+ PARCLinkedList *deque = parcLinkedList_Create();
+
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+
+ parcLinkedList_Append(deque, object1);
+ PARCLinkedList *actual = parcLinkedList_Append(deque, object2);
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+
+ assertTrue(deque == actual, "Expected parcLinkedList_Append to return its argument.");
+ assertTrue(parcLinkedList_Size(deque) == 2, "Expected size of 2, actual %zd", parcLinkedList_Size(deque));
+
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_AppendAll)
+{
+ PARCLinkedList *other = parcLinkedList_Create();
+
+ for (int i = 0; i < 1000; i++) {
+ PARCBuffer *buffer = parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), i);
+ parcLinkedList_Append(other, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ PARCLinkedList *list = parcLinkedList_Create();
+
+ parcLinkedList_AppendAll(list, other);
+
+ assertTrue(parcLinkedList_Equals(list, other), "Expected equal lists.");
+
+ parcLinkedList_Release(&list);
+ parcLinkedList_Release(&other);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_AppendAll_None)
+{
+ PARCLinkedList *other = parcLinkedList_Create();
+
+ PARCLinkedList *list = parcLinkedList_Create();
+
+ parcLinkedList_AppendAll(list, other);
+
+ assertTrue(parcLinkedList_Equals(list, other), "Expected equal lists.");
+
+ parcLinkedList_Release(&list);
+ parcLinkedList_Release(&other);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_CreateDestroy)
+{
+ PARCLinkedList *deque = parcLinkedList_Create();
+ assertNotNull(deque, "Expected non-null result from parcLinkedList_Create()");
+
+ parcLinkedList_Release(&deque);
+ assertNull(deque, "Expected parcLinkedList_Destroy to null the pointer");
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_HashCode)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *deque = parcLinkedList_Create();
+ parcLinkedList_Append(deque, object1);
+ parcLinkedList_Append(deque, object2);
+ parcLinkedList_Append(deque, object3);
+
+ parcLinkedList_HashCode(deque);
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_GetFirst)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *deque = parcLinkedList_Create();
+ parcLinkedList_Append(deque, object1);
+ parcLinkedList_Append(deque, object2);
+ parcLinkedList_Append(deque, object3);
+
+ PARCBuffer *actual = parcLinkedList_GetFirst(deque);
+ assertTrue(parcBuffer_Equals(object1, actual), "Order of objects in the list is wrong.");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_GetLast)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *deque = parcLinkedList_Create();
+ parcLinkedList_Append(deque, object1);
+ parcLinkedList_Append(deque, object2);
+ parcLinkedList_Append(deque, object3);
+
+ PARCBuffer *actual = parcLinkedList_GetLast(deque);
+ assertTrue(parcBuffer_Equals(object3, actual), "Order of objects in the list is wrong.");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Prepend_One)
+{
+ PARCLinkedList *deque = parcLinkedList_Create();
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCLinkedList *actual = parcLinkedList_Prepend(deque, object1);
+ parcBuffer_Release(&object1);
+
+ assertTrue(deque == actual, "Expected parcLinkedList_Append to return its argument.");
+ assertTrue(parcLinkedList_Size(deque) == 1, "Expected size of 1, actual %zd", parcLinkedList_Size(deque));
+ assertTrue(deque->head != NULL, "Expected head to be not null.");
+ assertTrue(deque->head == deque->tail, "Expected head to be equal to the tail.");
+
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Prepend_Two)
+{
+ PARCLinkedList *deque = parcLinkedList_Create();
+
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCLinkedList *actual = parcLinkedList_Prepend(deque, object1);
+ parcLinkedList_Prepend(deque, object1);
+ parcBuffer_Release(&object1);
+
+ assertTrue(deque == actual, "Expected parcLinkedList_Prepend to return its argument.");
+ assertTrue(parcLinkedList_Size(deque) == 2, "Expected size of 2, actual %zd", parcLinkedList_Size(deque));
+
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Prepend_Three)
+{
+ PARCLinkedList *deque = parcLinkedList_Create();
+
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+ parcLinkedList_Prepend(deque, object1);
+ parcLinkedList_Prepend(deque, object2);
+ PARCLinkedList *actual = parcLinkedList_Prepend(deque, object3);
+
+ assertTrue(deque == actual, "Expected parcLinkedList_Prepend to return its argument.");
+ assertTrue(parcLinkedList_Size(deque) == 3, "Expected size of 3, actual %zd", parcLinkedList_Size(deque));
+
+ PARCBuffer *peek = parcLinkedList_GetFirst(deque);
+ assertTrue(parcBuffer_Equals(object3, peek), "Order of objects failed");
+
+ peek = parcLinkedList_GetLast(deque);
+ assertTrue(parcBuffer_Equals(object1, peek), "Order of objects failed");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_RemoveFirst)
+{
+ PARCLinkedList *list = parcLinkedList_Create();
+
+ for (int i = 0; i < 1000; i++) {
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), i));
+ parcLinkedList_Append(list, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ PARCBuffer *peek = parcLinkedList_RemoveFirst(list);
+ assertTrue(parcObject_GetReferenceCount(peek) == 1, "Expected reference count to be 1.");
+ assertTrue(parcBuffer_GetUint32(peek) == 0, "Objects out of order.");
+
+ parcBuffer_Release(&peek);
+ parcLinkedList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_RemoveFirst_SingleElement)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCLinkedList *deque = parcLinkedList_Create();
+ parcLinkedList_Prepend(deque, object1);
+
+ PARCBuffer *peek = parcLinkedList_RemoveFirst(deque);
+ assertTrue(parcBuffer_Equals(object1, peek),
+ "Objects out of order.");
+
+ parcBuffer_Release(&peek);
+ parcBuffer_Release(&object1);
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_RemoveLast)
+{
+ PARCLinkedList *list = parcLinkedList_Create();
+
+ for (int i = 0; i < 1000; i++) {
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), i));
+ parcLinkedList_Append(list, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ PARCBuffer *peek = parcLinkedList_RemoveLast(list);
+ assertTrue(parcObject_GetReferenceCount(peek) == 1, "Expected reference count to be 1.");
+ assertTrue(parcBuffer_GetUint32(peek) == 999, "Objects out of order.");
+
+ parcBuffer_Release(&peek);
+ parcLinkedList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_RemoveLast_SingleElement)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+
+ PARCLinkedList *deque = parcLinkedList_Create();
+ parcLinkedList_Prepend(deque, object1);
+
+ PARCBuffer *peek = parcLinkedList_RemoveLast(deque);
+ assertTrue(parcBuffer_Equals(object1, peek),
+ "Objects out of order.");
+
+ parcBuffer_Release(&object1);
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Remove)
+{
+ PARCLinkedList *deque = parcLinkedList_Create();
+
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ parcLinkedList_Prepend(deque, object3);
+ parcLinkedList_Prepend(deque, object2);
+ parcLinkedList_Prepend(deque, object1);
+
+ bool found = parcLinkedList_Remove(deque, object2);
+ assertTrue(found, "Expected item to be found");
+ assertTrue(parcLinkedList_Size(deque) == 2, "Expected size of 2, actual %zd", parcLinkedList_Size(deque));
+
+ PARCBuffer *peek;
+ peek = parcLinkedList_RemoveFirst(deque);
+ assertTrue(parcBuffer_Equals(object1, peek), "Object1 was not first in list");
+ parcBuffer_Release(&peek);
+
+ peek = parcLinkedList_RemoveFirst(deque);
+ assertTrue(parcBuffer_Equals(object3, peek), "Object3 was not second in list");
+ parcBuffer_Release(&peek);
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_RemoveAtIndex)
+{
+ PARCLinkedList *list = parcLinkedList_Create();
+
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ parcLinkedList_Prepend(list, object3);
+ parcLinkedList_Prepend(list, object2);
+ parcLinkedList_Prepend(list, object1);
+
+ PARCBuffer *actual = parcLinkedList_RemoveAtIndex(list, 1);
+
+ assertTrue(parcBuffer_Equals(object2, actual), "Wrong object returned from parcLinkedList_RemoveAtIndex");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcBuffer_Release(&actual);
+ parcLinkedList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_RemoveNotFound)
+{
+ PARCLinkedList *deque = parcLinkedList_Create();
+
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+ PARCBuffer *object4 = parcBuffer_WrapCString("4");
+
+ parcLinkedList_Prepend(deque, object3);
+ parcLinkedList_Prepend(deque, object2);
+ parcLinkedList_Prepend(deque, object1);
+
+ bool found = parcLinkedList_Remove(deque, object4);
+ assertFalse(found, "Expected item to be not found");
+ assertTrue(parcLinkedList_Size(deque) == 3, "Expected size of 3, actual %zd", parcLinkedList_Size(deque));
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcBuffer_Release(&object4);
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Size)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *deque = parcLinkedList_Create();
+ parcLinkedList_Prepend(deque, object1);
+ parcLinkedList_Prepend(deque, object2);
+ parcLinkedList_Prepend(deque, object3);
+
+ assertTrue(parcLinkedList_Size(deque) == 3,
+ "Expected 3, actual %zd", parcLinkedList_Size(deque));
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_IsEmpty)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+
+ PARCLinkedList *deque = parcLinkedList_Create();
+
+ assertTrue(parcLinkedList_IsEmpty(deque), "Expected true.");
+ parcLinkedList_Prepend(deque, object1);
+ assertFalse(parcLinkedList_IsEmpty(deque), "Expected false.");
+
+ parcBuffer_Release(&object1);
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_GetAtIndex)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *deque = parcLinkedList_Create();
+ parcLinkedList_Append(deque, object1);
+ parcLinkedList_Append(deque, object2);
+ parcLinkedList_Append(deque, object3);
+
+ PARCBuffer *actual;
+ actual = parcLinkedList_GetAtIndex(deque, 0);
+ assertTrue(parcBuffer_Equals(actual, object1), "parcLinkedList_GetAtIndex failed");
+ actual = parcLinkedList_GetAtIndex(deque, 1);
+ assertTrue(parcBuffer_Equals(actual, object2), "parcLinkedList_GetAtIndex failed");
+ actual = parcLinkedList_GetAtIndex(deque, 2);
+ assertTrue(parcBuffer_Equals(actual, object3), "parcLinkedList_GetAtIndex failed");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_SetAtIndex)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *deque = parcLinkedList_Create();
+ parcLinkedList_Append(deque, object1);
+ parcLinkedList_Append(deque, object2);
+ parcLinkedList_Append(deque, object3);
+
+ PARCBuffer *newObject = parcBuffer_WrapCString("Hello");
+
+ PARCBuffer *actual = parcLinkedList_SetAtIndex(deque, 0, newObject);
+ assertTrue(parcBuffer_Equals(actual, object1), "parcLinkedList_SetAtIndex failed to return the old value.");
+ parcBuffer_Release(&actual);
+
+ actual = parcLinkedList_GetAtIndex(deque, 0);
+ assertTrue(parcBuffer_Equals(actual, newObject), "parcLinkedList_SetAtIndex failed to set the new value.");
+
+ parcBuffer_Release(&newObject);
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcLinkedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Contains_True)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *list = parcLinkedList_Create();
+ parcLinkedList_Append(list, object1);
+ parcLinkedList_Append(list, object2);
+ parcLinkedList_Append(list, object3);
+
+ bool actual = parcLinkedList_Contains(list, object2);
+ assertTrue(actual, "Expected parcLinkedList_Contains to return true for object in the list");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcLinkedList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Contains_False)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *list = parcLinkedList_Create();
+ parcLinkedList_Append(list, object1);
+ parcLinkedList_Append(list, object3);
+
+ bool actual = parcLinkedList_Contains(list, object2);
+ assertFalse(actual, "Expected parcLinkedList_Contains to return false for object not in the list");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcLinkedList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Equals)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *x = parcLinkedList_Create();
+ parcLinkedList_Append(x, object1);
+ parcLinkedList_Append(x, object2);
+ PARCLinkedList *y = parcLinkedList_Create();
+ parcLinkedList_Append(y, object1);
+ parcLinkedList_Append(y, object2);
+ PARCLinkedList *z = parcLinkedList_Create();
+ parcLinkedList_Append(z, object1);
+ parcLinkedList_Append(z, object2);
+ PARCLinkedList *u1 = parcLinkedList_Create();
+ parcLinkedList_Append(u1, object2);
+ PARCLinkedList *u2 = parcLinkedList_Create();
+ parcLinkedList_Append(u2, object2);
+ parcLinkedList_Append(u2, object3);
+
+ parcObjectTesting_AssertEqualsFunction(parcLinkedList_Equals, x, y, z, u1, u2, NULL);
+
+ parcLinkedList_Release(&x);
+ parcLinkedList_Release(&y);
+ parcLinkedList_Release(&z);
+ parcLinkedList_Release(&u1);
+ parcLinkedList_Release(&u2);
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Copy)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+ parcLinkedList_Append(x, object1);
+ parcLinkedList_Append(x, object2);
+ parcLinkedList_Append(x, object3);
+
+ PARCLinkedList *y = parcLinkedList_Copy(x);
+
+ assertTrue(parcLinkedList_Equals(x, y), "Expected the copy to be equal to the original.");
+
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+
+ parcLinkedList_Release(&y);
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_InsertAtIndex_Head)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+ PARCBuffer *object4 = parcBuffer_WrapCString("4");
+ parcLinkedList_Append(x, object1);
+ parcLinkedList_Append(x, object2);
+ parcLinkedList_Append(x, object3);
+
+ parcLinkedList_InsertAtIndex(x, 0, object4);
+
+ PARCBuffer *actual = parcLinkedList_GetAtIndex(x, 0);
+
+ assertTrue(actual == object4, "Unexpected object at index 0");
+
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcBuffer_Release(&object4);
+
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_InsertAtIndex_HeadEmptyList)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+ PARCBuffer *object4 = parcBuffer_WrapCString("4");
+
+ parcLinkedList_InsertAtIndex(x, 0, object4);
+ assertTrue(x->head->object == object4, "Malformed linked list node does not contain the proper object reference");
+ assertTrue(x->head == x->tail, "Expected the list head and tail to be the same for a single element list.");
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+
+ PARCBuffer *actual = parcLinkedList_GetAtIndex(x, 0);
+
+ assertTrue(actual == object4, "Unexpected object at index 0");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcBuffer_Release(&object4);
+
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_InsertAtIndex_Tail)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+ PARCBuffer *object4 = parcBuffer_WrapCString("4");
+ parcLinkedList_Append(x, object1);
+ parcLinkedList_Append(x, object2);
+ parcLinkedList_Append(x, object3);
+
+ parcLinkedList_InsertAtIndex(x, 3, object4);
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+
+ PARCBuffer *actual = parcLinkedList_GetAtIndex(x, 3);
+
+ assertTrue(actual == object4, "Unexpected object at index 3");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcBuffer_Release(&object4);
+
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_InsertAtIndex_Middle)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+ PARCBuffer *object4 = parcBuffer_WrapCString("4");
+ parcLinkedList_Append(x, object1);
+ parcLinkedList_Append(x, object2);
+ parcLinkedList_Append(x, object3);
+
+ parcLinkedList_InsertAtIndex(x, 1, object4);
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+
+ assertTrue(parcLinkedList_GetAtIndex(x, 0) == object1, "Unexpected object at index 1");
+ assertTrue(parcLinkedList_GetAtIndex(x, 1) == object4, "Unexpected object at index 1");
+ assertTrue(parcLinkedList_GetAtIndex(x, 2) == object2, "Unexpected object at index 1");
+ assertTrue(parcLinkedList_GetAtIndex(x, 3) == object3, "Unexpected object at index 1");
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcBuffer_Release(&object4);
+
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Display)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+ parcLinkedList_Append(x, object1);
+ parcLinkedList_Append(x, object2);
+ parcLinkedList_Append(x, object3);
+
+ parcLinkedList_Display(x, 0);
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_Display_NULL)
+{
+ parcLinkedList_Display(NULL, 0);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_CreateIterator)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+
+ uint32_t expectedCount = 10;
+ for (uint32_t i = 0; i < expectedCount; i++) {
+ PARCBuffer *object = parcBuffer_Allocate(sizeof(int));
+ parcBuffer_PutUint32(object, i);
+ parcBuffer_Flip(object);
+ parcLinkedList_Append(x, object);
+ parcBuffer_Release(&object);
+ }
+
+ PARCIterator *iterator = parcLinkedList_CreateIterator(x);
+ uint32_t expected = 0;
+ while (parcIterator_HasNext(iterator)) {
+ PARCBuffer *buffer = (PARCBuffer *) parcIterator_Next(iterator);
+ uint32_t actual = parcBuffer_GetUint32(buffer);
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+ expected++;
+ }
+ parcIterator_Release(&iterator);
+
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_CreateIterator_Remove)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+ for (size_t i = 0; i < 5; i++) {
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutUint64(buffer, i);
+ parcBuffer_Flip(buffer);
+ parcLinkedList_Append(x, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+
+ PARCIterator *iterator = parcLinkedList_CreateIterator(x);
+ size_t expected = 0;
+ while (parcIterator_HasNext(iterator)) {
+ size_t actual = parcBuffer_GetUint64(parcIterator_Next(iterator));
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+ parcIterator_Remove(iterator);
+ expected++;
+ }
+ parcIterator_Release(&iterator);
+
+ iterator = parcLinkedList_CreateIterator(x);
+ assertFalse(parcIterator_HasNext(iterator), "Expected an interator on an empty list to not HaveNext");
+ parcIterator_Release(&iterator);
+
+ assertTrue(parcLinkedList_Size(x) == 0, "List is not empty.");
+
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_CreateIterator_RemoveHead)
+{
+ size_t listSize = 5;
+
+ PARCLinkedList *x = parcLinkedList_Create();
+ for (size_t i = 0; i < listSize; i++) {
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutUint64(buffer, i);
+ parcBuffer_Flip(buffer);
+ parcLinkedList_Append(x, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+ parcLinkedList_Display(x, 0);
+
+ PARCIterator *iterator = parcLinkedList_CreateIterator(x);
+ if (parcIterator_HasNext(iterator)) {
+ PARCBuffer *buffer = (PARCBuffer *) parcIterator_Next(iterator);
+ size_t actual = parcBuffer_GetUint64(buffer);
+ assertTrue(actual == 0, "Expected %d, actual %zd", 0, actual);
+ parcIterator_Remove(iterator);
+ }
+ parcIterator_Release(&iterator);
+
+ iterator = parcLinkedList_CreateIterator(x);
+ assertTrue(parcIterator_HasNext(iterator), "Expected an interator on a non-empty list to HaveNext");
+ parcIterator_Release(&iterator);
+
+ assertTrue(parcLinkedList_Size(x) == listSize - 1, "Expected the list to be %zd, actual %zd", listSize - 1, parcLinkedList_Size(x));
+
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_CreateIterator_RemoveMiddle)
+{
+ size_t listSize = 5;
+
+ PARCLinkedList *x = parcLinkedList_Create();
+ for (size_t i = 0; i < listSize; i++) {
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutUint64(buffer, i);
+ parcBuffer_Flip(buffer);
+ parcLinkedList_Append(x, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+ assertTrue(parcLinkedList_Size(x) == listSize, "Expected the list to be %zd, actual %zd", listSize, parcLinkedList_Size(x));
+
+
+ PARCIterator *iterator = parcLinkedList_CreateIterator(x);
+ for (size_t i = 0; i <= listSize / 2; i++) {
+ if (parcIterator_HasNext(iterator)) {
+ parcIterator_Next(iterator);
+ }
+ }
+ parcIterator_Remove(iterator);
+
+ parcIterator_Release(&iterator);
+
+
+ iterator = parcLinkedList_CreateIterator(x);
+ size_t expected = 0;
+ while (parcIterator_HasNext(iterator)) {
+ if (expected != (listSize / 2)) {
+ size_t actual = parcBuffer_GetUint64(parcIterator_Next(iterator));
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+ }
+ expected++;
+ }
+ parcIterator_Release(&iterator);
+
+ assertTrue(parcLinkedList_Size(x) == listSize - 1, "Expected the list to be %zd, actual %zd", listSize - 1, parcLinkedList_Size(x));
+
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_CreateIterator_RemoveTail)
+{
+ size_t listSize = 5;
+
+ PARCLinkedList *x = parcLinkedList_Create();
+ for (size_t i = 0; i < listSize; i++) {
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ parcBuffer_PutUint64(buffer, i);
+ parcBuffer_Flip(buffer);
+ parcLinkedList_Append(x, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+ assertTrue(parcLinkedList_Size(x) == listSize, "Expected the list to be %zd, actual %zd", listSize, parcLinkedList_Size(x));
+
+ PARCIterator *iterator = parcLinkedList_CreateIterator(x);
+ for (size_t i = 0; i < listSize; i++) {
+ if (parcIterator_HasNext(iterator)) {
+ parcIterator_Next(iterator);
+ }
+ }
+ parcIterator_Remove(iterator);
+
+ parcIterator_Release(&iterator);
+
+ assertTrue(parcLinkedList_Size(x) == listSize - 1, "Expected the list to be %zd, actual %zd", listSize - 1, parcLinkedList_Size(x));
+
+
+ iterator = parcLinkedList_CreateIterator(x);
+ size_t expected = 0;
+ while (parcIterator_HasNext(iterator)) {
+ size_t actual = parcBuffer_GetUint64(parcIterator_Next(iterator));
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+ expected++;
+ }
+ parcIterator_Release(&iterator);
+
+ assertTrue(parcLinkedList_IsValid(x), "PARCLinkedList is invalid.");
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_SetEquals_True)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *x = parcLinkedList_Create();
+ parcLinkedList_Append(x, object1);
+ parcLinkedList_Append(x, object2);
+ PARCLinkedList *y = parcLinkedList_Create();
+ parcLinkedList_Append(y, object2);
+ parcLinkedList_Append(y, object1);
+
+ PARCLinkedList *u1 = parcLinkedList_Create();
+ parcLinkedList_Append(u1, object2);
+
+ PARCLinkedList *u2 = parcLinkedList_Create();
+ parcLinkedList_Append(u2, object2);
+ parcLinkedList_Append(u2, object3);
+
+ assertTrue(parcLinkedList_SetEquals(x, y), "Expected to lists with the same elements to be equal regarless of order.");
+
+ parcLinkedList_Release(&x);
+ parcLinkedList_Release(&y);
+ parcLinkedList_Release(&u1);
+ parcLinkedList_Release(&u2);
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+}
+
+LONGBOW_TEST_CASE(Global, parcLinkedList_SetEquals_False)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCLinkedList *x = parcLinkedList_Create();
+ parcLinkedList_Append(x, object1);
+ parcLinkedList_Append(x, object2);
+
+ PARCLinkedList *u1 = parcLinkedList_Create();
+ parcLinkedList_Append(u1, object2);
+
+ PARCLinkedList *u2 = parcLinkedList_Create();
+ parcLinkedList_Append(u2, object2);
+ parcLinkedList_Append(u2, object3);
+
+ assertFalse(parcLinkedList_SetEquals(x, u1), "Expected to lists without the same elements to be equal regarless of order.");
+
+ parcLinkedList_Release(&x);
+ parcLinkedList_Release(&u1);
+ parcLinkedList_Release(&u2);
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _parcLinkedListNode_Create);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ bool leaked = parcMemoryTesting_ExpectedOutstanding(0, "%s leaks memory \n", longBowTestCase_GetName(testCase)) != true;
+ if (leaked) {
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Local, _parcLinkedListNode_Create)
+{
+ PARCBuffer *object = parcBuffer_Allocate(10);
+ struct parc_linkedlist_node *previous = NULL;
+ struct parc_linkedlist_node *next = NULL;
+
+ struct parc_linkedlist_node *actual = _parcLinkedListNode_Create(object, previous, next);
+ parcBuffer_Release(&object);
+ _parcLinkedListNode_Destroy(NULL, &actual);
+}
+
+LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, parcLinkedList_Append);
+ LONGBOW_RUN_TEST_CASE(Performance, parcLinkedList_N2);
+ LONGBOW_RUN_TEST_CASE(Performance, parcLinkedList_CreateIterator);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ parcMemory_SetInterface(&PARCStdlibMemoryAsPARCMemory);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Performance, parcLinkedList_Append)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+
+ for (size_t i = 0; i < 100000; i++) {
+ parcLinkedList_Append(x, object1);
+ }
+
+ parcBuffer_Release(&object1);
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Performance, parcLinkedList_N2)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+
+ for (size_t i = 0; i < 100000; i++) {
+ parcLinkedList_Append(x, object1);
+ }
+
+ for (size_t expected = 0; expected < parcLinkedList_Size(x); expected++) {
+ PARCBuffer *actual = (PARCBuffer *) parcLinkedList_GetAtIndex(x, expected);
+ assertTrue(parcBuffer_Equals(object1, actual), "Mismatched value in the list.");
+ }
+
+ parcBuffer_Release(&object1);
+
+ parcLinkedList_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Performance, parcLinkedList_CreateIterator)
+{
+ PARCLinkedList *x = parcLinkedList_Create();
+
+ uint32_t expectedCount = 100000;
+ for (uint32_t i = 0; i < expectedCount; i++) {
+ PARCBuffer *object = parcBuffer_Allocate(sizeof(int));
+ parcBuffer_PutUint32(object, i);
+ parcBuffer_Flip(object);
+ parcLinkedList_Append(x, object);
+ parcBuffer_Release(&object);
+ }
+
+ PARCIterator *iterator = parcLinkedList_CreateIterator(x);
+ uint32_t expected = 0;
+ while (parcIterator_HasNext(iterator)) {
+ PARCBuffer *buffer = (PARCBuffer *) parcIterator_Next(iterator);
+ uint32_t actual = parcBuffer_GetUint32(buffer);
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+ expected++;
+ }
+ parcIterator_Release(&iterator);
+
+ parcLinkedList_Release(&x);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(PARCLinkedList);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_List.c b/libparc/parc/algol/test/test_parc_List.c
new file mode 100644
index 00000000..59a7d136
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_List.c
@@ -0,0 +1,872 @@
+/*
+ * 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_List.c"
+#include <LongBow/unit-test.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <parc/testing/parc_MemoryTesting.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <parc/algol/parc_ArrayList.h>
+#include <parc/algol/parc_LinkedList.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(PARCList)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(PARCList);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+// LONGBOW_RUN_TEST_FIXTURE(Errors);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(PARCList)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(PARCList)
+{
+ 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_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_Add);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_AddAll);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcList_Release);
+
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_Equals_Contract);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_Equals_Contract_Deep);
+
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_FromInitialCapacity);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_Get);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_New);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_Length);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_Remove_AtIndex_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_Remove_AtIndex);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_Remove_AtIndex_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_RemoveAndDestroy_AtIndex_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_RemoveAndDestroy_AtIndex);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_RemoveAndDestroy_AtIndex_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_InsertAtIndex);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_InsertAtIndex_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_InsertAtIndex_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_InsertAtIndex_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARCList_IsEmpty);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Global, PARCList_Add)
+{
+ PARCList *list = parcList(parcArrayList_Create(parcArrayList_StdlibFreeFunction), PARCArrayListAsPARCList);
+
+ parcList_Add(list, 0);
+ size_t actual = parcList_Size(list);
+ assertTrue(1 == actual, "Expected=%d, actual=%zu", 1, actual);
+
+ parcList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_AddAll)
+{
+ PARCList *list = parcList(parcArrayList_Create(parcArrayList_StdlibFreeFunction), PARCArrayListAsPARCList);
+
+ void *elements[] = {
+ strdup("a"),
+ strdup("b"),
+ strdup("c"),
+ };
+
+ parcList_AddAll(list, 3, elements);
+ size_t actual = parcList_Size(list);
+
+ assertTrue(3 == actual, "Expected=%d, actual=%zu", 3, actual);
+
+ parcList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_Copy)
+{
+ char *a = strdup("apple");
+ char *b = strdup("bananna");
+ char *c = strdup("cherry");
+
+ PARCList *list = parcList(parcArrayList_Create(parcArrayList_StdlibFreeFunction), PARCArrayListAsPARCList);
+
+ parcList_Add(list, a);
+ parcList_Add(list, b);
+ parcList_Add(list, c);
+
+ parcList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, parcList_Release)
+{
+ PARCList *list = parcList(parcArrayList_Create(parcArrayList_StdlibFreeFunction), PARCArrayListAsPARCList);
+
+ parcList_Release(&list);
+ assertNull(list, "Expected null.");
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_Equals_Empty)
+{
+ PARCArrayList *a = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+ PARCArrayList *b = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+ assertTrue(parcArrayList_Equals(a, b), "Equal values were expected to be equal");
+
+ parcArrayList_Destroy(&a);
+ parcArrayList_Destroy(&b);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_Equals_Same)
+{
+ PARCArrayList *a = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+ assertTrue(parcArrayList_Equals(a, a), "Expected the same array list to be equal to itself.");
+
+ parcArrayList_Destroy(&a);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_Equals_Contract)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+ char d[] = "potato";
+
+ PARCArrayList *x = parcArrayList_Create(NULL);
+ parcArrayList_Add(x, a);
+ parcArrayList_Add(x, b);
+ parcArrayList_Add(x, c);
+
+ PARCArrayList *y = parcArrayList_Create(NULL);
+ parcArrayList_Add(y, a);
+ parcArrayList_Add(y, b);
+ parcArrayList_Add(y, c);
+
+ PARCArrayList *z = parcArrayList_Create(NULL);
+ parcArrayList_Add(z, a);
+ parcArrayList_Add(z, b);
+ parcArrayList_Add(z, c);
+
+ PARCArrayList *u1 = parcArrayList_Create(NULL);
+ parcArrayList_Add(u1, a);
+ parcArrayList_Add(u1, b);
+
+ PARCArrayList *u2 = parcArrayList_Create(NULL);
+ parcArrayList_Add(u1, a);
+ parcArrayList_Add(u2, b);
+ parcArrayList_Add(u2, c);
+ parcArrayList_Add(u2, c);
+
+ PARCArrayList *u3 = parcArrayList_Create(NULL);
+ parcArrayList_Add(u3, a);
+ parcArrayList_Add(u3, b);
+ parcArrayList_Add(u3, d);
+
+ parcObjectTesting_AssertEqualsFunction(parcArrayList_Equals, x, y, z, u1, u2, u3);
+
+ parcArrayList_Destroy(&x);
+ parcArrayList_Destroy(&y);
+ parcArrayList_Destroy(&z);
+ parcArrayList_Destroy(&u1);
+ parcArrayList_Destroy(&u2);
+ parcArrayList_Destroy(&u3);
+}
+
+static bool
+stringEquals(void *x, void *y)
+{
+ return strcmp((char *) x, (char *) y) == 0;
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_Equals_Contract_Deep)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+ char d[] = "potato";
+
+ PARCArrayList *x = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(x, a);
+ parcArrayList_Add(x, b);
+ parcArrayList_Add(x, c);
+
+ PARCArrayList *y = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(y, a);
+ parcArrayList_Add(y, b);
+ parcArrayList_Add(y, c);
+
+ PARCArrayList *z = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(z, a);
+ parcArrayList_Add(z, b);
+ parcArrayList_Add(z, c);
+
+ PARCArrayList *u1 = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(u1, a);
+ parcArrayList_Add(u1, b);
+
+ PARCArrayList *u2 = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(u2, a);
+ parcArrayList_Add(u2, b);
+ parcArrayList_Add(u2, c);
+ parcArrayList_Add(u2, c);
+
+ PARCArrayList *u3 = parcArrayList_Create_Capacity(stringEquals, NULL, 0);
+ parcArrayList_Add(u3, a);
+ parcArrayList_Add(u3, b);
+ parcArrayList_Add(u3, d);
+
+ parcObjectTesting_AssertEqualsFunction(parcArrayList_Equals, x, y, z, u1, u2, u3);
+
+ parcArrayList_Destroy(&x);
+ parcArrayList_Destroy(&y);
+ parcArrayList_Destroy(&z);
+ parcArrayList_Destroy(&u1);
+ parcArrayList_Destroy(&u2);
+ parcArrayList_Destroy(&u3);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_FromInitialCapacity)
+{
+ PARCArrayList *array = parcArrayList_Create_Capacity(NULL, parcArrayList_StdlibFreeFunction, 10);
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(0 == actual, "Expected=%d, actual=%zu", 0, actual);
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_Get)
+{
+ PARCArrayList *array = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+
+ char *expected = strdup("Hello World");
+ parcArrayList_Add(array, expected);
+
+ char *actual = parcArrayList_Get(array, 0);
+
+ assertTrue(expected == actual, "Expected=%p, actual=%p", (void *) expected, (void *) actual);
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_New)
+{
+ PARCArrayList *array = parcArrayList_Create(parcArrayList_StdlibFreeFunction);
+ size_t size = parcArrayList_Size(array);
+ assertTrue(0 == size, "Expected %d actual=%zd", 0, size);
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_Length)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, 0);
+
+ size_t size = parcArrayList_Size(array);
+ assertTrue(1 == size, "Expected %d actual=%zd", 1, size);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_IsEmpty)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ assertTrue(parcArrayList_IsEmpty(array), "Expected a new array to be empty.");
+
+ parcArrayList_Add(array, 0);
+ assertFalse(parcArrayList_IsEmpty(array), "Expected an array with more than zero elements to be empty.");
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_InsertAtIndex)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+
+ parcArrayList_Add(array, (void *) 1);
+ parcArrayList_Add(array, (void *) 2);
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(2 == actual, "Expected=%d, actual=%zu", 2, actual);
+
+ parcArrayList_InsertAtIndex(array, 1, (void *) 3);
+
+ actual = parcArrayList_Size(array);
+ assertTrue(3 == actual, "Expected=%d, actual=%zu", 3, actual);
+
+ void *element0 = parcArrayList_Get(array, 0);
+ assertTrue(element0 == (void *) 1, "Element 1 moved?");
+
+ void *element1 = parcArrayList_Get(array, 1);
+ assertTrue(element1 == (void *) 3, "Element 1 moved?");
+
+ void *element2 = parcArrayList_Get(array, 2);
+ assertTrue(element2 == (void *) 2, "Element 1 moved?");
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_InsertAtIndex_Empty)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+
+ parcArrayList_InsertAtIndex(array, 0, (void *) 3);
+
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(1 == actual, "Expected=%d, actual=%zu", 1, actual);
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_InsertAtIndex_First)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+
+ parcArrayList_Add(array, (void *) 1);
+ parcArrayList_InsertAtIndex(array, 0, (void *) 2);
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(2 == actual, "Expected=%d, actual=%zu", 2, actual);
+
+ void *element0 = parcArrayList_Get(array, 0);
+ assertTrue(element0 == (void *) 2, "Element 1 moved?");
+
+ void *element1 = parcArrayList_Get(array, 1);
+ assertTrue(element1 == (void *) 1, "Element 1 moved?");
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_InsertAtIndex_Last)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+
+ parcArrayList_Add(array, (void *) 1);
+ parcArrayList_Add(array, (void *) 2);
+ size_t actual = parcArrayList_Size(array);
+
+ assertTrue(2 == actual, "Expected=%d, actual=%zu", 2, actual);
+
+ parcArrayList_InsertAtIndex(array, 2, (void *) 3);
+
+ actual = parcArrayList_Size(array);
+ assertTrue(3 == actual, "Expected=%d, actual=%zu", 3, actual);
+
+ void *element0 = parcArrayList_Get(array, 0);
+ assertTrue(element0 == (void *) 1, "Element 1 moved?");
+
+ void *element1 = parcArrayList_Get(array, 1);
+ assertTrue(element1 == (void *) 2, "Element 1 moved?");
+
+ void *element2 = parcArrayList_Get(array, 2);
+ assertTrue(element2 == (void *) 3, "Element 1 moved?");
+
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_Remove_AtIndex_First)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, b);
+ parcArrayList_Add(expected, c);
+
+ void *removedElement = parcArrayList_RemoveAtIndex(array, 0);
+
+ assertTrue(removedElement == a, "Expected ");
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_Remove_AtIndex)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, a);
+ parcArrayList_Add(expected, c);
+
+ void *removedElement = parcArrayList_RemoveAtIndex(array, 1);
+
+ assertTrue(removedElement == b, "Expected ");
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+
+LONGBOW_TEST_CASE(Global, PARCList_Remove_AtIndex_Last)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, a);
+ parcArrayList_Add(expected, b);
+
+ void *removedElement = parcArrayList_RemoveAtIndex(array, 2);
+
+ assertTrue(removedElement == c, "Expected ");
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_RemoveAndDestroy_AtIndex_First)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, b);
+ parcArrayList_Add(expected, c);
+
+ parcArrayList_RemoveAndDestroyAtIndex(array, 0);
+
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_RemoveAndDestroy_AtIndex)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, a);
+ parcArrayList_Add(expected, c);
+
+ parcArrayList_RemoveAndDestroyAtIndex(array, 1);
+
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(Global, PARCList_RemoveAndDestroy_AtIndex_Last)
+{
+ char a[] = "apple";
+ char b[] = "bananna";
+ char c[] = "cherry";
+
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, a);
+ parcArrayList_Add(array, b);
+ parcArrayList_Add(array, c);
+
+ PARCArrayList *expected = parcArrayList_Create(NULL);
+ parcArrayList_Add(expected, a);
+ parcArrayList_Add(expected, b);
+
+ parcArrayList_RemoveAndDestroyAtIndex(array, 2);
+
+ assertTrue(parcArrayList_Equals(expected, array), "Expected ");
+
+ parcArrayList_Destroy(&expected);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Errors)
+{
+ LONGBOW_RUN_TEST_CASE(Errors, PARCList_InsertAtIndex_OutOfCapacity);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Errors)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+
+ longBowTestCase_SetClipBoardData(testCase, array);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Errors)
+{
+ PARCArrayList *array = longBowTestCase_GetClipBoardData(testCase);
+ parcArrayList_Destroy(&array);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Errors %s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, PARCList_InsertAtIndex_OutOfCapacity, .event = &LongBowAssertEvent)
+{
+ PARCArrayList *array = longBowTestCase_GetClipBoardData(testCase);
+
+ parcArrayList_Add(array, (void *) 1);
+ parcArrayList_Add(array, (void *) 2);
+
+ parcArrayList_InsertAtIndex(array, 200, (void *) 3);
+}
+
+
+LONGBOW_TEST_FIXTURE(PARCList)
+{
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_Add);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_AddCollection);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_AddCollectionAtIndex);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_Contains);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_ContainsCollection);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_Equals);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_IsEmpty);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_GetAtIndex);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_Remove);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_RemoveCollection);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_RetainCollection);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_HashCode);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_IndexOf);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_LastIndexOf);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_Copy);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_Clear);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_Destroy);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_RemoveAtIndex);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_SetAtIndex);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_Size);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_SubList);
+ LONGBOW_RUN_TEST_CASE(PARCList, parcList_ToArray);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(PARCList)
+{
+ longBowTestCase_SetInt(testCase, "initialAllocations", parcMemory_Outstanding());
+ longBowTestCase_Set(testCase, "linkedList", parcLinkedList_Create());
+ longBowTestCase_Set(testCase, "list", parcLinkedList_AsPARCList(longBowTestCase_Get(testCase, "linkedList")));
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(PARCList)
+{
+ PARCLinkedList *linkedList = longBowTestCase_Get(testCase, "linkedList");
+ parcLinkedList_Release(&linkedList);
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+ parcList_Release(&list);
+
+ int initialAllocations = longBowTestCase_GetInt(testCase, "initalAllocations");
+ if (!parcMemoryTesting_ExpectedOutstanding(initialAllocations, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+//#include "test_parc_List_modular.c"
+
+LONGBOW_TEST_CASE(PARCList, parcList_Add)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), 1));
+ parcList_Add(list, buffer);
+ parcBuffer_Release(&buffer);
+
+ size_t actual = parcList_Size(list);
+ assertTrue(1 == actual, "Expected=%d, actual=%zu", 1, actual);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_AddCollection)
+{
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_AddCollectionAtIndex)
+{
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_Contains)
+{
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_ContainsCollection)
+{
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_Equals)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+ PARCList *copy = parcList_Copy(list);
+
+ assertTrue(parcList_Equals(list, copy), "Expected copy to be equal to the original.");
+
+ parcList_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_IsEmpty)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+ assertTrue(parcList_IsEmpty(list), "Expected list to be empty.");
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_GetAtIndex)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+
+ for (int i = 0; i < 1000; i++) {
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), i));
+ parcList_Add(list, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ uint32_t actual = parcBuffer_GetUint32(parcList_GetAtIndex(list, 0));
+
+ assertTrue(actual == 0, "Expected %u, actual %u\n", 0, actual);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_Remove)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), 1));
+ parcList_Add(list, buffer);
+ parcBuffer_Release(&buffer);
+
+ buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), 1));
+
+ bool actual = parcList_Remove(list, buffer);
+ assertTrue(actual, "Expected element to have been found and removed.");
+
+ parcBuffer_Release(&buffer);
+
+ buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), 3));
+
+ actual = parcList_Remove(list, buffer);
+ assertFalse(actual, "Expected element to have not been found and removed.");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_RemoveCollection)
+{
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_RetainCollection)
+{
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_HashCode)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+ parcList_HashCode(list);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_IndexOf)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+
+ for (int i = 0; i < 1000; i++) {
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), i));
+ parcList_Add(list, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ uint32_t expected = 10;
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), 10));
+ size_t actual = parcList_IndexOf(list, buffer);
+
+ parcBuffer_Release(&buffer);
+
+ assertTrue(expected == actual, "Expected %u, actual %zu", expected, actual);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_LastIndexOf)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+
+ for (int i = 0; i < 1000; i++) {
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), 1));
+ parcList_Add(list, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ uint32_t expected = 999;
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), 1));
+ size_t actual = parcList_LastIndexOf(list, buffer);
+
+ parcBuffer_Release(&buffer);
+
+ assertTrue(expected == actual, "Expected %u, actual %zu", expected, actual);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_Copy)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+ PARCList *copy = parcList_Copy(list);
+
+ assertTrue(parcList_Equals(list, copy), "Expected copy to be equal to the original.");
+
+ parcList_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_Clear)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+ parcList_Clear(list);
+
+ assertTrue(parcList_IsEmpty(list), "Expected list to be empty.");
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_Destroy)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+ PARCList *copy = parcList_Copy(list);
+
+ parcList_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_RemoveAtIndex)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+
+ for (int i = 0; i < 1000; i++) {
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), i));
+ parcList_Add(list, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ PARCBuffer *buffer = parcList_RemoveAtIndex(list, 0);
+ uint32_t actual = parcBuffer_GetUint32(buffer);
+ assertTrue(actual == 0, "Expected buffer 0.");
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_SetAtIndex)
+{
+ PARCList *list = longBowTestCase_Get(testCase, "list");
+
+ for (int i = 0; i < 1000; i++) {
+ PARCBuffer *buffer = parcBuffer_Flip(parcBuffer_PutUint32(parcBuffer_Allocate(sizeof(int)), i));
+ parcList_Add(list, buffer);
+ parcBuffer_Release(&buffer);
+ }
+
+ PARCBuffer *buffer = parcBuffer_WrapCString("1");
+
+ PARCBuffer *oldValue = parcList_SetAtIndex(list, 50, buffer);
+
+ PARCBuffer *actual = parcList_GetAtIndex(list, 50);
+ assertTrue(parcBuffer_Equals(buffer, actual), "parcList_SetAtIndex set the wrong location.");
+ parcBuffer_Release(&buffer);
+ parcBuffer_Release(&oldValue);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_Size)
+{
+ PARCArrayList *array = parcArrayList_Create(NULL);
+ parcArrayList_Add(array, 0);
+
+ size_t size = parcArrayList_Size(array);
+ assertTrue(1 == size, "Expected %d actual=%zd", 1, size);
+ parcArrayList_Destroy(&array);
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_SubList)
+{
+}
+
+LONGBOW_TEST_CASE(PARCList, parcList_ToArray)
+{
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(PARCList);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Memory.c b/libparc/parc/algol/test/test_parc_Memory.c
new file mode 100755
index 00000000..5fb18ce3
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Memory.c
@@ -0,0 +1,220 @@
+/*
+ * 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 <stdio.h>
+
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.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_Memory.c"
+
+LONGBOW_TEST_RUNNER(parc_Memory)
+{
+ // 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(Static);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Memory)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Memory)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcMemory_RoundUpToMultiple);
+ LONGBOW_RUN_TEST_CASE(Global, parcMemory_RoundUpToCacheLine);
+ LONGBOW_RUN_TEST_CASE(Global, parcMemory_Allocate);
+ LONGBOW_RUN_TEST_CASE(Global, parcMemory_AllocateAndClear);
+ LONGBOW_RUN_TEST_CASE(Global, parcMemory_MemAlign);
+ LONGBOW_RUN_TEST_CASE(Global, parcMemory_Reallocate);
+ LONGBOW_RUN_TEST_CASE(Global, parcMemory_StringDuplicate);
+ LONGBOW_RUN_TEST_CASE(Global, parcMemory_Outstanding);
+ LONGBOW_RUN_TEST_CASE(Global, parcMemory_SetInterface);
+ LONGBOW_RUN_TEST_CASE(Global, parcMemory_Format);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcMemory_RoundUpToMultiple)
+{
+ size_t actual = parcMemory_RoundUpToMultiple(14, 12);
+ assertTrue((actual % 12) == 0, "Expected %zd to be a multiple of %d", actual, 12);
+ assertTrue(24 == actual, "Expected 24, actual %zd", actual);
+
+ actual = parcMemory_RoundUpToMultiple(14, 20);
+ assertTrue((actual % 20) == 0, "Expected %zd to be a multiple of %d", actual, 20);
+ assertTrue(20 == actual, "Expected 20, actual %zd", actual);
+
+ actual = parcMemory_RoundUpToMultiple(20, 20);
+ assertTrue((actual % 20) == 0, "Expected %zd to be a multiple of %d", actual, 20);
+ assertTrue(20 == actual, "Expected 20, actual %zd", actual);
+
+ actual = parcMemory_RoundUpToMultiple(0, 20);
+ assertTrue((actual % 20) == 0, "Expected %zd to be a multiple of %d", actual, 20);
+ assertTrue(20 == actual, "Expected 20, actual %zd", actual);
+
+ actual = parcMemory_RoundUpToMultiple(8, 0);
+ assertTrue(actual == 8, "Expected %d, actual %zd", 8, actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcMemory_RoundUpToCacheLine)
+{
+ size_t actual = parcMemory_RoundUpToCacheLine(LEVEL1_DCACHE_LINESIZE - 1);
+ assertTrue((actual % LEVEL1_DCACHE_LINESIZE) == 0,
+ "Expected %zd to be a multiple of %d", actual, LEVEL1_DCACHE_LINESIZE);
+}
+
+LONGBOW_TEST_CASE(Global, parcMemory_Allocate)
+{
+ void *pointer;
+ pointer = parcMemory_Allocate(sizeof(int));
+ assertNotNull(pointer, "Expected pointer to not be NULL");
+
+ parcMemory_Deallocate(&pointer);
+ assertNull(pointer, "Expected pointer to not be NULL");
+}
+
+LONGBOW_TEST_CASE(Global, parcMemory_MemAlign)
+{
+ void *pointer;
+ int actual = parcMemory_MemAlign(&pointer, sizeof(void *), sizeof(int));
+ assertTrue(actual == 0, "Expected successful return value.");
+ assertNotNull(pointer, "Expected pointer to not be NULL");
+
+ parcMemory_Deallocate(&pointer);
+ assertNull(pointer, "Expected pointer to not be NULL");
+}
+
+LONGBOW_TEST_CASE(Global, parcMemory_Reallocate)
+{
+ void *pointer;
+ int actual = parcMemory_MemAlign(&pointer, sizeof(void *), sizeof(int));
+ assertTrue(actual == 0, "Expected successful return value.");
+
+ pointer = parcMemory_Reallocate(pointer, sizeof(int) * 2);
+ assertNotNull(pointer, "Expected pointer to not be NULL");
+
+ parcMemory_Deallocate(&pointer);
+ assertNull(pointer, "Expected pointer to not be NULL");
+}
+
+LONGBOW_TEST_CASE(Global, parcMemory_AllocateAndClear)
+{
+ void *pointer;
+ pointer = parcMemory_AllocateAndClear(sizeof(int));
+ assertNotNull(pointer, "Expected pointer to not be NULL");
+
+ for (int i = 0; i < sizeof(int); i++) {
+ assertTrue(((char *) pointer)[i] == 0, "Expected cell to be zero.");
+ }
+
+ parcMemory_Deallocate(&pointer);
+ assertNull(pointer, "Expected pointer to not be NULL");
+}
+
+LONGBOW_TEST_CASE(Global, parcMemory_StringDuplicate)
+{
+ char *expected = "Hello";
+
+ char *actual = parcMemory_StringDuplicate(expected, strlen(expected));
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected %s, actual %s", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcMemory_Outstanding)
+{
+ void *pointer;
+ pointer = parcMemory_Allocate(sizeof(int));
+
+ size_t expected = 1;
+ size_t actual = parcMemory_Outstanding();
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+
+ parcMemory_Deallocate(&pointer);
+
+ expected = 0;
+ actual = parcMemory_Outstanding();
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcMemory_SetInterface)
+{
+ const PARCMemoryInterface *old = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+
+ parcMemory_SetInterface(old);
+}
+
+LONGBOW_TEST_CASE(Global, parcMemory_Format)
+{
+ char *expected = "Hello World";
+ char *actual = parcMemory_Format("Hello %s", "World");
+
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate(&actual);
+}
+
+LONGBOW_TEST_FIXTURE(Static)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Memory);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Network.c b/libparc/parc/algol/test/test_parc_Network.c
new file mode 100755
index 00000000..864fe25d
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Network.c
@@ -0,0 +1,668 @@
+/*
+ * 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_Network.c"
+
+#include <LongBow/unit-test.h>
+
+#include <stdio.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+#include <sys/un.h>
+
+LONGBOW_TEST_RUNNER(parc_Networking)
+{
+ // 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);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Networking)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Networking)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_SockInet4AddressAny);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_SockInet4Address_BuildString);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_SockInet6Address_BuildString);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_LinkAddress_BuildString_dashes);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_LinkAddress_BuildString_colons);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_Inet4Equals);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_dashes);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_colons);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_dots);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_ParseLinkAddress_BadScheme);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_BadLink);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_BadMixOfDashesAndDots);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_BadMixOfDotsAndDashes);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_BadSpecification);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_ParseInet4Address);
+
+ LONGBOW_RUN_TEST_CASE(Global, parseMAC48Address);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_ParseMAC48Address_Colons);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_ParseMAC48Address_Colons_TooShort);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_ParseMAC48Address_Colons_Garbage);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_ParseMAC48Address);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_ParseMAC48Address_TooShort);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_SockAddress_ipv4);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_SockAddress_ipv6);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_SockAddress_hostname);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_IsSocketLocal_PF_LOCAL);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_IsSocketLocal_PF_INET4);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_IsSocketLocal_PF_INET6);
+ LONGBOW_RUN_TEST_CASE(Global, parcNetwork_IsSocketLocal_PF_IPX);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_SockInet4AddressAny)
+{
+ struct sockaddr_in *test_sock = parcNetwork_SockInet4AddressAny();
+
+ assertNotNull(test_sock, "Expected a not null pointer\n");
+ assertTrue(test_sock->sin_family == AF_INET, "Expecting sin_family to be AF_INET\n");
+ assertTrue(test_sock->sin_addr.s_addr == INADDR_ANY, "Expecting sin_addr.s_addr to be set to INADDR_ANY\n");
+#if defined(SIN6_LEN)
+ assertTrue(test_sock->sin_len == sizeof(struct sockaddr_in), "Expecting sockaddr.sin_len to be %zu not %hhu\n",
+ sizeof(struct sockaddr_in), test_sock->sin_len);
+#endif
+
+ parcMemory_Deallocate((void **) &test_sock);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_SockInet4Address_BuildString)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ struct sockaddr_in *address = parcNetwork_SockInet4Address("127.0.0.1", 1234);
+#if defined(SIN6_LEN)
+ assertTrue(address->sin_len == sizeof(struct sockaddr_in), "Expecting sockaddr.sin_len to be %zu not %hhu\n",
+ sizeof(struct sockaddr_in), address->sin_len);
+#endif
+ parcNetwork_SockInet4Address_BuildString(address, composer);
+
+ char *expected = "inet4://127.0.0.1:1234";
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcMemory_Deallocate((void **) &address);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_SockInet6Address_BuildString)
+{
+ struct sockaddr_in6 *address = parcNetwork_SockInet6Address("2001:720:1500:1::a100", 1234, 0, 1);
+#if defined(SIN6_LEN)
+ assertTrue(address->sin6_len == sizeof(struct sockaddr_in6), "Expecting sockaddr.sin6_len to be %zu not %hhu\n",
+ sizeof(struct sockaddr_in6), address->sin6_len);
+#endif
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcNetwork_SockInet6Address_BuildString(address, composer);
+
+ char *expected = "inet6://[2001:720:1500:1::a100%1]:1234";
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcMemory_Deallocate((void **) &address);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_LinkAddress_BuildString_dashes)
+{
+ char *expected = "link://01-23-45-67-89-ab";
+
+ PARCBuffer *address = parcNetwork_ParseLinkAddress(expected);
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ parcNetwork_LinkAddress_BuildString((unsigned char *) parcBuffer_Overlay(address, 0), parcBuffer_Remaining(address), composer);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcBufferComposer_Release(&composer);
+ parcBuffer_Release(&address);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_LinkAddress_BuildString_colons)
+{
+ char *expected = "link://01-23-45-67-89-ab";
+
+ PARCBuffer *address = parcNetwork_ParseLinkAddress("link://01:23:45:67:89:ab");
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcNetwork_LinkAddress_BuildString((unsigned char *) parcBuffer_Overlay(address, 0), parcBuffer_Remaining(address), composer);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcBufferComposer_Release(&composer);
+ parcBuffer_Release(&address);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_dashes)
+{
+ char *expected = "link://01-23-45-67-89-ab";
+ PARCBuffer *address = parcNetwork_ParseLinkAddress(expected);
+ parcBuffer_Flip(address);
+
+ PARCBuffer *e = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ parcBuffer_SetPosition(address, 0);
+ parcBuffer_SetLimit(address, 6);
+
+ parcBuffer_SetPosition(e, 0);
+ parcBuffer_SetLimit(e, 6);
+
+ assertTrue(parcBuffer_Equals(address, e),
+ "Expected result failed.");
+
+ parcBuffer_Release(&e);
+ parcBuffer_Release(&address);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_colons)
+{
+ char *expected = "link://01:23:45:67:89:ab";
+ PARCBuffer *address = parcNetwork_ParseLinkAddress(expected);
+
+ PARCBuffer *e = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ parcBuffer_SetPosition(address, 0);
+ parcBuffer_SetPosition(e, 0);
+ parcBuffer_SetLimit(address, 6);
+ parcBuffer_SetLimit(e, 6);
+
+ assertTrue(parcBuffer_Equals(address, e),
+ "Expected result failed.");
+
+ parcBuffer_Release(&e);
+ parcBuffer_Release(&address);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_dots)
+{
+ char *expected = "link://0123.4567.89ab";
+ PARCBuffer *address = parcNetwork_ParseLinkAddress(expected);
+
+ PARCBuffer *e = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ parcBuffer_SetPosition(address, 0);
+ parcBuffer_SetPosition(e, 0);
+ parcBuffer_SetLimit(address, 6);
+ parcBuffer_SetLimit(e, 6);
+
+ assertTrue(parcBuffer_Equals(address, e),
+ "Expected result failed.");
+
+ parcBuffer_Release(&e);
+ parcBuffer_Release(&address);
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, parcNetwork_ParseLinkAddress_BadScheme, .event = &LongBowTrapIllegalValue)
+{
+ char *expected = "asdf://";
+ parcNetwork_ParseLinkAddress(expected);
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, parcNetwork_LinkAddress_Parse_BadLink, .event = &LongBowTrapIllegalValue)
+{
+ char *expected = "link://";
+ parcNetwork_ParseLinkAddress(expected);
+ printf("Hello\n");
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, parcNetwork_LinkAddress_Parse_BadSpecification, .event = &LongBowTrapIllegalValue)
+{
+ char *expected = "link://a";
+ parcNetwork_ParseLinkAddress(expected);
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, parcNetwork_LinkAddress_Parse_BadMixOfDashesAndDots, .event = &LongBowTrapIllegalValue)
+{
+ char *expected = "link://01-23-45.6789ab";
+ parcNetwork_ParseLinkAddress(expected);
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, parcNetwork_LinkAddress_Parse_BadMixOfDotsAndDashes, .event = &LongBowTrapIllegalValue)
+{
+ char *expected = "link://012345.67-89-ab";
+ parcNetwork_ParseLinkAddress(expected);
+}
+
+LONGBOW_TEST_CASE(Global, parseMAC48Address)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ bool actual = parcNetwork_ParseMAC48Address("01-23-45-67-89-ab", buffer);
+ assertTrue(actual, "Expected parcNetwork_ParseMAC48Address() to return true");
+
+ parcBuffer_Flip(buffer);
+
+ assertTrue(parcBuffer_Equals(expected, buffer), "Expected buffer contents failed.");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_ParseMAC48Address_Colons)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ bool actual = parcNetwork_ParseMAC48Address("01:23:45:67:89:ab", buffer);
+ assertTrue(actual, "Expected parcNetwork_ParseMAC48Address() to return true");
+ parcBuffer_Flip(buffer);
+
+ assertTrue(parcBuffer_Equals(expected, buffer), "Expected buffer contents failed.");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_ParseMAC48Address_Colons_TooShort)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ bool actual = parcNetwork_ParseMAC48Address("01:23:45:67:89", buffer);
+ assertFalse(actual, "Expected parcNetwork_ParseMAC48Address() to return false");
+ assertTrue(parcBuffer_Position(buffer) == 0, "Expected buffer to be unmodified.");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_ParseMAC48Address_Colons_Garbage)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ bool actual = parcNetwork_ParseMAC48Address("0x:23:45:67:89:ab", buffer);
+ assertFalse(actual, "Expected parcNetwork_ParseMAC48Address() to return false");
+ assertTrue(parcBuffer_Position(buffer) == 0, "Expected the PARCBuffer to be unchanged.");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_ParseMAC48Address)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ bool actual = parcNetwork_ParseMAC48Address("0123.4567.89ab", buffer);
+ assertTrue(actual, "Expected _parseLinkAddressDot() to return true");
+ parcBuffer_Flip(buffer);
+
+ assertTrue(parcBuffer_Equals(expected, buffer), "Expected buffer contents failed.");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_ParseMAC48Address_TooShort)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ bool actual = parcNetwork_ParseMAC48Address("0123.4567", buffer);
+ assertFalse(actual, "Expected parcNetwork_ParseMAC48Address() to return false");
+ assertTrue(parcBuffer_Position(buffer) == 0, "Expected the PARCBuffer to be unchanged.");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_ParseInet4Address)
+{
+ struct sockaddr_in *address = parcNetwork_SockInet4Address("127.0.0.1", 1234);
+
+ PARCBufferComposer *composer = parcNetwork_SockInet4Address_BuildString(address, parcBufferComposer_Create());
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *addressURI = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ struct sockaddr_in *actual = parcNetwork_ParseInet4Address(addressURI);
+
+ assertTrue(parcNetwork_Inet4Equals(address, actual),
+ "Expected Addresses are not equal");
+
+ parcMemory_Deallocate((void **) &actual);
+ parcMemory_Deallocate((void **) &addressURI);
+ parcBufferComposer_Release(&composer);
+ parcMemory_Deallocate((void **) &address);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_Inet4Equals)
+{
+ struct sockaddr_in *x = parcNetwork_SockInet4Address("127.0.0.1", 1234);
+ struct sockaddr_in *y = parcNetwork_SockInet4Address("127.0.0.1", 1234);
+ struct sockaddr_in *z = parcNetwork_SockInet4Address("127.0.0.1", 1234);
+ struct sockaddr_in *u1 = parcNetwork_SockInet4Address("127.0.0.2", 1234);
+ struct sockaddr_in *u2 = parcNetwork_SockInet4Address("127.0.0.1", 4567);
+
+ parcObjectTesting_AssertEqualsFunction(parcNetwork_Inet4Equals, x, y, z, u1, u2);
+
+ parcMemory_Deallocate((void **) &x);
+ parcMemory_Deallocate((void **) &y);
+ parcMemory_Deallocate((void **) &z);
+ parcMemory_Deallocate((void **) &u1);
+ parcMemory_Deallocate((void **) &u2);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_SockAddress_ipv4)
+{
+ const char *ipv4 = "1.1.1.1";
+ unsigned short port = 5959;
+
+ struct sockaddr_in truth = {
+ .sin_family = PF_INET,
+ .sin_port = htons(port),
+ .sin_addr.s_addr = htonl(0x01010101)
+ };
+
+ struct sockaddr_in *test = (struct sockaddr_in *) parcNetwork_SockAddress(ipv4, port);
+ assertNotNull(test, "Got null address for %s port %u", ipv4, port);
+ assertTrue(truth.sin_family == test->sin_family, "wrong family, expected %d got %d", truth.sin_family, test->sin_family);
+ assertTrue(truth.sin_port == test->sin_port, "wrong port, expected %u got %u", truth.sin_port, test->sin_port);
+
+ assertTrue(memcmp(&truth.sin_addr, &test->sin_addr, sizeof(struct in_addr)) == 0, "struct in_addr did not compare");
+ parcMemory_Deallocate((void **) &test);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_SockAddress_ipv6)
+{
+ const char *ipv6 = "fe80::aa20:66ff:fe00:314a";
+ uint8_t truth_addr[16] = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0xaa, 0x20, 0x66, 0xff, 0xfe, 0x00, 0x31, 0x4a };
+
+ unsigned short port = 5959;
+
+ struct sockaddr_in6 truth = {
+ .sin6_family = PF_INET6,
+ .sin6_port = htons(port)
+ };
+
+ memcpy(&truth.sin6_addr, truth_addr, sizeof(truth.sin6_addr));
+
+
+ struct sockaddr_in6 *test = (struct sockaddr_in6 *) parcNetwork_SockAddress(ipv6, port);
+ if (test == NULL) {
+ testSkip("IPv6 is not supported in the runtime environment.");
+ }
+ assertTrue(truth.sin6_family == test->sin6_family, "wrong family, expected %d got %d", truth.sin6_family, test->sin6_family);
+ assertTrue(truth.sin6_port == test->sin6_port, "wrong port, expected %u got %u", truth.sin6_port, test->sin6_port);
+
+ assertTrue(memcmp(&truth.sin6_addr, &test->sin6_addr, sizeof(struct in6_addr)) == 0, "struct in_addr did not compare");
+ parcMemory_Deallocate((void **) &test);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_SockAddress_hostname)
+{
+ const char *name = "localhost";
+ unsigned short port = 5959;
+
+ struct sockaddr *test = parcNetwork_SockAddress(name, port);
+ assertNotNull(test, "Got null looking up '%s'", name);
+ parcMemory_Deallocate((void **) &test);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_IsSocketLocal_PF_LOCAL)
+{
+ struct sockaddr_un name;
+ name.sun_family = PF_LOCAL;
+
+ bool isLocal = parcNetwork_IsSocketLocal((struct sockaddr *) &name);
+ assertTrue(isLocal, "PF_LOCAL address did not return as local");
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_IsSocketLocal_PF_IPX)
+{
+ struct sockaddr_un name;
+ name.sun_family = PF_IPX;
+
+ bool isLocal = parcNetwork_IsSocketLocal((struct sockaddr *) &name);
+ assertFalse(isLocal, "Expected parcNetwork_IsSocketLocal(PF_PUP) to return false");
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_IsSocketLocal_PF_INET4)
+{
+ struct sockaddr *s = parcNetwork_SockAddress("127.1.1.1", 5900);
+ bool isLoopback = parcNetwork_IsSocketLocal(s);
+ assertTrue(isLoopback, "127.1.1.1 should be called loopback");
+ parcMemory_Deallocate((void **) &s);
+}
+
+LONGBOW_TEST_CASE(Global, parcNetwork_IsSocketLocal_PF_INET6)
+{
+ struct sockaddr *s = parcNetwork_SockAddress("::1", 5900);
+ bool isLoopback = parcNetwork_IsSocketLocal(s);
+ assertTrue(isLoopback, "::1 should be called loopback");
+ parcMemory_Deallocate((void **) &s);
+}
+
+
+// =======================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, parcNetwork_IsInet6Local_True);
+ LONGBOW_RUN_TEST_CASE(Local, parcNetwork_IsInet6Local_False);
+ LONGBOW_RUN_TEST_CASE(Local, parcNetwork_IsInet4Local_True);
+ LONGBOW_RUN_TEST_CASE(Local, parcNetwork_IsInet4Local_False);
+
+ LONGBOW_RUN_TEST_CASE(Local, _parseMAC48AddressDashOrColon);
+ LONGBOW_RUN_TEST_CASE(Local, _parseMAC48AddressDashOrColon_Colons);
+ LONGBOW_RUN_TEST_CASE(Local, _parseMAC48AddressDot);
+ LONGBOW_RUN_TEST_CASE(Local, _parseMAC48AddressDot_TooShort);
+ LONGBOW_RUN_TEST_CASE(Local, _parseMAC48AddressDashOrColon_Colons_TooShort);
+ LONGBOW_RUN_TEST_CASE(Local, _parseMAC48AddressDashOrColon_Colons_Garbage);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ 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(Local, parcNetwork_IsInet6Local_True)
+{
+ struct sockaddr *s = parcNetwork_SockAddress("::1", 5900);
+
+ bool isLoopback = _isInet6Loopback((struct sockaddr_in6 *) s);
+ assertTrue(isLoopback, "::1 should be called loopback");
+ parcMemory_Deallocate((void **) &s);
+}
+
+LONGBOW_TEST_CASE(Local, parcNetwork_IsInet6Local_False)
+{
+ struct sockaddr *s = parcNetwork_SockAddress("fe80::aa20:66ff:fe00:1", 5900);
+
+ bool isLoopback = _isInet6Loopback((struct sockaddr_in6 *) s);
+ assertFalse(isLoopback, "fe80::aa20:66ff:fe00:1 should not be called loopback");
+ parcMemory_Deallocate((void **) &s);
+}
+
+LONGBOW_TEST_CASE(Local, parcNetwork_IsInet4Local_True)
+{
+ struct sockaddr *s = parcNetwork_SockAddress("127.1.1.1", 5900);
+
+ bool isLoopback = _isInet4Loopback((struct sockaddr_in *) s);
+ assertTrue(isLoopback, "127.1.1.1 should be called loopback");
+ parcMemory_Deallocate((void **) &s);
+}
+
+LONGBOW_TEST_CASE(Local, parcNetwork_IsInet4Local_False)
+{
+ struct sockaddr *s = parcNetwork_SockAddress("13.1.1.1", 5900);
+
+ bool isLoopback = _isInet4Loopback((struct sockaddr_in *) s);
+ assertFalse(isLoopback, "13.1.1.1 should not be called loopback");
+ parcMemory_Deallocate((void **) &s);
+}
+
+LONGBOW_TEST_CASE(Local, _parseMAC48AddressDashOrColon)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ PARCBuffer *actual = _parseMAC48AddressDashOrColon("01-23-45-67-89-ab", buffer);
+ assertNotNull(actual, "Expected _parseLinkAddressDashOrColon() to return non-NULL value");
+ parcBuffer_Flip(actual);
+
+ assertTrue(parcBuffer_Equals(expected, actual), "Expected buffer contents failed.");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Local, _parseMAC48AddressDashOrColon_Colons)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ PARCBuffer *actual = _parseMAC48AddressDashOrColon("01:23:45:67:89:ab", buffer);
+ assertNotNull(actual, "Expected _parseLinkAddressDashOrColon() to return non-NULL value");
+ parcBuffer_Flip(actual);
+
+ assertTrue(parcBuffer_Equals(expected, actual), "Expected buffer contents failed.");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Local, _parseMAC48AddressDashOrColon_Colons_TooShort)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ PARCBuffer *actual = _parseMAC48AddressDashOrColon("01:23:45:67:89", buffer);
+ assertNull(actual, "Expected _parseLinkAddressDashOrColon() to return NULL value");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Local, _parseMAC48AddressDashOrColon_Colons_Garbage)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ PARCBuffer *actual = _parseMAC48AddressDashOrColon("0x:23:45:67:89:ab", buffer);
+ assertNull(actual, "Expected _parseLinkAddressDashOrColon() to return NULL value");
+ assertTrue(parcBuffer_Position(buffer) == 0, "Expected the PARCBuffer to be unchanged.");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Local, _parseMAC48AddressDot)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ PARCBuffer *actual = _parseMAC48AddressDot("0123.4567.89ab", buffer);
+ assertNotNull(actual, "Expected _parseLinkAddressDot() to return non-NULL value");
+ parcBuffer_Flip(actual);
+
+ assertTrue(parcBuffer_Equals(expected, actual), "Expected buffer contents failed.");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Local, _parseMAC48AddressDot_TooShort)
+{
+ PARCBuffer *expected = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(7);
+ PARCBuffer *actual = _parseMAC48AddressDot("0123.4567", buffer);
+ assertNull(actual, "Expected _parseLinkAddressDot() to return NULL value");
+
+ parcBuffer_Release(&expected);
+ parcBuffer_Release(&buffer);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Networking);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Object.c b/libparc/parc/algol/test/test_parc_Object.c
new file mode 100755
index 00000000..687654fe
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Object.c
@@ -0,0 +1,1580 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+#include "../parc_Object.c"
+
+#include <inttypes.h>
+#include <sys/time.h>
+
+#include <LongBow/unit-test.h>
+
+#include <parc/testing/parc_ObjectTesting.h>
+#include <parc/testing/parc_MemoryTesting.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_StdlibMemory.h>
+
+typedef struct {
+ int calledCount;
+ int val;
+} _dummy_object;
+
+typedef _dummy_object _DummyObject;
+
+static void
+_dummy_Destroy(_DummyObject **obj __attribute__((unused)))
+{
+}
+
+static _DummyObject *
+_dummy_Copy(const _DummyObject *obj);
+
+
+static bool
+_dummy_Equals(const _DummyObject *x, const _DummyObject *y)
+{
+ const _DummyObject *dummy1 = x;
+ const _DummyObject *dummy2 = y;
+ return (dummy1->calledCount == dummy2->calledCount);
+}
+
+static int
+_dummy_Compare(const _DummyObject *x, const _DummyObject *y)
+{
+ const _DummyObject *dummy1 = x;
+ const _DummyObject *dummy2 = y;
+ if (dummy1->calledCount == dummy2->calledCount) {
+ return 0;
+ } else if (dummy1->calledCount < dummy2->calledCount) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+static uint32_t
+_dummy_HashCode(const _DummyObject *obj)
+{
+ _DummyObject *dummy = (_DummyObject *) obj;
+ dummy->calledCount++;
+ return 1337;
+}
+
+static char *
+_dummy_ToString(const _DummyObject *x __attribute__((unused)))
+{
+ char *str = (char *) parcMemory_Allocate(6);
+ char *test = "dummy";
+ sprintf(str, "%s", test);
+ return str;
+}
+
+static PARCJSON *
+_dummy_ToJSON(const _DummyObject *x __attribute__((unused)))
+{
+ PARCJSON *json = parcJSON_ParseString("{ \"type\" : \"dummy\" }");
+ return json;
+}
+
+parcObject_Override(_DummyObject, PARCObject,
+ .destroy = (PARCObjectDestroy *) _dummy_Destroy,
+ .copy = (PARCObjectCopy *) _dummy_Copy,
+ .toString = (PARCObjectToString *) _dummy_ToString,
+ .equals = (PARCObjectEquals *) _dummy_Equals,
+ .compare = (PARCObjectCompare *) _dummy_Compare,
+ .hashCode = (PARCObjectHashCode *) _dummy_HashCode,
+ .toJSON = (PARCObjectToJSON *) _dummy_ToJSON);
+
+static _DummyObject *
+_dummy_Copy(const _DummyObject *obj)
+{
+ _DummyObject *newDummy = parcObject_CreateInstance(_DummyObject);
+ const _DummyObject *dummy = obj;
+ newDummy->calledCount = dummy->calledCount;
+ return newDummy;
+}
+
+typedef _dummy_object _DummyObjectNoHash;
+parcObject_ExtendPARCObject(_DummyObjectNoHash,
+ _dummy_Destroy,
+ _dummy_Copy,
+ _dummy_ToString,
+ _dummy_Equals,
+ _dummy_Compare,
+ NULL,
+ _dummy_ToJSON);
+
+static bool
+_meta_destructor_true(PARCObject **objPtr)
+{
+ return true;
+}
+
+static bool
+_meta_destructor_false(PARCObject **objPtr)
+{
+ (*objPtr) = NULL;
+ return false;
+}
+
+static PARCObject *
+_meta_copy(const PARCObject *ptr)
+{
+ _DummyObject *d = parcMemory_AllocateAndClear(sizeof(_DummyObject));
+ _DummyObject *xx = (_DummyObject *) ptr;
+ d->val = xx->val;
+ return d;
+}
+
+static bool
+_meta_equals(const PARCObject *x, const PARCObject *y)
+{
+ _DummyObject *xx = (_DummyObject *) x;
+ _DummyObject *yy = (_DummyObject *) y;
+ return (xx->val == yy->val);
+}
+
+static int
+_meta_compare(const PARCObject *x, const PARCObject *y)
+{
+ _DummyObject *xx = (_DummyObject *) x;
+ _DummyObject *yy = (_DummyObject *) y;
+
+ if (xx->val == yy->val) {
+ return 0;
+ } else if (xx->val < yy->val) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+static PARCHashCode
+_meta_hashCode(const PARCObject *ptr)
+{
+ _DummyObject *xx = (_DummyObject *) ptr;
+ return xx->val;
+}
+
+static char *
+_meta_toString(const PARCObject *ptr)
+{
+ _DummyObject *xx = (_DummyObject *) ptr;
+
+ char *result;
+ parcMemory_MemAlign((void **) &result, sizeof(void *), sizeof(char));
+ assertNotNull(result, "parcMemory_Allocate returned NULL");
+
+ char *p = result;
+ sprintf(result, "%d", xx->val);
+
+ return p;
+}
+
+static PARCJSON *
+_meta_toJson(const PARCObject *ptr)
+{
+ _DummyObject *xx = (_DummyObject *) ptr;
+
+ PARCJSON *json = parcJSON_Create();
+ parcJSON_AddInteger(json, "value", xx->val);
+
+ return json;
+}
+
+static const PARCMemoryInterface *_originalMemoryProvider;
+
+LONGBOW_TEST_RUNNER(parcObject)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+ LONGBOW_RUN_TEST_FIXTURE(PARCObjectDescriptor);
+ LONGBOW_RUN_TEST_FIXTURE(Static);
+ LONGBOW_RUN_TEST_FIXTURE(StaticObjects);
+ LONGBOW_RUN_TEST_FIXTURE(Meta);
+ LONGBOW_RUN_TEST_FIXTURE(AcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Subclasses);
+ LONGBOW_RUN_TEST_FIXTURE(Fail);
+ LONGBOW_RUN_TEST_FIXTURE(Locking);
+ LONGBOW_RUN_TEST_FIXTURE(WaitNotify);
+ LONGBOW_RUN_TEST_FIXTURE(Synchronization);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(parcObject)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(parcObject)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Static)
+{
+ LONGBOW_RUN_TEST_CASE(Static, _objectHeaderIsValid);
+ LONGBOW_RUN_TEST_CASE(Static, _parcObject_PrefixLength);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Static)
+{
+ _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Static)
+{
+ parcMemory_SetInterface(_originalMemoryProvider);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+struct timeval _testObject;
+
+parcObject_Override(_testObject, PARCObject);
+
+LONGBOW_TEST_CASE(Static, _objectHeaderIsValid)
+{
+ PARCObject *object = parcObject_CreateInstanceImpl(&_testObject_Descriptor);
+
+ _PARCObjectHeader *header = _parcObject_Header(object);
+
+ assertTrue(_parcObjectHeader_IsValid(header, object), "Expected _parcObject_HeaderHeaderIsValid to be valid");
+
+ parcObject_Release(&object);
+}
+
+LONGBOW_TEST_CASE(Static, _parcObject_PrefixLength)
+{
+ // Test that the result is a multiple of the alignment value and greater than the size of _PARCObjectHeader.
+
+ // Compute the power of 2 value of sizeof(void *)
+ unsigned int v = sizeof(void *);
+ unsigned int r = 0; // r will be lg(v)
+
+ while (v >>= 1) {
+ r++;
+ }
+ PARCObjectDescriptor descriptor;
+
+ for (int i = r; i < 20; i++) {
+ descriptor.objectAlignment = 1 << i;
+ size_t actual = _parcObject_PrefixLength(&descriptor);
+ assertTrue((actual & (descriptor.objectAlignment - 1)) == 0,
+ "Alignment needs to be a multiple of %u", descriptor.objectAlignment);
+ }
+}
+
+LONGBOW_TEST_FIXTURE(AcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcObject_Acquire);
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcObject_Release);
+// LONGBOW_RUN_TEST_CASE(AcquireRelease, parcObject_Acquire_Invalid);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(AcquireRelease)
+{
+ _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(AcquireRelease)
+{
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ parcMemory_SetInterface(_originalMemoryProvider);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcObject_Acquire)
+{
+ struct timeval *expected = parcObject_CreateInstanceImpl(&_testObject_Descriptor);
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcObject_Acquire, expected);
+ parcObject_Release((void **) &expected);
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcObject_Release)
+{
+ struct timeval *time = parcObject_CreateInstanceImpl(&_testObject_Descriptor);
+ parcObject_AssertValid(time);
+
+ time->tv_sec = 1;
+ time->tv_usec = 2;
+
+ PARCReferenceCount count = parcObject_Release((PARCObject **) &time);
+ assertTrue(count == 0, "Expected reference count to be zero");
+ assertTrue(time == 0, "Expected memory pointer to be NULL after destroy.");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Create);
+// LONGBOW_RUN_TEST_CASE(Global, parcObject_CreateAndClear);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_IsValid);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_IsValid_NotValid);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_IsInstanceOf);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Copy_Default);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Release);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Compare_Default);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Compare_NoOverride);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Compare);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Equals_Default);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Equals_NoOverride);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_HashCode_Default);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_HashCode_NoOverride);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_ToString_Default);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_ToString_NoOverride);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_ToString);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_ToJSON_Default);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_ToJSON_NoOverride);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_GetReferenceCount);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Display_Default);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Display_NoOverride);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_Display);
+ LONGBOW_RUN_TEST_CASE(Global, parcObject_GetDescriptor);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+
+ parcMemory_SetInterface(_originalMemoryProvider);
+
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Release)
+{
+ struct timeval *time = parcObject_CreateInstanceImpl(&_testObject_Descriptor);
+ parcObject_AssertValid(time);
+
+ time->tv_sec = 1;
+ time->tv_usec = 2;
+
+ PARCReferenceCount count = parcObject_Release((PARCObject **) &time);
+ assertTrue(count == 0, "Expected reference count to be zero");
+ assertTrue(time == 0, "Expected memory pointer to be NULL after destroy.");
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Create)
+{
+ struct timeval *time = parcObject_CreateInstanceImpl(&_testObject_Descriptor);
+ parcObject_AssertValid(time);
+
+ time->tv_sec = 1;
+ time->tv_usec = 2;
+
+ PARCReferenceCount count = parcObject_Release((PARCObject **) &time);
+ assertTrue(count == 0, "Expected reference count to be zero");
+ assertTrue(time == 0, "Expected memory pointer to be NULL after destroy.");
+}
+
+//LONGBOW_TEST_CASE(Global, parcObject_CreateAndClear)
+//{
+// struct timeval *time = parcObject_CreateAndClear(struct timeval);
+// parcObject_AssertValid(time);
+//
+// time->tv_sec = 1;
+// time->tv_usec = 2;
+//
+// PARCReferenceCount count = parcObject_Release((PARCObject **) &time);
+// assertTrue(count == 0, "Expected reference count to be zero");
+// assertTrue(time == 0, "Expected memory pointer to be NULL after destroy.");
+//}
+
+LONGBOW_TEST_CASE(Global, parcObject_IsValid)
+{
+ PARCObject *object = parcObject_CreateInstanceImpl(&_testObject_Descriptor);
+ assertTrue(parcObject_IsValid(object), "Expected valid PARCObject");
+
+ parcObject_Release(&object);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_IsInstanceOf)
+{
+ _DummyObject *dummy1 = parcObject_CreateInstance(_DummyObject);
+ assertTrue(parcObject_IsInstanceOf(dummy1, &PARCObject_Descriptor),
+ "Expected _DummyObject to be an instance of PARCObject");
+
+ parcObject_Release((PARCObject **) &dummy1);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_IsValid_NotValid)
+{
+ PARCObject *object = parcObject_CreateInstanceImpl(&_testObject_Descriptor);
+ PARCObject *alias = object;
+ parcObject_Release(&object);
+ assertFalse(parcObject_IsValid(object), "Expected invalid PARCObject");
+ assertFalse(parcObject_IsValid(alias), "Expected invalid PARCObject");
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Copy_Default)
+{
+ struct timeval *time = parcObject_CreateInstanceImpl(&_testObject_Descriptor);
+ parcObject_AssertValid(time);
+
+ time->tv_sec = 1;
+ time->tv_usec = 2;
+
+ struct timeval *copy = parcObject_Copy(time);
+
+ parcObject_AssertValid(copy);
+
+ assertTrue(copy->tv_sec == 1, "Expected tv_sec to equal 1");
+ assertTrue(copy->tv_usec == 2, "Expected tv_usec to equal 2");
+
+ PARCReferenceCount count = parcObject_Release((PARCObject **) &copy);
+ assertTrue(count == 0, "Expected reference count to be zero");
+ assertTrue(copy == 0, "Expected memory pointer to be NULL after destroy.");
+
+ parcObject_Release((PARCObject *) &time);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Copy)
+{
+ _DummyObject *dummy1 = parcObject_CreateInstance(_DummyObject);
+ dummy1->calledCount = 100;
+
+ _DummyObject *dummy2 = parcObject_Copy(dummy1);
+
+ assertTrue(dummy2->calledCount == dummy1->calledCount,
+ "Expected called counts to be the same. Got %d, expected %d.", dummy1->calledCount, dummy2->calledCount);
+
+ parcObject_Release((PARCObject **) &dummy1);
+ parcObject_Release((PARCObject **) &dummy2);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Compare_Default)
+{
+ struct timeval *time1 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+ parcObject_AssertValid(time1);
+
+ time1->tv_sec = 1;
+ time1->tv_usec = 2;
+
+ struct timeval *time2 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+ parcObject_AssertValid(time2);
+
+ time2->tv_sec = 1;
+ time2->tv_usec = 2;
+
+ int compareResult = parcObject_Compare(time1, time2);
+ assertTrue(compareResult == 0, "Expected objects to compare equal. Comparison result: %d", compareResult);
+ compareResult = parcObject_Compare(time1, time1);
+ assertTrue(compareResult == 0, "Expected same object to be equal since they have identical pointer addresses. Comparison result: %d", compareResult);
+
+ parcObject_Release((PARCObject *) &time1);
+ parcObject_Release((PARCObject *) &time2);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Compare_NoOverride)
+{
+ const PARCObjectDescriptor *descriptor =
+ parcObjectDescriptor_Create("override",
+ sizeof(struct timeval), sizeof(void*),
+ true,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL);
+ struct timeval *time1 = parcObject_CreateAndClearInstanceImpl(descriptor);
+ parcObject_AssertValid(time1);
+
+ time1->tv_sec = 1;
+ time1->tv_usec = 2;
+
+ struct timeval *time2 = parcObject_CreateAndClearInstanceImpl(descriptor);
+ parcObject_AssertValid(time2);
+
+ time2->tv_sec = 1;
+ time2->tv_usec = 2;
+
+ int compareResult = parcObject_Compare(time1, time2);
+ assertTrue(compareResult == 0, "Expected objects to compare equal. Comparison result: %d", compareResult);
+ compareResult = parcObject_Compare(time1, time1);
+ assertTrue(compareResult == 0, "Expected same object to be equal since they have identical pointer addresses. Comparison result: %d", compareResult);
+
+ parcObject_Release((PARCObject *) &time1);
+ parcObject_Release((PARCObject *) &time2);
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Compare)
+{
+ _DummyObject *value = parcObject_CreateAndClearInstance(_DummyObject);
+ _DummyObject *equality[2];
+ equality[0] = parcObject_CreateAndClearInstance(_DummyObject);
+ equality[1] = NULL;
+ _DummyObject *lesser[2];
+ lesser[0] = parcObject_CreateAndClearInstance(_DummyObject);
+ lesser[1] = NULL;
+
+ _DummyObject *greater[2];
+ greater[0] = parcObject_CreateAndClearInstance(_DummyObject);
+ greater[1] = NULL;
+
+ value->calledCount = 50;
+ equality[0]->calledCount = 50;
+ lesser[0]->calledCount = 10;
+ greater[0]->calledCount = 80;
+
+ parcObjectTesting_AssertCompareTo(parcObject_Compare, value, equality, lesser, greater);
+
+ parcObject_Release((void **) &value);
+ parcObject_Release((void **) &equality[0]);
+ parcObject_Release((void **) &lesser[0]);
+ parcObject_Release((void **) &greater[0]);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Equals_Default)
+{
+ struct timeval *x = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+ memset(x, 0, sizeof(struct timeval));
+ x->tv_sec = 1;
+ x->tv_usec = 2;
+
+ struct timeval *y = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+ memset(y, 0, sizeof(struct timeval));
+ y->tv_sec = 1;
+ y->tv_usec = 2;
+
+ assertTrue(parcObject_Equals(x, y), "Expected equality");
+
+ struct timeval *z = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+ z->tv_sec = 1;
+ z->tv_usec = 2;
+
+ struct timeval *unequal1 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+ unequal1->tv_sec = 1;
+ unequal1->tv_usec = 1;
+
+ struct timeval *unequal2 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+ unequal2->tv_sec = 0;
+ unequal2->tv_usec = 0;
+
+ parcObjectTesting_AssertEqualsFunction(parcObject_Equals, x, y, z, unequal1, unequal2, NULL);
+
+ parcObject_Release((PARCObject *) &x);
+ parcObject_Release((PARCObject *) &y);
+ parcObject_Release((PARCObject *) &z);
+ parcObject_Release((PARCObject *) &unequal1);
+ parcObject_Release((PARCObject *) &unequal2);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Equals_NoOverride)
+{
+ const PARCObjectDescriptor *descriptor =
+ parcObjectDescriptor_Create("override", sizeof(struct timeval), sizeof(void*), true,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL);
+
+ struct timeval *x = parcObject_CreateAndClearInstanceImpl(descriptor);
+ memset(x, 0, sizeof(struct timeval));
+ x->tv_sec = 1;
+ x->tv_usec = 2;
+
+ struct timeval *y = parcObject_CreateAndClearInstanceImpl(descriptor);
+ memset(y, 0, sizeof(struct timeval));
+ y->tv_sec = 1;
+ y->tv_usec = 2;
+
+ assertTrue(parcObject_Equals(x, y), "Expected equality");
+
+ struct timeval *z = parcObject_CreateAndClearInstanceImpl(descriptor);
+ z->tv_sec = 1;
+ z->tv_usec = 2;
+
+ struct timeval *unequal1 = parcObject_CreateAndClearInstanceImpl(descriptor);
+ unequal1->tv_sec = 1;
+ unequal1->tv_usec = 1;
+
+ struct timeval *unequal2 = parcObject_CreateAndClearInstanceImpl(descriptor);
+ unequal2->tv_sec = 0;
+ unequal2->tv_usec = 0;
+
+ parcObjectTesting_AssertEqualsFunction(parcObject_Equals, x, y, z, unequal1, unequal2, NULL);
+
+ parcObject_Release((PARCObject *) &x);
+ parcObject_Release((PARCObject *) &y);
+ parcObject_Release((PARCObject *) &z);
+ parcObject_Release((PARCObject *) &unequal1);
+ parcObject_Release((PARCObject *) &unequal2);
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Equals)
+{
+ _DummyObject *x = parcObject_CreateInstance(_DummyObject);
+ x->calledCount = 100;
+ _DummyObject *y = parcObject_CreateInstance(_DummyObject);
+ y->calledCount = 100;
+ _DummyObject *z = parcObject_CreateInstance(_DummyObject);
+ z->calledCount = 100;
+
+ _DummyObject *unequal1 = parcObject_CreateInstance(_DummyObject);
+ unequal1->calledCount = 50;
+
+ PARCObject *unequal2 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+
+ PARCObjectDescriptor dummyMeta2 = parcObject_DescriptorName(_DummyObject);
+ _DummyObject *unequal3 = parcObject_CreateAndClearInstanceImpl(&dummyMeta2);
+ unequal3->calledCount = 100;
+
+ PARCObject *unequal4 = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+
+ parcObjectTesting_AssertEqualsFunction(parcObject_Equals, x, y, z, unequal1, unequal2, unequal3, unequal4, NULL);
+
+ parcObject_Release((PARCObject **) &x);
+ parcObject_Release((PARCObject **) &y);
+ parcObject_Release((PARCObject **) &z);
+ parcObject_Release((PARCObject **) &unequal1);
+ parcObject_Release((PARCObject **) &unequal2);
+ parcObject_Release((PARCObject **) &unequal3);
+ parcObject_Release((PARCObject **) &unequal4);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_HashCode_Default)
+{
+ struct timeval *time = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+ parcObject_AssertValid(time);
+
+ time->tv_sec = 1;
+ time->tv_usec = 2;
+
+ PARCHashCode hashCode = parcObject_HashCode(time);
+ PARCHashCode expected = parcHashCode_Hash((void *) time, sizeof(struct timeval));
+ assertTrue(hashCode == expected, "Hash codes do not match. Got %" PRIPARCHashCode ", expected %" PRIPARCHashCode ".", hashCode, expected);
+
+ parcObject_Release((PARCObject *) &time);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_HashCode_NoOverride)
+{
+ const PARCObjectDescriptor *descriptor =
+ parcObjectDescriptor_Create("override", sizeof(struct timeval), sizeof(void*), true,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL);
+ struct timeval *time = parcObject_CreateAndClearInstanceImpl(descriptor);
+ parcObject_AssertValid(time);
+
+ time->tv_sec = 1;
+ time->tv_usec = 2;
+
+ PARCHashCode hashCode = parcObject_HashCode(time);
+ PARCHashCode expected = parcHashCode_Hash((void *) time, sizeof(struct timeval));
+ assertTrue(hashCode == expected, "Hash codes do not match. Got %" PRIPARCHashCode ", expected %" PRIPARCHashCode ".", hashCode, expected);
+
+ parcObject_Release((PARCObject *) &time);
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_HashCode)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+
+ PARCHashCode hashCode = parcObject_HashCode(dummy);
+ assertTrue(hashCode == 1337, "Expected hashcode to be 1337, got %" PRIPARCHashCode, hashCode);
+
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_ToString)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+
+ char *strRep = parcObject_ToString(dummy);
+ assertTrue(strcmp(strRep, "dummy") == 0, "Expected 'dummy' string representation, got %s", strRep);
+
+ parcMemory_Deallocate((void **) &strRep);
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_ToString_Default)
+{
+ _DummyObject *dummy = parcObject_CreateAndClearInstanceImpl(&_DummyObject_Descriptor);
+
+ char *strRep = parcObject_ToString(dummy);
+
+ parcMemory_Deallocate((void **) &strRep);
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_ToString_NoOverride)
+{
+ const PARCObjectDescriptor *descriptor =
+ parcObjectDescriptor_Create("override", sizeof(struct timeval), sizeof(void*), true,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL);
+ _DummyObject *dummy = parcObject_CreateAndClearInstanceImpl(descriptor);
+
+ char *strRep = parcObject_ToString(dummy);
+
+ parcMemory_Deallocate((void **) &strRep);
+ parcObject_Release((PARCObject **) &dummy);
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_ToJSON_Default)
+{
+ size_t expectedSize = sizeof(struct timeval);
+ PARCObject *memory = parcObject_CreateAndClearInstanceImpl(&_testObject_Descriptor);
+
+ PARCJSON *json = parcObject_ToJSON(memory);
+
+ const PARCJSONPair *lengthPair = parcJSON_GetPairByName(json, "objectLength");
+ PARCJSONValue *lengthValue = parcJSONPair_GetValue(lengthPair);
+ uint64_t actualLength = parcJSONValue_GetInteger(lengthValue);
+
+ const PARCJSONPair *alignmentPair = parcJSON_GetPairByName(json, "objectAlignment");
+ PARCJSONValue *alignmentValue = parcJSONPair_GetValue(alignmentPair);
+ int alignment = (int) parcJSONValue_GetInteger(alignmentValue);
+
+ assertTrue(actualLength >= expectedSize,
+ "Expected length to be >= %zd, actual %" PRIu64 "", expectedSize, actualLength);
+ assertTrue(alignment == sizeof(void *), "Expected objectAlignment to be %zd, got %d",
+ sizeof(void *), alignment);
+
+ parcJSON_Release(&json);
+ parcObject_Release(&memory);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_ToJSON)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+
+ PARCJSON *json = parcObject_ToJSON(dummy);
+ char *strRep = parcJSON_ToString(json);
+ assertTrue(strcmp(strRep, "{ \"type\" : \"dummy\" }") == 0, "Expected fixed JSON object with a specific string representation, got %s", strRep);
+
+ parcMemory_Deallocate((void **) &strRep);
+ parcJSON_Release(&json);
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_ToJSON_NoOverride)
+{
+ const PARCObjectDescriptor *descriptor =
+ parcObjectDescriptor_Create("override", sizeof(struct timeval), sizeof(void*), true,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL);
+
+ size_t expectedSize = sizeof(struct timeval);
+ PARCObject *memory = parcObject_CreateAndClearInstanceImpl(descriptor);
+
+ PARCJSON *json = parcObject_ToJSON(memory);
+ const PARCJSONPair *lengthPair = parcJSON_GetPairByName(json, "objectLength");
+ PARCJSONValue *lengthValue = parcJSONPair_GetValue(lengthPair);
+ uint64_t actualLength = parcJSONValue_GetInteger(lengthValue);
+
+ const PARCJSONPair *alignmentPair = parcJSON_GetPairByName(json, "objectAlignment");
+ PARCJSONValue *alignmentValue = parcJSONPair_GetValue(alignmentPair);
+ int alignment = (int) parcJSONValue_GetInteger(alignmentValue);
+
+ assertTrue(actualLength >= expectedSize,
+ "Expected length to be >= %zd, actual %" PRIu64 "", expectedSize, actualLength);
+ assertTrue(alignment == sizeof(void *), "Expected objectAlignment to be %zd, got %d",
+ sizeof(void *), alignment);
+
+ parcJSON_Release(&json);
+ parcObject_Release(&memory);
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_GetReferenceCount)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+ PARCReferenceCount refCount = parcObject_GetReferenceCount(dummy);
+ assertTrue(refCount == 1, "Expected reference count to be 1, got %" PRIu64 "", refCount);
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Display_Default)
+{
+ _DummyObject *dummy = parcObject_CreateAndClearInstanceImpl(&_DummyObject_Descriptor);
+ parcObject_Display(dummy, 0);
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Display_NoOverride)
+{
+ const PARCObjectDescriptor *descriptor =
+ parcObjectDescriptor_Create("override", sizeof(struct timeval), sizeof(void*), true,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL);
+
+ _DummyObject *dummy = parcObject_CreateAndClearInstanceImpl(descriptor);
+ parcObject_Display(dummy, 0);
+ parcObject_Release((PARCObject **) &dummy);
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_Display)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+ parcObject_Display(dummy, 0);
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_CASE(Global, parcObject_GetDescriptor)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+ const PARCObjectDescriptor *descriptor = parcObject_GetDescriptor(dummy);
+
+ assertTrue(descriptor == &_DummyObject_Descriptor, "Expected pointer to _DummyObject_Descriptor");
+
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_FIXTURE(Subclasses)
+{
+ LONGBOW_RUN_TEST_CASE(Subclasses, parcObject_Copy);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Subclasses)
+{
+ _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Subclasses)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ parcMemory_SetInterface(_originalMemoryProvider);
+
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Subclasses, parcObject_Copy)
+{
+ const PARCObjectDescriptor *objectType =
+ parcObjectDescriptor_Create("Dummy", sizeof(_DummyObject), sizeof(void*), true,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &PARCObject_Descriptor, NULL);
+
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+ parcObject_SetDescriptor(dummy, objectType);
+
+ dummy->calledCount = 100;
+
+ _DummyObject *dummy2 = parcObject_Copy(dummy);
+
+ assertTrue(dummy2->calledCount == dummy->calledCount,
+ "Expected called counts to be the same. Got %d, expected %d.", dummy->calledCount, dummy2->calledCount);
+
+ parcObject_Release((PARCObject **) &dummy);
+ parcObject_Release((PARCObject **) &dummy2);
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &objectType);
+}
+
+LONGBOW_TEST_FIXTURE(Locking)
+{
+ LONGBOW_RUN_TEST_CASE(Locking, parcObject_TryLock_Unlock);
+ LONGBOW_RUN_TEST_CASE(Locking, parcObject_Lock_Unlock);
+ LONGBOW_RUN_TEST_CASE(Locking, parcObject_TryLock_AlreadyLockedSameThread);
+ LONGBOW_RUN_TEST_CASE(Locking, parcObject_Lock_AlreadyLocked);
+}
+static uint32_t initialAllocations;
+
+LONGBOW_TEST_FIXTURE_SETUP(Locking)
+{
+ _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ initialAllocations = parcMemory_Outstanding();
+
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+
+ longBowTestCase_SetClipBoardData(testCase, dummy);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Locking)
+{
+ _DummyObject *dummy = longBowTestCase_GetClipBoardData(testCase);
+
+ parcObject_Release((PARCObject **) &dummy);
+
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ parcMemory_SetInterface(_originalMemoryProvider);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ parcMemory_SetInterface(_originalMemoryProvider);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Locking, parcObject_TryLock_Unlock)
+{
+ _DummyObject *dummy = longBowTestCase_GetClipBoardData(testCase);
+
+ bool actual = parcObject_TryLock(dummy);
+
+ assertTrue(actual, "Expected parcObject_TryLock to succeed.");
+
+ actual = parcObject_IsLocked(dummy);
+ assertTrue(actual, "Expected parcObject_IsLocked to be true.");
+
+ actual = parcObject_Unlock(dummy);
+ assertTrue(actual, "Expected parcObject_Unlock to succeed.");
+
+ actual = parcObject_IsLocked(dummy);
+ assertFalse(actual, "Expected parcObject_IsLocked to be false.");
+}
+
+LONGBOW_TEST_CASE(Locking, parcObject_Lock_Unlock)
+{
+ _DummyObject *dummy = longBowTestCase_GetClipBoardData(testCase);
+
+ bool actual = parcObject_Lock(dummy);
+
+ assertTrue(actual, "Expected parcObject_Lock to succeed.");
+
+ actual = parcObject_IsLocked(dummy);
+ assertTrue(actual, "Expected parcObject_IsLocked to be true.");
+
+ actual = parcObject_Unlock(dummy);
+ assertTrue(actual, "Expected parcObject_Unlock to succeed.");
+
+ actual = parcObject_IsLocked(dummy);
+ assertFalse(actual, "Expected parcObject_IsLocked to be false.");
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Locking, parcObject_TryLock_AlreadyLockedSameThread, .event = &LongBowTrapCannotObtainLockEvent)
+{
+ _DummyObject *dummy = longBowTestCase_GetClipBoardData(testCase);
+
+ bool actual = parcObject_TryLock(dummy);
+
+ assertTrue(actual, "Expected parcObject_TryLock to succeed.");
+
+ actual = parcObject_TryLock(dummy);
+
+ assertFalse(actual, "Expected parcObject_TryLock to fail when already locked by the same thread.");
+
+ actual = parcObject_Unlock(dummy);
+ assertTrue(actual, "Expected parcObject_Unlock to succeed.");
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Locking, parcObject_Lock_AlreadyLocked, .event = &LongBowTrapCannotObtainLockEvent)
+{
+ _DummyObject *dummy = longBowTestCase_GetClipBoardData(testCase);
+
+ bool actual = parcObject_Lock(dummy);
+
+ assertTrue(actual, "Expected parcObject_Lock to succeed.");
+
+ actual = parcObject_IsLocked(dummy);
+ assertTrue(actual, "Expected locked object to indicate being locked.");
+
+ parcObject_Lock(dummy);
+}
+
+LONGBOW_TEST_FIXTURE(WaitNotify)
+{
+ LONGBOW_RUN_TEST_CASE(WaitNotify, parcObject_WaitNotify);
+ LONGBOW_RUN_TEST_CASE(WaitNotify, parcObject_WaitNotify2);
+ LONGBOW_RUN_TEST_CASE(WaitNotify, parcObject_WaitUntil);
+ LONGBOW_RUN_TEST_CASE(WaitNotify, parcObject_WaitFor);
+ LONGBOW_RUN_TEST_CASE(WaitNotify, parcObject_WaitNotifyAll);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(WaitNotify)
+{
+ _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(WaitNotify)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+
+ parcMemory_SetInterface(_originalMemoryProvider);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// Just wait until told to wakeup, then increment a counter and unlock.
+static void *
+waiter(void *data)
+{
+ _DummyObject *dummy = data;
+
+ while (parcObject_TryLock(dummy) == false) {
+ ;
+ }
+ assertTrue(parcObject_IsLocked(dummy), "%p object %p not locked.", (void *) pthread_self(), (void *) dummy);
+ parcObject_Wait(dummy);
+
+ dummy->val++;
+ parcObject_Unlock(dummy);
+
+ return data;
+}
+
+LONGBOW_TEST_CASE(WaitNotify, parcObject_WaitNotify)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+
+ dummy->val = 0;
+
+ pthread_t thread_A;
+ pthread_t thread_B;
+ pthread_t thread_C;
+ pthread_create(&thread_A, NULL, waiter, dummy);
+ pthread_create(&thread_B, NULL, waiter, dummy);
+ pthread_create(&thread_C, NULL, waiter, dummy);
+
+ while (dummy->val != 3) {
+ while (parcObject_TryLock(dummy) == false) {
+ ;
+ }
+ parcObject_Notify(dummy);
+ parcObject_Unlock(dummy);
+ }
+
+ pthread_join(thread_A, NULL);
+// pthread_join(thread_B, NULL);
+// pthread_join(thread_C, NULL);
+
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_CASE(WaitNotify, parcObject_WaitNotifyAll)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+
+ dummy->val = 0;
+
+ pthread_t thread_A;
+ pthread_t thread_B;
+ pthread_t thread_C;
+ pthread_create(&thread_A, NULL, waiter, dummy);
+ pthread_create(&thread_B, NULL, waiter, dummy);
+ pthread_create(&thread_C, NULL, waiter, dummy);
+
+ while (dummy->val != 3) {
+ while (parcObject_TryLock(dummy) == false) {
+ ;
+ }
+ parcObject_NotifyAll(dummy);
+ parcObject_Unlock(dummy);
+ }
+
+ pthread_join(thread_A, NULL);
+// pthread_join(thread_B, NULL);
+// pthread_join(thread_C, NULL);
+
+ assertTrue(dummy->val == 3, "Expected the counter to be 3, actual %d", dummy->val);
+
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+static void *
+decrement(void *data)
+{
+ _DummyObject *dummy = data;
+
+ while (parcObject_TryLock(dummy) == false) {
+ ;
+ }
+ while (dummy->val < 12) {
+ parcObject_Wait(dummy);
+ dummy->val--;
+ }
+ parcObject_Unlock(dummy);
+
+ return data;
+}
+
+LONGBOW_TEST_CASE(WaitNotify, parcObject_WaitNotify2)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+
+ dummy->val = 0;
+
+ pthread_t thread_A;
+ pthread_create(&thread_A, NULL, decrement, dummy);
+
+ dummy->val = 2;
+ while (parcObject_TryLock(dummy) == false) {
+ ;
+ }
+ while (dummy->val <= 12) {
+ parcObject_Notify(dummy);
+ dummy->val += 2;
+ }
+ parcObject_Unlock(dummy);
+
+ pthread_join(thread_A, NULL);
+
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_CASE(WaitNotify, parcObject_WaitUntil)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+
+ dummy->val = 0;
+
+ time_t now;
+ time_t then;
+ time(&then);
+ if (parcObject_Lock(dummy)) {
+ struct timespec future;
+ future.tv_sec = then + 3;
+ future.tv_nsec = 0;
+ parcObject_WaitUntil(dummy, &future);
+
+ time(&now);
+ long expected = now - 1; // Subtract 1 because the future may have been computed at the 999,999,999 nanosecond mark.
+ assertTrue(now >= expected, "Expected now %ld, to be later than than %ld", now, expected);
+ parcObject_Unlock(dummy);
+ }
+
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_CASE(WaitNotify, parcObject_WaitFor)
+{
+ _DummyObject *dummy = parcObject_CreateInstance(_DummyObject);
+
+ dummy->val = 0;
+
+ time_t now;
+ time_t then;
+ time(&then);
+ if (parcObject_Lock(dummy)) {
+ uint64_t nanoSeconds = 1000000000;
+ parcObject_WaitFor(dummy, nanoSeconds);
+
+ time(&now);
+ now++; // Advance now by 1 because of the precision mismatch between gettimeofday and nanosecond resolution of parcObject_WaitFor
+ assertTrue(now >= then + (nanoSeconds / 1000000000),
+ "Expected now %ld, to be later than time %" PRIu64, now, then + (nanoSeconds / 1000000000));
+ parcObject_Unlock(dummy);
+ }
+
+ parcObject_Release((PARCObject **) &dummy);
+}
+
+LONGBOW_TEST_FIXTURE(Fail)
+{
+}
+
+typedef struct {
+ PARCObject *value;
+} TestData;
+
+LONGBOW_TEST_FIXTURE_SETUP(Fail)
+{
+ _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+ data->value = parcObject_CreateInstance(_DummyObjectNoHash);
+ if (data->value == NULL) {
+ return LONGBOW_STATUS_SETUP_FAILED;
+ }
+ longBowTestCase_SetClipBoardData(testCase, data);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Fail)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ parcObject_Release(&data->value);
+ parcMemory_Deallocate((void **) &data);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+
+ parcMemory_SetInterface(_originalMemoryProvider);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, _parcObject_PrefixLength_10000000);
+ LONGBOW_RUN_TEST_CASE(Performance, parcObject_CreateRelease);
+ LONGBOW_RUN_TEST_CASE(Performance, parcObject_Create);
+ LONGBOW_RUN_TEST_CASE(Performance, parcObject_AcquireRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ parcMemory_SetInterface(&PARCStdlibMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Performance, _parcObject_PrefixLength_10000000)
+{
+ // Test that the result is a multiple of the alignment value and greater than the size of _PARCObjectHeader.
+
+ // Compute the power of 2 value of sizeof(void *)
+ unsigned int v = sizeof(void *);
+ unsigned int r = 0; // r will be lg(v)
+
+ while (v >>= 1) {
+ r++;
+ }
+
+ PARCObjectDescriptor descriptor;
+
+ for (int i = r; i < 20; i++) {
+ descriptor.objectAlignment = 1 << i;
+ size_t actual = _parcObject_PrefixLength(&descriptor);
+ assertTrue((actual & (descriptor.objectAlignment - 1)) == 0,
+ "Alignment needs to be a multiple of %u", descriptor.objectAlignment);
+ }
+}
+
+#define OBJECT_COUNT 10000000
+#define OBJECT_SIZE 1200
+
+typedef struct { char bytes[OBJECT_SIZE]; } PerformanceObject;
+
+parcObject_Override(PerformanceObject, PARCObject);
+
+LONGBOW_TEST_CASE(Performance, parcObject_CreateRelease)
+{
+ for (int i = 0; i < OBJECT_COUNT; i++) {
+ PARCObject *object = parcObject_CreateInstanceImpl(&PerformanceObject_Descriptor);
+
+ PARCObject *object1 = parcObject_Acquire(object);
+ PARCObject *object2 = parcObject_Acquire(object);
+ parcObject_Release(&object1);
+ parcObject_Release(&object2);
+
+ parcObject_Release(&object);
+ }
+}
+
+void *objects[OBJECT_COUNT];
+
+LONGBOW_TEST_CASE(Performance, parcObject_AcquireRelease)
+{
+ PARCObject *object = parcObject_CreateInstanceImpl(&PerformanceObject_Descriptor);
+
+ for (int i = 0; i < OBJECT_COUNT; i++) {
+ objects[i] = parcObject_Acquire(object);
+ }
+
+ for (int i = 0; i < OBJECT_COUNT; i++) {
+ parcObject_Release(&objects[i]);
+ }
+
+ parcObject_Release(&object);
+}
+
+LONGBOW_TEST_CASE(Performance, parcObject_Create)
+{
+ for (int i = 0; i < OBJECT_COUNT; i++) {
+ objects[i] = parcObject_CreateInstanceImpl(&PerformanceObject_Descriptor);
+ }
+
+ for (int i = 0; i < OBJECT_COUNT; i++) {
+ parcObject_Release(&objects[i]);
+ }
+}
+
+LONGBOW_TEST_FIXTURE(Meta)
+{
+ LONGBOW_RUN_TEST_CASE(Meta, _metaDestructor_True);
+ LONGBOW_RUN_TEST_CASE(Meta, _metaDestructor_False);
+ LONGBOW_RUN_TEST_CASE(Meta, _metaDestructor_None);
+
+ LONGBOW_RUN_TEST_CASE(Meta, parcObjectDescriptor_Create);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Meta)
+{
+ _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ _DummyObject *data;
+ parcMemory_MemAlign((void **) &data, sizeof(void *), sizeof(_DummyObject));
+ data->val = 10;
+ longBowTestCase_SetClipBoardData(testCase, data);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Meta)
+{
+ _DummyObject *data = longBowTestCase_GetClipBoardData(testCase);
+ parcMemory_Deallocate((void **) &data);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ parcMemory_SetInterface(_originalMemoryProvider);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks %d memory allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Meta, parcObjectDescriptor_Create)
+{
+ const PARCObjectDescriptor *interface = parcObjectDescriptor_Create("Meta",
+ sizeof(struct timeval), sizeof(void*),
+ true,
+ _meta_destructor_true, NULL, _meta_copy, _meta_toString,
+ _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL,
+ &PARCObject_Descriptor, NULL);
+
+ assertNotNull(interface, "Expected interface instance to be allocated correctly.");
+
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &interface);
+ assertNull(interface, "Expected parcObjectDescriptor_Destroy to NULL the input pointer");
+}
+
+LONGBOW_TEST_CASE(Meta, _metaDestructor_True)
+{
+ const PARCObjectDescriptor *interface =
+ parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true,
+ _meta_destructor_true, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL,
+ &PARCObject_Descriptor, NULL);
+ _DummyObject *data = longBowTestCase_GetClipBoardData(testCase);
+ bool actual = _parcObject_Destructor(interface, (PARCObject **) &data);
+
+ assertTrue(actual, "Expected destructor to return true.");
+
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &interface);
+}
+
+LONGBOW_TEST_CASE(Meta, _metaDestructor_False)
+{
+ const PARCObjectDescriptor *descriptor =
+ parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true,
+ _meta_destructor_false, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL,
+ &PARCObject_Descriptor, NULL);
+ _DummyObject *data = longBowTestCase_GetClipBoardData(testCase);
+ bool actual = _parcObject_Destructor(descriptor, (PARCObject **) &data);
+
+ assertNull(data, "Expected destructor function to have been called to nullify the reference.");
+ assertFalse(actual, "Expected destructor to return false.");
+
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor);
+}
+
+LONGBOW_TEST_CASE(Meta, _metaDestructor_None)
+{
+ const PARCObjectDescriptor *interface = parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true,
+ NULL, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, &PARCObject_Descriptor, NULL);
+ _DummyObject *data = longBowTestCase_GetClipBoardData(testCase);
+ _parcObject_Destructor(interface, (void **) &data);
+
+ assertNotNull(data, "Expected destructor function to have been called to nullify the reference.");
+
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &interface);
+}
+
+LONGBOW_TEST_FIXTURE(PARCObjectDescriptor)
+{
+ LONGBOW_RUN_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_Create);
+ LONGBOW_RUN_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_CreateExtension);
+ LONGBOW_RUN_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_GetSuperType);
+ LONGBOW_RUN_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_GetTypeState);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(PARCObjectDescriptor)
+{
+ longBowTestCase_SetInt(testCase, "initialAllocations", parcMemory_Outstanding());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(PARCObjectDescriptor)
+{
+ int initialAllocations = longBowTestCase_GetInt(testCase, "initialAllocations");
+
+ uint32_t outstandingAllocations = parcMemory_Outstanding() - initialAllocations;
+
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations);
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_Create)
+{
+ const PARCObjectDescriptor *descriptor = parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true,
+ NULL, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, &PARCObject_Descriptor, NULL);
+
+ parcObjectDescriptor_Destroy((PARCObjectDescriptor **) &descriptor);
+}
+
+LONGBOW_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_CreateExtension)
+{
+ PARCObjectDescriptor *descriptor = parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true,
+ NULL, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, &PARCObject_Descriptor, NULL);
+
+ PARCObjectDescriptor *extension = parcObjectDescriptor_CreateExtension(descriptor, "Extension");
+
+ parcObjectDescriptor_Destroy(&extension);
+ parcObjectDescriptor_Destroy(&descriptor);
+}
+
+LONGBOW_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_GetSuperType)
+{
+ PARCObjectDescriptor *descriptor = parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true,
+ NULL, NULL, _meta_copy, _meta_toString, _meta_equals, _meta_compare, _meta_hashCode, _meta_toJson, NULL, &PARCObject_Descriptor, NULL);
+
+ const PARCObjectDescriptor *superType = parcObjectDescriptor_GetSuperType(descriptor);
+
+ assertTrue(superType == &PARCObject_Descriptor, "Expected a pointer to PARCObject_Descriptor");
+
+ parcObjectDescriptor_Destroy(&descriptor);
+}
+
+LONGBOW_TEST_CASE(PARCObjectDescriptor, parcObjectDescriptor_GetTypeState)
+{
+ PARCObjectDescriptor *descriptor = parcObjectDescriptor_Create("Meta", sizeof(struct timeval), sizeof(void*), true,
+ NULL, NULL, _meta_copy, _meta_toString, _meta_equals,
+ _meta_compare, _meta_hashCode, _meta_toJson, NULL,
+ &PARCObject_Descriptor,
+ (PARCObjectTypeState *) &PARCObject_Descriptor);
+
+ PARCObjectTypeState *state = parcObjectDescriptor_GetTypeState(descriptor);
+
+ assertTrue(state == &PARCObject_Descriptor, "Expected a pointer to PARCObject_Descriptor");
+
+ parcObjectDescriptor_Destroy(&descriptor);
+}
+
+LONGBOW_TEST_FIXTURE(StaticObjects)
+{
+ LONGBOW_RUN_TEST_CASE(StaticObjects, parcObject_WrapImpl);
+ LONGBOW_RUN_TEST_CASE(StaticObjects, parcObject_InitInstanceImpl);
+ LONGBOW_RUN_TEST_CASE(StaticObjects, parcObject_InitAndClearInstanceImpl);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(StaticObjects)
+{
+ _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(StaticObjects)
+{
+ parcMemory_SetInterface(_originalMemoryProvider);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(StaticObjects, parcObject_WrapImpl)
+{
+ char *origin = (char[parcObject_TotalSize(sizeof(void*), 10)]) { 0 };
+
+ PARCObject *result = parcObject_WrapImpl(origin, &parcObject_DescriptorName(PARCObject));
+
+ parcObject_AssertValid(result);
+
+ parcObject_Release(&result);
+}
+
+PARCObject *globalObject = parcObject_Instance(PARCObject, sizeof(void*), 10);
+
+LONGBOW_TEST_CASE(StaticObjects, parcObject_InitInstanceImpl)
+{
+ parcObject_InitInstanceImpl(globalObject, &PARCObject_Descriptor);
+
+ parcObject_AssertValid(globalObject);
+
+// parcObject_Release(&globalObject);
+}
+
+LONGBOW_TEST_CASE(StaticObjects, parcObject_InitAndClearInstanceImpl)
+{
+ parcObject_InitAndClearInstanceImpl(globalObject, &PARCObject_Descriptor);
+
+ parcObject_AssertValid(globalObject);
+
+// parcObject_Release(&globalObject);
+}
+
+LONGBOW_TEST_FIXTURE(Synchronization)
+{
+ LONGBOW_RUN_TEST_CASE(Synchronization, parcObject_SynchronizeBegin);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Synchronization)
+{
+ _originalMemoryProvider = parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Synchronization)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+
+ parcMemory_SetInterface(_originalMemoryProvider);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestRunner_GetName(testRunner), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Synchronization, parcObject_SynchronizeBegin)
+{
+ PARCObject *dummy = parcObject_CreateInstance(_DummyObject);
+
+ bool result = parcObject_BarrierSet(dummy);
+ assertTrue(result, "Expected parcObject_BarrierSet to always return true.");
+
+ _PARCObjectHeader *header = _parcObject_Header(dummy);
+ assertTrue(header->barrier, "Expected the header barrier to be set.");
+
+ result = parcObject_BarrierUnset(dummy);
+ assertFalse(result, "Expected parcObject_BarrierUnset to always return false.");
+ assertFalse(header->barrier, "Expected the header barrier to NOT be set.");
+
+ parcObject_Release(&dummy);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parcObject);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
+
diff --git a/libparc/parc/algol/test/test_parc_PathName.c b/libparc/parc/algol/test/test_parc_PathName.c
new file mode 100755
index 00000000..b596aaa2
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_PathName.c
@@ -0,0 +1,458 @@
+/*
+ * 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_PathName.c"
+#include <LongBow/unit-test.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_SafeMemory.h"
+#include <parc/testing/parc_ObjectTesting.h>
+
+#define PATH_SEGMENT "A"
+
+LONGBOW_TEST_RUNNER(parc_PathName)
+{
+ // 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);
+ LONGBOW_RUN_TEST_FIXTURE(AcquireRelease);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_PathName)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_PathName)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(AcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcPathName_Create);
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcPathName_Release);
+ LONGBOW_RUN_TEST_CASE(AcquireRelease, parcPathName_AcquireRelease);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(AcquireRelease)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(AcquireRelease)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(AcquireRelease, parcPathName_Create)
+{
+ PARCPathName *pathName = parcPathName_Create();
+ assertNotNull(pathName, "Expected a non-null pointer");
+
+ parcPathName_Release(&pathName);
+ assertNull(pathName, "Expected parcPathName_Release to null the pointer");
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcPathName_Release)
+{
+ PARCPathName *pathName = parcPathName_Create();
+ assertNotNull(pathName, "Expected a non-null pointer");
+
+ parcPathName_Release(&pathName);
+ assertNull(pathName, "Expected parcPathName_Release to null the pointer");
+}
+
+LONGBOW_TEST_CASE(AcquireRelease, parcPathName_AcquireRelease)
+{
+ PARCPathName *original = parcPathName_Create();
+ assertNotNull(original, "Expected non-null result from parcPathName_Create()");
+
+ PARCPathName *reference = parcPathName_Acquire(original);
+ assertTrue(original == reference, "Expected the reference to be equal to the original.");
+
+ parcPathName_Release(&original);
+ assertNull(original, "Expected parcDeque_Release to null the pointer");
+
+ parcPathName_Append(reference, (void *) "Hello");
+ size_t expected = 1;
+ size_t actual = parcPathName_Size(reference);
+ assertTrue(expected == actual,
+ "Expected size %zd, actual %zd", expected, actual);
+ parcPathName_Release(&reference);
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Create);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Size);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Append);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Prepend);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_IsAbsolute);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_MakeAbsolute);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Parse_AbsolutePath);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Parse_AbsolutePath_Limited);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Parse_RelativePath);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_ToString_AbsolutePath);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_ToString_RelativePath);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Head);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Tail);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Tail_ExceedsLength);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcPathName_Copy);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Global, parcPathName_Size)
+{
+ char *path = "/a/b/c";
+ PARCPathName *pathName = parcPathName_Parse(path);
+ assertNotNull(pathName, "Expected a non-null pointer");
+ assertTrue(pathName->isAbsolute, "Expected the PARCPathName to be absolute.");
+
+ assertTrue(parcPathName_Size(pathName) == 3, "Expected 3, actual %zu", parcPathName_Size(pathName));
+ parcPathName_Release(&pathName);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Prepend)
+{
+ PARCPathName *pathName = parcPathName_Create();
+ size_t size = 1000;
+
+ char expected[10];
+ for (size_t i = 0; i < size; i++) {
+ sprintf(expected, "%zd", i);
+ parcPathName_Prepend(pathName, expected);
+ }
+ assertNotNull(pathName, "Expected a non-null pointer");
+
+ size_t actual = parcPathName_Size(pathName);
+ assertTrue(size == actual,
+ "Expected %zd, actual %zd", size, actual);
+
+ for (size_t i = 0; i < size; i++) {
+ sprintf(expected, "%zd", size - i - 1);
+ char *segment = parcDeque_GetAtIndex(pathName->path, i);
+ assertTrue(strcmp(segment, expected) == 0,
+ "Expected %s, actual %s", expected, segment);
+ }
+
+ parcPathName_Release(&pathName);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Append)
+{
+ PARCPathName *pathName = parcPathName_Create();
+ size_t size = 1000;
+
+ char expected[10];
+ for (size_t i = 0; i < size; i++) {
+ sprintf(expected, "%zd", i);
+ parcPathName_Append(pathName, expected);
+ }
+ assertNotNull(pathName, "Expected a non-null pointer");
+
+ size_t actual = parcPathName_Size(pathName);
+ assertTrue(size == actual,
+ "Expected %zd, actual %zd", size, actual);
+
+ for (size_t i = 0; i < size; i++) {
+ sprintf(expected, "%zd", i);
+ char *segment = parcDeque_GetAtIndex(pathName->path, i);
+ assertTrue(strcmp(segment, expected) == 0,
+ "Expected %s, actual %s", expected, segment);
+ }
+
+ parcPathName_Release(&pathName);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Create)
+{
+ PARCPathName *pathName = parcPathName_Create();
+ assertNotNull(pathName, "Expected a non-null pointer");
+
+ parcPathName_Release(&pathName);
+ assertNull(pathName, "Expected parcPathName_Release to null the pointer");
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_IsAbsolute)
+{
+ char *path = "/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/aa/bb/cc/dd/ee/ff/gg/hh/ii/jj/kk/ll/mm/nn/oo/pp/qq/rr/ss/tt/uu/vv/ww/xx/yy/zz";
+ PARCPathName *pathName = parcPathName_Parse(path);
+ assertNotNull(pathName, "Expected a non-null pointer");
+ assertTrue(parcPathName_IsAbsolute(pathName), "Expected the PARCPathName to be absolute.");
+
+ parcPathName_Release(&pathName);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_MakeAbsolute)
+{
+#define PATH "a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z"
+ char *expected = PATH;
+ PARCPathName *pathName = parcPathName_Parse(expected);
+ assertNotNull(pathName, "Expected a non-null pointer");
+ assertFalse(pathName->isAbsolute, "Expected the PARCPathName to be relative.");
+
+ parcPathName_MakeAbsolute(pathName, true);
+
+ char *actual = parcPathName_ToString(pathName);
+ assertTrue(strcmp("/" PATH, actual) == 0,
+ "Expected '%s' actual '%s'", expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+ parcPathName_Release(&pathName);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Parse_AbsolutePath)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ for (int i = 0; i < 1000; i++) {
+ parcBufferComposer_Format(composer, "/%d", i);
+ }
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *path = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ PARCPathName *pathName = parcPathName_Parse(path);
+ assertNotNull(pathName, "Expected a non-null pointer");
+ assertTrue(pathName->isAbsolute, "Expected the PARCPathName to be absolute.");
+
+
+ char *actual = parcPathName_ToString(pathName);
+ assertTrue(strcmp(path, actual) == 0, "Expected %s, actual %s", path, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcMemory_Deallocate((void **) &path);
+
+ parcPathName_Release(&pathName);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Parse_AbsolutePath_Limited)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ for (int i = 0; i < 10; i++) {
+ parcBufferComposer_Format(composer, "/%d", i);
+ }
+ parcBufferComposer_Format(composer, "?hello world");
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *path = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ size_t limit = strchr(path, '?') - path;
+ PARCPathName *pathName = parcPathName_ParseToLimit(limit, path);
+
+ assertNotNull(pathName, "Expected a non-null pointer");
+ assertTrue(pathName->isAbsolute, "Expected the PARCPathName to be absolute.");
+
+ path[limit] = 0;
+ char *actual = parcPathName_ToString(pathName);
+ assertTrue(strcmp(path, actual) == 0, "Expected %s, actual %s", path, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcMemory_Deallocate((void **) &path);
+
+ parcPathName_Release(&pathName);
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Parse_RelativePath)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ for (int i = 0; i < 1000; i++) {
+ parcBufferComposer_Format(composer, "%d/", i);
+ }
+ parcBufferComposer_Format(composer, "%d", 1000);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *expected = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ PARCPathName *pathName = parcPathName_Parse(expected);
+ assertNotNull(pathName, "Expected a non-null pointer");
+ assertFalse(pathName->isAbsolute, "Expected the PARCPathName to be relative.");
+
+ char *actual = parcPathName_ToString(pathName);
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s' actual '%s'", expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+ parcMemory_Deallocate((void **) &expected);
+
+ parcPathName_Release(&pathName);
+
+ parcBufferComposer_Release(&composer);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_ToString_AbsolutePath)
+{
+ char *path = "/a/b/c";
+ PARCPathName *pathName = parcPathName_Parse(path);
+ assertNotNull(pathName, "Expected a non-null pointer");
+ assertTrue(pathName->isAbsolute, "Expected the PARCPathName to be absolute.");
+
+ char *actual = parcPathName_ToString(pathName);
+
+ assertTrue(strcmp(path, actual) == 0, "Expected '%s' actual '%s'", path, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+
+ parcPathName_Release(&pathName);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_ToString_RelativePath)
+{
+ char *path = "a/b/c";
+ PARCPathName *pathName = parcPathName_Parse(path);
+ assertNotNull(pathName, "Expected a non-null pointer");
+ assertFalse(pathName->isAbsolute, "Expected the PARCPathName to be relative.");
+
+ char *actual = parcPathName_ToString(pathName);
+
+ assertTrue(strcmp(path, actual) == 0, "Expected '%s' actual '%s'", path, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+
+ parcPathName_Release(&pathName);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Head)
+{
+ PARCPathName *original = parcPathName_Parse("/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT);
+ assertNotNull(original, "Expected a non-null pointer");
+
+ PARCPathName *expected = parcPathName_Parse("/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT);
+ PARCPathName *actual = parcPathName_Head(original, 3);
+
+ assertTrue(parcPathName_Equals(expected, actual),
+ "expected did not match actual");
+
+ parcPathName_Release(&original);
+ parcPathName_Release(&expected);
+ parcPathName_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Tail)
+{
+ PARCPathName *original = parcPathName_Parse("/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT);
+ assertNotNull(original, "Expected a non-null pointer");
+
+ PARCPathName *expected = parcPathName_Parse(PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT);
+ PARCPathName *actual = parcPathName_Tail(original, 3);
+
+ assertTrue(parcPathName_Equals(expected, actual),
+ "expected did not match actual");
+
+ parcPathName_Release(&original);
+ parcPathName_Release(&expected);
+ parcPathName_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Tail_ExceedsLength)
+{
+ PARCPathName *original = parcPathName_Parse("/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT "/" PATH_SEGMENT);
+ assertNotNull(original, "Expected a non-null pointer");
+
+ PARCPathName *actual = parcPathName_Tail(original, 10000000);
+
+ parcPathName_MakeAbsolute(original, false);
+
+ assertTrue(parcPathName_Equals(original, actual),
+ "expected did not match actual");
+
+ parcPathName_Release(&original);
+ parcPathName_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Equals)
+{
+ PARCPathName *x = parcPathName_Parse("/a/b/c/d/");
+ PARCPathName *y = parcPathName_Parse("/a/b/c/d/");
+ PARCPathName *z = parcPathName_Parse("/a/b/c/d/");
+ PARCPathName *u1 = parcPathName_Parse("/a/b/c/d/e");
+ PARCPathName *u2 = parcPathName_Parse("/a/b/c/");
+ PARCPathName *u3 = parcPathName_Parse("a/b/c/");
+
+ parcObjectTesting_AssertEqualsFunction(parcPathName_Equals, x, y, z, u1, u2, u3, NULL);
+
+ parcPathName_Release(&x);
+ parcPathName_Release(&y);
+ parcPathName_Release(&z);
+ parcPathName_Release(&u1);
+ parcPathName_Release(&u2);
+ parcPathName_Release(&u3);
+}
+
+LONGBOW_TEST_CASE(Global, parcPathName_Copy)
+{
+ PARCPathName *x = parcPathName_Parse("/a/b/c/d/");
+ PARCPathName *y = parcPathName_Copy(x);
+
+ assertTrue(parcPathName_Equals(x, y), "Expected the copy to be equal to the original.");
+
+ parcPathName_Release(&x);
+ parcPathName_Release(&y);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_PathName);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_PriorityQueue.c b/libparc/parc/algol/test/test_parc_PriorityQueue.c
new file mode 100644
index 00000000..d42066e4
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_PriorityQueue.c
@@ -0,0 +1,492 @@
+/*
+ * 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 <config.h>
+#include <inttypes.h>
+
+#include "../parc_PriorityQueue.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(parc_PriorityQueue)
+{
+ // 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_PriorityQueue)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_PriorityQueue)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Add);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Add_Expand);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Clear);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Clear_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Create);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_ParcFreeDestroyer);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Peek);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Poll);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Peek_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Poll_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Size);
+ LONGBOW_RUN_TEST_CASE(Global, parcPriorityQueue_Uint64CompareTo);
+}
+
+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;
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Add)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 60, 70, 50, 71, 72, 55 };
+ size_t count = 6;
+
+ for (int i = 0; i < count; i++) {
+ parcPriorityQueue_Add(queue, &data[i]);
+ }
+
+ assertTrue(parcPriorityQueue_Size(queue) == count, "Wrong size got %zu expected %zu", parcPriorityQueue_Size(queue), count);
+ parcPriorityQueue_Destroy(&queue);
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Add_Expand)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ size_t capacity = queue->capacity;
+ for (int i = 0; i <= capacity; i++) {
+ parcPriorityQueue_Add(queue, &capacity);
+ }
+
+ assertTrue(capacity < queue->capacity, "Did not expand queue before %zu after %zu", capacity, queue->capacity);
+ parcPriorityQueue_Destroy(&queue);
+}
+
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Clear)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 60, 70, 50, 71, 72, 55 };
+ size_t count = 6;
+
+ for (int i = 0; i < count; i++) {
+ parcPriorityQueue_Add(queue, &data[i]);
+ }
+
+ parcPriorityQueue_Clear(queue);
+
+ assertTrue(parcPriorityQueue_Size(queue) == 0, "Wrong size got %zu expected %d", parcPriorityQueue_Size(queue), 0);
+ parcPriorityQueue_Destroy(&queue);
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Clear_Destroy)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, parcPriorityQueue_ParcFreeDestroyer);
+ uint64_t *value = parcMemory_Allocate(sizeof(uint64_t));
+ assertNotNull(value, "parcMemory_Allocate(%zu) returned NULL", sizeof(uint64_t));
+ *value = 1;
+ parcPriorityQueue_Add(queue, value);
+
+ parcPriorityQueue_Clear(queue);
+
+ assertTrue(parcPriorityQueue_Size(queue) == 0, "Wrong size got %zu expected %d", parcPriorityQueue_Size(queue), 0);
+ parcPriorityQueue_Destroy(&queue);
+
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance after clear with destroy: %u", parcMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Create)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_ParcFreeDestroyer)
+{
+ size_t before_balance = parcMemory_Outstanding();
+ uint64_t *a = parcMemory_Allocate(sizeof(uint64_t));
+ assertNotNull(a, "parcMemory_Allocate(%zu) returned NULL", sizeof(uint64_t));
+ *a = 1;
+ parcPriorityQueue_ParcFreeDestroyer((void **) &a);
+ size_t after_balance = parcMemory_Outstanding();
+ assertTrue(a == NULL, "Did not null double pointer");
+ assertTrue(before_balance == after_balance, "Memory imbalance after destroy: before %zu after %zu", before_balance, after_balance);
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Peek)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 60, 70, 50, 71, 72, 55 };
+ size_t count = 6;
+
+ for (int i = 0; i < count; i++) {
+ parcPriorityQueue_Add(queue, &data[i]);
+ }
+
+ uint64_t *test = parcPriorityQueue_Peek(queue);
+
+ assertTrue(*test == 50, "Wrong head element, expected 50 got %" PRIu64 "", *test);
+ assertTrue(parcPriorityQueue_Size(queue) == count, "Queue should not have shunk, size %zu expected %zu", parcPriorityQueue_Size(queue), count);
+ parcPriorityQueue_Destroy(&queue);
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Poll)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 60, 70, 50, 71, 72, 55 };
+ size_t count = 6;
+
+ for (int i = 0; i < count; i++) {
+ parcPriorityQueue_Add(queue, &data[i]);
+ }
+
+ uint64_t *test = parcPriorityQueue_Poll(queue);
+
+ assertTrue(*test == 50, "Wrong head element, expected 50 got %" PRIu64 "", *test);
+ assertTrue(queue->size == count - 1, "Queue should have shunk, size %zu expected %zu", queue->size, count - 1);
+ parcPriorityQueue_Destroy(&queue);
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Peek_Empty)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t *test = parcPriorityQueue_Peek(queue);
+ assertNull(test, "Peek on empty queue should return null, got %p", (void *) test);
+ parcPriorityQueue_Destroy(&queue);
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Poll_Empty)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t *test = parcPriorityQueue_Poll(queue);
+ assertNull(test, "Poll on empty queue should return null, got %p", (void *) test);
+ parcPriorityQueue_Destroy(&queue);
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Size)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcPriorityQueue_Uint64CompareTo)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_BubbleUp_True);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_BubbleUp_False);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_Expand);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_LeftChildIndex);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_ParentIndex);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_RightChildIndex);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_Swap);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_TrickleDown);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_TrickleLeftChild_True);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_TrickleLeftChild_False);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_TrickleRightChild_Case1_True);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_TrickleRightChild_Case2_True);
+ LONGBOW_RUN_TEST_CASE(Local, parcPriorityQueue_TrickleRightChild_Case1_False);
+}
+
+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, parcPriorityQueue_BubbleUp_True)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 50, 6 };
+
+ queue->array[0].data = &data[0];
+ queue->array[1].data = &data[1];
+ queue->size = 2;
+
+ _bubbleUp(queue, 1);
+ assertTrue(queue->array[0].data == &data[1], "Element 6 did not make it to the root");
+
+ parcPriorityQueue_Destroy(&queue);
+}
+
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_BubbleUp_False)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 50, 60 };
+
+ queue->array[0].data = &data[0];
+ queue->array[1].data = &data[1];
+ queue->size = 2;
+
+ _bubbleUp(queue, 1);
+ assertTrue(queue->array[0].data == &data[0], "Element 60 did not stay as child");
+
+ parcPriorityQueue_Destroy(&queue);
+}
+
+
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_Expand)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ size_t before_capacity = queue->capacity;
+ _expand(queue);
+ size_t after_capacity = queue->capacity;
+
+ assertTrue(before_capacity < after_capacity, "Expected after capacity %zu to be larger than before %zu", after_capacity, before_capacity);
+ parcPriorityQueue_Destroy(&queue);
+}
+
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_LeftChildIndex)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_ParentIndex)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_RightChildIndex)
+{
+ testUnimplemented("");
+}
+
+/**
+ * Swaps two elements
+ */
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_Swap)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 50, 6 };
+
+ queue->array[0].data = &data[0];
+ queue->array[1].data = &data[1];
+ queue->size = 2;
+
+ _swap(queue, 0, 1);
+ assertTrue(queue->array[0].data == &data[1], "array[0] does not equal data[1]: %p != %p",
+ (void *) queue->array[0].data, (void *) &data[1]);
+ assertTrue(queue->array[1].data == &data[0], "array[1] does not equal data[0]: %p != %p",
+ (void *) queue->array[1].data, (void *) &data[0]);
+
+ parcPriorityQueue_Destroy(&queue);
+}
+
+/**
+ * Tests each case in TrickleDown:
+ * - right child exists, then
+ * - no right child, only left child, then
+ * - no child
+ *
+ * 60 50
+ * / \ / \
+ * 70 50 ====> 70 55
+ * / \ / \ / \ / \
+ * 71 72 55 x 71 72 60 x
+ */
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_TrickleDown)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 60, 70, 50, 71, 72, 55 };
+
+ queue->size = 6;
+ for (int i = 0; i < queue->size; i++) {
+ queue->array[i].data = &data[i];
+ }
+
+ _trickleDown(queue, 0);
+ assertTrue(*((uint64_t *) queue->array[0].data) == 50,
+ "Root not 50, got %" PRIu64 "\n",
+ (uint64_t) *((uint64_t *) queue->array[0].data));
+ assertTrue(*((uint64_t *) queue->array[2].data) == 55,
+ "Right not 55, got %" PRIu64 "\n",
+ (uint64_t) *((uint64_t *) queue->array[2].data));
+ assertTrue(*((uint64_t *) queue->array[5].data) == 60,
+ "Last not 60, got %" PRIu64 "\n",
+ (uint64_t) *((uint64_t *) queue->array[5].data));
+
+ parcPriorityQueue_Destroy(&queue);
+}
+
+/**
+ * Tests the TRUE case of this condition
+ *
+ * Case 3: Left child exists (right does not) and l.value < n.value
+ * In this case, swap(n.index, l.index) and set n.index = l.index
+ * 50 6
+ * / \ ===> / \
+ * 6 x 50 x
+ */
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_TrickleLeftChild_True)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 50, 6 };
+
+ queue->array[0].data = &data[0];
+ queue->array[1].data = &data[1];
+ queue->size = 2;
+
+ size_t nextElementIndex = _trickleLeftChild(queue, 0, 1);
+ assertTrue(nextElementIndex == 1, "nextElementIndex should have been left child 1, got %zu\n", nextElementIndex);
+
+ parcPriorityQueue_Destroy(&queue);
+}
+
+/**
+ * Tests the FALSE case of this condition
+ *
+ * Case 3: Left child exists (right does not) and l.value < n.value
+ * In this case, swap(n.index, l.index) and set n.index = l.index
+ * 50 6
+ * / \ ===> / \
+ * 6 x 50 x
+ */
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_TrickleLeftChild_False)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 6, 50 };
+
+ queue->array[0].data = &data[0];
+ queue->array[1].data = &data[1];
+ queue->size = 2;
+
+ size_t nextElementIndex = _trickleLeftChild(queue, 0, 1);
+ assertTrue(nextElementIndex == 0, "nextElementIndex should have been root 0, got %zu\n", nextElementIndex);
+
+ parcPriorityQueue_Destroy(&queue);
+}
+
+
+/**
+ * Tests the TRUE case
+ *
+ * Case 1: Right child exists and r.value < n.value && r.value < l.value
+ * In this case, swap(n.index, r.index) and set n.index = r.index.
+ * 50 6
+ * / \ ===> / \
+ * 9 6 9 50
+ */
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_TrickleRightChild_Case1_True)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 50, 9, 6 };
+
+ queue->array[0].data = &data[0];
+ queue->array[1].data = &data[1];
+ queue->array[2].data = &data[2];
+ queue->size = 3;
+
+ size_t nextElementIndex = _trickleRightChild(queue, 0, 1, 2);
+ assertTrue(nextElementIndex == 2, "nextElementIndex should have been right 2, got %zu\n", nextElementIndex);
+
+ parcPriorityQueue_Destroy(&queue);
+}
+
+/**
+ * Tests the FALSE case
+ *
+ * Case 1: Right child exists and r.value < n.value && r.value < l.value
+ * In this case, swap(n.index, r.index) and set n.index = r.index.
+ * 50 6
+ * / \ ===> / \
+ * 9 6 9 50
+ */
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_TrickleRightChild_Case1_False)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+
+ // r.value not < n.value
+ uint64_t data[] = { 6, 9, 50 };
+
+ queue->array[0].data = &data[0];
+ queue->array[1].data = &data[1];
+ queue->array[2].data = &data[2];
+ queue->size = 3;
+
+ size_t nextElementIndex = _trickleRightChild(queue, 0, 1, 2);
+ assertTrue(nextElementIndex == 0, "nextElementIndex should have been root 0, got %zu\n", nextElementIndex);
+
+ parcPriorityQueue_Destroy(&queue);
+}
+
+/**
+ * Tests the TRUE case
+ *
+ * Case 2: Right child exists and r.value < n.value && l.value <= r.value
+ * In this case swap(n.index, l.index) and set n.index = l.index
+ * This makes sense by transitivity that l <= r < n, so swap(n,l) satisfies the invariant.
+ * 50 6
+ * / \ ===> / \
+ * 6 9 50 9
+ */
+LONGBOW_TEST_CASE(Local, parcPriorityQueue_TrickleRightChild_Case2_True)
+{
+ PARCPriorityQueue *queue = parcPriorityQueue_Create(parcPriorityQueue_Uint64CompareTo, NULL);
+ uint64_t data[] = { 50, 6, 9 };
+
+ queue->array[0].data = &data[0];
+ queue->array[1].data = &data[1];
+ queue->array[2].data = &data[2];
+ queue->size = 3;
+
+ size_t nextElementIndex = _trickleRightChild(queue, 0, 1, 2);
+ assertTrue(nextElementIndex == 1, "nextElementIndex should have been left 1, got %zu\n", nextElementIndex);
+
+ parcPriorityQueue_Destroy(&queue);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_PriorityQueue);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Properties.c b/libparc/parc/algol/test/test_parc_Properties.c
new file mode 100644
index 00000000..994b8d8e
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Properties.c
@@ -0,0 +1,277 @@
+/*
+ * 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_Properties.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_Properties)
+{
+ // 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(Specialized);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Properties)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Properties)
+{
+ 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)
+{
+ PARCProperties *instance = parcProperties_Create();
+ assertNotNull(instance, "Expected non-null result from parcProperties_Create();");
+
+ parcObjectTesting_AssertAcquire(instance);
+
+ parcProperties_Release(&instance);
+ assertNull(instance, "Expected null result from parcProperties_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcProperties_Compare);
+ LONGBOW_RUN_TEST_CASE(Global, parcProperties_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcProperties_Display);
+ LONGBOW_RUN_TEST_CASE(Global, parcProperties_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcProperties_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcProperties_IsValid);
+ LONGBOW_RUN_TEST_CASE(Global, parcProperties_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Global, parcProperties_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, parcProperties_Compare)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcProperties_Copy)
+{
+ PARCProperties *instance = parcProperties_Create();
+ PARCProperties *copy = parcProperties_Copy(instance);
+ assertTrue(parcProperties_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcProperties_Release(&instance);
+ parcProperties_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Global, parcProperties_Display)
+{
+ PARCProperties *instance = parcProperties_Create();
+ parcProperties_SetProperty(instance, "foo", "bar");
+ parcProperties_SetProperty(instance, "xyzzy", "plugh");
+
+ parcProperties_Display(instance, 0);
+ parcProperties_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcProperties_Equals)
+{
+ PARCProperties *x = parcProperties_Create();
+ PARCProperties *y = parcProperties_Create();
+ PARCProperties *z = parcProperties_Create();
+
+ parcObjectTesting_AssertEquals(x, y, z, NULL);
+
+ parcProperties_Release(&x);
+ parcProperties_Release(&y);
+ parcProperties_Release(&z);
+}
+
+LONGBOW_TEST_CASE(Global, parcProperties_HashCode)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Global, parcProperties_IsValid)
+{
+ PARCProperties *instance = parcProperties_Create();
+ assertTrue(parcProperties_IsValid(instance), "Expected parcProperties_Create to result in a valid instance.");
+
+ parcProperties_Release(&instance);
+ assertFalse(parcProperties_IsValid(instance), "Expected parcProperties_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Global, parcProperties_ToJSON)
+{
+ PARCProperties *instance = parcProperties_Create();
+
+ parcProperties_SetProperty(instance, "foo", "bar");
+ PARCJSON *json = parcProperties_ToJSON(instance);
+
+ parcJSON_Release(&json);
+
+ parcProperties_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcProperties_ToString)
+{
+ PARCProperties *instance = parcProperties_Create();
+
+ parcProperties_SetProperty(instance, "foo", "bar");
+ parcProperties_SetProperty(instance, "bar", "baz");
+ char *string = parcProperties_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcProperties_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+ parcProperties_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Specialized)
+{
+ LONGBOW_RUN_TEST_CASE(Specialized, parcProperties_SetProperty);
+ LONGBOW_RUN_TEST_CASE(Specialized, parcProperties_GetProperty);
+ LONGBOW_RUN_TEST_CASE(Specialized, parcProperties_GetPropertyDefault);
+ LONGBOW_RUN_TEST_CASE(Specialized, parcProperties_GetAsBoolean_true);
+ LONGBOW_RUN_TEST_CASE(Specialized, parcProperties_GetAsBoolean_false);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Specialized)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Specialized)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Specialized, parcProperties_SetProperty)
+{
+ PARCProperties *instance = parcProperties_Create();
+ char *expected = "bar";
+ parcProperties_SetProperty(instance, "foo", expected);
+
+ const char *actual = parcProperties_GetProperty(instance, "foo");
+ assertTrue(strcmp("bar", actual) == 0, "Expected %s, actual %s", expected, actual);
+
+ parcProperties_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Specialized, parcProperties_GetProperty)
+{
+ PARCProperties *instance = parcProperties_Create();
+ char *expected = "bar";
+ parcProperties_SetProperty(instance, "foo", expected);
+
+ const char *actual = parcProperties_GetProperty(instance, "foo");
+ assertTrue(strcmp("bar", actual) == 0, "Expected %s, actual %s", expected, actual);
+
+ parcProperties_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Specialized, parcProperties_GetPropertyDefault)
+{
+ PARCProperties *instance = parcProperties_Create();
+ char *expected = "bar";
+ parcProperties_SetProperty(instance, "foo", expected);
+
+ const char *actual = parcProperties_GetPropertyDefault(instance, "blurfl", "defaultValue");
+ assertTrue(strcmp("defaultValue", actual) == 0, "Expected %s, actual %s", "defaultValue", actual);
+
+ parcProperties_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Specialized, parcProperties_GetAsBoolean_true)
+{
+ PARCProperties *instance = parcProperties_Create();
+ char *expected = "true";
+ parcProperties_SetProperty(instance, "foo", expected);
+
+ bool actual = parcProperties_GetAsBoolean(instance, "foo", false);
+ assertTrue(actual, "Expected true");
+
+ parcProperties_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Specialized, parcProperties_GetAsBoolean_false)
+{
+ PARCProperties *instance = parcProperties_Create();
+ char *expected = "false";
+ parcProperties_SetProperty(instance, "foo", expected);
+
+ bool actual = parcProperties_GetAsBoolean(instance, "foo", true);
+ assertFalse(actual, "Expected false");
+
+ parcProperties_Release(&instance);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Properties);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
+
+
diff --git a/libparc/parc/algol/test/test_parc_RandomAccessFile.c b/libparc/parc/algol/test/test_parc_RandomAccessFile.c
new file mode 100644
index 00000000..796b69d8
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_RandomAccessFile.c
@@ -0,0 +1,380 @@
+/*
+ * 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_RandomAccessFile.c"
+
+#include <sys/param.h>
+
+#include <fcntl.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(parcRandomAccessFile_RandomAccessFile)
+{
+ // 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(parcRandomAccessFile_RandomAccessFile)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parcRandomAccessFile_RandomAccessFile)
+{
+ 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)
+{
+ char dirname[] = "/tmp/RandomAccessFile_XXXXXX";
+ char filename[MAXPATHLEN];
+
+ char *temporaryDirectory = mkdtemp(dirname);
+ assertNotNull(temporaryDirectory, "tmp_dirname should not be null");
+ sprintf(filename, "%s/tmpfile", temporaryDirectory);
+
+ PARCFile *file = parcFile_Create(filename);
+ PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file);
+ assertNotNull(instance, "Expected non-null result from parcRandomAccessFile_Open();");
+
+ parcObjectTesting_AssertAcquireReleaseContract(parcRandomAccessFile_Acquire, instance);
+
+ parcRandomAccessFile_Release(&instance);
+ assertNull(instance, "Expected null result from parcRandomAccessFile_Release();");
+
+ parcFile_Release(&file);
+}
+
+LONGBOW_TEST_FIXTURE(Object)
+{
+ LONGBOW_RUN_TEST_CASE(Object, parcRandomAccessFile_Display);
+ // XXX: Disable this test until fixed
+ //LONGBOW_RUN_TEST_CASE(Object, parcRandomAccessFile_Equals);
+ LONGBOW_RUN_TEST_CASE(Object, parcRandomAccessFile_IsValid);
+ LONGBOW_RUN_TEST_CASE(Object, parcRandomAccessFile_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Object, parcRandomAccessFile_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, parcRandomAccessFile_Display)
+{
+ char dirname[] = "/tmp/RandomAccessFile_XXXXXX";
+ char filename[MAXPATHLEN];
+
+ char *temporaryDirectory = mkdtemp(dirname);
+ assertNotNull(temporaryDirectory, "tmp_dirname should not be null");
+ sprintf(filename, "%s/tmpfile", temporaryDirectory);
+
+ PARCFile *file = parcFile_Create(filename);
+ PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file);
+ parcFile_Release(&file);
+
+ parcRandomAccessFile_Display(instance, 0);
+ parcRandomAccessFile_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcRandomAccessFile_Equals)
+{
+ char dirname[] = "/tmp/RandomAccessFile_XXXXXX";
+ char filename[MAXPATHLEN];
+
+ char *temporaryDirectory = mkdtemp(dirname);
+ assertNotNull(temporaryDirectory, "tmp_dirname should not be null");
+
+ sprintf(filename, "%s/tmpfileX", temporaryDirectory);
+ PARCFile *fileX = parcFile_Create(filename);
+
+ sprintf(filename, "%s/tmpfileY", temporaryDirectory);
+ PARCFile *fileY = parcFile_Create(filename);
+
+ sprintf(filename, "%s/tmpfileZ", temporaryDirectory);
+ PARCFile *fileZ = parcFile_Create(filename);
+
+ PARCRandomAccessFile *x = parcRandomAccessFile_Open(fileX);
+ PARCRandomAccessFile *y = parcRandomAccessFile_Open(fileY);
+ PARCRandomAccessFile *z = parcRandomAccessFile_Open(fileZ);
+ parcFile_Release(&fileX);
+ parcFile_Release(&fileY);
+ parcFile_Release(&fileZ);
+
+ parcObjectTesting_AssertEquals(x, y, z, NULL);
+
+ parcRandomAccessFile_Close(x);
+ parcRandomAccessFile_Close(y);
+ parcRandomAccessFile_Close(z);
+
+ parcRandomAccessFile_Release(&x);
+ parcRandomAccessFile_Release(&y);
+ parcRandomAccessFile_Release(&z);
+}
+
+LONGBOW_TEST_CASE(Object, parcRandomAccessFile_IsValid)
+{
+ char dirname[] = "/tmp/RandomAccessFile_XXXXXX";
+ char filename[MAXPATHLEN];
+
+ char *temporaryDirectory = mkdtemp(dirname);
+ assertNotNull(temporaryDirectory, "tmp_dirname should not be null");
+ sprintf(filename, "%s/tmpfile", temporaryDirectory);
+
+ PARCFile *file = parcFile_Create(filename);
+ parcFile_CreateNewFile(file);
+
+ PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file);
+ parcFile_Release(&file);
+ assertTrue(parcRandomAccessFile_IsValid(instance), "Expected parcRandomAccessFile_Create to result in a valid instance.");
+
+ parcRandomAccessFile_Release(&instance);
+ assertFalse(parcRandomAccessFile_IsValid(instance), "Expected parcRandomAccessFile_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Object, parcRandomAccessFile_ToJSON)
+{
+ char dirname[] = "/tmp/RandomAccessFile_XXXXXX";
+ char filename[MAXPATHLEN];
+
+ char *temporaryDirectory = mkdtemp(dirname);
+ assertNotNull(temporaryDirectory, "tmp_dirname should not be null");
+ sprintf(filename, "%s/tmpfile", temporaryDirectory);
+
+ PARCFile *file = parcFile_Create(filename);
+ PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file);
+ parcFile_Release(&file);
+
+ PARCJSON *json = parcRandomAccessFile_ToJSON(instance);
+
+ const PARCJSONPair *pair = parcJSON_GetPairByName(json, "fname");
+ PARCJSONValue *value = parcJSONPair_GetValue(pair);
+ PARCBuffer *buffer = parcJSONValue_GetString(value);
+
+ char *string = parcBuffer_ToString(buffer);
+ assertTrue(strcmp(filename, string) == 0, "The file was stored correctly");
+
+ parcMemory_Deallocate(&string);
+
+ parcJSON_Release(&json);
+
+ parcRandomAccessFile_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcRandomAccessFile_ToString)
+{
+ char dirname[] = "/tmp/RandomAccessFile_XXXXXX";
+ char filename[MAXPATHLEN];
+
+ char *temporaryDirectory = mkdtemp(dirname);
+ assertNotNull(temporaryDirectory, "tmp_dirname should not be null");
+ sprintf(filename, "%s/tmpfile", temporaryDirectory);
+
+ PARCFile *file = parcFile_Create(filename);
+ PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file);
+ parcFile_Release(&file);
+
+ char *string = parcRandomAccessFile_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcRandomAccessFile_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+ parcRandomAccessFile_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Specialization)
+{
+ LONGBOW_RUN_TEST_CASE(Object, parcRandomAccessFile_Read);
+ LONGBOW_RUN_TEST_CASE(Object, parcRandomAccessFile_Write);
+ LONGBOW_RUN_TEST_CASE(Object, parcRandomAccessFile_Seek);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Specialization)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Specialization)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) {
+ parcSafeMemory_ReportAllocation(STDOUT_FILENO);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Object, parcRandomAccessFile_Read)
+{
+ char *fname = "tmpfile";
+
+ PARCFile *file = parcFile_Create(fname);
+
+ parcFile_CreateNewFile(file);
+ FILE *fp = fopen(fname, "w");
+ fseek(fp, 0, SEEK_SET);
+
+ uint8_t data[128];
+ for (int i = 0; i < 128; i++) {
+ data[i] = i;
+ }
+ fwrite(data, 1, 128, fp);
+ fclose(fp);
+
+ PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file);
+ parcFile_Release(&file);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(128);
+ size_t numBytes = parcRandomAccessFile_Read(instance, buffer);
+ assertTrue(numBytes == 128, "Expected 128 bytes to be read, but got %zu", numBytes);
+
+ parcBuffer_Flip(buffer);
+ uint8_t *bytes = parcBuffer_Overlay(buffer, parcBuffer_Remaining(buffer));
+ assertTrue(memcmp(data, bytes, 128) == 0, "Expected buffers to be equal");
+
+ parcBuffer_Release(&buffer);
+ parcRandomAccessFile_Close(instance);
+ parcRandomAccessFile_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Object, parcRandomAccessFile_Write)
+{
+ char *fname = "tmpfile";
+
+ PARCFile *file = parcFile_Create(fname);
+
+ parcFile_CreateNewFile(file);
+
+ uint8_t data[128];
+ for (int i = 0; i < 128; i++) {
+ data[i] = i;
+ }
+
+ PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file);
+ PARCBuffer *buffer = parcBuffer_Allocate(128);
+ parcBuffer_PutArray(buffer, 128, data);
+ parcBuffer_Flip(buffer);
+ size_t numBytes = parcRandomAccessFile_Write(instance, buffer);
+ assertTrue(numBytes == 128, "Expected 128 bytes to be read, but got %zu", numBytes);
+ parcBuffer_Release(&buffer);
+
+ parcRandomAccessFile_Close(instance);
+ parcRandomAccessFile_Release(&instance);
+
+ uint8_t bytes[128];
+ FILE *fp = fopen(fname, "r");
+ numBytes = fread(bytes, 1, 128, fp);
+ assertTrue(numBytes == 128, "Expected 128 bytes to be read, but got %zu", numBytes);
+
+ fclose(fp);
+
+ assertTrue(memcmp(data, bytes, 128) == 0, "Expected buffers to be equal");
+
+ parcFile_Release(&file);
+}
+
+LONGBOW_TEST_CASE(Object, parcRandomAccessFile_Seek)
+{
+ char *fname = "tmpfile";
+
+ PARCFile *file = parcFile_Create(fname);
+
+ parcFile_CreateNewFile(file);
+ FILE *fp = fopen(fname, "w");
+ fseek(fp, 0, SEEK_SET);
+
+ uint8_t data[128];
+ for (int i = 0; i < 128; i++) {
+ data[i] = i;
+ }
+ fwrite(data, 1, 128, fp);
+ fclose(fp);
+
+ PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file);
+ PARCBuffer *buffer = parcBuffer_Allocate(128);
+ parcRandomAccessFile_Seek(instance, 64, PARCRandomAccessFilePosition_Start);
+ size_t numBytes = parcRandomAccessFile_Read(instance, buffer);
+ assertTrue(numBytes == 64, "Expected 64 bytes to be read, but got %zu", numBytes);
+
+ parcRandomAccessFile_Seek(instance, 0, PARCRandomAccessFilePosition_End);
+ parcBuffer_Flip(buffer);
+ numBytes = parcRandomAccessFile_Read(instance, buffer);
+ assertTrue(numBytes == 0, "Expected 0 bytes to be read, but got %zu", numBytes);
+
+ parcRandomAccessFile_Seek(instance, 0, PARCRandomAccessFilePosition_Start);
+ parcBuffer_Flip(buffer);
+ numBytes = parcRandomAccessFile_Read(instance, buffer);
+ assertTrue(numBytes == 128, "Expected 128 bytes to be read, but got %zu", numBytes);
+
+ parcBuffer_Release(&buffer);
+ parcRandomAccessFile_Close(instance);
+ parcRandomAccessFile_Release(&instance);
+
+ parcFile_Release(&file);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parcRandomAccessFile_RandomAccessFile);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_ReadOnlyBuffer.c b/libparc/parc/algol/test/test_parc_ReadOnlyBuffer.c
new file mode 100644
index 00000000..19e250f8
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_ReadOnlyBuffer.c
@@ -0,0 +1,689 @@
+/*
+ * 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_ReadOnlyBuffer.c"
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <LongBow/unit-test.h>
+#include <LongBow/debugging.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parc_ReadableBuffer)
+{
+ // 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(Getters);
+ LONGBOW_RUN_TEST_FIXTURE(CreateDestroy);
+ LONGBOW_RUN_TEST_FIXTURE(Errors);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_ReadableBuffer)
+{
+ 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_ReadableBuffer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+LONGBOW_TEST_FIXTURE(CreateDestroy)
+{
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcReadOnlyBuffer_Create);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcReadOnlyBuffer_Allocate_AcquireRelease);
+// LONGBOW_RUN_TEST_CASE(CreateDestroy, parcReadOnlyBuffer_Allocate_AcquireRelease_TooMany);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcReadOnlyBuffer_Wrap);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcReadOnlyBuffer_Wrap_NULL);
+ LONGBOW_RUN_TEST_CASE(CreateDestroy, parcReadOnlyBuffer_Wrap_WithOffset);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(CreateDestroy)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(CreateDestroy)
+{
+ 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(CreateDestroy, parcReadOnlyBuffer_Create)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+ PARCReadOnlyBuffer *actual = parcReadOnlyBuffer_Create(buffer);
+
+ assertTrue(parcReadOnlyBuffer_Position(actual) == 0, "Expected initial position to be 0.");
+ assertTrue(parcReadOnlyBuffer_Limit(actual) == 10, "Expected initial limit to be 10.");
+
+ parcReadOnlyBuffer_Release(&actual);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcReadOnlyBuffer_Wrap_NULL)
+{
+ PARCReadOnlyBuffer *actual = parcReadOnlyBuffer_Create(parcBuffer_Wrap(NULL, 10, 0, 10));
+ assertNull(actual, "Expected parcReadOnlyBuffer_Wrap to return NULL");
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcReadOnlyBuffer_Wrap)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 0, 10);
+
+ PARCReadOnlyBuffer *actual = parcReadOnlyBuffer_Create(buffer);
+ assertTrue(parcReadOnlyBuffer_Position(actual) == 0, "Expected initial position to be 0.");
+ assertTrue(parcReadOnlyBuffer_Limit(actual) == sizeof(array) / sizeof(array[0]), "Expected initial limit to be 10.");
+
+ parcReadOnlyBuffer_Release(&actual);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcReadOnlyBuffer_Wrap_WithOffset)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(array, 10, 3, 10);
+
+ PARCReadOnlyBuffer *actual = parcReadOnlyBuffer_Create(buffer);
+ parcBuffer_Release(&buffer);
+ assertTrue(parcReadOnlyBuffer_Capacity(actual) == 10, "Expected initial capacity to be 3.");
+ assertTrue(parcReadOnlyBuffer_Limit(actual) == 10, "Expected initial limit to be 3.");
+ assertTrue(parcReadOnlyBuffer_Position(actual) == 3, "Expected initial position to be 0.");
+
+ parcReadOnlyBuffer_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(CreateDestroy, parcReadOnlyBuffer_Allocate_AcquireRelease)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(10);
+
+ PARCReadOnlyBuffer *expected = parcReadOnlyBuffer_Create(buffer);
+ PARCReadOnlyBuffer *actual = parcReadOnlyBuffer_Acquire(expected);
+
+ assertTrue(expected == actual, "Expected %p, actual %p", (void *) expected, (void *) actual);
+
+ parcReadOnlyBuffer_Release(&expected);
+ assertTrue(expected == NULL, "Expected parcReadOnlyBuffer_Release to NULL the pointer.");
+ parcReadOnlyBuffer_Release(&actual);
+ assertTrue(actual == NULL, "Expected parcReadOnlyBuffer_Release to NULL the pointer.");
+ parcBuffer_Release(&buffer);
+}
+
+//LONGBOW_TEST_CASE_EXPECTS(CreateDestroy, parcReadOnlyBuffer_Allocate_AcquireRelease_TooMany, .event = &LongBowTrapIllegalValue)
+//{
+// PARCBuffer *buffer = parcBuffer_Allocate(10);
+// PARCReadOnlyBuffer *expected = parcReadOnlyBuffer_Create(buffer);
+// PARCReadOnlyBuffer *actual = parcReadOnlyBuffer_Acquire(expected);
+// PARCReadOnlyBuffer *alias = actual;
+//
+// parcBuffer_Release(&buffer);
+// parcReadOnlyBuffer_Release(&expected);
+// parcReadOnlyBuffer_Release(&actual);
+// parcReadOnlyBuffer_Release(&alias); // this must fail.
+//}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Array);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_ArrayOffset);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Clear);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Flip);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_GetByte);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_GetArray);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_HasRemaining);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Mark);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Overlay);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Position);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Remaining);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Rewind);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_SetLimit);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_SetLimit_TruncatePosition);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_SetPosition);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_ToString);
+ LONGBOW_RUN_TEST_CASE(Global, parcReadOnlyBuffer_Display);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Equals)
+{
+ PARCReadOnlyBuffer *x = parcReadOnlyBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 10);
+ PARCReadOnlyBuffer *y = parcReadOnlyBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 10);
+ PARCReadOnlyBuffer *z = parcReadOnlyBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 10);
+ PARCReadOnlyBuffer *u1 = parcReadOnlyBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10 }, 10, 0, 10);
+ PARCReadOnlyBuffer *u2 = parcReadOnlyBuffer_Wrap((uint8_t [10]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 9, 0, 9);
+ PARCReadOnlyBuffer *u3 = parcReadOnlyBuffer_Wrap((uint8_t [9]) { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 9, 0, 9);
+ PARCReadOnlyBuffer *u4 = parcReadOnlyBuffer_SetPosition(parcReadOnlyBuffer_Wrap((uint8_t [9]) { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 9, 0, 9), 2);
+ PARCReadOnlyBuffer *u5 = parcReadOnlyBuffer_SetPosition(parcReadOnlyBuffer_Wrap((uint8_t [9]) { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 9, 0, 9), 9);
+ PARCReadOnlyBuffer *u6 = parcReadOnlyBuffer_SetPosition(parcReadOnlyBuffer_Wrap((uint8_t [9]) { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 9, 0, 9), 9);
+
+ parcObjectTesting_AssertEqualsFunction(parcReadOnlyBuffer_Equals, x, y, z, u1, u2, u3, u4, u5, u6, NULL);
+
+ parcReadOnlyBuffer_Release(&x);
+ parcReadOnlyBuffer_Release(&y);
+ parcReadOnlyBuffer_Release(&z);
+ parcReadOnlyBuffer_Release(&u1);
+ parcReadOnlyBuffer_Release(&u2);
+ parcReadOnlyBuffer_Release(&u3);
+ parcReadOnlyBuffer_Release(&u4);
+ parcReadOnlyBuffer_Release(&u5);
+ parcReadOnlyBuffer_Release(&u6);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Array)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *readWriteBuffer = parcBuffer_Wrap(expected, 10, 0, 10);
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Create(readWriteBuffer);
+ parcBuffer_Release(&readWriteBuffer);
+
+ PARCByteArray *array = parcReadOnlyBuffer_Array(buffer);
+ uint8_t *actual = parcByteArray_Array(array);
+
+ parcReadOnlyBuffer_Release(&buffer);
+
+ assertTrue(expected == actual,
+ "Expected %p, actual %p",
+ (void *) expected, (void *) actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Flip)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_PutArray(parcBuffer_Allocate(10), 10, expected);
+
+ PARCReadOnlyBuffer *actual = parcReadOnlyBuffer_Create(buffer);
+
+ parcReadOnlyBuffer_Flip(actual);
+ assertTrue(parcReadOnlyBuffer_Position(actual) == 0,
+ "Expected position to be 0.");
+ assertTrue(parcReadOnlyBuffer_Limit(actual) == 10,
+ "Expected limit to be 10.");
+
+ parcReadOnlyBuffer_Release(&actual);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Copy)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_PutArray(parcBuffer_Allocate(10), 10, expected);
+
+ PARCReadOnlyBuffer *original = parcReadOnlyBuffer_Create(buffer);
+
+ PARCReadOnlyBuffer *copy = parcReadOnlyBuffer_Copy(original);
+
+ assertTrue(parcReadOnlyBuffer_Equals(original, copy), "Expected the copy to be equal to the original.");
+
+ parcReadOnlyBuffer_Release(&copy);
+ parcReadOnlyBuffer_Release(&original);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Clear)
+{
+ uint8_t expected[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCBuffer *buffer = parcBuffer_PutArray(parcBuffer_Allocate(10), 10, expected);
+
+ PARCReadOnlyBuffer *actual = parcReadOnlyBuffer_Create(buffer);
+ assertTrue(parcReadOnlyBuffer_Position(actual) == 10, "Expected position to be 10.");
+ assertTrue(parcReadOnlyBuffer_Limit(actual) == 10, "Expected limit to be 10.");
+
+ parcReadOnlyBuffer_Clear(actual);
+ assertTrue(parcReadOnlyBuffer_Position(actual) == 0, "Expected position to be 0.");
+ assertTrue(parcReadOnlyBuffer_Limit(actual) == 10, "Expected limit to be 10.");
+
+ parcBuffer_Release(&buffer);
+ parcReadOnlyBuffer_Release(&actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_ArrayOffset)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ size_t expected = 5;
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, expected, 10);
+
+ size_t actual = parcReadOnlyBuffer_ArrayOffset(buffer);
+ parcReadOnlyBuffer_Release(&buffer);
+
+ assertTrue(0 == actual,
+ "Expected offset to be 0, actual %zu", actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Position)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ size_t expected = 5;
+ parcReadOnlyBuffer_SetPosition(buffer, expected);
+
+ size_t actual = parcReadOnlyBuffer_Position(buffer);
+
+ assertTrue(expected == actual,
+ "Expected position to be 0, actual %zu", actual);
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Overlay)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ uint8_t expected[5] = { 5, 6, 7, 8, 9 };
+
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ size_t position = 5;
+ parcReadOnlyBuffer_SetPosition(buffer, position);
+ uint8_t *actual = parcReadOnlyBuffer_Overlay(buffer, sizeof(array) - position);
+
+ assertTrue(memcmp(expected, actual, sizeof(expected)) == 0,
+ "Array contents should not be different.");
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_SetPosition)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ size_t expected = 2;
+ parcReadOnlyBuffer_SetPosition(buffer, expected);
+ size_t actual = parcReadOnlyBuffer_Position(buffer);
+
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_SetLimit)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ size_t expected = 2;
+ parcReadOnlyBuffer_SetLimit(buffer, expected);
+ size_t actual = parcReadOnlyBuffer_Limit(buffer);
+
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_SetLimit_TruncatePosition)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ parcReadOnlyBuffer_SetPosition(buffer, 5);
+ parcReadOnlyBuffer_Mark(buffer);
+
+ size_t expected = 2;
+ parcReadOnlyBuffer_SetLimit(buffer, expected);
+ size_t actual = parcReadOnlyBuffer_Limit(buffer);
+
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Remaining)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ size_t expected = 10;
+ size_t actual = parcReadOnlyBuffer_Remaining(buffer);
+
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_HasRemaining)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+ bool actual = parcReadOnlyBuffer_HasRemaining(buffer);
+
+ assertTrue(actual, "Expected true");
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Rewind)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+ parcReadOnlyBuffer_SetPosition(buffer, 4);
+ size_t actual = parcReadOnlyBuffer_Position(buffer);
+ assertTrue(actual == 4, "Expected position to be at 4.");
+
+ parcReadOnlyBuffer_Rewind(buffer);
+
+ actual = parcReadOnlyBuffer_Position(buffer);
+ assertTrue(actual == 0, "Expected position to be at 0.");
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Mark)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ size_t expected = 2;
+ parcReadOnlyBuffer_SetPosition(buffer, expected);
+ parcReadOnlyBuffer_Mark(buffer);
+ parcReadOnlyBuffer_SetPosition(buffer, 4);
+ parcReadOnlyBuffer_Reset(buffer);
+ size_t actual = parcReadOnlyBuffer_Position(buffer);
+
+ assertTrue(expected == actual, "Expected %zd, actual %zd", expected, actual);
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_GetByte)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ uint8_t actual = parcReadOnlyBuffer_GetUint8(buffer);
+
+ assertTrue(array[0] == actual,
+ "Expected %d, actual %d", array[0], actual);
+
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_GetArray)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ uint8_t actual[10];
+
+ parcReadOnlyBuffer_GetArray(buffer, actual, sizeof(actual));
+
+ assertTrue(memcmp(array, actual, sizeof(actual)) == 0,
+ "Expected arrays to be equal.");
+
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_HashCode)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ PARCBuffer *referenceBuffer = parcBuffer_Wrap(array, 10, 0, 10);
+
+ PARCReadOnlyBuffer *buffer1 = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ PARCReadOnlyBuffer *buffer2 = parcReadOnlyBuffer_Wrap(array, 10, 0, 10);
+
+ uint32_t hashX = parcReadOnlyBuffer_HashCode(buffer1);
+ uint32_t hashY = parcReadOnlyBuffer_HashCode(buffer2);
+ uint32_t referenceHash = parcBuffer_HashCode(referenceBuffer);
+
+ assertTrue(hashX == hashY, "Expected %u, actual %u", hashX, hashY);
+ assertTrue(hashX == referenceHash, "Expected %u, actual %u", hashX, hashY);
+
+ parcReadOnlyBuffer_Release(&buffer2);
+ parcReadOnlyBuffer_Release(&buffer1);
+ parcBuffer_Release(&referenceBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_ToString)
+{
+ uint8_t array[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 'x' };
+
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, sizeof(array), 0, sizeof(array));
+
+ char *actual = parcReadOnlyBuffer_ToString(buffer);
+
+ assertTrue(strcmp("hello worldx", actual) == 0, "Expected 'hello world', actual %s", actual);
+
+ parcMemory_Deallocate((void **) &actual);
+
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, parcReadOnlyBuffer_Display)
+{
+ uint8_t array[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 'x' };
+
+ PARCReadOnlyBuffer *buffer = parcReadOnlyBuffer_Wrap(array, sizeof(array), 0, sizeof(array));
+
+ parcReadOnlyBuffer_Display(buffer, 0);
+
+ parcReadOnlyBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_FIXTURE(Getters)
+{
+ LONGBOW_RUN_TEST_CASE(Getters, parcReadOnlyBuffer_GetUint8);
+ LONGBOW_RUN_TEST_CASE(Getters, parcReadOnlyBuffer_GetUint16);
+ LONGBOW_RUN_TEST_CASE(Getters, parcReadOnlyBuffer_GetUint32);
+ LONGBOW_RUN_TEST_CASE(Getters, parcReadOnlyBuffer_GetUint64);
+ LONGBOW_RUN_TEST_CASE(Getters, parcReadOnlyBuffer_GetAtIndex);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Getters)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(100);
+
+ longBowTestCase_SetClipBoardData(testCase, buffer);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Getters)
+{
+ 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(Getters, parcReadOnlyBuffer_GetAtIndex)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(uint8_t));
+ uint8_t expected = 0x12;
+
+ parcBuffer_PutUint8(buffer, expected);
+ parcBuffer_Flip(buffer);
+
+ PARCReadOnlyBuffer *readOnly = parcReadOnlyBuffer_Create(buffer);
+ uint8_t actual = parcReadOnlyBuffer_GetAtIndex(readOnly, 0);
+
+ parcReadOnlyBuffer_Release(&readOnly);
+ parcBuffer_Release(&buffer);
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+}
+
+LONGBOW_TEST_CASE(Getters, parcReadOnlyBuffer_GetUint8)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(uint8_t));
+ uint8_t expected = 0x12;
+
+ parcBuffer_PutUint8(buffer, expected);
+ parcBuffer_Flip(buffer);
+
+ PARCReadOnlyBuffer *readOnly = parcReadOnlyBuffer_Create(buffer);
+ uint8_t actual = parcReadOnlyBuffer_GetUint8(readOnly);
+
+ parcReadOnlyBuffer_Release(&readOnly);
+ parcBuffer_Release(&buffer);
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+}
+
+LONGBOW_TEST_CASE(Getters, parcReadOnlyBuffer_GetUint16)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(uint16_t));
+ uint16_t expected = 0x1234;
+
+ parcBuffer_PutUint16(buffer, expected);
+ parcBuffer_Flip(buffer);
+
+ PARCReadOnlyBuffer *readOnly = parcReadOnlyBuffer_Create(buffer);
+ uint16_t actual = parcReadOnlyBuffer_GetUint16(readOnly);
+
+ parcReadOnlyBuffer_Release(&readOnly);
+ parcBuffer_Release(&buffer);
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+}
+
+LONGBOW_TEST_CASE(Getters, parcReadOnlyBuffer_GetUint32)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(uint32_t));
+ uint32_t expected = 0x12345678;
+
+ parcBuffer_PutUint32(buffer, expected);
+ parcBuffer_Flip(buffer);
+
+ PARCReadOnlyBuffer *readOnly = parcReadOnlyBuffer_Create(buffer);
+ uint32_t actual = parcReadOnlyBuffer_GetUint32(readOnly);
+
+ parcReadOnlyBuffer_Release(&readOnly);
+ parcBuffer_Release(&buffer);
+ assertTrue(expected == actual, "Expected %d, actual %d", expected, actual);
+}
+
+LONGBOW_TEST_CASE(Getters, parcReadOnlyBuffer_GetUint64)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(uint64_t));
+ uint64_t expected = 0x1234567812345678;
+
+ parcBuffer_PutUint64(buffer, expected);
+ parcBuffer_Flip(buffer);
+
+ PARCReadOnlyBuffer *readOnly = parcReadOnlyBuffer_Create(buffer);
+ uint64_t actual = parcReadOnlyBuffer_GetUint64(readOnly);
+
+ parcReadOnlyBuffer_Release(&readOnly);
+ parcBuffer_Release(&buffer);
+ assertTrue(expected == actual, "Expected %" PRIu64 ", actual %" PRIu64 "", expected, actual);
+}
+
+LONGBOW_TEST_FIXTURE(Errors)
+{
+ LONGBOW_RUN_TEST_CASE(Errors, parcReadOnlyBuffer_GetByte_Underflow);
+ LONGBOW_RUN_TEST_CASE(Errors, parcReadOnlyBuffer_Mark_mark_exceeds_position);
+}
+
+typedef struct parc_buffer_longbow_clipboard {
+ PARCReadOnlyBuffer *buffer;
+} parcReadOnlyBuffer_LongBowClipBoard;
+
+LONGBOW_TEST_FIXTURE_SETUP(Errors)
+{
+ uint8_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ parcReadOnlyBuffer_LongBowClipBoard *testData = calloc(1, sizeof(parcReadOnlyBuffer_LongBowClipBoard));
+ testData->buffer = parcReadOnlyBuffer_Wrap(array, sizeof(array), 0, sizeof(array));
+
+ longBowTestCase_SetClipBoardData(testCase, testData);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Errors)
+{
+ parcReadOnlyBuffer_LongBowClipBoard *testData = longBowTestCase_GetClipBoardData(testCase);
+ parcReadOnlyBuffer_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, parcReadOnlyBuffer_GetByte_Underflow, .event = &LongBowTrapOutOfBounds)
+{
+ parcReadOnlyBuffer_LongBowClipBoard *testData = longBowTestCase_GetClipBoardData(testCase);
+ PARCReadOnlyBuffer *buffer = testData->buffer;
+
+ parcReadOnlyBuffer_SetPosition(buffer, 10);
+ parcReadOnlyBuffer_GetUint8(buffer); // this will fail.
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, parcReadOnlyBuffer_Mark_mark_exceeds_position, .event = &LongBowAssertEvent)
+{
+ parcReadOnlyBuffer_LongBowClipBoard *testData = longBowTestCase_GetClipBoardData(testCase);
+ PARCReadOnlyBuffer *buffer = testData->buffer;
+
+ size_t expected = 2;
+ parcReadOnlyBuffer_SetPosition(buffer, expected);
+ parcReadOnlyBuffer_Mark(buffer);
+ parcReadOnlyBuffer_SetPosition(buffer, 0);
+ parcReadOnlyBuffer_Reset(buffer);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_ReadableBuffer);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_SafeMemory.c b/libparc/parc/algol/test/test_parc_SafeMemory.c
new file mode 100644
index 00000000..53c0b3c8
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_SafeMemory.c
@@ -0,0 +1,813 @@
+/*
+ * 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_SafeMemory.c"
+
+#include <LongBow/unit-test.h>
+
+#include <fcntl.h>
+
+LONGBOW_TEST_RUNNER(safetyMemory)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Static);
+ LONGBOW_RUN_TEST_FIXTURE(ReportAllocation);
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Errors);
+
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(safetyMemory)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(safetyMemory)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Static)
+{
+ LONGBOW_RUN_TEST_CASE(Static, PARCSafeMemory_Report);
+ LONGBOW_RUN_TEST_CASE(Static, _parcSafeMemory_StateToString);
+ LONGBOW_RUN_TEST_CASE(Static, _parcSafeMemory_GetPrefixState_OK);
+ LONGBOW_RUN_TEST_CASE(Static, _parcSafeMemory_GetPrefixState_ALREADYFREE);
+ LONGBOW_RUN_TEST_CASE(Static, _parcSafeMemory_GetPrefixState_UNDERRUN);
+ LONGBOW_RUN_TEST_CASE(Static, _parcSafeMemory_FormatPrefix);
+ LONGBOW_RUN_TEST_CASE(Static, _computeUsableMemoryLength);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Static)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Static, PARCSafeMemory_Report)
+{
+ size_t expectedSize = 100;
+ void *memory = parcSafeMemory_Allocate(expectedSize);
+ int fd = open("/dev/null", O_WRONLY);
+ _parcSafeMemory_Report(memory, fd);
+ close(fd);
+ parcSafeMemory_Deallocate(&memory);
+}
+
+LONGBOW_TEST_CASE(Static, _parcSafeMemory_StateToString)
+{
+ assertNotNull(_parcSafeMemory_StateToString(PARCSafeMemoryState_OK),
+ "PARCSafeMemoryState_OK cannot be a NULL string.");
+ assertNotNull(_parcSafeMemory_StateToString(PARCSafeMemoryState_MISMATCHED),
+ "PARCSafeMemoryState_MISMATCHED cannot be a NULL string.");
+ assertNotNull(_parcSafeMemory_StateToString(PARCSafeMemoryState_UNDERRUN),
+ "PARCSafeMemoryState_UNDERRUN cannot be a NULL string.");
+ assertNotNull(_parcSafeMemory_StateToString(PARCSafeMemoryState_OVERRUN),
+ "PARCSafeMemoryState_OVERRUN cannot be a NULL string.");
+ assertNotNull(_parcSafeMemory_StateToString(PARCSafeMemoryState_NOTHINGALLOCATED),
+ "PARCSafeMemoryState_NOTHINGALLOCATED cannot be a NULL string.");
+ assertNotNull(_parcSafeMemory_StateToString(PARCSafeMemoryState_ALREADYFREE),
+ "PARCSafeMemoryState_ALREADYFREE cannot be a NULL string.");
+ assertNotNull(_parcSafeMemory_StateToString(-1),
+ "Garbage cannot be represented by a NULL string.");
+}
+
+LONGBOW_TEST_CASE(Static, _parcSafeMemory_GetPrefixState_OK)
+{
+ size_t expectedLength = 5;
+ int expectedAlignment = sizeof(void *);
+ char origin[100]; // just some number
+
+ void *memory = _parcSafeMemory_FormatPrefix((PARCSafeMemoryOrigin *) origin, expectedLength, expectedAlignment);
+ PARCSafeMemoryState actual = _parcSafeMemory_GetPrefixState(memory);
+ assertTrue(actual == PARCSafeMemoryState_OK,
+ "Expected PARCSafeMemoryState_OK, actual = %d", actual);
+}
+
+LONGBOW_TEST_CASE(Static, _parcSafeMemory_GetPrefixState_ALREADYFREE)
+{
+ PARCSafeMemoryUsable *usable = parcSafeMemory_Allocate(10);
+ PARCSafeMemoryUsable *saved = usable;
+
+ parcSafeMemory_Deallocate((void **) &usable);
+
+ PARCSafeMemoryState actual = _parcSafeMemory_GetPrefixState(saved);
+ assertTrue(actual == PARCSafeMemoryState_ALREADYFREE,
+ "Expected PARCSafeMemoryState_ALREADYFREE, actual = %d", actual);
+}
+
+LONGBOW_TEST_CASE(Static, _parcSafeMemory_GetPrefixState_UNDERRUN)
+{
+ char *usable = parcSafeMemory_Allocate(10);
+
+ char savedByte = usable[-1];
+ usable[-1] = 0;
+
+ PARCSafeMemoryState actual = _parcSafeMemory_GetPrefixState((PARCSafeMemoryUsable *) usable);
+ assertTrue(actual == PARCSafeMemoryState_UNDERRUN,
+ "Expected PARCSafeMemoryState_UNDERRUN, actual = %d", actual);
+ usable[-1] = savedByte;
+ parcSafeMemory_Deallocate((void **) &usable);
+}
+
+LONGBOW_TEST_CASE(Static, _parcSafeMemory_FormatPrefix)
+{
+ size_t expectedLength = 5;
+ int expectedAlignment = sizeof(void *) - 1;
+ char base[100]; // just some number
+ void *memory = _parcSafeMemory_FormatPrefix((PARCSafeMemoryOrigin *) base, expectedLength, expectedAlignment);
+
+ assertNull(memory,
+ "Expected _parcSafeMemory_FormatPrefix to return NULL for bad alignment specification.");
+}
+
+LONGBOW_TEST_CASE(Static, _computeUsableMemoryLength)
+{
+ size_t actual = _computeUsableMemoryLength(100, sizeof(void *));
+
+ // The result must be >= to the requested length and an even multiple of sizeof(void *)
+ assertTrue(actual >= 100 && (actual % sizeof(void *)) == 0,
+ "Expected the result to be >= to the requested length and an even multiple of sizeof(void *)");
+}
+
+LONGBOW_TEST_FIXTURE(ReportAllocation)
+{
+ LONGBOW_RUN_TEST_CASE(ReportAllocation, parcSafeMemory_ReportAllocation_Empty);
+ LONGBOW_RUN_TEST_CASE(ReportAllocation, parcSafeMemory_ReportAllocation_One);
+ LONGBOW_RUN_TEST_CASE(ReportAllocation, parcSafeMemory_ReportAllocation_Deallocated);
+}
+
+LONGBOW_TEST_CASE(ReportAllocation, parcSafeMemory_ReportAllocation_Empty)
+{
+ _parcSafeMemory_DeallocateAll();
+ int fd = open("/dev/null", O_WRONLY);
+ size_t result = parcSafeMemory_ReportAllocation(fd);
+ close(fd);
+ assertTrue(result == 0, "Expected 0, was %zd", result);
+}
+
+LONGBOW_TEST_CASE(ReportAllocation, parcSafeMemory_ReportAllocation_One)
+{
+ void *memory;
+ size_t size = 100;
+
+ memory = parcSafeMemory_Allocate(size);
+
+ int fd = open("/dev/null", O_WRONLY);
+ size_t result = parcSafeMemory_ReportAllocation(fd);
+ close(fd);
+ assertTrue(result == 1, "Expected 1, was %zd", result);
+
+ parcSafeMemory_Deallocate(&memory);
+}
+
+LONGBOW_TEST_CASE(ReportAllocation, parcSafeMemory_ReportAllocation_Deallocated)
+{
+ size_t size = 100;
+ void *memory = parcSafeMemory_Allocate(size);
+ assertTrue(parcSafeMemory_Outstanding() != 0, "No memory allocated!");
+ PARCSafeMemoryState state = _parcSafeMemory_GetState(memory);
+ parcSafeMemory_Deallocate(&memory);
+ assertTrue(state == PARCSafeMemoryState_OK, "Expected uncorrupted memory.");
+
+ int fd = open("/dev/null", O_WRONLY);
+ size_t result = parcSafeMemory_ReportAllocation(fd);
+ close(fd);
+
+ assertTrue(result == 0, "Expected 0, was %zd", result);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(ReportAllocation)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(ReportAllocation)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_Allocate);
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_MemAlign);
+
+ LONGBOW_RUN_TEST_CASE(Global, PARCSafeMemory_Realloc_Larger);
+ LONGBOW_RUN_TEST_CASE(Global, PARCSafeMemory_Realloc_Smaller);
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_Reallocate_Zero);
+ LONGBOW_RUN_TEST_CASE(Global, PARCSafeMemory_Validate);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_Allocate_BadAlignment);
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_Allocate_BadSize);
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_AllocateAndClear);
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_Reallocate);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_Deallocate_NothingAllocated);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_IsValid_True);
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_IsValid_False);
+
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_Display);
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_Display_NULL);
+
+ LONGBOW_RUN_TEST_CASE(Global, compute_prefix_length);
+ LONGBOW_RUN_TEST_CASE(Global, _parcSafeMemory_FormatMemory);
+ LONGBOW_RUN_TEST_CASE(Global, memory_prefix_format);
+ LONGBOW_RUN_TEST_CASE(Global, memory_prefix_validate);
+ LONGBOW_RUN_TEST_CASE(Global, memory_suffix_format);
+ LONGBOW_RUN_TEST_CASE(Global, memory_suffix_validate);
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_StringDuplicate);
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_StringDuplicate_Long);
+ LONGBOW_RUN_TEST_CASE(Global, parcSafeMemory_StringDuplicate_Short);
+ LONGBOW_RUN_TEST_CASE(Global, validateAlignment);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ assertTrue(parcSafeMemory_Outstanding() == 0, "Expected 0 outstanding allocations")
+ {
+ printf("Leaking test case: %s", longBowTestCase_GetName(testCase));
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+
+LONGBOW_TEST_CASE(Global, validateAlignment)
+{
+ assertTrue(_alignmentIsValid(sizeof(void *)),
+ "Expected alignment of sizeof(void *) failed.");
+ assertTrue(_alignmentIsValid(16),
+ "Expected alignment of 16 failed.");
+}
+
+LONGBOW_TEST_CASE(Global, compute_prefix_length)
+{
+ // Test that the result is a multiple of the alignment value and greater than the size of _MemoryPrefix.
+ for (int i = 0; i < 9; i++) {
+ size_t alignment = 1 << i;
+ size_t actual = _computePrefixLength(alignment);
+ assertTrue((actual & (alignment - 1)) == 0,
+ "Alignment needs to be a multiple of %zd", alignment);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, memory_prefix_format)
+{
+ size_t expectedLength = 5;
+ int expectedAlignment = sizeof(void *);
+ char base[100];
+ void *memory = _parcSafeMemory_FormatPrefix((PARCSafeMemoryOrigin *) base, expectedLength, expectedAlignment);
+
+ _MemoryPrefix *prefix = _parcSafeMemory_GetPrefix(memory);
+
+ assertAligned(prefix, sizeof(void *),
+ "prefix address %p is not aligned to %d",
+ memory, expectedAlignment);
+ assertAligned(memory, expectedAlignment,
+ "memory address %p is not aligned to %d",
+ memory, expectedAlignment);
+
+ assertTrue((void *) prefix >= (void *) base,
+ "Expected >= %p, actual %p", (void *) base, (void *) prefix);
+ assertTrue(_parcSafeMemory_PrefixMagic == prefix->magic,
+ "Prefix magic is wrong.");
+ assertTrue(expectedLength == prefix->requestedLength,
+ "Expected length %zd, actual %zd", expectedLength, prefix->requestedLength);
+ assertTrue(expectedAlignment == prefix->alignment,
+ "Expected alignment %d, actual %zu",
+ expectedAlignment, prefix->alignment);
+ assertTrue(_parcSafeMemory_Guard == prefix->guard,
+ "Prefix guard is wrong.");
+}
+
+LONGBOW_TEST_CASE(Global, memory_suffix_format)
+{
+ size_t expectedLength = 5;
+ int expectedAlignment = sizeof(void *);
+ char base[100];
+ void *memory = _parcSafeMemory_FormatPrefix((PARCSafeMemoryOrigin *) base, expectedLength, expectedAlignment);
+
+ _MemorySuffix *suffix = _parcSafeMemory_FormatSuffix(memory);
+ assertAligned(suffix, sizeof(void *), "suffix pointer is not aligned to %zu", sizeof(void*));
+}
+
+LONGBOW_TEST_CASE(Global, memory_suffix_validate)
+{
+ size_t expectedLength = 5;
+ int expectedAlignment = sizeof(void *);
+ char base[100];
+ void *memory = _parcSafeMemory_FormatPrefix((PARCSafeMemoryOrigin *) base, expectedLength, expectedAlignment);
+
+ _MemorySuffix *suffix = _parcSafeMemory_FormatSuffix(memory);
+ assertAligned(suffix, sizeof(void *),
+ "suffix pointer is not aligned to %zu", sizeof(void*));
+
+ PARCSafeMemoryState suffixState = _parcSafeMemory_GetSuffixState(memory);
+ assertTrue(suffixState == PARCSafeMemoryState_OK,
+ "Expected PARCSafeMemoryState_OK suffix state, actual %s", _parcSafeMemory_StateToString(suffixState));
+}
+
+LONGBOW_TEST_CASE(Global, memory_prefix_validate)
+{
+ size_t expectedLength = 5;
+ int expectedAlignment = sizeof(void *);
+ char base[100];
+
+ void *memory = _parcSafeMemory_FormatPrefix((PARCSafeMemoryOrigin *) base, expectedLength, expectedAlignment);
+ PARCSafeMemoryState actual = _parcSafeMemory_GetPrefixState(memory);
+ assertTrue(actual == PARCSafeMemoryState_OK,
+ "Expected valid prefix, actual = %d", actual);
+}
+
+LONGBOW_TEST_CASE(Global, _parcSafeMemory_FormatMemory)
+{
+ size_t expectedLength = 5;
+ int expectedAlignment = sizeof(void *);
+ char base[100];
+
+ void *memory = _parcSafeMemory_FormatMemory((PARCSafeMemoryOrigin *) base, expectedLength, expectedAlignment);
+
+ PARCSafeMemoryState state = _parcSafeMemory_GetState(memory);
+
+ assertTrue(state == PARCSafeMemoryState_OK,
+ "Memory did not validate. Actual %d", state);
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_Allocate)
+{
+ void *memory;
+ size_t size = 100;
+
+ memory = parcSafeMemory_Allocate(size);
+
+ assertTrue(memory != NULL,
+ "Expected non-NULL return.");
+
+ assertTrue((_parcSafeMemory_GetPrefixState(memory)) == PARCSafeMemoryState_OK,
+ "Prefix did not validate.");
+ parcSafeMemory_Deallocate(&memory);
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_MemAlign)
+{
+ void *memory;
+ size_t size = 100;
+
+ int failure = parcSafeMemory_MemAlign(&memory, sizeof(void *), size);
+ assertTrue(failure == 0,
+ "parcSafeMemory_MemAlign failed: %d", failure);
+
+ assertTrue(memory != NULL,
+ "Expected non-NULL return.");
+
+ assertTrue((_parcSafeMemory_GetPrefixState(memory)) == PARCSafeMemoryState_OK,
+ "Prefix did not validate.");
+ parcSafeMemory_Deallocate(&memory);
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_ReportAllocation)
+{
+ void *memory;
+ size_t size = 100;
+
+ memory = parcSafeMemory_Allocate(size);
+ assertTrue(memory != NULL, "Expected non-NULL return.");
+ PARCSafeMemoryState prefixState = _parcSafeMemory_GetPrefixState(memory);
+ assertTrue(prefixState == PARCSafeMemoryState_OK,
+ "Prefix did not validate.");
+
+ parcSafeMemory_ReportAllocation(1);
+}
+
+LONGBOW_TEST_CASE(Global, PARCSafeMemory_Validate)
+{
+ void *memory;
+ size_t size = 100;
+
+ memory = parcSafeMemory_Allocate(size);
+
+ assertTrue(_parcSafeMemory_GetState(memory) == PARCSafeMemoryState_OK,
+ "Memory did not validate.");
+ parcSafeMemory_Deallocate(&memory);
+}
+
+LONGBOW_TEST_CASE(Global, PARCSafeMemory_Realloc_Larger)
+{
+ void *memory = parcSafeMemory_Allocate(100);
+
+ for (unsigned char i = 0; i < 100; i++) {
+ ((unsigned char *) memory)[i] = i;
+ }
+
+ assertTrue(_parcSafeMemory_GetState(memory) == PARCSafeMemoryState_OK,
+ "Expected memory to be OK.");
+
+ size_t expectedLength = 100 + 1;
+ unsigned char *newMemory = parcSafeMemory_Reallocate(memory, expectedLength);
+
+ assertTrue(_parcSafeMemory_GetState((PARCSafeMemoryUsable *) memory) != PARCSafeMemoryState_OK,
+ "Expected original memory to NOT be OK.");
+ assertTrue(_parcSafeMemory_GetState((PARCSafeMemoryUsable *) newMemory) == PARCSafeMemoryState_OK,
+ "Expected new memory to be OK.");
+
+ _MemoryPrefix *prefix = _parcSafeMemory_GetPrefix((PARCSafeMemoryUsable *) newMemory);
+ assertTrue(prefix->requestedLength == expectedLength,
+ "Prefix Expected length %zd, actual %zd", expectedLength, prefix->requestedLength);
+
+ for (int i = 0; i < 100; i++) {
+ assertTrue(((unsigned char *) newMemory)[i] == i,
+ "PARCSafeMemory_Realloc did not copy old memory correctly");
+ }
+
+ assertTrue(parcSafeMemory_Outstanding() != 0,
+ "No memory allocated!");
+ PARCSafeMemoryState state = _parcSafeMemory_GetState((PARCSafeMemoryUsable *) newMemory);
+ parcSafeMemory_Deallocate((void **) &newMemory);
+ assertTrue(state == PARCSafeMemoryState_OK,
+ "Expected PARCSafeMemory_Deallocate of new memory to be OK, actual =%d", state);
+ assertTrue(_parcSafeMemory_GetState(memory) != PARCSafeMemoryState_OK,
+ "Expected old memory to be invalid.");
+}
+
+LONGBOW_TEST_CASE(Global, PARCSafeMemory_Realloc_Smaller)
+{
+ void *memory = parcSafeMemory_Allocate(100);
+ assertTrue(_parcSafeMemory_GetState(memory) == PARCSafeMemoryState_OK,
+ "Memory did not validate.");
+
+ for (unsigned char i = 0; i < 100; i++) {
+ ((unsigned char *) memory)[i] = i;
+ }
+
+ size_t expectedLength = 100 - 1;
+ unsigned char *newMemory = parcSafeMemory_Reallocate(memory, expectedLength);
+
+ assertTrue(_parcSafeMemory_GetState(memory) != PARCSafeMemoryState_OK,
+ "Expected original memory to NOT be OK.");
+ assertTrue(_parcSafeMemory_GetState((PARCSafeMemoryUsable *) newMemory) == PARCSafeMemoryState_OK,
+ "Expected new memory to be OK.");
+
+ _MemoryPrefix *prefix = _parcSafeMemory_GetPrefix((PARCSafeMemoryUsable *) newMemory);
+ assertTrue(prefix->requestedLength == expectedLength,
+ "Prefix Expected length %zd, actual %zd", expectedLength, prefix->requestedLength);
+
+ for (int i = 0; i < expectedLength; i++) {
+ assertTrue(((unsigned char *) newMemory)[i] == i,
+ "PARCSafeMemory_Realloc did not copy correctly");
+ }
+
+ assertTrue(parcSafeMemory_Outstanding() != 0,
+ "No memory allocated!");
+ PARCSafeMemoryState state = _parcSafeMemory_GetState((PARCSafeMemoryUsable *) newMemory);
+ parcSafeMemory_Deallocate((void **) &newMemory);
+ assertTrue(state == PARCSafeMemoryState_OK,
+ "Expected PARCSafeMemory_Deallocate of new memory to be OK, actual =%d", state);
+ assertTrue(_parcSafeMemory_GetState(memory) != PARCSafeMemoryState_OK,
+ "Expected old memory to be invalid.");
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_Reallocate_Zero)
+{
+ void *memory = parcSafeMemory_Allocate(100);
+ assertTrue(_parcSafeMemory_GetState(memory) == PARCSafeMemoryState_OK,
+ "Memory did not validate.");
+
+ for (unsigned char i = 0; i < 100; i++) {
+ ((unsigned char *) memory)[i] = i;
+ }
+
+ size_t expectedLength = 0;
+ unsigned char *newMemory = parcSafeMemory_Reallocate(memory, expectedLength);
+
+ assertTrue(newMemory == NULL,
+ "Expected NULL, actual %p", (void *) newMemory);
+
+ parcSafeMemory_Deallocate(&memory);
+ assertNull(memory,
+ "Expected memory pointer to be NULL.");
+}
+
+LONGBOW_TEST_CASE(Global, PARCSafeMemory_DoubleFree)
+{
+ size_t expectedSize = 100;
+
+ void *memory = parcSafeMemory_Allocate(expectedSize);
+ assertTrue(_parcSafeMemory_GetState(memory) == PARCSafeMemoryState_OK,
+ "Memory did not validate.");
+
+ for (unsigned char i = 0; i < expectedSize; i++) {
+ ((unsigned char *) memory)[i] = i;
+ }
+
+ assertTrue(parcSafeMemory_Outstanding() != 0,
+ "No memory allocated!");
+ PARCSafeMemoryState state = _parcSafeMemory_GetState(memory);
+ parcSafeMemory_Deallocate(&memory);
+ assertTrue(state == PARCSafeMemoryState_OK,
+ "Expected memory to validate");
+ assertTrue(parcSafeMemory_Outstanding() != 0,
+ "No memory allocated!");
+ state = _parcSafeMemory_GetState(memory);
+ parcSafeMemory_Deallocate(&memory);
+ assertTrue(state == PARCSafeMemoryState_UNDERRUN,
+ "Expected memory to be underrun (double free).");
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_StringDuplicate)
+{
+ char *string = "hello world";
+ char *actual = parcSafeMemory_StringDuplicate(string, strlen(string));
+
+ assertTrue(strcmp(string, actual) == 0,
+ "Expected %s, actual %s", string, actual);
+ parcSafeMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_StringDuplicate_Long)
+{
+ char *string = "hello world";
+ char *actual = parcSafeMemory_StringDuplicate(string, SIZE_MAX);
+
+ assertTrue(strcmp(string, actual) == 0,
+ "Expected %s, actual %s", string, actual);
+ parcSafeMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_StringDuplicate_Short)
+{
+ char *string = "hello world";
+ char *expected = "hello";
+ char *actual = parcSafeMemory_StringDuplicate(string, 5);
+
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected %s, actual %s", expected, actual);
+ parcSafeMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_Allocate_BadAlignment)
+{
+ void *result;
+ size_t alignment = 3;
+ size_t size = 100;
+
+ int failure = parcSafeMemory_MemAlign(&result, alignment, size);
+ assertTrue(failure == EINVAL,
+ "parcSafeMemory_MemAlign failed to report bad aligment specification");
+ assertTrue(parcSafeMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocations, actual %d", parcSafeMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_Allocate_BadSize)
+{
+ void *result;
+ size_t alignment = sizeof(void *);
+ size_t size = 0;
+
+ int failure = parcSafeMemory_MemAlign(&result, alignment, size);
+ assertTrue(failure == EINVAL,
+ "parcSafeMemory_MemAlign failed to report bad aligment specification");
+ assertTrue(parcSafeMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocation, actual %d", parcSafeMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_AllocateAndClear)
+{
+ void *result;
+ size_t size = 100;
+
+ result = parcSafeMemory_AllocateAndClear(size);
+ assertNotNull(result,
+ "parcSafeMemory_AllocateAndClear failed: NULL result.");
+
+ for (size_t i = 0; i < size; i++) {
+ assertTrue(((char *) result)[i] == 0,
+ "parcSafeMemory_AllocateAndClear failed to zero memory at index %zd", i);
+ }
+ assertTrue(parcSafeMemory_Outstanding() == 1,
+ "Expected 1 outstanding allocation, actual %d", parcSafeMemory_Outstanding());
+ parcSafeMemory_Deallocate(&result);
+ assertTrue(parcSafeMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocation, actual %d", parcSafeMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_Reallocate)
+{
+ size_t size = 100;
+
+ void *result = parcSafeMemory_AllocateAndClear(size);
+ assertNotNull(result,
+ "parcSafeMemory_Allocate failed: NULL.");
+
+ for (size_t i = 0; i < size; i++) {
+ assertTrue(((char *) result)[i] == 0,
+ "parcSafeMemory_AllocateAndClear failed to zero memory at index %zd", i);
+ }
+
+ result = parcSafeMemory_Reallocate(result, size * 2);
+
+ assertTrue(parcSafeMemory_Outstanding() == 1,
+ "Expected 1 outstanding allocation, actual %d", parcSafeMemory_Outstanding());
+ parcSafeMemory_Deallocate(&result);
+ assertTrue(parcSafeMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocations, actual %d", parcSafeMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_Deallocate_NothingAllocated)
+{
+ void *result = 0;
+
+ parcSafeMemory_Deallocate(&result);
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_IsValid_True)
+{
+ void *result = parcSafeMemory_AllocateAndClear(5);
+
+ assertTrue(parcSafeMemory_IsValid(result), "Expected properly allocated memory to be valid PARC Safe Memory.");
+
+ parcSafeMemory_Deallocate(&result);
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_IsValid_False)
+{
+ char *memory[10];
+
+ assertFalse(parcSafeMemory_IsValid(memory), "Expected improperly allocated memory to be invalid PARC Safe Memory.");
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_Display)
+{
+ void *result = parcSafeMemory_AllocateAndClear(5);
+
+ parcSafeMemory_Display(result, 0);
+ parcSafeMemory_Deallocate(&result);
+}
+
+LONGBOW_TEST_CASE(Global, parcSafeMemory_Display_NULL)
+{
+ parcSafeMemory_Display(NULL, 0);
+}
+
+LONGBOW_TEST_FIXTURE(Errors)
+{
+ LONGBOW_RUN_TEST_CASE(Errors, parcSafeMemory_Reallocate_NULL);
+ LONGBOW_RUN_TEST_CASE(Errors, PARCSafeMemory_Deallocate_Overrun);
+ LONGBOW_RUN_TEST_CASE(Errors, PARCSafeMemory_Deallocate_Underrun);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Errors)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Errors)
+{
+ // The tests purposefully wreck the various per-allocation accounting structures for the allocated memory in order to test for
+ // properly catching the overrun, underrun or other damage.
+ // As a result any cleanup of allocated memory is not possible, so these tests leak allocated memory.
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Errors, parcSafeMemory_Reallocate_NULL)
+{
+ void *result = NULL;
+ size_t size = 100;
+
+ result = parcSafeMemory_Reallocate(result, size * 2);
+
+ assertTrue(parcSafeMemory_Outstanding() == 1,
+ "Expected 1 outstanding allocation, actual %d", parcSafeMemory_Outstanding());
+ parcSafeMemory_Deallocate(&result);
+ assertTrue(parcSafeMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocations, actual %d", parcSafeMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, PARCSafeMemory_Deallocate_Underrun, .event = &LongBowTrapUnexpectedStateEvent)
+{
+ size_t expectedSize = sizeof(void *) * 2;
+ void *memory = parcSafeMemory_Allocate(expectedSize);
+ assertTrue(_parcSafeMemory_GetState(memory) == PARCSafeMemoryState_OK,
+ "Memory did not validate.");
+
+ for (int i = -2; i < (int) expectedSize; i++) {
+ ((unsigned char *) memory)[i] = (unsigned char) i;
+ }
+
+ assertTrue(_parcSafeMemory_GetState(memory) == PARCSafeMemoryState_UNDERRUN,
+ "Memory did not underrun.");
+
+ assertTrue(parcSafeMemory_Outstanding() != 0,
+ "No memory allocated!");
+ PARCSafeMemoryState state = _parcSafeMemory_GetState(memory);
+ parcSafeMemory_Deallocate(&memory);
+
+ assertTrue(state == PARCSafeMemoryState_UNDERRUN,
+ "Expected memory to be underrun");
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Errors, PARCSafeMemory_Deallocate_Overrun, .event = &LongBowTrapUnexpectedStateEvent)
+{
+ size_t expectedSize = 100;
+ void *memory = parcSafeMemory_Allocate(expectedSize);
+ assertTrue(_parcSafeMemory_GetState(memory) == PARCSafeMemoryState_OK,
+ "Memory did not validate.");
+
+ for (unsigned char i = 0; i < expectedSize + 5; i++) {
+ ((unsigned char *) memory)[i] = i;
+ }
+
+ assertTrue(parcSafeMemory_Outstanding() != 0,
+ "No memory allocated!");
+ assertTrue(_parcSafeMemory_GetState(memory) != PARCSafeMemoryState_OK,
+ "Expected not OK, actual %s", _parcSafeMemory_StateToString(_parcSafeMemory_GetState(memory)));
+ // this is expected to fail
+ parcSafeMemory_Deallocate(&memory);
+}
+
+LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, parcSafeMemory_AllocateDeallocate_1000000_WorstCase);
+ LONGBOW_RUN_TEST_CASE(Performance, parcSafeMemory_AllocateDeallocate_1000000_BestCase);
+
+ LONGBOW_RUN_TEST_CASE(Performance, _computeUsableMemoryLength);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+void *memory[1000000];
+
+LONGBOW_TEST_CASE(Performance, parcSafeMemory_AllocateDeallocate_1000000_WorstCase)
+{
+ size_t size = 100;
+
+ for (int i = 0; i < sizeof(memory) / sizeof(memory[0]); i++) {
+ memory[i] = parcSafeMemory_Allocate(size);
+ }
+ for (int i = 0; i < sizeof(memory) / sizeof(memory[0]); i++) {
+ parcSafeMemory_Deallocate(&memory[i]);
+ }
+}
+
+LONGBOW_TEST_CASE(Performance, parcSafeMemory_AllocateDeallocate_1000000_BestCase)
+{
+ size_t size = 100;
+
+ for (int i = 0; i < sizeof(memory) / sizeof(memory[0]); i++) {
+ memory[i] = parcSafeMemory_Allocate(size);
+ }
+
+ int i = sizeof(memory) / sizeof(memory[0]);
+ do {
+ i--;
+ parcSafeMemory_Deallocate(&memory[i]);
+ } while (i > 0);
+}
+
+LONGBOW_TEST_CASE(Performance, _computeUsableMemoryLength)
+{
+ for (int i = 0; i < 100000000; i++) {
+ size_t alignment = sizeof(void *);
+ size_t requestedLength = 10;
+ _computeUsableMemoryLength(requestedLength, alignment);
+ }
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(safetyMemory);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_SortedList.c b/libparc/parc/algol/test/test_parc_SortedList.c
new file mode 100644
index 00000000..f0445d86
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_SortedList.c
@@ -0,0 +1,510 @@
+/*
+ * 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_SortedList.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_SortedList)
+{
+ // 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(Specialization);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_SortedList)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_SortedList)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(CreateAcquireRelease)
+{
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease);
+ LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateCompare);
+}
+
+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)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+ assertNotNull(instance, "Expected non-null result from parcSortedList_Create();");
+
+ parcObjectTesting_AssertAcquire(instance);
+
+ parcSortedList_Release(&instance);
+ assertNull(instance, "Expected null result from parcSortedList_Release();");
+}
+
+// A signum function to compare two PARCBuffers by length of buffer.
+static int
+_compareTwoBuffersByLength(const PARCObject *buf1, const PARCObject *buf2)
+{
+ size_t size1 = parcBuffer_Limit((PARCBuffer *) buf1);
+ size_t size2 = parcBuffer_Limit((PARCBuffer *) buf2);
+
+ if (size1 > size2) {
+ return 1;
+ } else if (size2 > size1) {
+ return -1;
+ }
+ return 0;
+}
+
+LONGBOW_TEST_CASE(CreateAcquireRelease, CreateCompare)
+{
+ PARCSortedList *instance = parcSortedList_CreateCompare(_compareTwoBuffersByLength);
+
+ PARCBuffer *buf1 = parcBuffer_WrapCString("medium long");
+ PARCBuffer *buf2 = parcBuffer_WrapCString("somewhat longer");
+ PARCBuffer *buf3 = parcBuffer_WrapCString("short");
+
+ parcSortedList_Add(instance, buf1);
+ parcSortedList_Add(instance, buf2);
+ parcSortedList_Add(instance, buf3);
+
+ PARCBuffer *test = parcSortedList_GetAtIndex(instance, 0);
+ assertTrue(test == buf3, "Expected the shortes buffer first");
+
+ test = parcSortedList_GetAtIndex(instance, 1);
+ assertTrue(test == buf1, "Expected the medium length buffer second");
+
+ test = parcSortedList_GetAtIndex(instance, 2);
+ assertTrue(test == buf2, "Expected the longest buffer last");
+
+ parcBuffer_Release(&buf1);
+ parcBuffer_Release(&buf2);
+ parcBuffer_Release(&buf3);
+
+ parcSortedList_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcSortedList_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcSortedList_Display);
+ LONGBOW_RUN_TEST_CASE(Global, parcSortedList_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcSortedList_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcSortedList_IsValid);
+ LONGBOW_RUN_TEST_CASE(Global, parcSortedList_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Global, parcSortedList_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, parcSortedList_Copy)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+ PARCSortedList *copy = parcSortedList_Copy(instance);
+ assertTrue(parcSortedList_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcSortedList_Release(&instance);
+ parcSortedList_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Global, parcSortedList_Display)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+ parcSortedList_Display(instance, 0);
+ parcSortedList_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcSortedList_Equals)
+{
+ PARCSortedList *x = parcSortedList_Create();
+ PARCSortedList *y = parcSortedList_Create();
+ PARCSortedList *z = parcSortedList_Create();
+
+ parcObjectTesting_AssertEquals(x, y, z, NULL);
+
+ parcSortedList_Release(&x);
+ parcSortedList_Release(&y);
+ parcSortedList_Release(&z);
+}
+
+LONGBOW_TEST_CASE(Global, parcSortedList_HashCode)
+{
+ PARCSortedList *x = parcSortedList_Create();
+ PARCSortedList *y = parcSortedList_Create();
+
+ parcObjectTesting_AssertHashCode(x, y);
+
+ parcSortedList_Release(&x);
+ parcSortedList_Release(&y);
+}
+
+LONGBOW_TEST_CASE(Global, parcSortedList_IsValid)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+ assertTrue(parcSortedList_IsValid(instance), "Expected parcSortedList_Create to result in a valid instance.");
+
+ parcSortedList_Release(&instance);
+ assertFalse(parcSortedList_IsValid(instance), "Expected parcSortedList_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Global, parcSortedList_ToJSON)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+
+ PARCJSON *json = parcSortedList_ToJSON(instance);
+
+ parcJSON_Release(&json);
+
+ parcSortedList_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcSortedList_ToString)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+
+ char *string = parcSortedList_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcSortedList_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+ parcSortedList_Release(&instance);
+}
+
+LONGBOW_TEST_FIXTURE(Specialization)
+{
+ LONGBOW_RUN_TEST_CASE(Specialization, parcSortedList_Add);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcSortedList_Remove);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcSortedList_GetAtIndex);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcSortedList_GetFirst);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcSortedList_GetLast);
+
+ LONGBOW_RUN_TEST_CASE(Specialization, parcSortedList_RemoveFirst);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcSortedList_RemoveFirst_SingleElement);
+ LONGBOW_RUN_TEST_CASE(Specialization, parcSortedList_RemoveLast);
+}
+
+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;
+}
+
+static void
+dump(PARCSortedList *i)
+{
+ PARCIterator *iterator = parcSortedList_CreateIterator(i);
+ while (parcIterator_HasNext(iterator)) {
+ PARCBuffer *buffer = parcIterator_Next(iterator);
+ parcBuffer_Display(buffer, 0);
+ }
+
+ parcIterator_Release(&iterator);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcSortedList_Add)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+ PARCBuffer *element1 = parcBuffer_WrapCString("1");
+ PARCBuffer *element2 = parcBuffer_WrapCString("2");
+ PARCBuffer *element3 = parcBuffer_WrapCString("3");
+ PARCBuffer *element4 = parcBuffer_WrapCString("4");
+ PARCBuffer *element7 = parcBuffer_WrapCString("7");
+ PARCBuffer *element6 = parcBuffer_WrapCString("6");
+ PARCBuffer *element5 = parcBuffer_WrapCString("5");
+ PARCBuffer *element8 = parcBuffer_WrapCString("8");
+
+ parcSortedList_Add(instance, element2);
+ parcSortedList_Display(instance, 0);
+ parcSortedList_Add(instance, element8);
+ parcSortedList_Display(instance, 0);
+ parcSortedList_Add(instance, element3);
+ parcSortedList_Display(instance, 0);
+ parcSortedList_Add(instance, element4);
+ parcSortedList_Display(instance, 0);
+ parcSortedList_Add(instance, element7);
+ parcSortedList_Display(instance, 0);
+ parcSortedList_Add(instance, element6);
+ parcSortedList_Display(instance, 0);
+ parcSortedList_Add(instance, element5);
+ parcSortedList_Display(instance, 0);
+ parcSortedList_Add(instance, element1);
+ parcSortedList_Display(instance, 0);
+ parcSortedList_Add(instance, element6);
+ parcSortedList_Display(instance, 0);
+
+ dump(instance);
+
+ parcBuffer_Release(&element1);
+ parcBuffer_Release(&element2);
+ parcBuffer_Release(&element3);
+ parcBuffer_Release(&element4);
+ parcBuffer_Release(&element5);
+ parcBuffer_Release(&element6);
+ parcBuffer_Release(&element7);
+ parcBuffer_Release(&element8);
+ parcSortedList_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcSortedList_Remove)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+ PARCBuffer *element1 = parcBuffer_WrapCString("1");
+ PARCBuffer *element2 = parcBuffer_WrapCString("2");
+ PARCBuffer *element3 = parcBuffer_WrapCString("3");
+ PARCBuffer *element4 = parcBuffer_WrapCString("4");
+ PARCBuffer *element7 = parcBuffer_WrapCString("7");
+ PARCBuffer *element6 = parcBuffer_WrapCString("6");
+ PARCBuffer *element5 = parcBuffer_WrapCString("5");
+ PARCBuffer *element8 = parcBuffer_WrapCString("8");
+
+ parcSortedList_Add(instance, element1);
+ parcSortedList_Add(instance, element2);
+ parcSortedList_Add(instance, element3);
+ parcSortedList_Display(instance, 0);
+
+ parcSortedList_Remove(instance, element2);
+
+ assertTrue(parcSortedList_Size(instance) == 2, "Expected list to be 2 in size");
+
+ parcBuffer_Release(&element1);
+ parcBuffer_Release(&element2);
+ parcBuffer_Release(&element3);
+ parcBuffer_Release(&element4);
+ parcBuffer_Release(&element5);
+ parcBuffer_Release(&element6);
+ parcBuffer_Release(&element7);
+ parcBuffer_Release(&element8);
+ parcSortedList_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcSortedList_GetAtIndex)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+ PARCBuffer *element1 = parcBuffer_WrapCString("1");
+ PARCBuffer *element2 = parcBuffer_WrapCString("2");
+ PARCBuffer *element3 = parcBuffer_WrapCString("3");
+ PARCBuffer *element4 = parcBuffer_WrapCString("4");
+ PARCBuffer *element7 = parcBuffer_WrapCString("7");
+ PARCBuffer *element6 = parcBuffer_WrapCString("6");
+ PARCBuffer *element5 = parcBuffer_WrapCString("5");
+ PARCBuffer *element8 = parcBuffer_WrapCString("8");
+
+ parcSortedList_Add(instance, element1);
+ parcSortedList_Add(instance, element2);
+ parcSortedList_Add(instance, element3);
+
+ PARCBuffer *actual = (PARCBuffer *) parcSortedList_GetAtIndex(instance, 1);
+ assertTrue(parcBuffer_Equals(element2, actual), "Got the wrong value at index 1");
+
+ parcBuffer_Release(&element1);
+ parcBuffer_Release(&element2);
+ parcBuffer_Release(&element3);
+ parcBuffer_Release(&element4);
+ parcBuffer_Release(&element5);
+ parcBuffer_Release(&element6);
+ parcBuffer_Release(&element7);
+ parcBuffer_Release(&element8);
+ parcSortedList_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcSortedList_GetFirst)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+ PARCBuffer *element1 = parcBuffer_WrapCString("1");
+ PARCBuffer *element2 = parcBuffer_WrapCString("2");
+ PARCBuffer *element3 = parcBuffer_WrapCString("3");
+ PARCBuffer *element4 = parcBuffer_WrapCString("4");
+ PARCBuffer *element7 = parcBuffer_WrapCString("7");
+ PARCBuffer *element6 = parcBuffer_WrapCString("6");
+ PARCBuffer *element5 = parcBuffer_WrapCString("5");
+ PARCBuffer *element8 = parcBuffer_WrapCString("8");
+
+ parcSortedList_Add(instance, element1);
+ parcSortedList_Add(instance, element2);
+ parcSortedList_Add(instance, element3);
+
+ PARCBuffer *actual = (PARCBuffer *) parcSortedList_GetFirst(instance);
+ assertTrue(parcBuffer_Equals(element1, actual), "Got the wrong value.");
+
+ parcBuffer_Release(&element1);
+ parcBuffer_Release(&element2);
+ parcBuffer_Release(&element3);
+ parcBuffer_Release(&element4);
+ parcBuffer_Release(&element5);
+ parcBuffer_Release(&element6);
+ parcBuffer_Release(&element7);
+ parcBuffer_Release(&element8);
+ parcSortedList_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcSortedList_GetLast)
+{
+ PARCSortedList *instance = parcSortedList_Create();
+ PARCBuffer *element1 = parcBuffer_WrapCString("1");
+ PARCBuffer *element2 = parcBuffer_WrapCString("2");
+ PARCBuffer *element3 = parcBuffer_WrapCString("3");
+ PARCBuffer *element4 = parcBuffer_WrapCString("4");
+ PARCBuffer *element7 = parcBuffer_WrapCString("7");
+ PARCBuffer *element6 = parcBuffer_WrapCString("6");
+ PARCBuffer *element5 = parcBuffer_WrapCString("5");
+ PARCBuffer *element8 = parcBuffer_WrapCString("8");
+
+ parcSortedList_Add(instance, element1);
+ parcSortedList_Add(instance, element2);
+ parcSortedList_Add(instance, element3);
+
+ PARCBuffer *actual = (PARCBuffer *) parcSortedList_GetLast(instance);
+ assertTrue(parcBuffer_Equals(element3, actual), "Got the wrong value at index 1");
+
+ parcBuffer_Release(&element1);
+ parcBuffer_Release(&element2);
+ parcBuffer_Release(&element3);
+ parcBuffer_Release(&element4);
+ parcBuffer_Release(&element5);
+ parcBuffer_Release(&element6);
+ parcBuffer_Release(&element7);
+ parcBuffer_Release(&element8);
+ parcSortedList_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcSortedList_RemoveFirst)
+{
+ PARCSortedList *deque = parcSortedList_Create();
+
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ parcSortedList_Add(deque, object1);
+ parcSortedList_Add(deque, object2);
+ parcSortedList_Add(deque, object3);
+
+ PARCBuffer *peek = parcSortedList_RemoveFirst(deque);
+ assertTrue(parcBuffer_Equals(object1, peek), "Objects out of order");
+
+ parcBuffer_Release(&peek);
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcSortedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcSortedList_RemoveFirst_SingleElement)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCSortedList *deque = parcSortedList_Create();
+ parcSortedList_Add(deque, object1);
+
+ PARCBuffer *peek = parcSortedList_RemoveFirst(deque);
+ assertTrue(parcBuffer_Equals(object1, peek),
+ "Objects out of order.");
+
+ parcBuffer_Release(&peek);
+ parcBuffer_Release(&object1);
+ parcSortedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcSortedList_RemoveLast)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+ PARCBuffer *object2 = parcBuffer_WrapCString("2");
+ PARCBuffer *object3 = parcBuffer_WrapCString("3");
+
+ PARCSortedList *deque = parcSortedList_Create();
+ parcSortedList_Add(deque, object1);
+ parcSortedList_Add(deque, object2);
+ parcSortedList_Add(deque, object3);
+
+ PARCBuffer *peek = parcSortedList_RemoveLast(deque);
+ assertTrue(parcBuffer_Equals(object3, peek),
+ "Objects out of order.");
+
+ parcBuffer_Release(&peek);
+
+ parcBuffer_Release(&object1);
+ parcBuffer_Release(&object2);
+ parcBuffer_Release(&object3);
+ parcSortedList_Release(&deque);
+}
+
+LONGBOW_TEST_CASE(Specialization, parcSortedList_RemoveLast_SingleElement)
+{
+ PARCBuffer *object1 = parcBuffer_WrapCString("1");
+
+ PARCSortedList *deque = parcSortedList_Create();
+ parcSortedList_Add(deque, object1);
+
+ PARCBuffer *peek = parcSortedList_RemoveLast(deque);
+ assertTrue(parcBuffer_Equals(object1, peek),
+ "Objects out of order.");
+
+ parcBuffer_Release(&object1);
+ parcSortedList_Release(&deque);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_SortedList);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Stack.c b/libparc/parc/algol/test/test_parc_Stack.c
new file mode 100755
index 00000000..3ca27682
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Stack.c
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+/**
+ * @header <#Headline Name#>
+ * @abstract <#Abstract#>
+ * @discussion
+ * <#Discussion#>
+ *
+ */
+#include "../parc_Stack.c"
+
+#include <LongBow/unit-test.h>
+#include <LongBow/debugging.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/algol/parc_ArrayList.h>
+#include <parc/algol/parc_Deque.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(test_parc_Stack)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(test_parc_Stack)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(test_parc_Stack)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcStack_IsEmpty_PARCDeque);
+ LONGBOW_RUN_TEST_CASE(Global, parcStack_IsEmpty_PARCArrayList);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Global, parcStack_IsEmpty_PARCDeque)
+{
+ PARCStackInterface dequeAsStack = {
+ .parcStack_Release = (void (*)(void **))parcDeque_Release,
+ .parcStack_IsEmpty = (bool (*)(const void *))parcDeque_IsEmpty,
+ .parcStack_Peek = (void *(*)(const void *))parcDeque_PeekLast,
+ .parcStack_Pop = (void *(*)(void *))parcDeque_RemoveLast,
+ .parcStack_Push = (void *(*)(void *, void *))parcDeque_Append,
+ .parcStack_Search = NULL
+ };
+
+ PARCStack *stack = parcStack(parcDeque_Create(), &dequeAsStack);
+
+ bool actual = parcStack_IsEmpty(stack);
+ parcStack_Release(&stack);
+ assertTrue(actual, "Expected the stack to be empty.");
+}
+
+LONGBOW_TEST_CASE(Global, parcStack_IsEmpty_PARCArrayList)
+{
+ PARCStackInterface arrayListAsStack = {
+ .parcStack_Release = (void (*)(void **))parcArrayList_Destroy,
+ .parcStack_IsEmpty = (bool (*)(const void *))parcArrayList_IsEmpty,
+ .parcStack_Peek = (void *(*)(const void *))parcArrayList_Peek,
+ .parcStack_Pop = (void *(*)(void *))parcArrayList_Pop,
+ .parcStack_Push = (void *(*)(void *, void *))parcArrayList_Add,
+ .parcStack_Search = NULL
+ };
+
+ PARCStack *stack = parcStack(parcArrayList_Create(NULL), &arrayListAsStack);
+
+ bool actual = parcStack_IsEmpty(stack);
+ parcStack_Release(&stack);
+ assertTrue(actual, "Expected the stack to be empty.");
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(test_parc_Stack);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_StdlibMemory.c b/libparc/parc/algol/test/test_parc_StdlibMemory.c
new file mode 100644
index 00000000..7cf49991
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_StdlibMemory.c
@@ -0,0 +1,326 @@
+/*
+ * 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_StdlibMemory.c"
+
+#include <LongBow/testing.h>
+#include <LongBow/debugging.h>
+
+#include <parc/testing/parc_MemoryTesting.h>
+
+LONGBOW_TEST_RUNNER(test_parc_StdlibMemory)
+{
+ // 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(Threads);
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(test_parc_StdlibMemory)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(test_parc_StdlibMemory)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcStdlibMemory_Allocate);
+ LONGBOW_RUN_TEST_CASE(Global, parcStdlibMemory_MemAlign_BadAlignment);
+ LONGBOW_RUN_TEST_CASE(Global, parcStdlibMemory_MemAlign_BadSize);
+ LONGBOW_RUN_TEST_CASE(Global, parcStdlibMemory_AllocateAndClear);
+ LONGBOW_RUN_TEST_CASE(Global, parcStdlibMemory_AllocateAndClear_BadSize);
+ LONGBOW_RUN_TEST_CASE(Global, parcStdlibMemory_Reallocate);
+ LONGBOW_RUN_TEST_CASE(Global, parcStdlibMemory_Reallocate_NULL);
+ LONGBOW_RUN_TEST_CASE(Global, parcStdlibMemory_StringDuplicate);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaks allocations.", longBowTestCase_GetFullName(testCase))) {
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcStdlibMemory_Allocate)
+{
+ size_t size = 100;
+
+ void *result = parcStdlibMemory_Allocate(size);
+
+ assertNotNull(result, "parcStdlibMemory_Allocate failed: NULL result.");
+ assertTrue(parcStdlibMemory_Outstanding() == 1,
+ "Expected 1 outstanding allocation, actual %d", parcStdlibMemory_Outstanding());
+ parcStdlibMemory_Deallocate(&result);
+}
+
+LONGBOW_TEST_CASE(Global, parcStdlibMemory_MemAlign_BadAlignment)
+{
+ void *result;
+ size_t alignment = 3;
+ size_t size = 1200;
+
+ int failure = parcStdlibMemory_MemAlign(&result, alignment, size);
+ assertTrue(failure == EINVAL,
+ "parcStdlibMemory_Allocate failed to report bad aligment specification");
+ assertTrue(parcStdlibMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocations, actual %d", parcStdlibMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parcStdlibMemory_MemAlign_BadSize)
+{
+ void *result;
+ size_t alignment = sizeof(void *);
+ size_t size = 0;
+
+ int failure = parcStdlibMemory_MemAlign(&result, alignment, size);
+ assertTrue(failure == EINVAL,
+ "parcStdlibMemory_Allocate failed to report bad aligment specification");
+ assertTrue(parcStdlibMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocation, actual %d", parcStdlibMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parcStdlibMemory_AllocateAndClear)
+{
+ size_t size = 1200;
+
+ void *result = parcStdlibMemory_AllocateAndClear(size);
+ assertNotNull(result, "parcStdlibMemory_Allocate failed: NULL result.");
+
+ for (size_t i = 0; i < size; i++) {
+ assertTrue(((char *) result)[i] == 0,
+ "parcStdlibMemory_AllocateAndClear failed to zero memory at index %zd", i);
+ }
+ assertTrue(parcStdlibMemory_Outstanding() == 1,
+ "Expected 1 outstanding allocation, actual %d", parcStdlibMemory_Outstanding());
+ parcStdlibMemory_Deallocate(&result);
+ assertTrue(parcStdlibMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocation, actual %d", parcStdlibMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parcStdlibMemory_AllocateAndClear_BadSize)
+{
+ void *result;
+ size_t alignment = sizeof(void *);
+ size_t size = 0;
+
+ int failure = parcStdlibMemory_MemAlign(&result, alignment, size);
+ assertTrue(failure == EINVAL,
+ "parcStdlibMemory_Allocate failed to report bad aligment specification");
+ assertTrue(parcStdlibMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocations, actual %d", parcStdlibMemory_Outstanding());
+}
+
+static void
+_test_SetMemory(unsigned char *memory, size_t size)
+{
+ for (size_t i = 0; i < size; i++) {
+ memory[i] = i;
+ }
+}
+
+static void
+_test_CheckMemory(unsigned char *memory, size_t size)
+{
+ for (size_t i = 0; i < size; i++) {
+ assertTrue(memory[i] == (i % 256), "memory failed to check at index %zd", i);
+ }
+}
+
+
+LONGBOW_TEST_CASE(Global, parcStdlibMemory_Reallocate)
+{
+ size_t size = 1200;
+
+ void *result = parcStdlibMemory_AllocateAndClear(size);
+ assertNotNull(result,
+ "parcStdlibMemory_Allocate failed: NULL result.");
+
+ _test_SetMemory(result, size);
+ _test_CheckMemory(result, size);
+
+ result = parcStdlibMemory_Reallocate(result, size * 2);
+
+ _test_CheckMemory(result, size);
+
+ assertTrue(parcStdlibMemory_Outstanding() == 1,
+ "Expected 1 outstanding allocation, actual %d", parcStdlibMemory_Outstanding());
+ parcStdlibMemory_Deallocate(&result);
+ assertTrue(parcStdlibMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocations, actual %d", parcStdlibMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parcStdlibMemory_Reallocate_NULL)
+{
+ void *result = NULL;
+ size_t size = 1200;
+
+ result = parcStdlibMemory_Reallocate(result, size * 2);
+ _test_SetMemory(result, size * 2);
+ _test_CheckMemory(result, size * 2);
+
+ assertTrue(parcStdlibMemory_Outstanding() == 1,
+ "Expected 1 outstanding allocation, actual %d", parcStdlibMemory_Outstanding());
+ parcStdlibMemory_Deallocate(&result);
+ assertTrue(parcStdlibMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocations, actual %d", parcStdlibMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, parcStdlibMemory_StringDuplicate)
+{
+ char *expected = "Hello World";
+ char *actual = parcStdlibMemory_StringDuplicate(expected, strlen(expected));
+
+ assertTrue(expected != actual,
+ "Expected a distinct pointer unequal to the original string");
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected strings to be equal. '%s' vs '%s'", expected, actual);
+
+ assertTrue(parcStdlibMemory_Outstanding() == 1,
+ "Expected 1 outstanding allocation, actual %d", parcStdlibMemory_Outstanding());
+ parcStdlibMemory_Deallocate((void **) &actual);
+ assertTrue(parcStdlibMemory_Outstanding() == 0,
+ "Expected 0 outstanding allocations, actual %d", parcStdlibMemory_Outstanding());
+}
+
+LONGBOW_TEST_FIXTURE(Threads)
+{
+ LONGBOW_RUN_TEST_CASE(Threads, Threads1000);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Threads)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Threads)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+void *
+allocator(void *unused)
+{
+ for (int i = 0; i < 1000; i++) {
+ void *memory = parcStdlibMemory_Allocate(10);
+ parcStdlibMemory_Deallocate(&memory);
+ }
+ return 0;
+}
+
+LONGBOW_TEST_CASE(Threads, Threads1000)
+{
+#define NTHREADS 1000
+ pthread_t thread[NTHREADS];
+
+ for (int i = 0; i < NTHREADS; i++) {
+ pthread_create(&thread[i], NULL, allocator, NULL);
+ }
+ for (int i = 0; i < NTHREADS; i++) {
+ pthread_join(thread[0], NULL);
+ }
+}
+
+LONGBOW_TEST_FIXTURE_OPTIONS(Performance, .enabled = false)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, parcStdlibMemory_AllocateDeallocate_Forward);
+ LONGBOW_RUN_TEST_CASE(Performance, parcStdlibMemory_AllocateDeallocate_Reverse);
+ LONGBOW_RUN_TEST_CASE(Performance, parcStdlibMemory_MemAlignDeallocate_Forward);
+ LONGBOW_RUN_TEST_CASE(Performance, parcStdlibMemory_MemAlignDeallocate_Reverse);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+#define ELEMENT_COUNT 1000000
+#define ELEMENT_SIZE 151
+void *memory[ELEMENT_COUNT];
+
+LONGBOW_TEST_CASE(Performance, parcStdlibMemory_AllocateDeallocate_Forward)
+{
+ for (int i = 0; i < ELEMENT_COUNT; i++) {
+ memory[i] = parcStdlibMemory_Allocate(ELEMENT_SIZE);
+ }
+ for (int i = 0; i < ELEMENT_COUNT; i++) {
+ parcStdlibMemory_Deallocate(&memory[i]);
+ }
+}
+
+LONGBOW_TEST_CASE(Performance, parcStdlibMemory_AllocateDeallocate_Reverse)
+{
+ for (int i = 0; i < ELEMENT_COUNT; i++) {
+ memory[i] = parcStdlibMemory_Allocate(ELEMENT_SIZE);
+ }
+
+ int i = ELEMENT_COUNT;
+ do {
+ i--;
+ parcStdlibMemory_Deallocate(&memory[i]);
+ } while (i > 0);
+}
+
+LONGBOW_TEST_CASE(Performance, parcStdlibMemory_MemAlignDeallocate_Forward)
+{
+ for (int i = 0; i < ELEMENT_COUNT; i++) {
+ parcStdlibMemory_MemAlign(&memory[i], sizeof(void *), ELEMENT_SIZE);
+ }
+ for (int i = 0; i < ELEMENT_COUNT; i++) {
+ parcStdlibMemory_Deallocate(&memory[i]);
+ }
+}
+
+LONGBOW_TEST_CASE(Performance, parcStdlibMemory_MemAlignDeallocate_Reverse)
+{
+ for (int i = 0; i < ELEMENT_COUNT; i++) {
+ parcStdlibMemory_MemAlign(&memory[i], sizeof(void *), ELEMENT_SIZE);
+ }
+
+ int i = ELEMENT_COUNT;
+ do {
+ i--;
+ parcStdlibMemory_Deallocate(&memory[i]);
+ } while (i > 0);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(test_parc_StdlibMemory);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_String.c b/libparc/parc/algol/test/test_parc_String.c
new file mode 100644
index 00000000..84d3d3da
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_String.c
@@ -0,0 +1,210 @@
+/*
+ * 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_String.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_String)
+{
+ // 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_String)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_String)
+{
+ 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)
+{
+ PARCString *instance = parcString_Create("Hello World");
+ assertNotNull(instance, "Expected non-null result from parcString_Create();");
+ parcObjectTesting_AssertAcquireReleaseImpl(instance);
+
+ parcString_Release(&instance);
+ assertNull(instance, "Expected null result from parcString_Release();");
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcString_Compare);
+ LONGBOW_RUN_TEST_CASE(Global, parcString_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, parcString_Display);
+ LONGBOW_RUN_TEST_CASE(Global, parcString_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcString_HashCode);
+ LONGBOW_RUN_TEST_CASE(Global, parcString_IsValid);
+ LONGBOW_RUN_TEST_CASE(Global, parcString_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Global, parcString_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, parcString_Compare)
+{
+ PARCString *string = parcString_Create("Hello1");
+ PARCString *equivalent[2] = {
+ parcString_Create("Hello1"),
+ NULL
+ };
+ PARCString *greater[2] = {
+ parcString_Create("Hello2"),
+ NULL
+ };
+ PARCString *lesser[2] = {
+ parcString_Create("Hello0"),
+ NULL
+ };
+
+ parcObjectTesting_AssertCompareTo(parcString_Compare, string, equivalent, lesser, greater);
+ parcString_Release(&string);
+ parcString_Release(&equivalent[0]);
+ parcString_Release(&greater[0]);
+ parcString_Release(&lesser[0]);
+}
+
+LONGBOW_TEST_CASE(Global, parcString_Copy)
+{
+ PARCString *instance = parcString_Create("Hello World");
+ PARCString *copy = parcString_Copy(instance);
+ assertTrue(parcString_Equals(instance, copy), "Expected the copy to be equal to the original");
+
+ parcString_Release(&instance);
+ parcString_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(Global, parcString_Display)
+{
+ PARCString *instance = parcString_Create("Hello World");
+ parcString_Display(instance, 0);
+ parcString_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcString_Equals)
+{
+ PARCString *x = parcString_Create("Hello World");
+ PARCString *y = parcString_Create("Hello World");
+ PARCString *z = parcString_Create("Hello World");
+
+ parcObjectTesting_AssertEquals(x, y, z, NULL);
+
+ parcString_Release(&x);
+ parcString_Release(&y);
+ parcString_Release(&z);
+}
+
+LONGBOW_TEST_CASE(Global, parcString_HashCode)
+{
+ PARCString *x = parcString_Create("Hello World");
+ PARCString *y = parcString_Create("Hello World");
+
+ parcObjectTesting_AssertHashCode(x, y);
+
+ parcString_Release(&x);
+ parcString_Release(&y);
+}
+
+LONGBOW_TEST_CASE(Global, parcString_IsValid)
+{
+ PARCString *instance = parcString_Create("Hello World");
+ assertTrue(parcString_IsValid(instance), "Expected parcString_Create to result in a valid instance.");
+
+ parcString_Release(&instance);
+ assertFalse(parcString_IsValid(instance), "Expected parcString_Release to result in an invalid instance.");
+}
+
+LONGBOW_TEST_CASE(Global, parcString_ToJSON)
+{
+ PARCString *instance = parcString_Create("Hello World");
+
+ PARCJSON *json = parcString_ToJSON(instance);
+
+ parcJSON_Release(&json);
+
+ parcString_Release(&instance);
+}
+
+LONGBOW_TEST_CASE(Global, parcString_ToString)
+{
+ PARCString *instance = parcString_Create("Hello World");
+
+ char *string = parcString_ToString(instance);
+
+ assertNotNull(string, "Expected non-NULL result from parcString_ToString");
+
+ parcMemory_Deallocate((void **) &string);
+ parcString_Release(&instance);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_String);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
+
+
diff --git a/libparc/parc/algol/test/test_parc_Time.c b/libparc/parc/algol/test/test_parc_Time.c
new file mode 100644
index 00000000..2befdde1
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Time.c
@@ -0,0 +1,144 @@
+/*
+ * 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 <LongBow/unit-test.h>
+#include <LongBow/debugging.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_Memory.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_Time.c"
+
+LONGBOW_TEST_RUNNER(test_parc_Time)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(test_parc_Time)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(test_parc_Time)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcTime_TimevalAsString);
+ LONGBOW_RUN_TEST_CASE(Global, parcTime_TimevalAsISO8601);
+ LONGBOW_RUN_TEST_CASE(Global, parcTime_TimevalAsRFC3339);
+ LONGBOW_RUN_TEST_CASE(Global, parcTime_RFC3339_Now);
+ LONGBOW_RUN_TEST_CASE(Global, parcTime_NowTimeval);
+ LONGBOW_RUN_TEST_CASE(Global, parcTime_NowMicroseconds);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Global, parcTime_TimevalAsString)
+{
+ struct timeval timeval;
+ timeval.tv_sec = 0;
+ timeval.tv_usec = 1000;
+
+ char *expected = "0.001000";
+ char *actual = parcTime_TimevalAsString(timeval);
+ assertTrue(strcmp(expected, actual) == 0, "Expected %s, actual %s", expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcTime_TimevalAsISO8601)
+{
+ struct timeval timeval;
+ timeval.tv_sec = 0;
+ timeval.tv_usec = 1000;
+
+ char *expected = "1970-01-01 00:00:00.001000Z";
+
+ char actual[64];
+ parcTime_TimevalAsISO8601(&timeval, actual);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected %s, actual %s", expected, actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcTime_TimevalAsRFC3339)
+{
+ struct timeval timeval;
+ timeval.tv_sec = 0;
+ timeval.tv_usec = 1000;
+
+ char *expected = "1970-01-01T00:00:00.001000Z";
+
+ char actual[64];
+ parcTime_TimevalAsRFC3339(&timeval, actual);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected %s, actual %s", expected, actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcTime_RFC3339_Now)
+{
+ struct timeval timeval;
+ gettimeofday(&timeval, NULL);
+
+ char actual[64];
+ parcTime_TimevalAsRFC3339(&timeval, actual);
+ printf("%s\n", actual);
+}
+
+LONGBOW_TEST_CASE(Global, parcTime_NowTimeval)
+{
+ struct timeval result = parcTime_NowTimeval();
+ assertTrue(result.tv_sec != 0, "Expected NOW to not be zero.");
+}
+
+LONGBOW_TEST_CASE(Global, parcTime_NowMicroseconds)
+{
+ uint64_t result = parcTime_NowMicroseconds();
+ assertTrue(result != 0, "Expected NOW to not be zero.");
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(test_parc_Time);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_TreeMap.c b/libparc/parc/algol/test/test_parc_TreeMap.c
new file mode 100755
index 00000000..9355380b
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_TreeMap.c
@@ -0,0 +1,1565 @@
+/*
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include "../parc_TreeMap.c"
+
+
+typedef struct {
+ int value;
+} _Int;
+
+static _Int *
+_int_Copy(const _Int *source);
+
+static bool
+_int_Equals(const _Int *a, const _Int *b)
+{
+ return a->value == b->value;
+}
+
+static int
+_int_Compare(const _Int *a, const _Int *b)
+{
+ int result = 0;
+ if (a->value > b->value) {
+ result = 1;
+ } else if (a->value < b->value) {
+ result = -1;
+ }
+
+ return result;
+}
+
+parcObject_ExtendPARCObject(_Int, NULL, _int_Copy, NULL, _int_Equals, _int_Compare, NULL, NULL);
+
+static
+parcObject_ImplementRelease(_int, _Int);
+
+static _Int *
+_int_Create(const int value)
+{
+ _Int *newObj = parcObject_CreateInstance(_Int);
+ assertNotNull(newObj, "parcMemory_Allocate(%zu) returned NULL", sizeof(int));
+ newObj->value = value;
+ return newObj;
+}
+
+static _Int *
+_int_Copy(const _Int *source)
+{
+ return _int_Create(source->value);
+}
+
+static _Int *
+_int_Set(_Int *obj, const int value)
+{
+ obj->value = value;
+ return obj;
+}
+static PARCBuffer*
+strBuf(char *key)
+{
+ return parcBuffer_WrapCString(key);
+}
+
+
+LONGBOW_TEST_RUNNER(PARC_TreeMap)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+ LONGBOW_RUN_TEST_FIXTURE(Stress);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(PARC_TreeMap)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+
+ int seed = (int) time(NULL);
+ srandom(seed);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(PARC_TreeMap)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_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_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Create);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Remove_Ordered);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Put_Release);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Put_Ordered);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Put_OutOfOrder);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Put_Overwrite);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_ReleaseTillEmpty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Size_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Size);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Size_Overwrite);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Get_EmptyTree);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Get_NonExistent);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Get_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Get);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Get_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Get_Biggest);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Get_Smallest);
+
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_FirstKey);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_FirstEntry);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_LastKey);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_LastEntry);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_FirstKey_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_LastKey_Empty);
+
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_LowerEntry);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_LowerKey);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_HigherEntry);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_HigherKey);
+
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Remove_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Remove);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Remove_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Remove_NonExistent);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_RemoveAndRelease_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_RemoveAndRelease);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_RemoveAndRelease_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_RemoveAndRelease_NonExistent);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Remove_WithSuccessorNonRoot);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Remove_LeftChildRightChild);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Keys);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Values);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Equals_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Equals_DifferentLength);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Equals_Not_Values);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Equals_Not_Keys);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Copy_Direct);
+
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Iterator);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_ValueIterator);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_KeyIterator);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Remove_Using_Iterator);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeMap_Remove_Element_Using_Iterator);
+}
+
+#define N_TEST_ELEMENTS 42
+
+typedef struct {
+ PARCTreeMap *testMap1;
+ PARCTreeMap *testMap2;
+ _Int *k[N_TEST_ELEMENTS];
+ _Int *v[N_TEST_ELEMENTS];
+} TestData;
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+ data->testMap1 = parcTreeMap_Create();
+ data->testMap2 = parcTreeMap_CreateCustom((PARCTreeMap_CustomCompare *) _int_Compare);
+
+ for (int i = 0; i < N_TEST_ELEMENTS; ++i) {
+ data->k[i] = _int_Create(i);
+ data->v[i] = _int_Create(i + 1000);
+ }
+ longBowTestCase_SetClipBoardData(testCase, data);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ parcTreeMap_Release(&data->testMap1);
+ parcTreeMap_Release(&data->testMap2);
+
+ for (int i = 0; i < N_TEST_ELEMENTS; ++i) {
+ _int_Release(&(data->k[i]));
+ _int_Release(&(data->v[i]));
+ }
+
+ parcMemory_Deallocate((void **) &data);
+
+ /*
+ * 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;
+}
+
+static
+int
+recursiveCheckBlackDepth(const PARCTreeMap *tree, const _RBNode *node)
+{
+ assertNotNull(tree, "Null tree?\n");
+ assertNotNull(node, "Null node?\n");
+ if (node == tree->nil) {
+ return 0;
+ }
+ int right_depth = recursiveCheckBlackDepth(tree, node->rightChild);
+ int left_depth = recursiveCheckBlackDepth(tree, node->leftChild);
+ assertTrue(right_depth == left_depth, "Wrong depth!!\n");
+ if (_rbNodeColor(node) == BLACK) {
+ return right_depth + 1;
+ }
+ return right_depth;
+}
+
+static
+void
+rbCheckTree(const PARCTreeMap *tree)
+{
+ assertNotNull(tree, "Tree can't be NULL");
+ _rbNodeAssertTreeInvariants(tree);
+ if (tree->size > 0) {
+ recursiveCheckBlackDepth(tree, tree->root);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Remove_Ordered)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+
+ for (int i = 0; i < 16; i++) {
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+
+ for (int i = 0; i < 14; i++) {
+ //rbPrintTreeString(tree1);
+ PARCObject *value = parcTreeMap_Remove(tree1, data->k[i]);
+ assertNotNull(value, "Data is null!");
+ assertTrue(_int_Equals(value, data->v[i]), "Expect the ordered value.");
+ parcObject_Release(&value);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Create)
+{
+ PARCTreeMap *map = parcTreeMap_Create();
+ parcTreeMap_Release(&map);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Acquire)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *map = parcTreeMap_Acquire(data->testMap1);
+ parcTreeMap_Release(&map);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Put_Release)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree = data->testMap1;
+
+ PARCBuffer *value1 = strBuf("value 1");
+ PARCBuffer *key1 = strBuf("1");
+ PARCBuffer *value2 = strBuf("value 2");
+ PARCBuffer *key2 = strBuf("2");
+ PARCBuffer *value3 = strBuf("value 3");
+ PARCBuffer *key3 = strBuf("3");
+
+ parcTreeMap_Put(tree, key1, value1);
+ parcTreeMap_Put(tree, key2, value2);
+ parcTreeMap_Put(tree, key3, value3);
+
+ parcBuffer_Release(&key1);
+ parcBuffer_Release(&value1);
+ parcBuffer_Release(&key2);
+ parcBuffer_Release(&value2);
+ parcBuffer_Release(&key3);
+ parcBuffer_Release(&value3);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Put_Overwrite)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree = data->testMap1;
+
+ parcTreeMap_Put(tree, data->k[1], data->v[1]);
+ parcTreeMap_Put(tree, data->k[2], data->v[2]);
+ parcTreeMap_Put(tree, data->k[3], data->v[3]);
+ parcTreeMap_Put(tree, data->k[3], data->v[4]);
+ parcTreeMap_Put(tree, data->k[3], data->v[5]);
+
+ assertTrue(3 == parcTreeMap_Size(tree), "Wrong size of tree should stay at 3");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Put_Ordered)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree = data->testMap1;
+
+ parcTreeMap_Put(tree, data->k[1], data->v[1]);
+ parcTreeMap_Put(tree, data->k[2], data->v[2]);
+ parcTreeMap_Put(tree, data->k[3], data->v[3]);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Put_OutOfOrder)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+
+ parcTreeMap_Put(tree1, data->k[4], data->v[4]);
+ parcTreeMap_Put(tree1, data->k[2], data->v[2]);
+ parcTreeMap_Put(tree1, data->k[3], data->v[3]);
+ parcTreeMap_Put(tree1, data->k[1], data->v[1]);
+
+ PARCTreeMap *tree2 = data->testMap2;
+ parcTreeMap_Put(tree2, data->k[1], data->v[1]);
+ parcTreeMap_Put(tree2, data->k[3], data->v[3]);
+ parcTreeMap_Put(tree2, data->k[2], data->v[2]);
+ parcTreeMap_Put(tree2, data->k[4], data->v[4]);
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Expect trees to be Equal");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Size_Empty)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree = data->testMap1;
+
+ assertTrue(0 == parcTreeMap_Size(tree), "Wrong size of tree - empty, start");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Size)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree = data->testMap1;
+
+ parcTreeMap_Put(tree, data->k[4], data->v[4]);
+ parcTreeMap_Put(tree, data->k[2], data->v[2]);
+ parcTreeMap_Put(tree, data->k[3], data->v[3]);
+
+ assertTrue(3 == parcTreeMap_Size(tree), "Wrong size of tree after add 3");
+
+ parcTreeMap_Put(tree, data->k[1], data->v[1]);
+
+ assertTrue(4 == parcTreeMap_Size(tree), "Wrong size of tree after add 1 more");
+
+ parcTreeMap_RemoveAndRelease(tree, data->k[2]);
+
+ size_t size = parcTreeMap_Size(tree);
+
+ assertTrue(3 == size, "Wrong size of tree after 1 delete (%zu instead of 3)", size);
+
+ parcTreeMap_Put(tree, data->k[7], data->v[7]);
+
+ assertTrue(4 == parcTreeMap_Size(tree), "Wrong size of tree after add 1 more");
+
+ parcTreeMap_RemoveAndRelease(tree, data->k[3]);
+ assertTrue(3 == parcTreeMap_Size(tree), "Wrong size of tree after del 1 more - 3");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_ReleaseTillEmpty)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ // This order of puts are removes exercises code paths
+ // in TreeMap not exercised in any other place.
+ int idx1a[7] = { 4, 2, 3, 1, 5, 7, 6 };
+ int idx1b[7] = { 3, 1, 4, 2, 6, 5, 7 };
+ int idx2a[7] = { 4, 6, 5, 7, 3, 1, 2 };
+ int idx2b[7] = { 5, 7, 4, 6, 2, 3, 1 };
+
+ for (int i = 0; i < 7; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[idx1a[i]], data->v[idx1a[i]]);
+ parcTreeMap_Put(tree2, data->k[idx2a[i]], data->v[idx2a[i]]);
+ }
+
+ for (int i = 0; i < 7; ++i) {
+ parcTreeMap_RemoveAndRelease(tree1, data->k[idx1b[i]]);
+ parcTreeMap_RemoveAndRelease(tree2, data->k[idx2b[i]]);
+ }
+
+ size_t size;
+ size = parcTreeMap_Size(tree1);
+
+ assertTrue(0 == size, "Wrong size of tree - empty (got %zu)", size);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Size_Overwrite)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree = data->testMap1;
+
+ parcTreeMap_Put(tree, data->k[4], data->v[4]);
+ parcTreeMap_Put(tree, data->k[2], data->v[2]);
+ parcTreeMap_Put(tree, data->k[3], data->v[3]);
+
+ // Size is 3 here, we'll insert the same number now..
+
+ parcTreeMap_Put(tree, data->k[3], data->v[23]);
+
+ assertTrue(3 == parcTreeMap_Size(tree), "Wrong size of tree after overwrite");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Get_EmptyTree)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree = data->testMap1;
+
+ PARCObject *value = parcTreeMap_Get(tree, data->k[1]);
+
+ assertTrue(NULL == value, "Object did not exist, must return NULL");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Get_NonExistent)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree = data->testMap1;
+
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+
+ PARCObject *value = parcTreeMap_Get(tree, data->k[23]);
+
+ assertTrue(NULL == value, "Object did not exist, must return NULL");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Get_First)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ for (long i = 1; i < 4; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+
+ PARCObject *value = parcTreeMap_Get(tree, data->k[1]);
+
+ assertTrue(_int_Equals(data->v[1], value), "Wrong value, got %ld", (long) value);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Get)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+
+ PARCObject *value = parcTreeMap_Get(tree, data->k[4]);
+
+ assertTrue(_int_Equals(data->v[4], value), "Wrong value, got %ld", (long) value);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Get_Last)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+
+ PARCObject *value = parcTreeMap_Get(tree, data->k[9]);
+
+ assertTrue(_int_Equals(data->v[9], value), "Wrong value, got %ld", (long) value);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Get_Smallest)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+
+
+ PARCObject *value = parcTreeMap_Get(tree, data->k[1]);
+
+ assertTrue(_int_Equals(data->v[1], value), "Wrong value, got %ld", (long) value);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Get_Biggest)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+
+ PARCObject *value = parcTreeMap_Get(tree, data->k[39]);
+
+ assertTrue(_int_Equals(data->v[39], value), "Wrong value, got %ld", (long) value);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_FirstEntry)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+
+ PARCKeyValue *entry = parcTreeMap_GetFirstEntry(tree);
+
+ assertTrue(_int_Equals(data->k[1], parcKeyValue_GetKey(entry)),
+ "Wrong value, got %ld", (long) parcKeyValue_GetKey(entry));
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_FirstKey)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+
+ PARCObject *key = parcTreeMap_GetFirstKey(tree);
+
+ assertTrue(_int_Equals(data->k[1], key), "Wrong value, got %ld", (long) key);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_FirstKey_Empty)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ PARCObject *key = parcTreeMap_GetFirstKey(tree);
+
+ assertNull(key, "Should get NULL on empty tree");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_LastKey_Empty)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ PARCObject *key = parcTreeMap_GetLastKey(tree);
+
+ assertNull(key, "Should get NULL on empty tree");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_LastEntry)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+
+ PARCKeyValue *entry = parcTreeMap_GetLastEntry(tree);
+
+ assertTrue(_int_Equals(data->k[39], parcKeyValue_GetKey(entry)),
+ "Wrong value, got %ld", (long) parcKeyValue_GetKey(entry));
+}
+
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_LastKey)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree = data->testMap1;
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree, data->k[i], data->v[i]);
+ }
+
+ PARCObject *key = parcTreeMap_GetLastKey(tree);
+
+ assertTrue(_int_Equals(data->k[39], key), "Wrong value, got %ld", (long) key);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Remove_First)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ parcTreeMap_Put(tree1, data->k[1], data->v[1]);
+
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ PARCObject *value = parcTreeMap_Remove(tree1, data->k[1]);
+ parcObject_Release(&value);
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Remove)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 31; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ parcTreeMap_Put(tree1, data->k[30], data->v[30]);
+
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ PARCObject *value = parcTreeMap_Remove(tree1, data->k[30]);
+ parcObject_Release(&value);
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Remove_Last)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ parcTreeMap_Put(tree1, data->k[41], data->v[41]);
+
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ PARCObject *value = parcTreeMap_Remove(tree1, data->k[41]);
+ assertNotNull(value, "Expected to find some object.");
+ assertTrue(_int_Equals(data->v[41], value), "Expected value 41 in return");
+ parcObject_Release(&value);
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees don't match after remove");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_RemoveAndRelease_First)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ parcTreeMap_Put(tree1, data->k[1], data->v[1]);
+
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ parcTreeMap_RemoveAndRelease(tree1, data->k[1]);
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_RemoveAndRelease)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 31; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ parcTreeMap_Put(tree1, data->k[30], data->v[30]);
+
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ parcTreeMap_RemoveAndRelease(tree1, data->k[30]);
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+
+ for (int i = 20; i < 30; i++) {
+ parcTreeMap_RemoveAndRelease(tree1, data->k[i]);
+ parcTreeMap_RemoveAndRelease(tree2, data->k[49 - i]);
+ }
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+
+ for (int i = 2; i < 10; i++) {
+ parcTreeMap_RemoveAndRelease(tree1, data->k[i]);
+ parcTreeMap_RemoveAndRelease(tree2, data->k[11 - i]);
+ }
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+
+ for (int i = 31; i < 40; i++) {
+ parcTreeMap_RemoveAndRelease(tree1, data->k[i]);
+ parcTreeMap_RemoveAndRelease(tree2, data->k[70 - i]);
+ }
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Remove_NonExistent)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ PARCObject *element = parcTreeMap_Remove(tree1, data->k[0]);
+
+ assertNull(element, "Return value must be NULL on non existing element");
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_RemoveAndRelease_NonExistent)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ parcTreeMap_RemoveAndRelease(tree1, data->k[0]);
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Remove_WithSuccessorNonRoot)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ int idx1[15] = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+ int idx2[13] = { 8, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+
+ for (int i = 0; i < 15; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[idx1[i]], data->v[idx1[i]]);
+ }
+
+ for (int i = 0; i < 13; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree2, data->k[idx2[i]], data->v[idx2[i]]);
+ }
+
+ _Int *key = _int_Create(4);
+ parcTreeMap_RemoveAndRelease(tree1, key);
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 12));
+ _int_Release(&key);
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Remove_LeftChildRightChild)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ int idx1[15] = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+
+ for (int i = 0; i < 15; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[idx1[i]], data->v[idx1[i]]);
+ parcTreeMap_Put(tree2, data->k[idx1[i]], data->v[idx1[i]]);
+ }
+
+ _Int *key = _int_Create(0);
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 13));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 7));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 14));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 6));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 15));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 12));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 11));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 10));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 9));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 8));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 5));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 4));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 3));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 2));
+ parcTreeMap_RemoveAndRelease(tree1, _int_Set(key, 1));
+
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 1));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 2));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 3));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 4));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 5));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 6));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 7));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 8));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 9));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 10));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 11));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 12));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 13));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 14));
+ parcTreeMap_RemoveAndRelease(tree2, _int_Set(key, 15));
+ _int_Release(&key);
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_RemoveAndRelease_Last)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+ parcTreeMap_Put(tree1, data->k[41], data->v[41]);
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ parcTreeMap_RemoveAndRelease(tree1, data->k[41]);
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Trees dont match after remove");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_LowerEntry)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+
+ // Empty Tree
+ PARCKeyValue *kv = parcTreeMap_GetLowerEntry(tree1, data->k[23]);
+ assertNull(kv, "Expected a NULL return for LowerEntry() on empty tree");
+
+ // Fill Tree
+ int max = N_TEST_ELEMENTS - 1;
+ for (int i = 21; i <= max; ++i) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+ for (int i = 1; i < 21; ++i) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+
+ // Using lowest key in tree
+ kv = parcTreeMap_GetLowerEntry(tree1, data->k[1]);
+ assertNull(kv, "Expected a NULL return for no lower entry");
+
+ // On all entries except the lowest tree
+ for (int i = max; i > 1; --i) {
+ kv = parcTreeMap_GetLowerEntry(tree1, data->k[i]);
+ assertNotNull(kv, "Expected a lower entry to exist");
+ _Int *key = (_Int *) parcKeyValue_GetKey(kv);
+ assertTrue(_int_Equals(key, data->k[i - 1]),
+ "Expected entry with key %d, got %d",
+ data->k[i - 1]->value, key->value);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_LowerKey)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+
+ // Empty Tree
+ _Int *key = (_Int *) parcTreeMap_GetLowerKey(tree1, data->k[23]);
+ assertNull(key, "Expected a NULL return for LowerEntry() on empty tree");
+
+ int max = N_TEST_ELEMENTS - 1;
+ for (int i = 21; i <= max; ++i) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+ for (int i = 1; i < 21; ++i) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+
+ // Using lowest key in tree
+ key = (_Int *) parcTreeMap_GetLowerKey(tree1, data->k[1]);
+ assertNull(key, "Expected a NULL return for no lower entry");
+
+ // On all entries except the lowest tree
+ for (int i = max; i > 1; --i) {
+ key = parcTreeMap_GetLowerKey(tree1, data->k[i]);
+ assertNotNull(key, "Expected a lower entry to exist");
+ assertTrue(_int_Equals(key, data->k[i - 1]),
+ "Expected entry with key %d, got %d",
+ data->k[i - 1]->value, key->value);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_HigherEntry)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+
+ // Empty Tree
+ PARCKeyValue *kv = parcTreeMap_GetHigherEntry(tree1, data->k[23]);
+ assertNull(kv, "Expected a NULL return for HigherEntry() on empty tree");
+
+ int max = N_TEST_ELEMENTS - 2;
+ for (int i = 21; i <= max; ++i) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+ for (int i = 1; i < 21; ++i) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+
+ // Using highest key in tree
+ kv = parcTreeMap_GetHigherEntry(tree1, data->k[max]);
+ assertNull(kv, "Expected a NULL return for no higher entry");
+
+ // On all entries except the lowest tree
+ for (int i = 1; i < max; ++i) {
+ kv = parcTreeMap_GetHigherEntry(tree1, data->k[i]);
+ assertNotNull(kv, "Expected a higher entry to exist");
+ _Int *key = (_Int *) parcKeyValue_GetKey(kv);
+ assertTrue(_int_Equals(key, data->k[i + 1]),
+ "Expected entry with key %d, got %d",
+ data->k[i + 1]->value, key->value);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_HigherKey)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+
+ // Empty Tree
+ _Int *key = (_Int *) parcTreeMap_GetHigherKey(tree1, data->k[23]);
+ assertNull(key, "Expected a NULL return for LowerEntry() on empty tree");
+
+ int max = N_TEST_ELEMENTS - 2;
+ for (int i = 21; i <= max; ++i) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+ for (int i = 1; i < 21; ++i) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+
+ key = (_Int *) parcTreeMap_GetHigherEntry(tree1, data->k[max]);
+ assertNull(key, "Expected a NULL return for no higher entry");
+
+ for (int i = 1; i < max; ++i) {
+ key = (_Int *) parcTreeMap_GetHigherKey(tree1, data->k[i]);
+ assertNotNull(key, "Expected a higher entry to exist");
+ assertTrue(_int_Equals(key, data->k[i + 1]),
+ "Expected entry with key %d, got %d",
+ data->k[i + 1]->value, key->value);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Keys)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+
+ PARCList *list = parcList(parcArrayList_Create(NULL), PARCArrayListAsPARCList);
+
+ // Insert in tree out of order
+ for (int i = 10; i < 20; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+ for (int i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+
+ // Insert in list in order
+ for (int i = 1; i < 20; i++) {
+ // Add some elements to the tree
+ parcList_Add(list, data->k[i]);
+ }
+
+ PARCList *keys = parcTreeMap_AcquireKeys(tree1);
+
+ assertTrue(parcList_Equals(list, keys), "Key list doesnt' match");
+
+ parcList_Release(&keys);
+ parcList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Values)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+
+ PARCList *list = parcList(parcArrayList_Create(NULL), PARCArrayListAsPARCList);
+
+ // Insert in tree out of order
+ for (int i = 10; i < 20; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+ for (int i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+
+ // Insert in list in order
+ for (int i = 1; i < 20; i++) {
+ // Add some elements to the tree
+ parcList_Add(list, data->v[i]);
+ }
+
+ PARCList *values = parcTreeMap_AcquireValues(tree1);
+
+ assertTrue(parcList_Equals(list, values), "Key list doesnt' match");
+
+ parcList_Release(&values);
+ parcList_Release(&list);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Equals_Empty)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Empty lists are not equal");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Equals_DifferentLength)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+
+ for (int i = 1; i < 20; i++) {
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[i]);
+ }
+
+ parcTreeMap_Put(tree2, data->k[41], data->v[41]);
+
+ assertFalse(parcTreeMap_Equals(tree1, tree2), "Lists are equal");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Equals_Not_Values)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 1; i < 20; i++) {
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i], data->v[20 - i]);
+ }
+
+ assertFalse(parcTreeMap_Equals(tree1, tree2), "Lists are equal");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Equals_Not_Keys)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 1; i < 20; i++) {
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[i + 1], data->v[i]);
+ }
+ assertTrue(parcTreeMap_Size(tree1) == parcTreeMap_Size(tree2), "Expect trees to have the same size.");
+
+ assertFalse(parcTreeMap_Equals(tree1, tree2), "Lists should not be equal");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Equals)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap2;
+
+ for (int i = 1; i < 40; i++) {
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ parcTreeMap_Put(tree2, data->k[40 - i], data->v[40 - i]);
+ }
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Lists are not equal");
+}
+
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Copy)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *treeCopy = parcTreeMap_Copy(tree1);
+
+ for (int i = 1; i < 10; i++) {
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+
+ assertFalse(parcTreeMap_Equals(tree1, treeCopy), "Lists are not equal");
+
+ parcTreeMap_Release(&treeCopy);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Copy_Direct)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+
+ for (int i = 1; i < 20; i++) {
+ parcTreeMap_Put(tree1, data->k[i], data->v[i]);
+ }
+
+ PARCTreeMap *treeCopy = parcTreeMap_Copy(tree1);
+
+ assertTrue(parcTreeMap_Equals(tree1, treeCopy), "Lists are not equal");
+
+ parcTreeMap_Release(&treeCopy);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_ValueIterator)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+
+ int idx1[15] = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+
+ for (int i = 0; i < 15; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[idx1[i]], data->v[idx1[i]]);
+ }
+
+ PARCIterator *it = parcTreeMap_CreateValueIterator(tree1);
+
+ for (int idx = 1; parcIterator_HasNext(it); ++idx) {
+ _Int *value = (_Int *) parcIterator_Next(it);
+ assertTrue(_int_Equals(value, data->v[idx]), "Expected value %d got %d", data->v[idx]->value, value->value);
+ }
+
+ parcIterator_Release(&it);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_KeyIterator)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+
+ int idx1[15] = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+
+ for (int i = 0; i < 15; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[idx1[i]], data->v[idx1[i]]);
+ }
+
+ PARCIterator *it = parcTreeMap_CreateKeyIterator(tree1);
+
+ for (int idx = 1; parcIterator_HasNext(it); ++idx) {
+ _Int *key = (_Int *) parcIterator_Next(it);
+ assertTrue(_int_Equals(key, data->k[idx]),
+ "Expected value %d got %d",
+ data->k[idx]->value,
+ key->value);
+ }
+
+ parcIterator_Release(&it);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Iterator)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+
+ int idx1[15] = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+
+ for (int i = 0; i < 15; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[idx1[i]], data->v[idx1[i]]);
+ }
+
+ PARCIterator *it = parcTreeMap_CreateKeyValueIterator(tree1);
+
+ for (int idx = 1; parcIterator_HasNext(it); ++idx) {
+ PARCKeyValue *kv = (PARCKeyValue *) parcIterator_Next(it);
+ assertTrue(_int_Equals((_Int *) parcKeyValue_GetKey(kv), data->k[idx]),
+ "Expected value %d got %d",
+ data->k[idx]->value,
+ ((_Int *) parcKeyValue_GetKey(kv))->value);
+ }
+
+ parcIterator_Release(&it);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Remove_Using_Iterator)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+
+ int idx1[15] = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+
+ for (int i = 0; i < 15; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[idx1[i]], data->v[idx1[i]]);
+ }
+
+ PARCIterator *it = parcTreeMap_CreateKeyValueIterator(tree1);
+ for (int idx = 1; parcIterator_HasNext(it); ++idx) {
+ parcIterator_Next(it);
+ parcIterator_Remove(it);
+ }
+ parcIterator_Release(&it);
+
+ assertTrue(parcTreeMap_Size(tree1) == 0, "Expect the tree to be empty after removes.");
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeMap_Remove_Element_Using_Iterator)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCTreeMap *tree1 = data->testMap1;
+ PARCTreeMap *tree2 = data->testMap1;
+
+ int idx1[15] = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 15, 13 }; //Missing 11
+
+ for (int i = 0; i < 14; i++) {
+ // Add some elements to the tree
+ parcTreeMap_Put(tree1, data->k[idx1[i]], data->v[idx1[i]]);
+ parcTreeMap_Put(tree2, data->k[idx1[i]], data->v[idx1[i]]);
+ }
+
+ parcTreeMap_Put(tree1, data->k[11], data->v[11]);
+
+
+ PARCIterator *it = parcTreeMap_CreateKeyValueIterator(tree1);
+ for (int idx = 1; parcIterator_HasNext(it); ++idx) {
+ parcIterator_Next(it);
+ if (idx == 11) {
+ parcIterator_Remove(it);
+ }
+ }
+ parcIterator_Release(&it);
+
+ assertTrue(parcTreeMap_Equals(tree1, tree2), "Expect the trees to be equal after remove.");
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ //LONGBOW_RUN_TEST_CASE(Local, PARC_TreeMap_EnsureRemaining_NonEmpty);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Stress)
+{
+ // LongBow could use a command line option to enable/disable tests
+ // See LongBow issue #5
+ if (getenv("LongBowStress")) {
+ LONGBOW_RUN_TEST_CASE(Stress, PARC_TreeMap_ExerciseRandomSeededSmall);
+ LONGBOW_RUN_TEST_CASE(Stress, PARC_TreeMap_ExerciseRandomSeeded);
+ }
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Stress)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Stress)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Stress, PARC_TreeMap_ExerciseRandomSeededSmall)
+{
+ unsigned seed;
+ char *seedString;
+
+ seedString = getenv("RBSeed");
+ if (seedString) {
+ seed = (unsigned) atol(seedString);
+ } else {
+ seed = 4179329122; // known to fail
+ }
+
+ for (int j = 0; j < 1; j++) {
+ // this test case should obtain a seed and number of iterations from a
+ // command line option once LongBow has that feature available
+
+ srandom(seed);
+ PARCTreeMap *tree = parcTreeMap_Create();
+
+ int inserts = 0;
+ int deletes = 0;
+
+ for (int i = 0; i < 100; i++) {
+ intptr_t item = 1 + (random() % 100);
+ int operation = random() % 1000;
+ if (operation < 400) {
+ inserts++;
+ parcTreeMap_Put(tree, (void *) item, (void *) (item << 8));
+ } else {
+ deletes++;
+ parcTreeMap_Remove(tree, (void *) item);
+ }
+ rbCheckTree(tree);
+ }
+
+ parcTreeMap_Release(&tree);
+ }
+}
+
+LONGBOW_TEST_CASE(Stress, PARC_TreeMap_ExerciseRandomSeeded)
+{
+ PARCTreeMap *tree1;
+ unsigned seed;
+ char *seedString;
+
+ // this test case should obtain a seed and number of iterations from a
+ // command line option once LongBow has that feature available
+ seedString = getenv("RBSeed");
+ if (seedString) {
+ seed = (unsigned) atol(seedString);
+ } else {
+ seed = 4179329122; // known to fail
+ }
+
+ srandom(seed);
+
+ tree1 = parcTreeMap_Create();
+
+ int inserts = 0;
+ int deletes = 0;
+
+ for (int i = 0; i < 100000; i++) {
+ intptr_t item = 1 + (random() % 10000);
+ int operation = random() % 1000;
+ if (operation < 400) {
+ inserts++;
+ parcTreeMap_Put(tree1, (void *) item, (void *) (item << 8));
+ } else {
+ deletes++;
+ parcTreeMap_Remove(tree1, (void *) item);
+ }
+ rbCheckTree(tree1);
+ }
+
+ parcTreeMap_Release(&tree1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(PARC_TreeMap);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_TreeRedBlack.c b/libparc/parc/algol/test/test_parc_TreeRedBlack.c
new file mode 100755
index 00000000..7fb1828a
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_TreeRedBlack.c
@@ -0,0 +1,1461 @@
+/*
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include "../parc_TreeRedBlack.c"
+
+
+void *
+keyNewInt(int key)
+{
+ int *newKey = parcMemory_Allocate(sizeof(int));
+ assertNotNull(newKey, "parcMemory_Allocate(%zu) returned NULL", sizeof(int));
+ *newKey = key;
+ return newKey;
+}
+
+void *
+valueNewInt(int value)
+{
+ int *newValue = parcMemory_Allocate(sizeof(int));
+ assertNotNull(newValue, "parcMemory_Allocate(%zu) returned NULL", sizeof(int));
+ *newValue = value;
+ return newValue;
+}
+
+void *
+keyCopy(const void *key)
+{
+ return keyNewInt(*(int *) key);
+}
+
+void *
+valueCopy(const void *value)
+{
+ return valueNewInt(*(int *) value);
+}
+
+void *
+keyNew(char *key)
+{
+ return parcMemory_StringDuplicate(key, strlen(key));
+}
+
+void *
+valueNew(char *value)
+{
+ return parcMemory_StringDuplicate(value, strlen(value));
+}
+
+int
+intComp(const void *key1, const void *key2)
+{
+ if (*(int *) key1 < *(int *) key2) {
+ return -1;
+ }
+ if (*(int *) key1 == *(int *) key2) {
+ return 0;
+ }
+ return 1;
+}
+
+bool
+intEquals(const void *int1, const void *int2)
+{
+ return intComp(int1, int2) == 0;
+}
+
+int
+pointerComp(const void *key1, const void *key2)
+{
+ if (key1 < key2) {
+ return -1;
+ }
+ if (key1 == key2) {
+ return 0;
+ }
+ return 1;
+}
+
+int
+stringComp(const void *key1, const void *key2)
+{
+ // We assume all keys are strings.
+ return strcmp(key1, key2);
+}
+
+void
+keyFree(void **value)
+{
+ parcMemory_Deallocate((void **) value);
+ *value = NULL;
+}
+
+void
+valueFree(void **key)
+{
+ parcMemory_Deallocate((void **) key);
+ *key = NULL;
+}
+
+
+LONGBOW_TEST_RUNNER(PARC_TreeRedBlack)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+ LONGBOW_RUN_TEST_FIXTURE(Stress);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(PARC_TreeRedBlack)
+{
+ int seed = (int) time(NULL);
+ printf("Seed = %u\n", seed);
+ srandom(seed);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(PARC_TreeRedBlack)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_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_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Remove_Ordered);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Create);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Insert_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Insert_Ordered);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Insert_OutOfOrder);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Insert_Overwrite);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_DestroyTillEmpty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Size_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Size);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Size_Overwrite);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get_EmptyTree);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get_NonExistent);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get_Biggest);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get_Smallest);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get_FirstKey);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get_LastKey);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get_FirstKey_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Get_LastKey_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Remove_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Remove);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Remove_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Remove_NonExistent);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_RemoveAndDestroy_First);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_RemoveAndDestroy);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_RemoveAndDestroy_Last);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_RemoveAndDestroy_NonExistent);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Remove_WithSuccessorNonRoot);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Remove_LeftChildRightChild);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Keys);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Values);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Equals_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Equals_Func);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Equals_DifferentLength);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Equals_Not_Values);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Equals_Not_Values_Func);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Equals_Not_Keys);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_Copy_Direct);
+ //LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_ExerciseRandom);
+ //LONGBOW_RUN_TEST_CASE(Global, PARC_TreeRedBlack_ExerciseRootFailure);
+}
+
+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("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ * return LONGBOW_STATUS_MEMORYLEAK;
+ * }
+ */
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static
+int
+strComp(const void *s1, const void *s2)
+{
+ return strcmp((char *) s1, (char *) s2);
+}
+
+static
+bool
+strEquals(const void *s1, const void *s2)
+{
+ return strcmp(s1, s2) == 0;
+}
+
+static
+int
+recursiveCheckBlackDepth(const PARCTreeRedBlack *tree, const Node *node)
+{
+ assertNotNull(tree, "Null tree?\n");
+ assertNotNull(node, "Null node?\n");
+ if (node == tree->nil) {
+ return 0;
+ }
+ int right_depth = recursiveCheckBlackDepth(tree, node->right_child);
+ int left_depth = recursiveCheckBlackDepth(tree, node->left_child);
+ assertTrue(right_depth == left_depth, "Wrong depth!!\n");
+ if (_rbNodeColor(node) == BLACK) {
+ return right_depth + 1;
+ }
+ return right_depth;
+}
+
+static
+void
+rbCheckTree(const PARCTreeRedBlack *tree)
+{
+ assertNotNull(tree, "Tree can't be NULL");
+ //printf("--- TREE ---\n");
+ if (tree->size > 0) {
+ //_rbNodeRecursiveRun((PARCTreeRedBlack *)tree,tree->root,rbCheckNode,(void *)tree);
+ recursiveCheckBlackDepth(tree, tree->root);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Remove_Ordered)
+{
+ char *insertList[16] = {
+ "01",
+ "02",
+ "03",
+ "04",
+ "05",
+ "06",
+ "07",
+ "08",
+ "09",
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "15",
+ "16"
+ };
+
+ PARCTreeRedBlack *tree1;
+
+ tree1 = parcTreeRedBlack_Create(strComp, NULL, NULL, strEquals, NULL, NULL);
+
+ for (int i = 0; i < 16; i++) {
+ parcTreeRedBlack_Insert(tree1, insertList[i], insertList[i]);
+ }
+
+ for (int i = 0; i < 14; i++) {
+ //rbPrintTreeString(tree1);
+ void *data = parcTreeRedBlack_Remove(tree1, insertList[i]);
+ assertNotNull(data, "Data is null!");
+ }
+
+ parcTreeRedBlack_Destroy(&tree1);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Create)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(stringComp, NULL, NULL, NULL, NULL, NULL);
+
+ parcTreeRedBlack_Destroy(&tree);
+
+ tree = parcTreeRedBlack_Create(stringComp, keyFree, NULL, NULL, valueFree, NULL);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Insert_Destroy)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(stringComp, keyFree, NULL, NULL, valueFree, NULL);
+
+ void *value1 = valueNew("value 1");
+ void *key1 = keyNew("1");
+ void *value2 = valueNew("value 2");
+ void *key2 = keyNew("2");
+ void *value3 = valueNew("value 3");
+ void *key3 = keyNew("3");
+
+ parcTreeRedBlack_Insert(tree, key1, value1);
+ parcTreeRedBlack_Insert(tree, key2, value2);
+ parcTreeRedBlack_Insert(tree, key3, value3);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Insert_Overwrite)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(stringComp, keyFree, NULL, NULL, valueFree, NULL);
+
+ parcTreeRedBlack_Insert(tree, keyNew("1"), valueNew("v1"));
+ parcTreeRedBlack_Insert(tree, keyNew("2"), valueNew("v2"));
+ parcTreeRedBlack_Insert(tree, keyNew("3"), valueNew("v3"));
+ parcTreeRedBlack_Insert(tree, keyNew("3"), valueNew("v4"));
+ parcTreeRedBlack_Insert(tree, keyNew("3"), valueNew("v5"));
+
+ assertTrue(3 == parcTreeRedBlack_Size(tree), "Wrong size of tree should stay at 3");
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Insert_Ordered)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ parcTreeRedBlack_Insert(tree, (void *) 1, (void *) 1001);
+ parcTreeRedBlack_Insert(tree, (void *) 2, (void *) 1002);
+ parcTreeRedBlack_Insert(tree, (void *) 3, (void *) 1003);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Insert_OutOfOrder)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ parcTreeRedBlack_Insert(tree, (void *) 4, (void *) 1004);
+ parcTreeRedBlack_Insert(tree, (void *) 2, (void *) 1002);
+ parcTreeRedBlack_Insert(tree, (void *) 3, (void *) 1003);
+ parcTreeRedBlack_Insert(tree, (void *) 1, (void *) 1001);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Size_Empty)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ assertTrue(0 == parcTreeRedBlack_Size(tree), "Wrong size of tree - empty, start");
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Size)
+{
+ PARCTreeRedBlack *tree;
+ size_t size;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ parcTreeRedBlack_Insert(tree, (void *) 4, (void *) 1004);
+ parcTreeRedBlack_Insert(tree, (void *) 2, (void *) 1002);
+ parcTreeRedBlack_Insert(tree, (void *) 3, (void *) 1003);
+
+ assertTrue(3 == parcTreeRedBlack_Size(tree), "Wrong size of tree after add 3");
+
+ parcTreeRedBlack_Insert(tree, (void *) 1, (void *) 1001);
+
+ assertTrue(4 == parcTreeRedBlack_Size(tree), "Wrong size of tree after add 1 more");
+
+ parcTreeRedBlack_RemoveAndDestroy(tree, (void *) 2);
+
+ size = parcTreeRedBlack_Size(tree);
+
+ assertTrue(3 == size, "Wrong size of tree after 1 delete (%zu instead of 3)", size);
+
+ parcTreeRedBlack_Insert(tree, (void *) 7, (void *) 1007);
+
+ assertTrue(4 == parcTreeRedBlack_Size(tree), "Wrong size of tree after add 1 more");
+
+ parcTreeRedBlack_RemoveAndDestroy(tree, (void *) 3);
+ assertTrue(3 == parcTreeRedBlack_Size(tree), "Wrong size of tree after del 1 more - 3");
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_DestroyTillEmpty)
+{
+ PARCTreeRedBlack *tree;
+ size_t size;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ parcTreeRedBlack_Insert(tree, (void *) 4, (void *) 1004);
+ parcTreeRedBlack_Insert(tree, (void *) 2, (void *) 1002);
+ parcTreeRedBlack_Insert(tree, (void *) 3, (void *) 1003);
+ parcTreeRedBlack_Insert(tree, (void *) 1, (void *) 1001);
+ parcTreeRedBlack_Insert(tree, (void *) 5, (void *) 1001);
+ parcTreeRedBlack_Insert(tree, (void *) 7, (void *) 1001);
+ parcTreeRedBlack_Insert(tree, (void *) 6, (void *) 1001);
+
+ parcTreeRedBlack_RemoveAndDestroy(tree, (void *) 3);
+ parcTreeRedBlack_RemoveAndDestroy(tree, (void *) 1);
+ parcTreeRedBlack_RemoveAndDestroy(tree, (void *) 4);
+ parcTreeRedBlack_RemoveAndDestroy(tree, (void *) 2);
+ parcTreeRedBlack_RemoveAndDestroy(tree, (void *) 6);
+ parcTreeRedBlack_RemoveAndDestroy(tree, (void *) 5);
+ parcTreeRedBlack_RemoveAndDestroy(tree, (void *) 7);
+
+ size = parcTreeRedBlack_Size(tree);
+
+ assertTrue(0 == size, "Wrong size of tree - empty (got %zu)", size);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Size_Overwrite)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ parcTreeRedBlack_Insert(tree, (void *) 4, (void *) 1004);
+ parcTreeRedBlack_Insert(tree, (void *) 2, (void *) 1002);
+ parcTreeRedBlack_Insert(tree, (void *) 3, (void *) 1003);
+
+ // Size is 3 here, we'll insert the same number now..
+
+ parcTreeRedBlack_Insert(tree, (void *) 3, (void *) 1033);
+
+ assertTrue(3 == parcTreeRedBlack_Size(tree), "Wrong size of tree after overwrite");
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get_EmptyTree)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ void *value = parcTreeRedBlack_Get(tree, (void *) 1);
+
+ assertTrue(NULL == value, "Object did not exist, must return NULL");
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get_NonExistent)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+
+ void *value = parcTreeRedBlack_Get(tree, (void *) 100);
+
+ assertTrue(NULL == value, "Object did not exist, must return NULL");
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get_First)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 1; i < 4; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+
+ void *value = parcTreeRedBlack_Get(tree, (void *) 1);
+
+ assertTrue((1 << 8) == (long) value, "Wrong value, got %ld", (long) value);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+
+ void *value = parcTreeRedBlack_Get(tree, (void *) 4);
+
+ assertTrue((4 << 8) == (long) value, "Wrong value, got %ld", (long) value);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get_Last)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+
+ void *value = parcTreeRedBlack_Get(tree, (void *) 9);
+
+ assertTrue((9 << 8) == (long) value, "Wrong value, got %ld", (long) value);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get_Smallest)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+
+
+ void *value = parcTreeRedBlack_Get(tree, (void *) 1);
+
+ assertTrue((1 << 8) == (long) value, "Wrong value, got %ld", (long) value);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get_Biggest)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+
+
+ void *value = parcTreeRedBlack_Get(tree, (void *) 39);
+
+ assertTrue((39 << 8) == (long) value, "Wrong value, got %ld", (long) value);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get_FirstKey)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+
+ void *key = parcTreeRedBlack_FirstKey(tree);
+
+ assertTrue(1 == (long) key, "Wrong value, got %ld", (long) key);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get_FirstKey_Empty)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ void *key = parcTreeRedBlack_FirstKey(tree);
+
+ assertNull(key, "Should get NULL on empty tree");
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get_LastKey_Empty)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ void *key = parcTreeRedBlack_LastKey(tree);
+
+ assertNull(key, "Should get NULL on empty tree");
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Get_LastKey)
+{
+ PARCTreeRedBlack *tree;
+
+ tree = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree, (void *) i, (void *) (i << 8));
+ }
+
+ void *key = parcTreeRedBlack_LastKey(tree);
+
+ assertTrue(39 == (long) key, "Wrong value, got %ld", (long) key);
+
+ parcTreeRedBlack_Destroy(&tree);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Remove_First)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ tree1 = parcTreeRedBlack_Create(intComp, keyFree, NULL, intEquals, valueFree, NULL);
+ tree2 = parcTreeRedBlack_Create(intComp, keyFree, NULL, intEquals, valueFree, NULL);
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8));
+ parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8));
+ }
+
+ parcTreeRedBlack_Insert(tree1, keyNewInt(1), valueNewInt(1 << 8));
+
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8));
+ parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8));
+ }
+
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8));
+ parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8));
+ }
+
+ int searchKey = 1;
+
+ void *data = parcTreeRedBlack_Remove(tree1, &searchKey);
+
+ valueFree(&data);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Trees dont match after remove");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Remove)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ tree1 = parcTreeRedBlack_Create(intComp, keyFree, NULL, intEquals, valueFree, NULL);
+ tree2 = parcTreeRedBlack_Create(intComp, keyFree, NULL, intEquals, valueFree, NULL);
+
+ for (int i = 31; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8));
+ parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8));
+ }
+
+ parcTreeRedBlack_Insert(tree1, keyNewInt(30), valueNewInt(31 << 8));
+
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8));
+ parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8));
+ }
+
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8));
+ parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8));
+ }
+
+ int searchKey = 30;
+
+ void *data = parcTreeRedBlack_Remove(tree1, &searchKey);
+
+ valueFree(&data);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Trees dont match after remove");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Remove_Last)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ tree1 = parcTreeRedBlack_Create(intComp, keyFree, NULL, intEquals, valueFree, NULL);
+ tree2 = parcTreeRedBlack_Create(intComp, keyFree, NULL, intEquals, valueFree, NULL);
+
+ for (int i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8));
+ parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8));
+ }
+ parcTreeRedBlack_Insert(tree1, keyNewInt(100), valueNewInt(100 << 8));
+ for (int i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8));
+ parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8));
+ }
+ for (int i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8));
+ parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8));
+ }
+
+ int searchKey = 100;
+
+ void *data = parcTreeRedBlack_Remove(tree1, &searchKey);
+
+ valueFree(&data);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Trees dont match after remove");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_RemoveAndDestroy_First)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+
+ parcTreeRedBlack_Insert(tree1, (void *) 1, (void *) (1 << 8));
+
+ for (long i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 1);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Trees dont match after remove");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_RemoveAndDestroy)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 31; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+
+ parcTreeRedBlack_Insert(tree1, (void *) 30, (void *) (30 << 8));
+
+ for (long i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 30);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Trees dont match after remove");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Remove_NonExistent)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+
+ void *element = parcTreeRedBlack_Remove(tree1, (void *) 100);
+
+ assertNull(element, "Return value must be NULL on non existing element");
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Trees dont match after remove");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_RemoveAndDestroy_NonExistent)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 100);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Trees dont match after remove");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Remove_WithSuccessorNonRoot)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ long insert1[15] = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+ long insert2[13] = { 8, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+
+
+ for (int i = 0; i < 15; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) insert1[i], (void *) (insert1[i] << 8));
+ }
+
+ for (int i = 0; i < 13; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree2, (void *) insert2[i], (void *) (insert2[i] << 8));
+ }
+
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 4);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 12);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Trees dont match after remove");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Remove_LeftChildRightChild)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ long insert1[15] = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+ long insert2[15] = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+
+
+ for (int i = 0; i < 15; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) insert1[i], (void *) (insert1[i] << 8));
+ }
+
+ for (int i = 0; i < 15; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree2, (void *) insert2[i], (void *) (insert2[i] << 8));
+ }
+
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 13);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 7);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 14);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 6);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 15);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 12);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 11);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 10);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 9);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 8);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 5);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 4);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 3);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 2);
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 1);
+
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 1);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 2);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 3);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 4);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 5);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 6);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 7);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 8);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 9);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 10);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 11);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 12);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 13);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 14);
+ parcTreeRedBlack_RemoveAndDestroy(tree2, (void *) 15);
+
+ //assertTrue(parcTreeRedBlack_Equals(tree1,tree2),"Trees dont match after remove");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_RemoveAndDestroy_Last)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 30; i < 40; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+ parcTreeRedBlack_Insert(tree1, (void *) 100, (void *) (100 << 8));
+ for (long i = 2; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 20; i < 30; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2, (void *) i, (void *) (i << 8));
+ }
+
+ parcTreeRedBlack_RemoveAndDestroy(tree1, (void *) 100);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Trees dont match after remove");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Keys)
+{
+ PARCTreeRedBlack *tree1;
+ PARCArrayList *list;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ list = parcArrayList_Create(NULL);
+
+ // Insert in tree out of order
+ for (long i = 10; i < 20; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ }
+
+ // Insert in list in order
+ for (long i = 1; i < 20; i++) {
+ // Add some elements to the tree
+ parcArrayList_Add(list, (void *) i);
+ }
+
+ PARCArrayList *keys = parcTreeRedBlack_Keys(tree1);
+
+ assertTrue(parcArrayList_Equals(list, keys), "Key list doesnt' match");
+
+ parcArrayList_Destroy(&keys);
+ parcArrayList_Destroy(&list);
+ parcTreeRedBlack_Destroy(&tree1);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Values)
+{
+ PARCTreeRedBlack *tree1;
+ PARCArrayList *list;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ list = parcArrayList_Create(NULL);
+
+ // Insert in tree out of order
+ for (long i = 10; i < 20; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ }
+ for (long i = 1; i < 10; i++) {
+ // Add some elements to the tree
+ parcTreeRedBlack_Insert(tree1, (void *) i, (void *) (i << 8));
+ }
+
+ // Insert in list in order
+ for (long i = 1; i < 20; i++) {
+ // Add some elements to the tree
+ parcArrayList_Add(list, (void *) (i << 8));
+ }
+
+ PARCArrayList *values = parcTreeRedBlack_Values(tree1);
+
+ assertTrue(parcArrayList_Equals(list, values), "Key list doesnt' match");
+
+ parcArrayList_Destroy(&values);
+ parcArrayList_Destroy(&list);
+ parcTreeRedBlack_Destroy(&tree1);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Equals_Empty)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Empty lists are not equal");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Equals_DifferentLength)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ int compareInserts = 100;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 1; i < compareInserts; i++) {
+ parcTreeRedBlack_Insert(tree1,
+ (void *) i,
+ (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2,
+ (void *) (compareInserts - i),
+ (void *) ((compareInserts - i) << 8));
+ }
+ parcTreeRedBlack_Insert(tree2, (void *) (1000), (void *) ((12304) << 8));
+
+ assertFalse(parcTreeRedBlack_Equals(tree1, tree2), "Lists are equal");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Equals_Not_Values)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ int compareInserts = 100;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 1; i < compareInserts; i++) {
+ parcTreeRedBlack_Insert(tree1,
+ (void *) i,
+ (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2,
+ (void *) (compareInserts - i),
+ (void *) ((compareInserts + i) << 8));
+ }
+
+ assertFalse(parcTreeRedBlack_Equals(tree1, tree2), "Lists are equal");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Equals_Not_Values_Func)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ int compareInserts = 100;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, keyFree, keyCopy, intEquals, valueFree, valueCopy);
+ tree2 = parcTreeRedBlack_Create(pointerComp, keyFree, keyCopy, intEquals, valueFree, valueCopy);
+
+ for (int i = 1; i < compareInserts; i++) {
+ parcTreeRedBlack_Insert(tree1,
+ keyNewInt(i),
+ valueNewInt(i + 1000));
+ parcTreeRedBlack_Insert(tree2,
+ keyNewInt(i),
+ valueNewInt(i + 2000));
+ }
+
+ assertFalse(parcTreeRedBlack_Equals(tree1, tree2), "Lists are equal");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Equals_Not_Keys)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ int compareInserts = 100;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 1; i < compareInserts; i++) {
+ parcTreeRedBlack_Insert(tree1,
+ (void *) i,
+ (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2,
+ (void *) (compareInserts + i),
+ (void *) ((compareInserts - i) << 8));
+ }
+
+ assertFalse(parcTreeRedBlack_Equals(tree1, tree2), "Lists are equal");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Equals)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ int compareInserts = 100;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+ tree2 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 1; i < compareInserts; i++) {
+ parcTreeRedBlack_Insert(tree1,
+ (void *) i,
+ (void *) (i << 8));
+ parcTreeRedBlack_Insert(tree2,
+ (void *) (compareInserts - i),
+ (void *) ((compareInserts - i) << 8));
+ }
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Lists are not equal");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Equals_Func)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ int compareInserts = 100;
+
+ tree1 = parcTreeRedBlack_Create(intComp, keyFree, keyCopy, intEquals, valueFree, valueCopy);
+ tree2 = parcTreeRedBlack_Create(intComp, keyFree, keyCopy, intEquals, valueFree, valueCopy);
+
+ for (int i = 1; i < compareInserts; i++) {
+ parcTreeRedBlack_Insert(tree1,
+ keyNewInt(i),
+ valueNewInt(i + 1000));
+ parcTreeRedBlack_Insert(tree2,
+ keyNewInt(i),
+ valueNewInt(i + 1000));
+ }
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Lists are not equal");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Copy)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ int compareInserts = 20;
+
+ tree1 = parcTreeRedBlack_Create(intComp, keyFree, keyCopy, intEquals, valueFree, valueCopy);
+
+ for (int i = 1; i < compareInserts; i++) {
+ void *key = keyNewInt(i);
+ void *value = valueNewInt(i + 1000);
+ //value = (void *) &((*(int*)value) + 100);
+ parcTreeRedBlack_Insert(tree1, key, value);
+ }
+
+ tree2 = parcTreeRedBlack_Copy(tree1);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Lists are not equal");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Copy_Direct)
+{
+ PARCTreeRedBlack *tree1;
+ PARCTreeRedBlack *tree2;
+
+ int compareInserts = 20;
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ for (long i = 1; i < compareInserts; i++) {
+ parcTreeRedBlack_Insert(tree1,
+ (void *) i,
+ (void *) (i << 8));
+ }
+
+ tree2 = parcTreeRedBlack_Copy(tree1);
+
+ assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Lists are not equal");
+
+ parcTreeRedBlack_Destroy(&tree1);
+ parcTreeRedBlack_Destroy(&tree2);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ //LONGBOW_RUN_TEST_CASE(Local, PARC_TreeRedBlack_EnsureRemaining_NonEmpty);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Stress)
+{
+ // LongBow could use a command line option to enable/disable tests
+ // See LongBow issue #5
+ if (getenv("LongBowStress")) {
+ LONGBOW_RUN_TEST_CASE(Stress, PARC_TreeRedBlack_ExerciseRandomSeededSmall);
+ LONGBOW_RUN_TEST_CASE(Stress, PARC_TreeRedBlack_ExerciseRandomSeeded);
+ }
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Stress)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Stress)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Stress, PARC_TreeRedBlack_ExerciseRandomSeededSmall)
+{
+ PARCTreeRedBlack *tree1;
+ unsigned seed;
+ char *seedString;
+
+ seedString = getenv("RBSeed");
+ if (seedString) {
+ seed = (unsigned) atol(seedString);
+ } else {
+ seed = 4179329122; // known to fail
+ }
+
+ for (int j = 0; j < 1; j++) {
+ // this test case should obtain a seed and number of iterations from a
+ // command line option once LongBow has that feature available
+
+ printf("Random seed %u\n", seed);
+
+ srandom(seed);
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ int inserts = 0;
+ int deletes = 0;
+
+ for (int i = 0; i < 100; i++) {
+ intptr_t item = 1 + (random() % 100);
+ int operation = random() % 1000;
+ if (operation < 400) {
+ inserts++;
+ parcTreeRedBlack_Insert(tree1, (void *) item, (void *) (item << 8));
+ } else {
+ deletes++;
+ parcTreeRedBlack_Remove(tree1, (void *) item);
+ }
+ rbCheckTree(tree1);
+ }
+
+ parcTreeRedBlack_Destroy(&tree1);
+ }
+}
+
+LONGBOW_TEST_CASE(Stress, PARC_TreeRedBlack_ExerciseRandomSeeded)
+{
+ PARCTreeRedBlack *tree1;
+ unsigned seed;
+ char *seedString;
+
+ // this test case should obtain a seed and number of iterations from a
+ // command line option once LongBow has that feature available
+ seedString = getenv("RBSeed");
+ if (seedString) {
+ seed = (unsigned) atol(seedString);
+ } else {
+ seed = 4179329122; // known to fail
+ }
+ printf("Random seed %u\n", seed);
+
+ srandom(seed);
+
+ tree1 = parcTreeRedBlack_Create(pointerComp, NULL, NULL, NULL, NULL, NULL);
+
+ int inserts = 0;
+ int deletes = 0;
+
+ for (int i = 0; i < 100000; i++) {
+ intptr_t item = 1 + (random() % 10000);
+ int operation = random() % 1000;
+ if (operation < 400) {
+ inserts++;
+ parcTreeRedBlack_Insert(tree1, (void *) item, (void *) (item << 8));
+ } else {
+ deletes++;
+ parcTreeRedBlack_Remove(tree1, (void *) item);
+ }
+ rbCheckTree(tree1);
+ }
+
+ parcTreeRedBlack_Destroy(&tree1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(PARC_TreeRedBlack);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_URI.c b/libparc/parc/algol/test/test_parc_URI.c
new file mode 100644
index 00000000..5050deb3
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_URI.c
@@ -0,0 +1,642 @@
+/*
+ * 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_URI.c"
+#include <LongBow/unit-test.h>
+
+#include <stdint.h>
+
+#include <parc/algol/parc_Hash.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+#include <parc/algol/parc_Hash.h>
+
+#include "_test_parc_URI.h"
+
+LONGBOW_TEST_RUNNER(parcURI)
+{
+ LONGBOW_RUN_TEST_FIXTURE(parcURI);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(parcURI)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(parcURI)
+{
+ 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(parcURI)
+{
+ LONGBOW_RUN_TEST_CASE(parcURI, parseScheme);
+ LONGBOW_RUN_TEST_CASE(parcURI, parseScheme_Only);
+ LONGBOW_RUN_TEST_CASE(parcURI, parseScheme_BadScheme);
+ LONGBOW_RUN_TEST_CASE(parcURI, parseScheme_EmptyScheme);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parseAuthority);
+ LONGBOW_RUN_TEST_CASE(parcURI, parseAuthority_NoAuthority);
+ LONGBOW_RUN_TEST_CASE(parcURI, parseAuthority_NoPath);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_Acquire);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_AuthorityEquals_SamePointer);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_AuthorityEquals_NullPointers);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_QueryEquals_SamePointer);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_QueryEquals_NullPointers);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_FragmentEquals_SamePointer);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_FragmentEquals_NullPointers);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SchemeEquals_SamePointer);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SchemeEquals_NullPointers);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_Parse);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_Parse_NoScheme);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_Parse_SchemeOnly);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetScheme);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetScheme_Reset);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetScheme_Resetting);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetFragment);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetFragment_Reset);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetFragment_Resetting);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetQuery);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetQuery_Reset);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetQuery_Resetting);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetAuthority);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetAuthority_Reset);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_SetAuthority_Resetting);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_Equals_Contract);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_GetPath);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_GetQuery);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_GetFragment);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_Copy);
+ LONGBOW_RUN_TEST_CASE(parcURI, parcURI_ToString_Full);
+
+ LONGBOW_RUN_TEST_CASE(parcURI, PARCURI_ToString_SchemeOnly);
+ LONGBOW_RUN_TEST_CASE(parcURI, PARCURI_ToString_NoAuthority);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(parcURI)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(parcURI)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_Acquire)
+{
+ char *uriString = URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+
+ PARCURI *uri = parcURI_Parse(uriString);
+
+ PARCURI *handle = parcURI_Acquire(uri);
+
+ assertTrue(parcURI_Equals(uri, handle), "Expected URI and acquired handle to be equal");
+
+ parcURI_Release(&handle);
+ parcURI_Release(&uri);
+ parcMemory_Deallocate((void **) &uriString);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_AuthorityEquals_SamePointer)
+{
+ char *authority = "authority@auth";
+ assertTrue(_parcURI_AuthorityEquals(authority, authority),
+ "Expected authorities to be equal since they're the same pointers: %p - %p",
+ (void *) authority, (void *) authority);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_AuthorityEquals_NullPointers)
+{
+ char *authority = "authority@auth";
+ assertFalse(_parcURI_AuthorityEquals(NULL, authority), "Expected authorities to not be equal since one is NULL");
+ assertFalse(_parcURI_AuthorityEquals(authority, NULL), "Expected authorities to not be equal since one is NULL");
+ assertTrue(_parcURI_AuthorityEquals(NULL, NULL), "Expected authorities to be equal since both are NULL");
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_QueryEquals_SamePointer)
+{
+ char *query = "query";
+ assertTrue(_parcURI_QueryEquals(query, query),
+ "Expected queries to be equal since they're the same pointers: %p - %p",
+ (void *) query, (void *) query);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_QueryEquals_NullPointers)
+{
+ char *query = "query";
+ assertFalse(_parcURI_QueryEquals(NULL, query), "Expected queries to not be equal since one is NULL");
+ assertFalse(_parcURI_QueryEquals(query, NULL), "Expected queries to not be equal since one is NULL");
+ assertTrue(_parcURI_QueryEquals(NULL, NULL), "Expected queries to be equal since both are NULL");
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_FragmentEquals_SamePointer)
+{
+ char *fragment = "fragment";
+ assertTrue(_parcURI_FragmentEquals(fragment, fragment),
+ "Expected fragments to be equal since they're the same pointers: %p - %p",
+ (void *) fragment, (void *) fragment);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_FragmentEquals_NullPointers)
+{
+ char *fragment = "fragment";
+ assertFalse(_parcURI_FragmentEquals(NULL, fragment), "Expected fragments to not be equal since one is NULL");
+ assertFalse(_parcURI_FragmentEquals(fragment, NULL), "Expected fragments to not be equal since one is NULL");
+ assertTrue(_parcURI_FragmentEquals(NULL, NULL), "Expected fragments to be equal since both are NULL");
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SchemeEquals_SamePointer)
+{
+ char *scheme = "scheme";
+ assertTrue(_parcURI_SchemeEquals(scheme, scheme),
+ "Expected schemes to be equal since they're the same pointers: %p - %p",
+ (void *) scheme, (void *) scheme);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SchemeEquals_NullPointers)
+{
+ char *scheme = "scheme";
+ assertFalse(_parcURI_SchemeEquals(NULL, scheme), "Expected schemes to not be equal since one is NULL");
+ assertFalse(_parcURI_SchemeEquals(scheme, NULL), "Expected schemes to not be equal since one is NULL");
+ assertTrue(_parcURI_SchemeEquals(NULL, NULL), "Expected schemes to be equal since both are NULL");
+}
+
+LONGBOW_TEST_CASE(parcURI, parseScheme_EmptyScheme)
+{
+ const char *pointer;
+ char *actual = _parseScheme(":", &pointer); // empty string
+ assertNull(actual, "Parsed scheme should be NULL since the input string was empty.");
+ actual = _parseScheme("", &pointer); // empty string
+ assertNull(actual, "Parsed scheme should be NULL since the input string was empty.");
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_Parse)
+{
+ char *uriString = URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+
+ PARCURI *uri = parcURI_Parse(uriString);
+ assertNotNull(uri, "Expected non-null result for '%s'", uriString);
+
+ memset(uriString, 0, strlen(uriString));
+
+ assertTrue(strcmp(URI_SCHEME, parcURI_GetScheme(uri)) == 0,
+ "Expected '%s', actual '%s'", URI_SCHEME, parcURI_GetScheme(uri));
+ assertTrue(strcmp(URI_AUTHORITY, parcURI_GetAuthority(uri)) == 0,
+ "Expected '%s', actual '%s'", URI_AUTHORITY, parcURI_GetAuthority(uri));
+ assertTrue(strcmp(URI_QUERY, parcURI_GetQuery(uri)) == 0,
+ "Expected '%s', actual '%s'", URI_QUERY, parcURI_GetQuery(uri));
+ assertTrue(strcmp(URI_FRAGMENT, parcURI_GetFragment(uri)) == 0,
+ "Expected '%s', actual '%s'", URI_FRAGMENT, parcURI_GetFragment(uri));
+
+ parcMemory_Deallocate((void **) &uriString);
+
+ parcURI_Release(&uri);
+ assertNull(uri, "Expected parcURI_Release to null the pointer.");
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_Parse_NoScheme)
+{
+ char *uriString = "/" URI_PATH_SEGMENT;
+
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+
+ PARCURI *uri = parcURI_Parse(uriString);
+ assertNull(uri,
+ "Expected null result for '%s'", uriString);
+ parcMemory_Deallocate((void **) &uriString);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_Parse_SchemeOnly)
+{
+ char *uriString = URI_SCHEME ":";
+
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+
+ PARCURI *uri = parcURI_Parse(uriString);
+ assertNotNull(uri,
+ "Expected non-null result for '%s'", uriString);
+
+ memset(uriString, 0, strlen(uriString));
+
+ assertTrue(strcmp(URI_SCHEME, parcURI_GetScheme(uri)) == 0,
+ "Expected '%s', actual '%s'", URI_SCHEME, parcURI_GetScheme(uri));
+ assertNull(parcURI_GetAuthority(uri),
+ "Expected NULL, actual '%s'", parcURI_GetAuthority(uri));
+ assertNull(parcURI_GetQuery(uri),
+ "Expected NULL, actual '%s'", parcURI_GetQuery(uri));
+ assertNull(parcURI_GetFragment(uri),
+ "Expected NULL, actual '%s'", parcURI_GetFragment(uri));
+
+ parcMemory_Deallocate((void **) &uriString);
+ parcURI_Release(&uri);
+ assertNull(uri,
+ "Expected parcURI_Release to null the pointer.");
+}
+
+LONGBOW_TEST_CASE(parcURI, parseScheme)
+{
+ const char *pointer;
+ char *actual = _parseScheme(URI_FULL, &pointer);
+ assertTrue(strcmp(URI_SCHEME, actual) == 0,
+ "Expected '%s' actual '%s'", URI_SCHEME, actual);
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(parcURI, parseScheme_Only)
+{
+ const char *pointer;
+ char *actual = _parseScheme(URI_SCHEME ":", &pointer);
+ assertTrue(strcmp(URI_SCHEME, actual) == 0,
+ "Expected '%s' actual '%s'", URI_SCHEME, actual);
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(parcURI, parseScheme_BadScheme)
+{
+ const char *pointer;
+ char *actual = _parseScheme("", &pointer);
+ assertNull(actual,
+ "Expected NULL actual '%s'", actual);
+}
+
+LONGBOW_TEST_CASE(parcURI, PARCURI_GetAuthority)
+{
+ PARCURI *uri = parcURI_Parse(URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT);
+ const char *actual = parcURI_GetAuthority(uri);
+ assertTrue(strcmp(TEST_URI_AUTHORITY, actual) == 0,
+ "Expected '%s' actual '%s'", URI_AUTHORITY, actual);
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_GetQuery)
+{
+ PARCURI *uri = parcURI_Parse(URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT);
+ const char *actual = parcURI_GetQuery(uri);
+ assertTrue(strcmp(URI_QUERY, actual) == 0,
+ "Expected '%s' actual '%s'", URI_FRAGMENT, actual);
+
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_GetFragment)
+{
+ PARCURI *uri = parcURI_Parse(URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT);
+ const char *actual = parcURI_GetFragment(uri);
+ assertTrue(strcmp(URI_FRAGMENT, actual) == 0,
+ "Expected '%s' actual '%s'", URI_FRAGMENT, actual);
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_GetPath)
+{
+ char *uriString = URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+ PARCURI *uri = parcURI_Parse(uriString);
+ PARCURIPath *actual = parcURI_GetPath(uri);
+
+ char *string = parcURIPath_ToString(actual);
+
+ char *expected = URI_PATH_SEGMENT "/" URI_PATH_SEGMENT;
+ assertTrue(strcmp(expected, string) == 0, "Expected '%s' actual '%s'", expected, string);
+
+ parcMemory_Deallocate((void **) &string);
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_Copy)
+{
+ PARCURI *uri = parcURI_Parse(URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT);
+ PARCURI *uri2 = parcURI_Copy(uri);
+
+ char *expected = parcURI_ToString(uri);
+ char *actual = parcURI_ToString(uri2);
+
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s' actual '%s'", expected, actual);
+ parcMemory_Deallocate((void **) &expected);
+ parcMemory_Deallocate((void **) &actual);
+ parcURI_Release(&uri);
+ parcURI_Release(&uri2);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_Equals_Contract)
+{
+ PARCURI *x = parcURI_Parse(URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT);
+ PARCURI *y = parcURI_Parse(URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT);
+ PARCURI *z = parcURI_Parse(URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT);
+ PARCURI *u = parcURI_Parse(URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "?" URI_QUERY);
+
+ parcObjectTesting_AssertEqualsFunction(parcURI_Equals, x, y, z, u);
+
+ parcURI_Release(&x);
+ parcURI_Release(&y);
+ parcURI_Release(&z);
+ parcURI_Release(&u);
+}
+
+LONGBOW_TEST_CASE(parcURI, PARCURI_GetScheme)
+{
+ PARCURI *uri = parcURI_Parse(URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT);
+ const char *actual = parcURI_GetScheme(uri);
+ assertTrue(strcmp(TEST_URI_SCHEME, actual) == 0,
+ "Expected '%s' actual '%s'", TEST_URI_SCHEME, actual);
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, PARCURI_Parse)
+{
+ PARCURI *uri = parcURI_Parse(URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT);
+ assertNotNull(uri,
+ "Expected a non-null result.");
+
+ assertTrue(strcmp(URI_SCHEME, parcURI_GetScheme(uri)) == 0,
+ "Expected '%s', actual '%s'", URI_SCHEME, parcURI_GetScheme(uri));
+ assertTrue(strcmp(URI_AUTHORITY, parcURI_GetAuthority(uri)) == 0,
+ "Expected '%s', actual '%s'", URI_AUTHORITY, parcURI_GetAuthority(uri));
+ assertTrue(strcmp(URI_QUERY, parcURI_GetQuery(uri)) == 0,
+ "Expected '%s', actual '%s'", URI_QUERY, parcURI_GetQuery(uri));
+ assertTrue(strcmp(URI_FRAGMENT, parcURI_GetFragment(uri)) == 0,
+ "Expected '%s', actual '%s'", URI_FRAGMENT, parcURI_GetFragment(uri));
+
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_ToString_Full)
+{
+ char *expected = URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+
+ PARCURI *uri = parcURI_Parse(expected);
+ char *actual = parcURI_ToString(uri);
+
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s' actual '%s'", expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, PARCURI_ToString_SchemeOnly)
+{
+ char *expected = URI_SCHEME ":" "/";
+ PARCURI *uri = parcURI_Parse(expected);
+ char *actual = parcURI_ToString(uri);
+
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s' actual '%s'", expected, actual);
+ parcURI_Release(&uri);
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(parcURI, PARCURI_ToString_NoAuthority)
+{
+ char *expected = URI_SCHEME ":" "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+ PARCURI *uri = parcURI_Parse(expected);
+ char *actual = parcURI_ToString(uri);
+
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s' actual '%s'", expected, actual);
+
+ parcURI_Release(&uri);
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(parcURI, parseAuthority)
+{
+ char *authority = "//" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT;
+ char *expected = URI_AUTHORITY;
+
+ const char *pointer;
+ char *actual = _parseAuthority(authority, &pointer);
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s' actual '%s'", expected, actual);
+ assertTrue(*pointer == '/',
+ "Expected '/' actual '%c'", *pointer);
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(parcURI, parseAuthority_NoAuthority)
+{
+ char *string = "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT;
+
+ const char *pointer;
+ char *actual = _parseAuthority(string, &pointer);
+ assertTrue(actual == NULL,
+ "Expected NULL actual '%s'", actual);
+ assertTrue(*pointer == '/',
+ "Expected '/' actual '%c'", *pointer);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetScheme)
+{
+ char *scheme = "scheme";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetScheme(uri, scheme);
+
+ assertTrue(strcmp(scheme, parcURI_GetScheme(uri)) == 0,
+ "Expected %s actual %s", scheme, parcURI_GetScheme(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetScheme_Resetting)
+{
+ char *scheme = "scheme";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetScheme(uri, scheme);
+ _parcURI_SetScheme(uri, scheme);
+
+ assertTrue(strcmp(scheme, parcURI_GetScheme(uri)) == 0,
+ "Expected %s actual %s", scheme, parcURI_GetScheme(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetScheme_Reset)
+{
+ char *scheme = "scheme";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetScheme(uri, scheme);
+ _parcURI_SetScheme(uri, NULL);
+
+ assertNull(parcURI_GetScheme(uri),
+ "Expected NULL actual %s", parcURI_GetScheme(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetFragment)
+{
+ char *fragment = "fragment";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetFragment(uri, fragment);
+
+ assertTrue(strcmp(fragment, parcURI_GetFragment(uri)) == 0,
+ "Expected %s actual %s", fragment, parcURI_GetFragment(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetFragment_Resetting)
+{
+ char *fragment = "fragment";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetFragment(uri, fragment);
+ _parcURI_SetFragment(uri, fragment);
+
+ assertTrue(strcmp(fragment, parcURI_GetFragment(uri)) == 0,
+ "Expected %s actual %s", fragment, parcURI_GetFragment(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetFragment_Reset)
+{
+ char *fragment = "query";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetFragment(uri, fragment);
+ _parcURI_SetFragment(uri, NULL);
+
+ assertNull(parcURI_GetFragment(uri),
+ "Expected NULL actual %s", parcURI_GetFragment(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetQuery)
+{
+ char *query = "query";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetQuery(uri, query);
+
+ assertTrue(strcmp(query, parcURI_GetQuery(uri)) == 0,
+ "Expected %s actual %s", query, parcURI_GetQuery(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetQuery_Resetting)
+{
+ char *query = "query";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetQuery(uri, query);
+ _parcURI_SetQuery(uri, query);
+
+ assertTrue(strcmp(query, parcURI_GetQuery(uri)) == 0,
+ "Expected %s actual %s", query, parcURI_GetQuery(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetQuery_Reset)
+{
+ char *query = "query";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetQuery(uri, query);
+ _parcURI_SetQuery(uri, NULL);
+
+ assertNull(parcURI_GetQuery(uri),
+ "Expected NULL actual %s", parcURI_GetQuery(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetAuthority)
+{
+ char *authority = "authority@auth";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetAuthority(uri, authority);
+
+ assertTrue(strcmp(authority, parcURI_GetAuthority(uri)) == 0,
+ "Expected %s actual %s", authority, parcURI_GetAuthority(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetAuthority_Resetting)
+{
+ char *authority = "query";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetAuthority(uri, authority);
+ _parcURI_SetAuthority(uri, authority);
+
+ assertTrue(strcmp(authority, parcURI_GetAuthority(uri)) == 0,
+ "Expected %s actual %s", authority, parcURI_GetAuthority(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parcURI_SetAuthority_Reset)
+{
+ char *query = "query";
+ PARCURI *uri = parcURI_Create();
+ _parcURI_SetAuthority(uri, query);
+ _parcURI_SetAuthority(uri, NULL);
+
+ assertNull(parcURI_GetAuthority(uri),
+ "Expected NULL actual %s", parcURI_GetAuthority(uri));
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURI, parseAuthority_NoPath)
+{
+ char *authority = "//" URI_AUTHORITY;
+ char *expected = URI_AUTHORITY;
+
+ const char *pointer;
+ char *actual = _parseAuthority(authority, &pointer);
+
+ assertTrue(strcmp(expected, actual) == 0,
+ "Expected '%s' actual '%s'", authority, actual);
+ assertTrue(*pointer == 0,
+ "Expected null actual '%c'", *pointer);
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(parcURI, parseFragment)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(parcURI, parsePath)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(parcURI, parseQuery)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parcURI);
+ int status = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(status);
+}
diff --git a/libparc/parc/algol/test/test_parc_URIAuthority.c b/libparc/parc/algol/test/test_parc_URIAuthority.c
new file mode 100644
index 00000000..e6d8196a
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_URIAuthority.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 "../parc_URIAuthority.c"
+#include <stdint.h>
+
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_URI.h>
+
+#include "_test_parc_URI.h"
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parcURIAuthority)
+{
+ LONGBOW_RUN_TEST_FIXTURE(parcURIAuthority);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(parcURIAuthority)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(parcURIAuthority)
+{
+ 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(parcURIAuthority)
+{
+ LONGBOW_RUN_TEST_CASE(parcURIAuthority, parcURIAuthority_Parse);
+
+ LONGBOW_RUN_TEST_CASE(parcURIAuthority, parcURIAuthority_Acquire);
+
+ LONGBOW_RUN_TEST_CASE(parcURIAuthority, parcURIAuthority_Equals);
+
+ LONGBOW_RUN_TEST_CASE(parcURIAuthority, parcURIAuthority_GetUserInfo);
+ LONGBOW_RUN_TEST_CASE(parcURIAuthority, parcURIAuthority_GetHostName);
+ LONGBOW_RUN_TEST_CASE(parcURIAuthority, parcURIAuthority_GetPort);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(parcURIAuthority)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(parcURIAuthority)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(parcURIAuthority, parcURIAuthority_Parse)
+{
+ char *uriString = URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+
+ PARCURI *uri = parcURI_Parse(uriString);
+
+ PARCURIAuthority *authority = parcURIAuthority_Parse(parcURI_GetAuthority(uri));
+
+ assertEqualStrings(parcURIAuthority_GetUserInfo(authority), URI_AUTHORITY_USERINFO);
+
+ parcURIAuthority_Release(&authority);
+
+ parcMemory_Deallocate((void **) &uriString);
+ parcURI_Release(&uri);
+
+ // URI without the port
+ uriString = URI_SCHEME "://" URI_AUTHORITY_USERINFO "@" URI_AUTHORITY_HOSTNAME "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+ uri = parcURI_Parse(uriString);
+ authority = parcURIAuthority_Parse(parcURI_GetAuthority(uri));
+
+ assertEqualStrings(parcURIAuthority_GetUserInfo(authority), URI_AUTHORITY_USERINFO);
+
+ parcURIAuthority_Release(&authority);
+ parcURI_Release(&uri);
+
+ // URI with literal V4 address
+ uriString = URI_SCHEME "://" URI_AUTHORITY_LITERAL_HOST "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+ uri = parcURI_Parse(uriString);
+ authority = parcURIAuthority_Parse(parcURI_GetAuthority(uri));
+
+ assertEqualStrings(parcURIAuthority_GetHostName(authority), URI_AUTHORITY_LITERAL_HOSTNAME);
+
+ parcURIAuthority_Release(&authority);
+ parcURI_Release(&uri);
+
+ // URI with literal V6 address
+ uriString = URI_SCHEME "://" URI_AUTHORITY_LITERAL_HOST6 "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+ uri = parcURI_Parse(uriString);
+ authority = parcURIAuthority_Parse(parcURI_GetAuthority(uri));
+
+ assertEqualStrings(parcURIAuthority_GetHostName(authority), URI_AUTHORITY_LITERAL_HOSTNAME6);
+
+ parcURIAuthority_Release(&authority);
+ parcURI_Release(&uri);
+
+ // URI with full literal V6 address
+ uriString = URI_SCHEME "://" URI_AUTHORITY_LITERAL_HOST6_2 "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+ uri = parcURI_Parse(uriString);
+ authority = parcURIAuthority_Parse(parcURI_GetAuthority(uri));
+
+ assertEqualStrings(parcURIAuthority_GetHostName(authority), URI_AUTHORITY_LITERAL_HOSTNAME6_2);
+
+ parcURIAuthority_Release(&authority);
+ parcURI_Release(&uri);
+
+ parcMemory_Deallocate((void **) &uriString);
+}
+
+LONGBOW_TEST_CASE(parcURIAuthority, parcURIAuthority_Acquire)
+{
+ char *uriString = URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+
+ PARCURI *uri = parcURI_Parse(uriString);
+
+ PARCURIAuthority *authority = parcURIAuthority_Parse(parcURI_GetAuthority(uri));
+ PARCURIAuthority *handle = parcURIAuthority_Acquire(authority);
+
+ assertTrue(parcURIAuthority_Equals(authority, handle), "URI Authorities should be equal since they refer to the same object.");
+
+ parcURIAuthority_Release(&authority);
+ parcURIAuthority_Release(&handle);
+
+ parcMemory_Deallocate((void **) &uriString);
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURIAuthority, parcURIAuthority_Equals)
+{
+ char *uriString1 = URI_SCHEME "://" URI_AUTHORITY;
+ uriString1 = parcMemory_StringDuplicate(uriString1, strlen(uriString1));
+ PARCURI *uri1 = parcURI_Parse(uriString1);
+ PARCURIAuthority *x = parcURIAuthority_Parse(parcURI_GetAuthority(uri1));
+
+ char *uriString2 = URI_SCHEME "://" URI_AUTHORITY;
+ uriString2 = parcMemory_StringDuplicate(uriString2, strlen(uriString2));
+ PARCURI *uri2 = parcURI_Parse(uriString2);
+ PARCURIAuthority *y = parcURIAuthority_Parse(parcURI_GetAuthority(uri2));
+
+ char *uriString3 = URI_SCHEME "://" URI_AUTHORITY;
+ uriString3 = parcMemory_StringDuplicate(uriString3, strlen(uriString3));
+ PARCURI *uri3 = parcURI_Parse(uriString3);
+ PARCURIAuthority *z = parcURIAuthority_Parse(parcURI_GetAuthority(uri3));
+
+ char *differentUriString = URI_SCHEME "://" URI_AUTHORITY_USERINFO;
+ differentUriString = parcMemory_StringDuplicate(differentUriString, strlen(differentUriString));
+ PARCURI *unequalUri = parcURI_Parse(differentUriString);
+ PARCURIAuthority *u = parcURIAuthority_Parse(parcURI_GetAuthority(unequalUri));
+
+ char *uriString5 = URI_SCHEME "://" URI_AUTHORITY_DIFFERENT_PORT;
+ uriString5 = parcMemory_StringDuplicate(uriString5, strlen(uriString5));
+ PARCURI *unequalUri5 = parcURI_Parse(uriString5);
+ PARCURIAuthority *u5 = parcURIAuthority_Parse(parcURI_GetAuthority(unequalUri5));
+
+ char *uriString4 = URI_SCHEME "://" URI_AUTHORITY_DIFFERENT_USER;
+ uriString4 = parcMemory_StringDuplicate(uriString4, strlen(uriString4));
+ PARCURI *unequalUri4 = parcURI_Parse(uriString4);
+ PARCURIAuthority *u4 = parcURIAuthority_Parse(parcURI_GetAuthority(unequalUri4));
+
+ parcObjectTesting_AssertEqualsFunction(parcURIAuthority_Equals, x, y, z, u);
+
+ assertFalse(parcURIAuthority_Equals(x, u4), "Expected URI authorities with different user info to be unequal");
+ assertFalse(parcURIAuthority_Equals(x, u5), "Expected URI authorities with different hsot names to be unequal");
+
+ parcURIAuthority_Release(&x);
+ parcURIAuthority_Release(&y);
+ parcURIAuthority_Release(&z);
+ parcURIAuthority_Release(&u);
+ parcURIAuthority_Release(&u4);
+ parcURIAuthority_Release(&u5);
+
+ parcMemory_Deallocate((void **) &uriString1);
+ parcMemory_Deallocate((void **) &uriString2);
+ parcMemory_Deallocate((void **) &uriString3);
+ parcMemory_Deallocate((void **) &uriString4);
+ parcMemory_Deallocate((void **) &uriString5);
+ parcMemory_Deallocate((void **) &differentUriString);
+
+ parcURI_Release(&uri1);
+ parcURI_Release(&uri2);
+ parcURI_Release(&uri3);
+ parcURI_Release(&unequalUri);
+ parcURI_Release(&unequalUri4);
+ parcURI_Release(&unequalUri5);
+}
+
+LONGBOW_TEST_CASE(parcURIAuthority, parcURIAuthority_GetUserInfo)
+{
+ char *uriString = URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+ PARCURI *uri = parcURI_Parse(uriString);
+ PARCURIAuthority *authority = parcURIAuthority_Parse(parcURI_GetAuthority(uri));
+
+ assertTrue(strcmp(URI_AUTHORITY_USERINFO, parcURIAuthority_GetUserInfo(authority)) == 0, "URI Authority user info should be equal: %s - %s", URI_AUTHORITY_USERINFO, parcURIAuthority_GetUserInfo(authority));
+
+ parcURIAuthority_Release(&authority);
+
+ parcMemory_Deallocate((void **) &uriString);
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURIAuthority, parcURIAuthority_GetHostName)
+{
+ char *uriString = URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+ PARCURI *uri = parcURI_Parse(uriString);
+ PARCURIAuthority *authority = parcURIAuthority_Parse(parcURI_GetAuthority(uri));
+
+ assertTrue(strcmp(URI_AUTHORITY_HOSTNAME, parcURIAuthority_GetHostName(authority)) == 0, "URI Authority host name should be equal: %s - %s", URI_AUTHORITY_HOSTNAME, parcURIAuthority_GetHostName(authority));
+
+ parcURIAuthority_Release(&authority);
+
+ parcMemory_Deallocate((void **) &uriString);
+ parcURI_Release(&uri);
+}
+
+LONGBOW_TEST_CASE(parcURIAuthority, parcURIAuthority_GetPort)
+{
+ char *uriString = URI_SCHEME "://" URI_AUTHORITY "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?" URI_QUERY "#" URI_FRAGMENT;
+ uriString = parcMemory_StringDuplicate(uriString, strlen(uriString));
+ PARCURI *uri = parcURI_Parse(uriString);
+ PARCURIAuthority *authority = parcURIAuthority_Parse(parcURI_GetAuthority(uri));
+
+ assertTrue(atol(URI_AUTHORITY_PORT_1) == parcURIAuthority_GetPort(authority),
+ "URI Authority host name should be equal: %ld - %ld", atol(URI_AUTHORITY_PORT_1), parcURIAuthority_GetPort(authority));
+
+ parcURIAuthority_Release(&authority);
+
+ parcMemory_Deallocate((void **) &uriString);
+ parcURI_Release(&uri);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parcURIAuthority);
+ int status = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(status);
+}
diff --git a/libparc/parc/algol/test/test_parc_URIPath.c b/libparc/parc/algol/test/test_parc_URIPath.c
new file mode 100644
index 00000000..29f34a96
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_URIPath.c
@@ -0,0 +1,406 @@
+/*
+ * 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_URIPath.c"
+#include <stdint.h>
+
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_URI.h>
+
+#include "_test_parc_URI.h"
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parcURIPath)
+{
+ LONGBOW_RUN_TEST_FIXTURE(parcURIPath);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(parcURIPath)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(parcURIPath)
+{
+ 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(parcURIPath)
+{
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Acquire);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Parse);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Parse_WithQuery);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Release);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Count);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Append);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_ToString);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Length);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Trim);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Copy);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Equals);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Compare_Identity);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Compare_Equal);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Compare_Unequal);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_Compose);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_StartsWith);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_StartsWith_Equal);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_StartsWith_Fail);
+ LONGBOW_RUN_TEST_CASE(parcURIPath, parcURIPath_BuildString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(parcURIPath)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(parcURIPath)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Acquire)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "//////" URI_PATH_SEGMENT, &pointer);
+ PARCURIPath *handle = parcURIPath_Acquire(path);
+
+ assertTrue(parcURIPath_Equals(path, handle), "URI paths should be equal: %s - %s", parcURIPath_ToString(path), parcURIPath_ToString(handle));
+
+ parcURIPath_Release(&path);
+ parcURIPath_Release(&handle);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Parse)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "//////" URI_PATH_SEGMENT, &pointer);
+ assertNotNull(path, "Expected non-null result.");
+ assertTrue(*pointer == 0, "Expected pointer to point to the null terminating byte.");
+
+ char *actualPath = parcURIPath_ToString(path);
+
+ char *expectedPath = URI_PATH_SEGMENT "/" URI_PATH_SEGMENT;
+ assertTrue(strcmp(expectedPath, actualPath) == 0, "Expected %s actual %s", expectedPath, actualPath);
+
+ parcMemory_Deallocate((void **) &actualPath);
+ parcURIPath_Release(&path);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Release)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT, &pointer);
+ assertNotNull(path, "Expected non-null result.");
+ parcURIPath_Release(&path);
+ assertNull(path, "Expected destroy to null the pointer.");
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Parse_WithQuery)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+ assertNotNull(path, "Expected non-null result.");
+ assertTrue(*pointer == '?', "Expected pointer to point to the terminating character.");
+
+ char *actualPath = parcURIPath_ToString(path);
+ char *expectedPath = URI_PATH_SEGMENT "/" URI_PATH_SEGMENT;
+ assertTrue(strcmp(expectedPath, actualPath) == 0, "Expected %s actual %s", expectedPath, actualPath);
+ parcMemory_Deallocate((void **) &actualPath);
+ parcURIPath_Release(&path);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Equals)
+{
+ const char *pointer;
+ PARCURIPath *x = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *y = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *z = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *u1 = parcURIPath_Parse("/" URI_PATH_SEGMENT "a/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *u2 = parcURIPath_Parse("/" URI_PATH_SEGMENT "?query", &pointer);
+
+ parcObjectTesting_AssertEqualsFunction(parcURIPath_Equals, x, y, z, u1, u2);
+
+ parcURIPath_Release(&x);
+ parcURIPath_Release(&y);
+ parcURIPath_Release(&z);
+ parcURIPath_Release(&u1);
+ parcURIPath_Release(&u2);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Copy)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *copy = parcURIPath_Copy(path);
+
+ assertTrue(copy != path, "Expected distinct instances of the path.");
+
+ int comparison = parcURIPath_Compare(path, copy);
+
+ assertTrue(comparison == 0, "Expected the copy to compare equal to the original.");
+
+ parcURIPath_Release(&path);
+ parcURIPath_Release(&copy);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_StartsWith)
+{
+ const char *pointer;
+ PARCURIPath *base = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *prefix = parcURIPath_Parse("/" URI_PATH_SEGMENT "?query", &pointer);
+
+ bool actual = parcURIPath_StartsWith(base, prefix);
+
+ assertTrue(actual, "Expected true, actual false.");
+
+ parcURIPath_Release(&prefix);
+ parcURIPath_Release(&base);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_StartsWith_Equal)
+{
+ const char *pointer;
+ PARCURIPath *base = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *prefix = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+
+ bool actual = parcURIPath_StartsWith(base, prefix);
+
+ assertTrue(actual, "Expected true, actual false.");
+
+ parcURIPath_Release(&prefix);
+ parcURIPath_Release(&base);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_StartsWith_Fail)
+{
+ const char *pointer;
+ PARCURIPath *base = parcURIPath_Parse("/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *prefix1 = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *prefix2 = parcURIPath_Parse("/" URI_PATH_SEGMENT "A?query", &pointer);
+
+ assertFalse(parcURIPath_StartsWith(base, prefix1),
+ "Expected false, actual true");
+
+ assertFalse(parcURIPath_StartsWith(base, prefix2),
+ "Expected false, actual true");
+
+ parcURIPath_Release(&prefix1);
+ parcURIPath_Release(&prefix2);
+ parcURIPath_Release(&base);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Compose)
+{
+ const char *pointer;
+ PARCURIPath *base = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *expected = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+
+ PARCURISegment *a = parcURISegment_Parse(URI_PATH_SEGMENT, &pointer);
+ PARCURIPath *actual = parcURIPath_Compose(base, a, a, NULL);
+ parcURISegment_Release(&a);
+
+ char *actualString = parcURIPath_ToString(actual);
+ char *expectedString = parcURIPath_ToString(expected);
+ assertTrue(parcURIPath_Compare(expected, actual) == 0, "Expected '%s' actual '%s'\n", expectedString, actualString);
+
+ parcMemory_Deallocate((void **) &actualString);
+ parcMemory_Deallocate((void **) &expectedString);
+
+ parcURIPath_Release(&actual);
+
+ parcURIPath_Release(&expected);
+ parcURIPath_Release(&base);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Compare_Identity)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+
+ PARCURIPath *equivalents[] = {
+ path,
+ parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query",&pointer),
+ NULL,
+ };
+ PARCURIPath *lessers[] = {
+ parcURIPath_Parse("/" URI_PATH_SEGMENT "?query", &pointer),
+ NULL,
+ };
+ PARCURIPath *greaters[] = {
+ parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer),
+ parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "AAA?query", &pointer),
+ NULL,
+ };
+
+ parcObjectTesting_AssertCompareTo(parcURIPath_Compare, path, equivalents, lessers, greaters);
+
+ for (int i = 0; equivalents[i] != NULL; i++) {
+ parcURIPath_Release(&equivalents[i]);
+ }
+ for (int i = 0; lessers[i] != NULL; i++) {
+ parcURIPath_Release(&lessers[i]);
+ }
+ for (int i = 0; greaters[i] != NULL; i++) {
+ parcURIPath_Release(&greaters[i]);
+ }
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Compare_Equal)
+{
+ const char *pointer;
+ PARCURIPath *pathA = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *pathB = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+
+ int comparison = parcURIPath_Compare(pathA, pathB);
+
+ assertTrue(comparison == 0, "Expected 0: equal paths to compare equal. Actual %d", comparison);
+ parcURIPath_Release(&pathA);
+ parcURIPath_Release(&pathB);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Compare_Unequal)
+{
+ const char *pointer;
+ PARCURIPath *pathA = parcURIPath_Parse("/" URI_PATH_SEGMENT "?query", &pointer);
+ PARCURIPath *pathB = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "?query", &pointer);
+
+ int comparison = parcURIPath_Compare(pathA, pathB);
+
+ assertTrue(comparison < 0, "Expected < 0: path A is less than path B. Actual %d", comparison);
+ parcURIPath_Release(&pathA);
+ parcURIPath_Release(&pathB);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Count)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT, &pointer);
+ assertNotNull(path, "Expected non-null result.");
+ assertTrue(*pointer == 0, "Expected pointer to point to the null terminating byte.");
+
+ size_t actual = parcURIPath_Count(path);
+ assertTrue(3 == actual, "Expected %d actual %zd", 3, actual);
+
+ parcURIPath_Release(&path);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_ToString)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT, &pointer);
+ assertNotNull(path, "Expected non-null result.");
+ assertTrue(*pointer == 0, "Expected pointer to point to the null terminating byte.");
+
+ char *actualString = parcURIPath_ToString(path);
+
+ char *expectedString = URI_PATH_SEGMENT "/" URI_PATH_SEGMENT;
+ assertTrue(strcmp(expectedString, actualString) == 0, "Expected %s actual %s", expectedString, actualString);
+
+ parcMemory_Deallocate((void **) &actualString);
+ parcURIPath_Release(&path);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Length)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT, &pointer);
+ assertNotNull(path, "Expected non-null result.");
+ assertTrue(*pointer == 0, "Expected pointer to point to the null terminating byte.");
+
+ size_t actualCount = parcURIPath_Length(path);
+
+ size_t expectedCount = 79;
+ assertTrue(expectedCount == actualCount, "Expected %zd actual %zd", expectedCount, actualCount);
+
+ parcURIPath_Release(&path);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Append)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT, &pointer);
+
+ PARCURISegment *segment = parcURISegment_Parse(URI_PATH_SEGMENT, &pointer);
+
+ PARCURIPath *result = parcURIPath_Append(path, segment);
+ assertTrue(result == path, "Expected %p, actual %p", (void *) path, (void *) result);
+
+ size_t actualCount = parcURIPath_Count(path);
+ assertTrue(3 == actualCount, "Expected 3, actual %zd", actualCount);
+
+ char *actualPath = parcURIPath_ToString(path);
+ char *expectedPath = URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT;
+ assertTrue(strcmp(expectedPath, actualPath) == 0, "Expected %s actual %s", expectedPath, actualPath);
+
+ parcMemory_Deallocate((void **) &actualPath);
+ parcURIPath_Release(&path);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_Trim)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT "/" URI_PATH_SEGMENT, &pointer);
+
+ parcURIPath_Trim(path, 2);
+ size_t actualCount = parcURIPath_Count(path);
+ assertTrue(2 == actualCount, "Expected 2, actual %zd", actualCount);
+
+ parcURIPath_Release(&path);
+}
+
+LONGBOW_TEST_CASE(parcURIPath, parcURIPath_BuildString)
+{
+ const char *pointer;
+ PARCURIPath *path = parcURIPath_Parse("/" URI_PATH_SEGMENT, &pointer);
+ PARCBufferComposer *target = parcBufferComposer_Create();
+
+ PARCBufferComposer *string = parcBufferComposer_Create();
+ parcBufferComposer_PutString(string, URI_PATH_SEGMENT);
+
+ PARCBuffer *b1 = parcBufferComposer_ProduceBuffer(string);
+ char *string1 = parcBuffer_ToString(b1);
+ parcBuffer_Release(&b1);
+
+ parcURIPath_BuildString(path, target);
+ PARCBuffer *b2 = parcBufferComposer_ProduceBuffer(target);
+ char *string2 = parcBuffer_ToString(b2);
+ parcBuffer_Release(&b2);
+
+ assertTrue(strncmp(string1, string2, strlen(string1)) == 0, "String representations of the paths should be equal: %s - %s", string1, string2);
+
+ parcMemory_Deallocate((void **) &string1);
+ parcMemory_Deallocate((void **) &string2);
+
+ parcBufferComposer_Release(&string);
+ parcBufferComposer_Release(&target);
+ parcURIPath_Release(&path);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parcURIPath);
+ int status = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(status);
+}
diff --git a/libparc/parc/algol/test/test_parc_URISegment.c b/libparc/parc/algol/test/test_parc_URISegment.c
new file mode 100644
index 00000000..640bab89
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_URISegment.c
@@ -0,0 +1,315 @@
+/*
+ * 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_URISegment.c"
+#include <LongBow/unit-test.h>
+
+#include <stdint.h>
+
+#include <parc/algol/parc_URI.h>
+
+#include "_test_parc_URI.h"
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/testing/parc_ObjectTesting.h>
+
+LONGBOW_TEST_RUNNER(parcURISegment)
+{
+ LONGBOW_RUN_TEST_FIXTURE(parcURISegment);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(parcURISegment)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(parcURISegment)
+{
+ 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(parcURISegment)
+{
+ LONGBOW_RUN_TEST_CASE(parcURISegment, _parcURISegment_fromHexDigit);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, _parcURISegment_parsePercentEncoded);
+
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_Acquire);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_Create);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_Parse);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_Parse_WithExtraSlashes);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_Parse_WithInvalidPercentage);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_Release);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_Length);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_ToString);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_Equals_Contract);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_Compare_Contract);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_Clone);
+ LONGBOW_RUN_TEST_CASE(parcURISegment, parcURISegment_GetBuffer);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(parcURISegment)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(parcURISegment)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(parcURISegment, _parcURISegment_fromHexDigit)
+{
+ const char test = 'G';
+ signed char actual = _fromHexDigit(test);
+ assertTrue(-1 == (int) actual, "Invalid hex digit should not be changed to a decimal value, we expect -1 as the result");
+}
+
+LONGBOW_TEST_CASE(parcURISegment, _parcURISegment_parsePercentEncoded)
+{
+ unsigned char buffer;
+
+ const char *test1 = "0G";
+ const char *result1 = _parsePercentEncoded(test1, &buffer);
+ assertTrue(NULL == result1, "Expected NULL parsed byte from invalid encoded percentage string, got %s", result1);
+ const char *test2 = "GG";
+ const char *result2 = _parsePercentEncoded(test2, &buffer);
+ assertTrue(NULL == result2, "Expected NULL parsed byte from invalid encoded percentage string, got %s", result2);
+ const char *test3 = "";
+ const char *result3 = _parsePercentEncoded(test3, &buffer);
+ assertTrue(NULL == result3, "Expected NULL parsed byte from empty encoded percentage string, got %s", result3);
+ const char *test4 = "0";
+ const char *result4 = _parsePercentEncoded(test4, &buffer);
+ assertTrue(NULL == result4, "Expected NULL parsed byte from half-empty encoded percentage string, got %s", result4);
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_Acquire)
+{
+ char *expected = URI_PATH_SEGMENT;
+
+ const char *pointer;
+ PARCURISegment *segment = parcURISegment_Parse(expected, &pointer);
+ PARCURISegment *handle = parcURISegment_Acquire(segment);
+ assertTrue(parcURISegment_Equals(segment, handle), "Expected URI segments to be equal: %s - %s", parcURISegment_ToString(segment), parcURISegment_ToString(handle));
+
+ parcURISegment_Release(&segment);
+ parcURISegment_Release(&handle);
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_Create)
+{
+ char *expected = URI_PATH_SEGMENT;
+
+ PARCURISegment *segment = parcURISegment_Create(strlen(expected), (unsigned char *) expected);
+ assertNotNull(segment, "Expected non-null result.");
+
+ parcURISegment_Release(&segment);
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_Parse)
+{
+ char *expected = URI_PATH_SEGMENT;
+
+ const char *pointer;
+ PARCURISegment *segment = parcURISegment_Parse(expected, &pointer);
+ assertNotNull(segment, "Expected non-null result.");
+
+ char *expectedBytes = URI_PATH_SEGMENT;
+
+ char *actualBytes = parcURISegment_ToString(segment);
+
+ assertTrue(strcmp(expectedBytes, actualBytes) == 0,
+ "Expected %s actual %s", expectedBytes, actualBytes);
+ parcMemory_Deallocate((void **) &actualBytes);
+
+ assertTrue(parcURISegment_Length(segment) == 39,
+ "Expected 39, actual %zd", parcURISegment_Length(segment));
+ assertTrue(*pointer == 0, "Expected pointer to point to the null terminating byte.");
+
+ parcURISegment_Release(&segment);
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_Parse_WithExtraSlashes)
+{
+ const char *pointer;
+ PARCURISegment *segment = parcURISegment_Parse(URI_PATH_SEGMENT_WITH_SLASHES, &pointer);
+ assertNotNull(segment, "Expected non-null result.");
+
+ char *expectedBytes = URI_PATH_SEGMENT;
+
+ char *actualBytes = parcURISegment_ToString(segment);
+
+ assertTrue(strcmp(expectedBytes, actualBytes) == 0,
+ "Expected %s actual %s", expectedBytes, actualBytes);
+ parcMemory_Deallocate((void **) &actualBytes);
+
+ assertTrue(parcURISegment_Length(segment) == 39,
+ "Expected 39, actual %zd", parcURISegment_Length(segment));
+ assertTrue(*pointer == '/', "Expected pointer to point to the slash character: %c", *pointer);
+
+ parcURISegment_Release(&segment);
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_Parse_WithInvalidPercentage)
+{
+ const char *pointer;
+ PARCURISegment *segment = parcURISegment_Parse(URI_PATH_SEGMENT "%G", &pointer);
+
+ assertNull(segment, "Parsed segment should be NULL since the last percent-encoded byte is invalid");
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_Release)
+{
+ char *expected = URI_PATH_SEGMENT;
+
+ const char *pointer;
+ PARCURISegment *segment = parcURISegment_Parse(expected, &pointer);
+ assertNotNull(segment, "Expected non-null result.");
+
+ parcURISegment_Release(&segment);
+ assertNull(segment, "Expected destroy to null the pointer");
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_Equals_Contract)
+{
+ char *expected = URI_PATH_SEGMENT;
+
+ const char *pointer;
+ PARCURISegment *x = parcURISegment_Parse(expected, &pointer);
+ PARCURISegment *y = parcURISegment_Parse(expected, &pointer);
+ PARCURISegment *z = parcURISegment_Parse(expected, &pointer);
+
+ parcObjectTesting_AssertEqualsFunction(parcURISegment_Equals, x, y, z, NULL);
+
+ parcURISegment_Release(&x);
+ parcURISegment_Release(&y);
+ parcURISegment_Release(&z);
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_Clone)
+{
+ char *expected = URI_PATH_SEGMENT;
+
+ const char *pointer;
+ PARCURISegment *segment = parcURISegment_Parse(expected, &pointer);
+ PARCURISegment *copy = parcURISegment_Clone(segment);
+
+ assertTrue(segment != copy, "Expected different instances of equal segments.");
+
+ int comparison = parcURISegment_Compare(segment, copy);
+ assertTrue(comparison == 0, "Expected equal segments.");
+
+ assertTrue(parcURISegment_Equals(segment, copy), "Expected equal segments");
+
+ parcURISegment_Release(&copy);
+ parcURISegment_Release(&segment);
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_Length)
+{
+ const char *pointer;
+ PARCURISegment *segment = parcURISegment_Parse(URI_PATH_SEGMENT, &pointer);
+ assertNotNull(segment,
+ "Expected non-null result.");
+ assertTrue(*pointer == 0,
+ "Expected pointer to point to the null terminating byte.");
+
+ size_t actual = parcURISegment_Length(segment);
+
+ assertTrue(actual == 39,
+ "Expected 39, actual %zd", actual);
+
+ parcURISegment_Release(&segment);
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_Compare_Contract)
+{
+ const char *pointer;
+ PARCURISegment *segment = parcURISegment_Parse("MMM", &pointer);
+
+ PARCURISegment *equivalents[] = {
+ segment,
+ parcURISegment_Parse("MMM",&pointer),
+ NULL,
+ };
+ PARCURISegment *lessers[] = {
+ parcURISegment_Parse("MM", &pointer),
+ parcURISegment_Parse("MML", &pointer),
+ NULL,
+ };
+ PARCURISegment *greaters[] = {
+ parcURISegment_Parse("MMMM", &pointer),
+ parcURISegment_Parse("MMN", &pointer),
+ NULL,
+ };
+ parcObjectTesting_AssertCompareTo(parcURISegment_Compare, segment, equivalents, lessers, greaters);
+
+ for (int i = 0; equivalents[i] != NULL; i++) {
+ parcURISegment_Release(&equivalents[i]);
+ }
+ for (int i = 0; lessers[i] != NULL; i++) {
+ parcURISegment_Release(&lessers[i]);
+ }
+ for (int i = 0; greaters[i] != NULL; i++) {
+ parcURISegment_Release(&greaters[i]);
+ }
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_ToString)
+{
+ const char *pointer;
+ PARCURISegment *segment = parcURISegment_Parse(URI_PATH_SEGMENT, &pointer);
+ assertNotNull(segment, "Expected non-null result.");
+ assertTrue(*pointer == 0, "Expected pointer to point to the null terminating byte.");
+
+ char *actual = parcURISegment_ToString(segment);
+
+ assertTrue(strcmp(URI_PATH_SEGMENT, actual) == 0, "Expected %s, actual %s", URI_PATH_SEGMENT, actual);
+
+ parcURISegment_Release(&segment);
+
+ parcMemory_Deallocate((void **) &actual);
+}
+
+LONGBOW_TEST_CASE(parcURISegment, parcURISegment_GetBuffer)
+{
+ const char *pointer;
+ PARCURISegment *segment = parcURISegment_Parse(URI_PATH_SEGMENT, &pointer);
+ assertNotNull(segment, "Expected non-null result.");
+ assertTrue(*pointer == 0, "Expected pointer to point to the null terminating byte.");
+
+ PARCBuffer *buffer = parcURISegment_GetBuffer(segment);
+
+ char *expected = URI_PATH_SEGMENT;
+ char *actual = (char *) parcBuffer_Overlay(buffer, 0);
+ size_t compareLength = strlen(URI_PATH_SEGMENT);
+ assertTrue(strncmp(expected, actual, compareLength), "Buffer does not contain original data.");
+
+ parcURISegment_Release(&segment);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parcURISegment);
+ int status = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(status);
+}
diff --git a/libparc/parc/algol/test/test_parc_Varint.c b/libparc/parc/algol/test/test_parc_Varint.c
new file mode 100755
index 00000000..cf0c865c
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Varint.c
@@ -0,0 +1,310 @@
+/*
+ * 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_Varint.c"
+
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_BufferComposer.h>
+
+LONGBOW_TEST_RUNNER(parc_VarInt)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(parc_VarInt)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_VarInt)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_And);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_AndUint16);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_AndUint32);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_AndUint64);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_AndUint8);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_AsSize);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_AsUint16);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_AsUint32);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_AsUint64);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_AsUint8);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_EqualsUint16);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_EqualsUint32);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_EqualsUint64);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_EqualsUint8);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_FromByteBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_FromUTF8ByteBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_FromUint32);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_FromUint64);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_FromUint8);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_New);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_Or);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_OrUint16);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_OrUint32);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_OrUint64);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_OrUint8);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_Set);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_ShiftLeft);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_ShiftRight);
+ LONGBOW_RUN_TEST_CASE(Global, parcVarint_ToString);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Global, parcVarint_And)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_AndUint16)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_AndUint32)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_AndUint64)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_AndUint8)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_AsSize)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_AsUint16)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_AsUint32)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_AsUint64)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_AsUint8)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_Destroy)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_Equals)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_EqualsUint16)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_EqualsUint32)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_EqualsUint64)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_EqualsUint8)
+{
+ unsigned char expected = 5;
+ PARCVarint *a = parcVarint_FromUint8(expected);
+ PARCVarint *b = parcVarint_FromUint8(expected);
+
+ assertTrue(parcVarint_Equals(a, b), "Equal instances failed to be equal.");
+ parcVarint_Destroy(&a);
+ parcVarint_Destroy(&b);
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_FromByteBuffer)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_FromUTF8ByteBuffer)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_PutString(composer, "10");
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+
+ PARCVarint *varint = parcVarint_FromUTF8ByteBuffer(buffer);
+
+ uint32_t actual = parcVarint_AsUint32(varint);
+
+ assertTrue(10 == actual, "Expected 10 actual %u", actual);
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+ parcVarint_Destroy(&varint);
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_FromUint32)
+{
+ uint32_t value = 0x12345678;
+ PARCVarint *a = parcVarint_FromUint32(value);
+ assertNotNull(a, "Probably out of memory.");
+
+ uint32_t actual = parcVarint_AsUint32(a);
+
+ assertEqual(value, actual, "%u");
+
+ parcVarint_Destroy(&a);
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_FromUint64)
+{
+ uint64_t value = 0x1234567812345678;
+ PARCVarint *a = parcVarint_FromUint64(value);
+ assertNotNull(a, "Probably out of memory.");
+
+ uint64_t actual = parcVarint_AsUint64(a);
+
+ assertEqual(value, actual, "%" PRIu64);
+
+ parcVarint_Destroy(&a);
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_FromUint8)
+{
+ uint8_t value = 0x12;
+ PARCVarint *a = parcVarint_FromUint8(value);
+ assertNotNull(a, "Probably out of memory.");
+
+ uint8_t actual = parcVarint_AsUint8(a);
+
+ assertEqual(value, actual, "%d");
+
+ parcVarint_Destroy(&a);
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_New)
+{
+ PARCVarint *a = parcVarint_Create();
+ assertNotNull(a, "Probably out of memory.");
+
+ parcVarint_Destroy(&a);
+ assertNull(a, "Destroy failed to nullify.");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_Or)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_OrUint16)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_OrUint32)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_OrUint64)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_OrUint8)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_Set)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_ShiftLeft)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_ShiftRight)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_CASE(Global, parcVarint_ToString)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_VarInt);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libparc/parc/algol/test/test_parc_Vector.c b/libparc/parc/algol/test/test_parc_Vector.c
new file mode 100644
index 00000000..bea435dc
--- /dev/null
+++ b/libparc/parc/algol/test/test_parc_Vector.c
@@ -0,0 +1,116 @@
+/*
+ * 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 <LongBow/unit-test.h>
+#include <LongBow/debugging.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+#include "../parc_Vector.c"
+
+LONGBOW_TEST_RUNNER(PARCVector)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(PARCVector)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(PARCVector)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("Tests leak memory by %d allocations\n", outstandingAllocations);
+ exit(1);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, parcVectorDestroy);
+ LONGBOW_RUN_TEST_CASE(Global, parcVectorGetLength);
+ LONGBOW_RUN_TEST_CASE(Global, parcVectorGetPointer);
+ LONGBOW_RUN_TEST_CASE(Global, parcVectorCreate);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDOUT_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(Global, parcVectorDestroy)
+{
+ const char *string = "Hello World";
+
+ PARCVector *x = parcVector_Create((void *) string, strlen(string));
+ parcVector_Destroy(&x);
+ assertNull(x, "Destroy did not nullify.");
+}
+
+LONGBOW_TEST_CASE(Global, parcVectorGetLength)
+{
+ const char *string = "Hello World";
+
+ PARCVector *x = parcVector_Create((void *) string, strlen(string));
+ size_t expected = strlen(string);
+ size_t actual = parcVector_GetLength(x);
+ assertEqual(expected, actual, "%zd");
+ parcVector_Destroy(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcVectorGetPointer)
+{
+ const char *expected = "Hello World";
+
+ PARCVector *x = parcVector_Create((void *) expected, strlen(expected));
+ const char *actual = parcVector_GetPointer(x);
+
+ assertEqual((void *) expected, (void *) actual, "%p");
+
+ parcVector_Destroy(&x);
+}
+
+LONGBOW_TEST_CASE(Global, parcVectorCreate)
+{
+ const char *string = "Hello World";
+
+ PARCVector *x = parcVector_Create((void *) string, strlen(string));
+ assertNotNull(x, "Probably out of memory.");
+ parcVector_Destroy(&x);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(PARCVector);
+ int status = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(status);
+}