summaryrefslogtreecommitdiff
path: root/3rdparty/plibsys/tests
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2022-08-27 23:52:56 -0500
committersanine <sanine.not@pm.me>2022-08-27 23:52:56 -0500
commita4dd0ad63c00f4dee3b86dfd3075d1d61b2b3180 (patch)
tree13bd5bfa15e6fea2a12f176bae79adf9c6fd0933 /3rdparty/plibsys/tests
parentbde3e4f1bb7b8f8abca0884a7d994ee1c17a66b1 (diff)
add plibsys
Diffstat (limited to '3rdparty/plibsys/tests')
-rw-r--r--3rdparty/plibsys/tests/CMakeLists.txt96
-rw-r--r--3rdparty/plibsys/tests/patomic_test.cpp118
-rw-r--r--3rdparty/plibsys/tests/pcondvariable_test.cpp230
-rw-r--r--3rdparty/plibsys/tests/pcryptohash_test.cpp662
-rw-r--r--3rdparty/plibsys/tests/pdir_test.cpp248
-rw-r--r--3rdparty/plibsys/tests/perror_test.cpp236
-rw-r--r--3rdparty/plibsys/tests/pfile_test.cpp61
-rw-r--r--3rdparty/plibsys/tests/phashtable_test.cpp320
-rw-r--r--3rdparty/plibsys/tests/pinifile_test.cpp357
-rw-r--r--3rdparty/plibsys/tests/plibraryloader_test.cpp179
-rw-r--r--3rdparty/plibsys/tests/plist_test.cpp200
-rw-r--r--3rdparty/plibsys/tests/pmacros_test.cpp646
-rw-r--r--3rdparty/plibsys/tests/pmain_test.cpp111
-rw-r--r--3rdparty/plibsys/tests/pmem_test.cpp171
-rw-r--r--3rdparty/plibsys/tests/pmutex_test.cpp146
-rw-r--r--3rdparty/plibsys/tests/pprocess_test.cpp49
-rw-r--r--3rdparty/plibsys/tests/prwlock_test.cpp224
-rw-r--r--3rdparty/plibsys/tests/psemaphore_test.cpp226
-rw-r--r--3rdparty/plibsys/tests/pshm_test.cpp313
-rw-r--r--3rdparty/plibsys/tests/pshmbuffer_test.cpp352
-rw-r--r--3rdparty/plibsys/tests/psocket_test.cpp1131
-rw-r--r--3rdparty/plibsys/tests/psocketaddress_test.cpp338
-rw-r--r--3rdparty/plibsys/tests/pspinlock_test.cpp148
-rw-r--r--3rdparty/plibsys/tests/pstdarg_test.cpp205
-rw-r--r--3rdparty/plibsys/tests/pstring_test.cpp289
-rw-r--r--3rdparty/plibsys/tests/ptestmacros.h131
-rw-r--r--3rdparty/plibsys/tests/ptimeprofiler_test.cpp126
-rw-r--r--3rdparty/plibsys/tests/ptree_test.cpp633
-rw-r--r--3rdparty/plibsys/tests/ptypes_test.cpp456
-rw-r--r--3rdparty/plibsys/tests/puthread_test.cpp481
30 files changed, 8883 insertions, 0 deletions
diff --git a/3rdparty/plibsys/tests/CMakeLists.txt b/3rdparty/plibsys/tests/CMakeLists.txt
new file mode 100644
index 0000000..54f747b
--- /dev/null
+++ b/3rdparty/plibsys/tests/CMakeLists.txt
@@ -0,0 +1,96 @@
+# The MIT License
+#
+# Copyright (C) 2018 Alexander Saprykin <saprykin.spb@gmail.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+project (tests CXX)
+set (OUTPUT_DIR ${CMAKE_BINARY_DIR})
+
+include (${PROJECT_SOURCE_DIR}/../cmake/PlatformDetect.cmake)
+plibsys_detect_target_os (PLIBSYS_TESTS_TARGET_OS)
+
+list (APPEND PLIBSYS_TEST_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/../src ${CMAKE_BINARY_DIR})
+
+if (MSVC)
+ list (APPEND PLIBSYS_TEST_COMPILE_DEFS -D_CRT_SECURE_NO_WARNINGS)
+endif()
+
+macro (plibsys_add_test_executable TEST_NAME SRC_FILE)
+ add_executable (${TEST_NAME} ${SRC_FILE})
+ target_link_libraries (${TEST_NAME} plibsys)
+ set_target_properties (${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
+
+ # QNX requires libm for sqrt() and friends
+ if (PLIBSYS_TESTS_TARGET_OS STREQUAL qnx)
+ target_link_libraries (${TEST_NAME} m)
+ endif()
+
+ # Add include directories
+ if (COMMAND target_include_directories)
+ target_include_directories (${TEST_NAME} PUBLIC ${PLIBSYS_TEST_INCLUDE_DIRS})
+ else()
+ include_directories (${PLIBSYS_TEST_INCLUDE_DIRS})
+ endif()
+
+ # Add compile definitions
+ if (PLIBSYS_TEST_COMPILE_DEFS)
+ if (COMMAND target_compile_definitions)
+ target_compile_definitions (${TEST_NAME} PRIVATE ${PLIBSYS_TEST_COMPILE_DEFS})
+ else()
+ add_definitions (${PLIBSYS_TEST_COMPILE_DEFS})
+ endif()
+ endif()
+
+ if (${TEST_NAME} STREQUAL "plibraryloader_test")
+ add_test (NAME ${TEST_NAME} COMMAND ${TEST_NAME} -- "$<TARGET_FILE:plibsys>")
+ else()
+ add_test (NAME ${TEST_NAME} COMMAND ${TEST_NAME})
+ endif()
+endmacro()
+
+plibsys_add_test_executable (patomic_test patomic_test.cpp)
+plibsys_add_test_executable (pcondvariable_test pcondvariable_test.cpp)
+plibsys_add_test_executable (pcryptohash_test pcryptohash_test.cpp)
+plibsys_add_test_executable (perror_test perror_test.cpp)
+plibsys_add_test_executable (pdir_test pdir_test.cpp)
+plibsys_add_test_executable (pfile_test pfile_test.cpp)
+plibsys_add_test_executable (phashtable_test phashtable_test.cpp)
+plibsys_add_test_executable (pinifile_test pinifile_test.cpp)
+plibsys_add_test_executable (plibraryloader_test plibraryloader_test.cpp)
+plibsys_add_test_executable (plist_test plist_test.cpp)
+plibsys_add_test_executable (pmacros_test pmacros_test.cpp)
+plibsys_add_test_executable (pmain_test pmain_test.cpp)
+plibsys_add_test_executable (pmem_test pmem_test.cpp)
+plibsys_add_test_executable (pmutex_test pmutex_test.cpp)
+plibsys_add_test_executable (pprocess_test pprocess_test.cpp)
+plibsys_add_test_executable (prwlock_test prwlock_test.cpp)
+plibsys_add_test_executable (psemaphore_test psemaphore_test.cpp)
+plibsys_add_test_executable (pshmbuffer_test pshmbuffer_test.cpp)
+plibsys_add_test_executable (pshm_test pshm_test.cpp)
+plibsys_add_test_executable (psocket_test psocket_test.cpp)
+plibsys_add_test_executable (psocketaddress_test psocketaddress_test.cpp)
+plibsys_add_test_executable (pspinlock_test pspinlock_test.cpp)
+plibsys_add_test_executable (pstdarg_test pstdarg_test.cpp)
+plibsys_add_test_executable (pstring_test pstring_test.cpp)
+plibsys_add_test_executable (ptimeprofiler_test ptimeprofiler_test.cpp)
+plibsys_add_test_executable (ptree_test ptree_test.cpp)
+plibsys_add_test_executable (ptypes_test ptypes_test.cpp)
+plibsys_add_test_executable (puthread_test puthread_test.cpp)
diff --git a/3rdparty/plibsys/tests/patomic_test.cpp b/3rdparty/plibsys/tests/patomic_test.cpp
new file mode 100644
index 0000000..6efb2d4
--- /dev/null
+++ b/3rdparty/plibsys/tests/patomic_test.cpp
@@ -0,0 +1,118 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+/* Actually we couldn't test the work of the atomic operations across the
+ * threads, but at least we can test the sanity of operations */
+
+P_TEST_MODULE_INIT ();
+
+P_TEST_CASE_BEGIN (patomic_general_test)
+{
+ p_libsys_init ();
+
+ (void) p_atomic_is_lock_free ();
+
+ pint atomic_int = 0;
+ p_atomic_int_set (&atomic_int, 10);
+
+ P_TEST_CHECK (p_atomic_int_add (&atomic_int, 5) == 10);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == 15);
+
+ p_atomic_int_add (&atomic_int, -5);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == 10);
+
+ p_atomic_int_inc (&atomic_int);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == 11);
+
+ P_TEST_CHECK (p_atomic_int_dec_and_test (&atomic_int) == FALSE);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == 10);
+
+ P_TEST_CHECK (p_atomic_int_compare_and_exchange (&atomic_int, 10, -10) == TRUE);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == -10);
+ P_TEST_CHECK (p_atomic_int_compare_and_exchange (&atomic_int, 10, 20) == FALSE);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == -10);
+
+ p_atomic_int_inc (&atomic_int);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == -9);
+
+ p_atomic_int_set (&atomic_int, 4);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == 4);
+
+ P_TEST_CHECK (p_atomic_int_xor ((puint *) &atomic_int, (puint) 1) == 4);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == 5);
+
+ P_TEST_CHECK (p_atomic_int_or ((puint *) &atomic_int, (puint) 2) == 5);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == 7);
+
+ P_TEST_CHECK (p_atomic_int_and ((puint *) &atomic_int, (puint) 1) == 7);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == 1);
+
+ p_atomic_int_set (&atomic_int, 51);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == 51);
+
+ for (pint i = 51; i > 1; --i) {
+ P_TEST_CHECK (p_atomic_int_dec_and_test (&atomic_int) == FALSE);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == (i - 1));
+ }
+
+ P_TEST_CHECK (p_atomic_int_dec_and_test (&atomic_int) == TRUE);
+ P_TEST_CHECK (p_atomic_int_get (&atomic_int) == 0);
+
+ ppointer atomic_pointer = NULL;
+ p_atomic_pointer_set (&atomic_pointer, PUINT_TO_POINTER (P_MAXSIZE));
+ P_TEST_CHECK (p_atomic_pointer_get (&atomic_pointer) == PUINT_TO_POINTER (P_MAXSIZE));
+
+ p_atomic_pointer_set (&atomic_pointer, PUINT_TO_POINTER (100));
+ P_TEST_CHECK (p_atomic_pointer_get (&atomic_pointer) == PUINT_TO_POINTER (100));
+ P_TEST_CHECK (p_atomic_pointer_add (&atomic_pointer, (pssize) 100) == 100);
+ P_TEST_CHECK (p_atomic_pointer_get (&atomic_pointer) == PUINT_TO_POINTER (200));
+
+ p_atomic_pointer_set (&atomic_pointer, PINT_TO_POINTER (4));
+ P_TEST_CHECK (p_atomic_pointer_get (&atomic_pointer) == PINT_TO_POINTER (4));
+
+ P_TEST_CHECK (p_atomic_pointer_xor (&atomic_pointer, (psize) 1) == 4);
+ P_TEST_CHECK (p_atomic_pointer_get (&atomic_pointer) == PINT_TO_POINTER (5));
+
+ P_TEST_CHECK (p_atomic_pointer_or (&atomic_pointer, (psize) 2) == 5);
+ P_TEST_CHECK (p_atomic_pointer_get (&atomic_pointer) == PINT_TO_POINTER (7));
+
+ P_TEST_CHECK (p_atomic_pointer_and (&atomic_pointer, (psize) 1) == 7);
+ P_TEST_CHECK (p_atomic_pointer_get (&atomic_pointer) == PINT_TO_POINTER (1));
+
+ P_TEST_CHECK (p_atomic_pointer_compare_and_exchange (&atomic_pointer, PUINT_TO_POINTER (1), NULL) == TRUE);
+ P_TEST_CHECK (p_atomic_pointer_get (&atomic_pointer) == NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (patomic_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pcondvariable_test.cpp b/3rdparty/plibsys/tests/pcondvariable_test.cpp
new file mode 100644
index 0000000..887b77f
--- /dev/null
+++ b/3rdparty/plibsys/tests/pcondvariable_test.cpp
@@ -0,0 +1,230 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2019 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+P_TEST_MODULE_INIT ();
+
+#define PCONDTEST_MAX_QUEUE 10
+
+static pint thread_wakeups = 0;
+static pint thread_queue = 0;
+static PCondVariable * queue_empty_cond = NULL;
+static PCondVariable * queue_full_cond = NULL;
+static PMutex * cond_mutex = NULL;
+volatile static pboolean is_working = TRUE;
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+static void * producer_test_thread (void *)
+{
+ while (is_working == TRUE) {
+ if (!p_mutex_lock (cond_mutex)) {
+ is_working = FALSE;
+ p_cond_variable_broadcast (queue_full_cond);
+ p_uthread_exit (1);
+ }
+
+ while (thread_queue >= PCONDTEST_MAX_QUEUE && is_working == TRUE) {
+ if (!p_cond_variable_wait (queue_empty_cond, cond_mutex)) {
+ is_working = FALSE;
+ p_cond_variable_broadcast (queue_full_cond);
+ p_mutex_unlock (cond_mutex);
+ p_uthread_exit (1);
+ }
+ }
+
+ if (is_working) {
+ ++thread_queue;
+ ++thread_wakeups;
+ }
+
+ if (!p_cond_variable_broadcast (queue_full_cond)) {
+ is_working = FALSE;
+ p_mutex_unlock (cond_mutex);
+ p_uthread_exit (1);
+ }
+
+ if (!p_mutex_unlock (cond_mutex)) {
+ is_working = FALSE;
+ p_cond_variable_broadcast (queue_full_cond);
+ p_uthread_exit (1);
+ }
+ }
+
+ p_cond_variable_broadcast (queue_full_cond);
+ p_uthread_exit (0);
+
+ return NULL;
+}
+
+static void * consumer_test_thread (void *)
+{
+ while (is_working == TRUE) {
+ if (!p_mutex_lock (cond_mutex)) {
+ is_working = FALSE;
+ p_cond_variable_signal (queue_empty_cond);
+ p_uthread_exit (1);
+ }
+
+ while (thread_queue <= 0 && is_working == TRUE) {
+ if (!p_cond_variable_wait (queue_full_cond, cond_mutex)) {
+ is_working = FALSE;
+ p_cond_variable_signal (queue_empty_cond);
+ p_mutex_unlock (cond_mutex);
+ p_uthread_exit (1);
+ }
+ }
+
+ if (is_working) {
+ --thread_queue;
+ ++thread_wakeups;
+ }
+
+ if (!p_cond_variable_signal (queue_empty_cond)) {
+ is_working = FALSE;
+ p_mutex_unlock (cond_mutex);
+ p_uthread_exit (1);
+ }
+
+ if (!p_mutex_unlock (cond_mutex)) {
+ is_working = FALSE;
+ p_cond_variable_signal (queue_empty_cond);
+ p_uthread_exit (1);
+ }
+ }
+
+ p_cond_variable_signal (queue_empty_cond);
+ p_uthread_exit (0);
+
+ return NULL;
+}
+
+P_TEST_CASE_BEGIN (pcondvariable_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+ P_TEST_CHECK (p_cond_variable_new () == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pcondvariable_bad_input_test)
+{
+ p_libsys_init ();
+
+ P_TEST_REQUIRE (p_cond_variable_broadcast (NULL) == FALSE);
+ P_TEST_REQUIRE (p_cond_variable_signal (NULL) == FALSE);
+ P_TEST_REQUIRE (p_cond_variable_wait (NULL, NULL) == FALSE);
+ p_cond_variable_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pcondvariable_general_test)
+{
+ PUThread *thr1, *thr2, *thr3;
+
+ p_libsys_init ();
+
+ queue_empty_cond = p_cond_variable_new ();
+ P_TEST_REQUIRE (queue_empty_cond != NULL);
+ queue_full_cond = p_cond_variable_new ();
+ P_TEST_REQUIRE (queue_full_cond != NULL);
+ cond_mutex = p_mutex_new ();
+ P_TEST_REQUIRE (cond_mutex != NULL);
+
+ is_working = TRUE;
+ thread_wakeups = 0;
+ thread_queue = 0;
+
+ thr1 = p_uthread_create ((PUThreadFunc) producer_test_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr1 != NULL);
+
+ thr2 = p_uthread_create ((PUThreadFunc) consumer_test_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr2 != NULL);
+
+ thr3 = p_uthread_create ((PUThreadFunc) consumer_test_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr3 != NULL);
+
+ P_TEST_REQUIRE (p_cond_variable_broadcast (queue_empty_cond) == TRUE);
+ P_TEST_REQUIRE (p_cond_variable_broadcast (queue_full_cond) == TRUE);
+
+ p_uthread_sleep (4000);
+
+ is_working = FALSE;
+
+ P_TEST_CHECK (p_uthread_join (thr1) == 0);
+ P_TEST_CHECK (p_uthread_join (thr2) == 0);
+ P_TEST_CHECK (p_uthread_join (thr3) == 0);
+
+ P_TEST_REQUIRE (thread_wakeups > 0 && thread_queue >= 0 && thread_queue <= 10);
+
+ p_uthread_unref (thr1);
+ p_uthread_unref (thr2);
+ p_uthread_unref (thr3);
+ p_cond_variable_free (queue_empty_cond);
+ p_cond_variable_free (queue_full_cond);
+ p_mutex_free (cond_mutex);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pcondvariable_nomem_test);
+ P_TEST_SUITE_RUN_CASE (pcondvariable_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (pcondvariable_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pcryptohash_test.cpp b/3rdparty/plibsys/tests/pcryptohash_test.cpp
new file mode 100644
index 0000000..30c1f91
--- /dev/null
+++ b/3rdparty/plibsys/tests/pcryptohash_test.cpp
@@ -0,0 +1,662 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <string.h>
+
+P_TEST_MODULE_INIT ();
+
+#define PCRYPTO_STRESS_LENGTH 10000
+#define PCRYPTO_MAX_UPDATES 1000000
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+static void
+general_hash_test (PCryptoHashType type,
+ psize hash_len,
+ const pchar *msg1,
+ const pchar *msg2,
+ const puchar *etalon1,
+ const puchar *etalon2,
+ const puchar *etalon3,
+ const pchar *hash1,
+ const pchar *hash2,
+ const pchar *hash3,
+ const pchar *hash_stress)
+{
+ PCryptoHash *crypto_hash;
+ psize dig_len;
+ pchar *hash_str;
+ pchar *long_str;
+ puchar *hash_dig;
+
+ crypto_hash = p_crypto_hash_new (type);
+
+ P_TEST_REQUIRE ((psize) p_crypto_hash_get_length (crypto_hash) == hash_len);
+ P_TEST_REQUIRE (p_crypto_hash_get_type (crypto_hash) == type);
+
+ hash_str = p_crypto_hash_get_string (crypto_hash);
+ P_TEST_REQUIRE (hash_str != NULL);
+ p_crypto_hash_reset (crypto_hash);
+ p_free (hash_str);
+
+ hash_dig = (puchar *) p_malloc0 (hash_len);
+ P_TEST_REQUIRE (hash_dig != NULL);
+
+ long_str = (pchar *) p_malloc0 (PCRYPTO_STRESS_LENGTH);
+ P_TEST_REQUIRE (long_str != NULL);
+
+ for (int i = 0; i < PCRYPTO_STRESS_LENGTH; ++i)
+ long_str[i] = (pchar) (97 + i % 20);
+
+ /* Case 1 */
+
+ /* Check string */
+ p_crypto_hash_update (crypto_hash, (const puchar *) msg1, strlen (msg1));
+ hash_str = p_crypto_hash_get_string (crypto_hash);
+ P_TEST_CHECK (strcmp (hash_str, hash1) == 0);
+ p_free (hash_str);
+
+ p_crypto_hash_reset (crypto_hash);
+
+ /* Check digest */
+ dig_len = hash_len;
+ p_crypto_hash_update (crypto_hash, (const puchar *) msg1, strlen (msg1));
+ p_crypto_hash_get_digest (crypto_hash, hash_dig, &dig_len);
+
+ P_TEST_CHECK (dig_len == hash_len);
+
+ for (unsigned int i = 0; i < hash_len; ++i)
+ P_TEST_CHECK (hash_dig[i] == etalon1[i]);
+
+ p_crypto_hash_reset (crypto_hash);
+
+ /* Case 2 */
+
+ /* Check string */
+ p_crypto_hash_update (crypto_hash, (const puchar *) msg2, strlen (msg2));
+ hash_str = p_crypto_hash_get_string (crypto_hash);
+ P_TEST_CHECK (strcmp (hash_str, hash2) == 0);
+ p_free (hash_str);
+
+ p_crypto_hash_reset (crypto_hash);
+
+ /* Check digest */
+ dig_len = hash_len;
+ p_crypto_hash_update (crypto_hash, (const puchar *) msg2, strlen (msg2));
+ p_crypto_hash_get_digest (crypto_hash, hash_dig, &dig_len);
+
+ P_TEST_CHECK (dig_len == hash_len);
+
+ for (unsigned int i = 0; i < hash_len; ++i)
+ P_TEST_CHECK (hash_dig[i] == etalon2[i]);
+
+ p_crypto_hash_reset (crypto_hash);
+
+ /* Case 3 */
+
+ /* Check string */
+ for (int i = 0; i < PCRYPTO_MAX_UPDATES; ++i)
+ p_crypto_hash_update (crypto_hash, (const puchar *) "a", 1);
+
+ hash_str = p_crypto_hash_get_string (crypto_hash);
+
+ P_TEST_CHECK (strcmp (hash_str, hash3) == 0);
+ p_free (hash_str);
+
+ p_crypto_hash_reset (crypto_hash);
+
+ /* Check digest */
+ dig_len = hash_len;
+ for (int i = 0; i < PCRYPTO_MAX_UPDATES; ++i)
+ p_crypto_hash_update (crypto_hash, (const puchar *) "a", 1);
+
+ p_crypto_hash_get_digest (crypto_hash, hash_dig, &dig_len);
+ P_TEST_CHECK (dig_len == hash_len);
+
+ for (unsigned int i = 0; i < hash_len; ++i)
+ P_TEST_CHECK (hash_dig[i] == etalon3[i]);
+
+ p_crypto_hash_reset (crypto_hash);
+
+ /* Stress test */
+ p_crypto_hash_update (crypto_hash, (const puchar *) long_str, PCRYPTO_STRESS_LENGTH);
+ hash_str = p_crypto_hash_get_string (crypto_hash);
+
+ P_TEST_CHECK (strcmp (hash_str, hash_stress) == 0);
+ p_free (hash_str);
+
+ p_crypto_hash_reset (crypto_hash);
+
+ p_free (long_str);
+ p_free (hash_dig);
+ p_crypto_hash_free (crypto_hash);
+}
+
+P_TEST_CASE_BEGIN (pcryptohash_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_crypto_hash_new (P_CRYPTO_HASH_TYPE_MD5) == NULL);
+ P_TEST_CHECK (p_crypto_hash_new (P_CRYPTO_HASH_TYPE_SHA1) == NULL);
+ P_TEST_CHECK (p_crypto_hash_new (P_CRYPTO_HASH_TYPE_GOST) == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pcryptohash_invalid_test)
+{
+ PCryptoHash *hash;
+ psize len;
+ pssize md5_len;
+ pchar *hash_str;
+ puchar *buf;
+
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_crypto_hash_new ((PCryptoHashType) -1) == NULL);
+ P_TEST_CHECK (p_crypto_hash_get_length (NULL) == 0);
+ P_TEST_CHECK (p_crypto_hash_get_string (NULL) == NULL);
+ P_TEST_CHECK ((pint) p_crypto_hash_get_type (NULL) == -1);
+ p_crypto_hash_free (NULL);
+
+ p_crypto_hash_update (NULL, NULL, 0);
+ p_crypto_hash_get_digest (NULL, NULL, NULL);
+
+ p_crypto_hash_get_digest (NULL, NULL, &len);
+ P_TEST_CHECK (len == 0);
+
+ p_crypto_hash_reset (NULL);
+
+ hash = p_crypto_hash_new (P_CRYPTO_HASH_TYPE_MD5);
+ P_TEST_CHECK (hash != NULL);
+
+ md5_len = p_crypto_hash_get_length (hash);
+ P_TEST_CHECK (md5_len > 0);
+
+ buf = (puchar *) p_malloc0 (md5_len);
+ P_TEST_CHECK (buf != NULL);
+
+ p_crypto_hash_get_digest (hash, buf, &len);
+ P_TEST_CHECK (len == 0);
+
+ p_crypto_hash_update (hash, (const puchar *) ("abc"), 3);
+ len = ((psize) md5_len) - 1;
+ p_crypto_hash_get_digest (hash, buf, &len);
+ P_TEST_CHECK (len == 0);
+
+ hash_str = p_crypto_hash_get_string (hash);
+ P_TEST_CHECK (strcmp (hash_str, "900150983cd24fb0d6963f7d28e17f72") == 0);
+ p_free (hash_str);
+
+ p_crypto_hash_update (hash, (const puchar *) ("abc"), 3);
+ hash_str = p_crypto_hash_get_string (hash);
+ P_TEST_CHECK (strcmp (hash_str, "900150983cd24fb0d6963f7d28e17f72") == 0);
+ p_free (hash_str);
+
+ p_crypto_hash_free (hash);
+ p_free (buf);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (md5_test)
+{
+ const puchar hash_etalon_1[] = {144, 1, 80, 152, 60, 210, 79, 176,
+ 214, 150, 63, 125, 40, 225, 127, 114};
+ const puchar hash_etalon_2[] = {130, 21, 239, 7, 150, 162, 11, 202,
+ 170, 225, 22, 211, 135, 108, 102, 74};
+ const puchar hash_etalon_3[] = {119, 7, 214, 174, 78, 2, 124, 112,
+ 238, 162, 169, 53, 194, 41, 111, 33};
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_MD5,
+ 16,
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "900150983cd24fb0d6963f7d28e17f72",
+ "8215ef0796a20bcaaae116d3876c664a",
+ "7707d6ae4e027c70eea2a935c2296f21",
+ "e19ea4a77c97fa6c2521ae1ca66982b9");
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (sha1_test)
+{
+ const puchar hash_etalon_1[] = {169, 153, 62, 54, 71, 6, 129, 106,
+ 186, 62, 37, 113, 120, 80, 194, 108,
+ 156, 208, 216, 157};
+ const puchar hash_etalon_2[] = {132, 152, 62, 68, 28, 59, 210, 110,
+ 186, 174, 74, 161, 249, 81, 41, 229,
+ 229, 70, 112, 241};
+ const puchar hash_etalon_3[] = { 52, 170, 151, 60, 212, 196, 218, 164,
+ 246, 30, 235, 43, 219, 173, 39, 49,
+ 101, 52, 1, 111};
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_SHA1,
+ 20,
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "a9993e364706816aba3e25717850c26c9cd0d89d",
+ "84983e441c3bd26ebaae4aa1f95129e5e54670f1",
+ "34aa973cd4c4daa4f61eeb2bdbad27316534016f",
+ "56309c2dbe04a348ec801ca5f40b035bad01f907");
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (sha2_224_test)
+{
+ const puchar hash_etalon_1[] = { 35, 9, 125, 34, 52, 5, 216, 34, 134, 66,
+ 164, 119, 189, 162, 85, 179, 42, 173, 188, 228,
+ 189, 160, 179, 247, 227, 108, 157, 167};
+ const puchar hash_etalon_2[] = {117, 56, 139, 22, 81, 39, 118, 204, 93, 186,
+ 93, 161, 253, 137, 1, 80, 176, 198, 69, 92,
+ 180, 245, 139, 25, 82, 82, 37, 37};
+ const puchar hash_etalon_3[] = { 32, 121, 70, 85, 152, 12, 145, 216, 187, 180,
+ 193, 234, 151, 97, 138, 75, 240, 63, 66, 88,
+ 25, 72, 178, 238, 78, 231, 173, 103, };
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_SHA2_224,
+ 28,
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
+ "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525",
+ "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67",
+ "4cf3d45b57e0d54981c4d86954e8378168d5a9f6ceab9e0aae5dd2f6");
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (sha2_256_test)
+{
+ const puchar hash_etalon_1[] = {186, 120, 22, 191, 143, 1, 207, 234,
+ 65, 65, 64, 222, 93, 174, 34, 35,
+ 176, 3, 97, 163, 150, 23, 122, 156,
+ 180, 16, 255, 97, 242, 0, 21, 173};
+ const puchar hash_etalon_2[] = { 36, 141, 106, 97, 210, 6, 56, 184,
+ 229, 192, 38, 147, 12, 62, 96, 57,
+ 163, 60, 228, 89, 100, 255, 33, 103,
+ 246, 236, 237, 212, 25, 219, 6, 193};
+ const puchar hash_etalon_3[] = {205, 199, 110, 92, 153, 20, 251, 146,
+ 129, 161, 199, 226, 132, 215, 62, 103,
+ 241, 128, 154, 72, 164, 151, 32, 14,
+ 4, 109, 57, 204, 199, 17, 44, 208};
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_SHA2_256,
+ 32,
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
+ "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0",
+ "4c2d7749e1b711ca652fda20dd29fe378fd9988f19eadadfa570682e2c55349f");
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (sha2_384_test)
+{
+ const puchar hash_etalon_1[] = {203, 0, 117, 63, 69, 163, 94, 139, 181, 160, 61, 105,
+ 154, 198, 80, 7, 39, 44, 50, 171, 14, 222, 209, 99,
+ 26, 139, 96, 90, 67, 255, 91, 237, 128, 134, 7, 43,
+ 161, 231, 204, 35, 88, 186, 236, 161, 52, 200, 37, 167};
+ const puchar hash_etalon_2[] = { 51, 145, 253, 221, 252, 141, 199, 57, 55, 7, 166, 91,
+ 27, 71, 9, 57, 124, 248, 177, 209, 98, 175, 5, 171,
+ 254, 143, 69, 13, 229, 243, 107, 198, 176, 69, 90, 133,
+ 32, 188, 78, 111, 95, 233, 91, 31, 227, 200, 69, 43};
+ const puchar hash_etalon_3[] = {157, 14, 24, 9, 113, 100, 116, 203, 8, 110, 131, 78,
+ 49, 10, 74, 28, 237, 20, 158, 156, 0, 242, 72, 82,
+ 121, 114, 206, 197, 112, 76, 42, 91, 7, 184, 179, 220,
+ 56, 236, 196, 235, 174, 151, 221, 216, 127, 61, 137, 133};
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_SHA2_384,
+ 48,
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7",
+ "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b",
+ "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985",
+ "533e016fd92dd8a8c339328bb5401c3e700e27cd72d8230059e1d4583a506fe8187607bf899a86961af2bf5521b359eb");
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (sha2_512_test)
+{
+ const puchar hash_etalon_1[] = {221, 175, 53, 161, 147, 97, 122, 186,
+ 204, 65, 115, 73, 174, 32, 65, 49,
+ 18, 230, 250, 78, 137, 169, 126, 162,
+ 10, 158, 238, 230, 75, 85, 211, 154,
+ 33, 146, 153, 42, 39, 79, 193, 168,
+ 54, 186, 60, 35, 163, 254, 235, 189,
+ 69, 77, 68, 35, 100, 60, 232, 14,
+ 42, 154, 201, 79, 165, 76, 164, 159};
+ const puchar hash_etalon_2[] = { 32, 74, 143, 198, 221, 168, 47, 10,
+ 12, 237, 123, 235, 142, 8, 164, 22,
+ 87, 193, 110, 244, 104, 178, 40, 168,
+ 39, 155, 227, 49, 167, 3, 195, 53,
+ 150, 253, 21, 193, 59, 27, 7, 249,
+ 170, 29, 59, 234, 87, 120, 156, 160,
+ 49, 173, 133, 199, 167, 29, 215, 3,
+ 84, 236, 99, 18, 56, 202, 52, 69};
+ const puchar hash_etalon_3[] = {231, 24, 72, 61, 12, 231, 105, 100,
+ 78, 46, 66, 199, 188, 21, 180, 99,
+ 142, 31, 152, 177, 59, 32, 68, 40,
+ 86, 50, 168, 3, 175, 169, 115, 235,
+ 222, 15, 242, 68, 135, 126, 166, 10,
+ 76, 176, 67, 44, 229, 119, 195, 27,
+ 235, 0, 156, 92, 44, 73, 170, 46,
+ 78, 173, 178, 23, 173, 140, 192, 155};
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_SHA2_512,
+ 64,
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
+ "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445",
+ "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b",
+ "411525772d02eef0e2ce1107d89b79b8cf6d704e88d4509f726c963d411df6df178c1c9473718f70b0e06c2fda6a9c25f6c91a925849f372634d5f63e6047a20");
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (sha3_224_test)
+{
+ const puchar hash_etalon_1[] = {230, 66, 130, 76, 63, 140, 242, 74, 208, 146,
+ 52, 238, 125, 60, 118, 111, 201, 163, 165, 22,
+ 141, 12, 148, 173, 115, 180, 111, 223};
+ const puchar hash_etalon_2[] = {138, 36, 16, 139, 21, 74, 218, 33, 201, 253,
+ 85, 116, 73, 68, 121, 186, 92, 126, 122, 183,
+ 110, 242, 100, 234, 208, 252, 206, 51};
+ const puchar hash_etalon_3[] = {214, 147, 53, 185, 51, 37, 25, 46, 81, 106,
+ 145, 46, 109, 25, 161, 92, 181, 28, 110, 213,
+ 193, 82, 67, 231, 167, 253, 101, 60};
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_SHA3_224,
+ 28,
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf",
+ "8a24108b154ada21c9fd5574494479ba5c7e7ab76ef264ead0fcce33",
+ "d69335b93325192e516a912e6d19a15cb51c6ed5c15243e7a7fd653c",
+ "425fbad801bf675651dcf61af1138831480b562e714c70a2a0050ad3");
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (sha3_256_test)
+{
+ const puchar hash_etalon_1[] = { 58, 152, 93, 167, 79, 226, 37, 178,
+ 4, 92, 23, 45, 107, 211, 144, 189,
+ 133, 95, 8, 110, 62, 157, 82, 91,
+ 70, 191, 226, 69, 17, 67, 21, 50};
+ const puchar hash_etalon_2[] = { 65, 192, 219, 162, 169, 214, 36, 8,
+ 73, 16, 3, 118, 168, 35, 94, 44,
+ 130, 225, 185, 153, 138, 153, 158, 33,
+ 219, 50, 221, 151, 73, 109, 51, 118};
+ const puchar hash_etalon_3[] = { 92, 136, 117, 174, 71, 74, 54, 52,
+ 186, 79, 213, 94, 200, 91, 255, 214,
+ 97, 243, 42, 202, 117, 198, 214, 153,
+ 208, 205, 203, 108, 17, 88, 145, 193};
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_SHA3_256,
+ 32,
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532",
+ "41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376",
+ "5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1",
+ "e37ed9f31da3d61740e04c3124a2da5dbe8be0a2ef5c8b5932d45eb1958219e2");
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (sha3_384_test)
+{
+ const puchar hash_etalon_1[] = {236, 1, 73, 130, 136, 81, 111, 201, 38, 69, 159, 88,
+ 226, 198, 173, 141, 249, 180, 115, 203, 15, 192, 140, 37,
+ 150, 218, 124, 240, 228, 155, 228, 178, 152, 216, 140, 234,
+ 146, 122, 199, 245, 57, 241, 237, 242, 40, 55, 109, 37};
+ const puchar hash_etalon_2[] = {153, 28, 102, 87, 85, 235, 58, 75, 107, 189, 251, 117,
+ 199, 138, 73, 46, 140, 86, 162, 44, 92, 77, 126, 66,
+ 155, 253, 188, 50, 185, 212, 173, 90, 160, 74, 31, 7,
+ 110, 98, 254, 161, 158, 239, 81, 172, 208, 101, 124, 34};
+ const puchar hash_etalon_3[] = {238, 233, 226, 77, 120, 193, 133, 83, 55, 152, 52, 81,
+ 223, 151, 200, 173, 158, 237, 242, 86, 198, 51, 79, 142,
+ 148, 141, 37, 45, 94, 14, 118, 132, 122, 160, 119, 77,
+ 219, 144, 168, 66, 25, 13, 44, 85, 139, 75, 131, 64};
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_SHA3_384,
+ 48,
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25",
+ "991c665755eb3a4b6bbdfb75c78a492e8c56a22c5c4d7e429bfdbc32b9d4ad5aa04a1f076e62fea19eef51acd0657c22",
+ "eee9e24d78c1855337983451df97c8ad9eedf256c6334f8e948d252d5e0e76847aa0774ddb90a842190d2c558b4b8340",
+ "3836508de3aa893ad8bd18df238a79e534bc55a6fae84a557bde0820ccfc3ad58e3eaab29a7d0d3bfc071c6d69b2e9d3");
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (sha3_512_test)
+{
+ const puchar hash_etalon_1[] = {183, 81, 133, 11, 26, 87, 22, 138,
+ 86, 147, 205, 146, 75, 107, 9, 110,
+ 8, 246, 33, 130, 116, 68, 247, 13,
+ 136, 79, 93, 2, 64, 210, 113, 46,
+ 16, 225, 22, 233, 25, 42, 243, 201,
+ 26, 126, 197, 118, 71, 227, 147, 64,
+ 87, 52, 11, 76, 244, 8, 213, 165,
+ 101, 146, 248, 39, 78, 236, 83, 240};
+ const puchar hash_etalon_2[] = { 4, 163, 113, 232, 78, 207, 181, 184,
+ 183, 124, 180, 134, 16, 252, 168, 24,
+ 45, 212, 87, 206, 111, 50, 106, 15,
+ 211, 215, 236, 47, 30, 145, 99, 109,
+ 238, 105, 31, 190, 12, 152, 83, 2,
+ 186, 27, 13, 141, 199, 140, 8, 99,
+ 70, 181, 51, 180, 156, 3, 13, 153,
+ 162, 125, 175, 17, 57, 214, 231, 94};
+ const puchar hash_etalon_3[] = { 60, 58, 135, 109, 161, 64, 52, 171,
+ 96, 98, 124, 7, 123, 185, 143, 126,
+ 18, 10, 42, 83, 112, 33, 45, 255,
+ 179, 56, 90, 24, 212, 243, 136, 89,
+ 237, 49, 29, 10, 157, 81, 65, 206,
+ 156, 197, 198, 110, 230, 137, 178, 102,
+ 168, 170, 24, 172, 232, 40, 42, 14,
+ 13, 181, 150, 201, 11, 10, 123, 135};
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_SHA3_512,
+ 64,
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0",
+ "04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e",
+ "3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87",
+ "16f59fe0b4344af86b37eb145afe41e9dadb45279d074c5bf5c649dd3d2952e47c0ac3a59ea19dc8395d04e8a72fddd9307b839c35fc4bc44a0463003b80dcf1");
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (gost3411_94_test)
+{
+ PCryptoHash *gost3411_94_hash;
+ pchar *hash_str;
+ const puchar hash_etalon_1[] = { 44, 239, 194, 247, 183, 189, 197, 20,
+ 225, 142, 165, 127, 167, 79, 243, 87,
+ 231, 250, 23, 214, 82, 199, 95, 105,
+ 203, 27, 231, 137, 62, 222, 72, 235};
+ const puchar hash_etalon_2[] = {195, 115, 12, 92, 188, 202, 207, 145,
+ 90, 194, 146, 103, 111, 33, 232, 189,
+ 78, 247, 83, 49, 217, 64, 94, 95,
+ 26, 97, 220, 49, 48, 166, 80, 17};
+ const puchar hash_etalon_3[] = {134, 147, 40, 122, 166, 47, 148, 120,
+ 247, 203, 49, 46, 192, 134, 107, 108,
+ 78, 74, 15, 17, 22, 4, 65, 232,
+ 244, 255, 205, 39, 21, 221, 85, 79};
+
+ p_libsys_init ();
+
+ general_hash_test (P_CRYPTO_HASH_TYPE_GOST,
+ 32,
+ "This is message, length=32 bytes",
+ "Suppose the original message has length = 50 bytes",
+ hash_etalon_1,
+ hash_etalon_2,
+ hash_etalon_3,
+ "2cefc2f7b7bdc514e18ea57fa74ff357e7fa17d652c75f69cb1be7893ede48eb",
+ "c3730c5cbccacf915ac292676f21e8bd4ef75331d9405e5f1a61dc3130a65011",
+ "8693287aa62f9478f7cb312ec0866b6c4e4a0f11160441e8f4ffcd2715dd554f",
+ "3738fb45a7f0de6a5447163c0b441ead7a23e48e7af553829dc4300a99f86343");
+
+ gost3411_94_hash = p_crypto_hash_new (P_CRYPTO_HASH_TYPE_GOST);
+
+ P_TEST_REQUIRE (gost3411_94_hash != NULL);
+
+ /* Repeat test */
+ p_crypto_hash_update (gost3411_94_hash, (const puchar *) "message digest", 14);
+ p_crypto_hash_update (gost3411_94_hash, (const puchar *) "message digest", 14);
+ p_crypto_hash_update (gost3411_94_hash, (const puchar *) "message digest", 14);
+ p_crypto_hash_update (gost3411_94_hash, (const puchar *) "message digest", 14);
+
+ hash_str = p_crypto_hash_get_string (gost3411_94_hash);
+ P_TEST_CHECK (strcmp (hash_str, "9c7b5288c8b3343b29e8ee4a5579593bd90131db7f6fed9b13af4399698b5d29") == 0);
+ p_free (hash_str);
+
+ p_crypto_hash_reset (gost3411_94_hash);
+ p_crypto_hash_free (gost3411_94_hash);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pcryptohash_nomem_test);
+ P_TEST_SUITE_RUN_CASE (pcryptohash_invalid_test);
+ P_TEST_SUITE_RUN_CASE (md5_test);
+ P_TEST_SUITE_RUN_CASE (sha1_test);
+ P_TEST_SUITE_RUN_CASE (sha2_224_test);
+ P_TEST_SUITE_RUN_CASE (sha2_256_test);
+ P_TEST_SUITE_RUN_CASE (sha2_384_test);
+ P_TEST_SUITE_RUN_CASE (sha2_512_test);
+ P_TEST_SUITE_RUN_CASE (sha3_224_test);
+ P_TEST_SUITE_RUN_CASE (sha3_256_test);
+ P_TEST_SUITE_RUN_CASE (sha3_384_test);
+ P_TEST_SUITE_RUN_CASE (sha3_512_test);
+ P_TEST_SUITE_RUN_CASE (gost3411_94_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pdir_test.cpp b/3rdparty/plibsys/tests/pdir_test.cpp
new file mode 100644
index 0000000..7b1689d
--- /dev/null
+++ b/3rdparty/plibsys/tests/pdir_test.cpp
@@ -0,0 +1,248 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2015-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <string.h>
+
+P_TEST_MODULE_INIT ();
+
+#define PDIR_ENTRY_DIR "test_2"
+#define PDIR_ENTRY_FILE "test_file.txt"
+#define PDIR_TEST_DIR "." P_DIR_SEPARATOR "pdir_test_dir"
+#define PDIR_TEST_DIR_IN "." P_DIR_SEPARATOR "pdir_test_dir" P_DIR_SEPARATOR "test_2"
+#define PDIR_TEST_FILE "." P_DIR_SEPARATOR "pdir_test_dir" P_DIR_SEPARATOR "test_file.txt"
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+P_TEST_CASE_BEGIN (pdir_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ /* Cleanup previous run */
+ p_dir_remove (PDIR_TEST_DIR_IN, NULL);
+ p_dir_remove (PDIR_TEST_DIR, NULL);
+
+ P_TEST_REQUIRE (p_dir_create (PDIR_TEST_DIR, 0777, NULL) == TRUE);
+ P_TEST_REQUIRE (p_dir_create (PDIR_TEST_DIR_IN, 0777, NULL) == TRUE);
+
+ P_TEST_CHECK (p_dir_new (PDIR_TEST_DIR"/", NULL) == NULL);
+
+ /* Revert memory management back */
+ p_mem_restore_vtable ();
+
+ /* Try out of memory when iterating */
+ PDir *dir = p_dir_new (PDIR_TEST_DIR"/", NULL);
+ P_TEST_CHECK (dir != NULL);
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_dir_get_next_entry (dir, NULL) == NULL);
+
+ /* Cleanup */
+ p_mem_restore_vtable ();
+
+ p_dir_free (dir);
+
+ P_TEST_CHECK (p_dir_remove (PDIR_TEST_DIR_IN, NULL) == TRUE);
+ P_TEST_CHECK (p_dir_remove (PDIR_TEST_DIR, NULL) == TRUE);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pdir_general_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_dir_new (NULL, NULL) == NULL);
+ P_TEST_CHECK (p_dir_new ("." P_DIR_SEPARATOR "pdir_test_dir_new", NULL) == NULL);
+ P_TEST_CHECK (p_dir_create (NULL, -1, NULL) == FALSE);
+#ifndef P_OS_VMS
+ P_TEST_CHECK (p_dir_create ("." P_DIR_SEPARATOR "pdir_test_dir_new" P_DIR_SEPARATOR "test_dir", -1, NULL) == FALSE);
+#endif
+ P_TEST_CHECK (p_dir_remove (NULL, NULL) == FALSE);
+ P_TEST_CHECK (p_dir_remove ("." P_DIR_SEPARATOR "pdir_test_dir_new", NULL) == FALSE);
+ P_TEST_CHECK (p_dir_is_exists (NULL) == FALSE);
+ P_TEST_CHECK (p_dir_is_exists ("." P_DIR_SEPARATOR "pdir_test_dir_new") == FALSE);
+ P_TEST_CHECK (p_dir_get_path (NULL) == NULL);
+ P_TEST_CHECK (p_dir_get_next_entry (NULL, NULL) == NULL);
+ P_TEST_CHECK (p_dir_rewind (NULL, NULL) == FALSE);
+
+ p_dir_entry_free (NULL);
+ p_dir_free (NULL);
+
+ /* Cleanup previous run */
+ p_dir_remove (PDIR_TEST_DIR_IN, NULL);
+ p_dir_remove (PDIR_TEST_DIR, NULL);
+
+ P_TEST_REQUIRE (p_dir_create (PDIR_TEST_DIR, 0777, NULL) == TRUE);
+ P_TEST_REQUIRE (p_dir_create (PDIR_TEST_DIR, 0777, NULL) == TRUE);
+ P_TEST_REQUIRE (p_dir_create (PDIR_TEST_DIR_IN, 0777, NULL) == TRUE);
+ P_TEST_REQUIRE (p_dir_create (PDIR_TEST_DIR_IN, 0777, NULL) == TRUE);
+
+ FILE *file = fopen (PDIR_TEST_FILE, "w");
+ P_TEST_REQUIRE (file != NULL);
+ P_TEST_REQUIRE (p_file_is_exists (PDIR_TEST_FILE) == TRUE);
+
+ fprintf (file, "This is a test file string\n");
+
+ P_TEST_CHECK (fclose (file) == 0);
+
+ P_TEST_CHECK (p_dir_is_exists (PDIR_TEST_DIR) == TRUE);
+ P_TEST_CHECK (p_dir_is_exists (PDIR_TEST_DIR_IN) == TRUE);
+
+ PDir *dir = p_dir_new (PDIR_TEST_DIR"/", NULL);
+
+ P_TEST_CHECK (dir != NULL);
+
+ pint dir_count = 0;
+ pint file_count = 0;
+ pboolean has_entry_dir = FALSE;
+ pboolean has_entry_file = FALSE;
+
+ PDirEntry *entry;
+
+ while ((entry = p_dir_get_next_entry (dir, NULL)) != NULL) {
+ P_TEST_CHECK (entry->name != NULL);
+
+ switch (entry->type) {
+ case P_DIR_ENTRY_TYPE_DIR:
+ ++dir_count;
+ break;
+ case P_DIR_ENTRY_TYPE_FILE:
+ ++file_count;
+ break;
+ case P_DIR_ENTRY_TYPE_OTHER:
+ default:
+ break;
+ }
+
+ if (strcmp (entry->name, PDIR_ENTRY_DIR) == 0)
+ has_entry_dir = TRUE;
+ else if (strcmp (entry->name, PDIR_ENTRY_FILE) == 0)
+ has_entry_file = TRUE;
+
+ p_dir_entry_free (entry);
+ }
+
+ P_TEST_CHECK (dir_count > 0 && dir_count < 4);
+ P_TEST_CHECK (file_count == 1);
+ P_TEST_CHECK (has_entry_dir == TRUE);
+ P_TEST_CHECK (has_entry_file == TRUE);
+
+ P_TEST_CHECK (p_dir_rewind (dir, NULL) == TRUE);
+
+ pint dir_count_2 = 0;
+ pint file_count_2 = 0;
+ has_entry_dir = FALSE;
+ has_entry_file = FALSE;
+
+ while ((entry = p_dir_get_next_entry (dir, NULL)) != NULL) {
+ P_TEST_CHECK (entry->name != NULL);
+
+ switch (entry->type) {
+ case P_DIR_ENTRY_TYPE_DIR:
+ ++dir_count_2;
+ break;
+ case P_DIR_ENTRY_TYPE_FILE:
+ ++file_count_2;
+ break;
+ case P_DIR_ENTRY_TYPE_OTHER:
+ default:
+ break;
+ }
+
+ if (strcmp (entry->name, PDIR_ENTRY_DIR) == 0)
+ has_entry_dir = TRUE;
+ else if (strcmp (entry->name, PDIR_ENTRY_FILE) == 0)
+ has_entry_file = TRUE;
+
+ p_dir_entry_free (entry);
+ }
+
+ P_TEST_CHECK (dir_count_2 > 0 && dir_count_2 < 4);
+ P_TEST_CHECK (file_count_2 == 1);
+ P_TEST_CHECK (has_entry_dir == TRUE);
+ P_TEST_CHECK (has_entry_file == TRUE);
+
+ /* Compare two previous attempts */
+ P_TEST_CHECK (dir_count == dir_count_2);
+ P_TEST_CHECK (file_count == file_count_2);
+
+ /* Remove all stuff */
+ P_TEST_CHECK (p_file_remove (PDIR_TEST_FILE, NULL) == TRUE);
+ P_TEST_CHECK (p_dir_remove (PDIR_TEST_DIR, NULL) == FALSE);
+ P_TEST_CHECK (p_dir_remove (PDIR_TEST_DIR_IN, NULL) == TRUE);
+ P_TEST_CHECK (p_dir_remove (PDIR_TEST_DIR, NULL) == TRUE);
+
+ P_TEST_CHECK (p_dir_is_exists (PDIR_TEST_DIR_IN) == FALSE);
+ P_TEST_CHECK (p_dir_is_exists (PDIR_TEST_DIR) == FALSE);
+
+ pchar *orig_path = p_dir_get_path (dir);
+ P_TEST_CHECK (strcmp (orig_path, PDIR_TEST_DIR"/") == 0);
+ p_free (orig_path);
+
+ p_dir_free (dir);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pdir_nomem_test);
+ P_TEST_SUITE_RUN_CASE (pdir_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/perror_test.cpp b/3rdparty/plibsys/tests/perror_test.cpp
new file mode 100644
index 0000000..1db2f4d
--- /dev/null
+++ b/3rdparty/plibsys/tests/perror_test.cpp
@@ -0,0 +1,236 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2016-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <string.h>
+
+P_TEST_MODULE_INIT ();
+
+#define PERROR_TEST_MESSAGE "PError test error message"
+#define PERROR_TEST_MESSAGE_2 "Another PError test error message"
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+P_TEST_CASE_BEGIN (perror_nomem_test)
+{
+ p_libsys_init ();
+
+ PError *error = p_error_new_literal (0, 0, NULL);
+ P_TEST_CHECK (error != NULL);
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_error_new () == NULL);
+ P_TEST_CHECK (p_error_new_literal (0, 0, NULL) == NULL);
+ P_TEST_CHECK (p_error_copy (error) == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_error_free (error);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (perror_invalid_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_error_get_message (NULL) == NULL);
+ P_TEST_CHECK (p_error_get_code (NULL) == 0);
+ P_TEST_CHECK (p_error_get_native_code (NULL) == 0);
+ P_TEST_CHECK (p_error_get_domain (NULL) == P_ERROR_DOMAIN_NONE);
+ P_TEST_CHECK (p_error_copy (NULL) == NULL);
+
+ PError *error = (PError *) 0x1;
+
+ p_error_set_code (NULL, 0);
+ p_error_set_native_code (NULL, 0);
+ p_error_set_message (NULL, NULL);
+
+ p_error_set_error (NULL, 0, 0, NULL);
+ p_error_set_error_p (NULL, 0, 0, NULL);
+
+ p_error_set_error_p (&error, 0, 0, NULL);
+ P_TEST_CHECK (error == (PError *) 0x1);
+
+ p_error_clear (NULL);
+ p_error_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (perror_general_test)
+{
+ p_libsys_init ();
+
+ /* Empty initialization test */
+ PError *error = p_error_new ();
+
+ P_TEST_CHECK (error != NULL);
+ P_TEST_CHECK (p_error_get_code (error) == 0);
+ P_TEST_CHECK (p_error_get_domain (error) == P_ERROR_DOMAIN_NONE);
+ P_TEST_CHECK (p_error_get_message (error) == NULL);
+
+ PError *copy_error = p_error_copy (error);
+
+ P_TEST_CHECK (copy_error != NULL);
+ P_TEST_CHECK (p_error_get_code (copy_error) == 0);
+ P_TEST_CHECK (p_error_get_domain (error) == P_ERROR_DOMAIN_NONE);
+ P_TEST_CHECK (p_error_get_message (copy_error) == NULL);
+
+ p_error_free (copy_error);
+ copy_error = NULL;
+
+ p_error_set_error (error, (pint) P_ERROR_DOMAIN_IO, -10, PERROR_TEST_MESSAGE);
+
+ P_TEST_CHECK (p_error_get_code (error) == (pint) P_ERROR_DOMAIN_IO);
+ P_TEST_CHECK (p_error_get_native_code (error) == -10);
+ P_TEST_CHECK (p_error_get_domain (error) == P_ERROR_DOMAIN_IO);
+ P_TEST_CHECK (strcmp (p_error_get_message (error), PERROR_TEST_MESSAGE) == 0);
+
+ /* Change internal data */
+ p_error_set_code (error, (pint) P_ERROR_DOMAIN_IPC);
+ p_error_set_native_code (error, -20);
+ p_error_set_message (error, PERROR_TEST_MESSAGE_2);
+
+ P_TEST_CHECK (p_error_get_code (error) == (pint) P_ERROR_DOMAIN_IPC);
+ P_TEST_CHECK (p_error_get_native_code (error) == -20);
+ P_TEST_CHECK (p_error_get_domain (error) == P_ERROR_DOMAIN_IPC);
+ P_TEST_CHECK (strcmp (p_error_get_message (error), PERROR_TEST_MESSAGE_2) == 0);
+
+ /* Revert data back */
+ p_error_set_code (error, 10);
+ p_error_set_native_code (error, -10);
+ p_error_set_message (error, PERROR_TEST_MESSAGE);
+
+ copy_error = p_error_copy (error);
+
+ P_TEST_CHECK (copy_error != NULL);
+ P_TEST_CHECK (p_error_get_code (copy_error) == 10);
+ P_TEST_CHECK (p_error_get_domain (error) == P_ERROR_DOMAIN_NONE);
+ P_TEST_CHECK (p_error_get_native_code (copy_error) == -10);
+
+ P_TEST_CHECK (strcmp (p_error_get_message (copy_error), PERROR_TEST_MESSAGE) == 0);
+
+ p_error_free (copy_error);
+ copy_error = NULL;
+
+ p_error_set_error (error, 20, -20, PERROR_TEST_MESSAGE_2);
+
+ P_TEST_CHECK (p_error_get_code (error) == 20);
+ P_TEST_CHECK (p_error_get_native_code (error) == -20);
+ P_TEST_CHECK (p_error_get_domain (error) == P_ERROR_DOMAIN_NONE);
+ P_TEST_CHECK (strcmp (p_error_get_message (error), PERROR_TEST_MESSAGE_2) == 0);
+
+ p_error_clear (error);
+
+ P_TEST_CHECK (p_error_get_code (error) == 0);
+ P_TEST_CHECK (p_error_get_native_code (error) == 0);
+ P_TEST_CHECK (p_error_get_domain (error) == P_ERROR_DOMAIN_NONE);
+ P_TEST_CHECK (p_error_get_message (error) == NULL);
+
+ p_error_free (error);
+ error = NULL;
+
+ /* Literal initialization test */
+ error = p_error_new_literal (30, -30, PERROR_TEST_MESSAGE);
+
+ P_TEST_CHECK (p_error_get_code (error) == 30);
+ P_TEST_CHECK (p_error_get_native_code (error) == -30);
+ P_TEST_CHECK (p_error_get_domain (error) == P_ERROR_DOMAIN_NONE);
+ P_TEST_CHECK (strcmp (p_error_get_message (error), PERROR_TEST_MESSAGE) == 0);
+
+ copy_error = p_error_copy (error);
+
+ P_TEST_CHECK (copy_error != NULL);
+ P_TEST_CHECK (p_error_get_code (copy_error) == 30);
+ P_TEST_CHECK (p_error_get_native_code (copy_error) == -30);
+ P_TEST_CHECK (p_error_get_domain (error) == P_ERROR_DOMAIN_NONE);
+ P_TEST_CHECK (strcmp (p_error_get_message (copy_error), PERROR_TEST_MESSAGE) == 0);
+
+ p_error_free (copy_error);
+ p_error_free (error);
+
+ /* Through the double pointer */
+ error = NULL;
+ p_error_set_error_p (&error, 10, -10, PERROR_TEST_MESSAGE);
+
+ P_TEST_CHECK (p_error_get_code (error) == 10);
+ P_TEST_CHECK (p_error_get_native_code (error) == -10);
+ P_TEST_CHECK (p_error_get_domain (error) == P_ERROR_DOMAIN_NONE);
+ P_TEST_CHECK (strcmp (p_error_get_message (error), PERROR_TEST_MESSAGE) == 0);
+
+ p_error_free (error);
+
+ /* System codes */
+ p_error_set_last_system (10);
+ P_TEST_CHECK (p_error_get_last_system () == 10);
+ p_error_set_last_system (0);
+ P_TEST_CHECK (p_error_get_last_system () == 0);
+
+#ifndef P_OS_OS2
+ p_error_set_last_net (20);
+ P_TEST_CHECK (p_error_get_last_net () == 20);
+ p_error_set_last_net (0);
+ P_TEST_CHECK (p_error_get_last_net () == 0);
+#endif
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (perror_nomem_test);
+ P_TEST_SUITE_RUN_CASE (perror_invalid_test);
+ P_TEST_SUITE_RUN_CASE (perror_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pfile_test.cpp b/3rdparty/plibsys/tests/pfile_test.cpp
new file mode 100644
index 0000000..7f3c643
--- /dev/null
+++ b/3rdparty/plibsys/tests/pfile_test.cpp
@@ -0,0 +1,61 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <stdio.h>
+
+P_TEST_MODULE_INIT ();
+
+#define PFILE_TEST_FILE "." P_DIR_SEPARATOR "pfile_test_file.txt"
+
+P_TEST_CASE_BEGIN (pfile_general_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_file_remove (NULL, NULL) == FALSE);
+
+ P_TEST_CHECK (p_file_is_exists (PFILE_TEST_FILE) == FALSE);
+ P_TEST_CHECK (p_file_remove ("." P_DIR_SEPARATOR" pfile_test_file_remove.txt", NULL) == FALSE);
+
+ FILE *file = fopen (PFILE_TEST_FILE, "w");
+ P_TEST_REQUIRE (file != NULL);
+ P_TEST_CHECK (p_file_is_exists (PFILE_TEST_FILE) == TRUE);
+
+ fprintf (file, "This is a test file string\n");
+
+ P_TEST_CHECK (fclose (file) == 0);
+ P_TEST_CHECK (p_file_remove (PFILE_TEST_FILE, NULL) == TRUE);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pfile_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/phashtable_test.cpp b/3rdparty/plibsys/tests/phashtable_test.cpp
new file mode 100644
index 0000000..2975fde
--- /dev/null
+++ b/3rdparty/plibsys/tests/phashtable_test.cpp
@@ -0,0 +1,320 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <stdlib.h>
+#include <time.h>
+
+P_TEST_MODULE_INIT ();
+
+#define PHASHTABLE_STRESS_COUNT 10000
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+static int test_hash_table_values (pconstpointer a, pconstpointer b)
+{
+ return a > b ? 0 : (a < b ? -1 : 1);
+}
+
+P_TEST_CASE_BEGIN (phashtable_nomem_test)
+{
+ p_libsys_init ();
+
+ PHashTable *table = p_hash_table_new ();
+ P_TEST_CHECK (table != NULL);
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_hash_table_new () == NULL);
+ p_hash_table_insert (table, PINT_TO_POINTER (1), PINT_TO_POINTER (10));
+ P_TEST_CHECK (p_hash_table_keys (table) == NULL);
+ P_TEST_CHECK (p_hash_table_values (table) == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_hash_table_free (table);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (phashtable_invalid_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_hash_table_keys (NULL) == NULL);
+ P_TEST_CHECK (p_hash_table_values (NULL) == NULL);
+ P_TEST_CHECK (p_hash_table_lookup (NULL, NULL) == NULL);
+ P_TEST_CHECK (p_hash_table_lookup_by_value (NULL, NULL, NULL) == NULL);
+ p_hash_table_insert (NULL, NULL, NULL);
+ p_hash_table_remove (NULL, NULL);
+ p_hash_table_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (phashtable_general_test)
+{
+ PHashTable *table = NULL;
+ PList *list = NULL;
+
+ p_libsys_init ();
+
+ table = p_hash_table_new ();
+ P_TEST_REQUIRE (table != NULL);
+
+ /* Test for NULL key */
+ p_hash_table_insert (table, NULL, PINT_TO_POINTER (1));
+ list = p_hash_table_keys (table);
+ P_TEST_REQUIRE (p_list_length (list) == 1);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) == 0);
+ p_list_free (list);
+ list = p_hash_table_values (table);
+ P_TEST_REQUIRE (p_list_length (list) == 1);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) == 1);
+ p_list_free (list);
+ p_hash_table_remove (table, NULL);
+
+ /* Test for insertion */
+ p_hash_table_insert (table, PINT_TO_POINTER (1), PINT_TO_POINTER (10));
+ list = p_hash_table_values (table);
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_REQUIRE (p_list_length (list) == 1);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) == 10);
+ p_list_free (list);
+ list = p_hash_table_keys (table);
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_REQUIRE (p_list_length (list) == 1);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) == 1);
+ p_list_free (list);
+
+ /* False remove */
+ p_hash_table_remove (table, PINT_TO_POINTER (2));
+ list = p_hash_table_values (table);
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_REQUIRE (p_list_length (list) == 1);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) == 10);
+ p_list_free (list);
+ list = p_hash_table_keys (table);
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_REQUIRE (p_list_length (list) == 1);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) == 1);
+ p_list_free (list);
+
+ /* Replace existing value */
+ p_hash_table_insert (table, PINT_TO_POINTER (1), PINT_TO_POINTER (15));
+ list = p_hash_table_values (table);
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_REQUIRE (p_list_length (list) == 1);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) == 15);
+ p_list_free (list);
+ list = p_hash_table_keys (table);
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_REQUIRE (p_list_length (list) == 1);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) == 1);
+ p_list_free (list);
+
+ /* More insertion */
+ p_hash_table_insert (table, PINT_TO_POINTER (2), PINT_TO_POINTER (20));
+ p_hash_table_insert (table, PINT_TO_POINTER (3), PINT_TO_POINTER (30));
+
+ list = p_hash_table_values (table);
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_REQUIRE (p_list_length (list) == 3);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) +
+ PPOINTER_TO_INT (list->next->data) +
+ PPOINTER_TO_INT (list->next->next->data) == 65);
+ p_list_free (list);
+ list = p_hash_table_keys (table);
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_REQUIRE (p_list_length (list) == 3);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) +
+ PPOINTER_TO_INT (list->next->data) +
+ PPOINTER_TO_INT (list->next->next->data) == 6);
+ p_list_free (list);
+
+ P_TEST_CHECK (PPOINTER_TO_INT (p_hash_table_lookup (table, PINT_TO_POINTER (1))) == 15);
+ P_TEST_CHECK (PPOINTER_TO_INT (p_hash_table_lookup (table, PINT_TO_POINTER (2))) == 20);
+ P_TEST_CHECK (PPOINTER_TO_INT (p_hash_table_lookup (table, PINT_TO_POINTER (3))) == 30);
+ P_TEST_CHECK (p_hash_table_lookup (table, PINT_TO_POINTER (4)) == (ppointer) -1);
+ p_hash_table_insert (table, PINT_TO_POINTER (22), PINT_TO_POINTER (20));
+
+ list = p_hash_table_lookup_by_value (table,
+ PINT_TO_POINTER (19),
+ (PCompareFunc) test_hash_table_values);
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_REQUIRE (p_list_length (list) == 3);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) +
+ PPOINTER_TO_INT (list->next->data) +
+ PPOINTER_TO_INT (list->next->next->data) == 27);
+ p_list_free (list);
+
+ list = p_hash_table_lookup_by_value (table,
+ PINT_TO_POINTER (20),
+ NULL);
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_REQUIRE (p_list_length (list) == 2);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) +
+ PPOINTER_TO_INT (list->next->data) == 24);
+ p_list_free (list);
+
+ P_TEST_REQUIRE (PPOINTER_TO_INT (p_hash_table_lookup (table, PINT_TO_POINTER (22))) == 20);
+
+ p_hash_table_remove (table, PINT_TO_POINTER (1));
+ p_hash_table_remove (table, PINT_TO_POINTER (2));
+
+ list = p_hash_table_keys (table);
+ P_TEST_REQUIRE (p_list_length (list) == 2);
+ p_list_free (list);
+ list = p_hash_table_values (table);
+ P_TEST_REQUIRE (p_list_length (list) == 2);
+ p_list_free (list);
+
+ p_hash_table_remove (table, PINT_TO_POINTER (3));
+
+ list = p_hash_table_keys (table);
+ P_TEST_REQUIRE (p_list_length (list) == 1);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) == 22);
+ p_list_free (list);
+ list = p_hash_table_values (table);
+ P_TEST_REQUIRE (p_list_length (list) == 1);
+ P_TEST_REQUIRE (PPOINTER_TO_INT (list->data) == 20);
+ p_list_free (list);
+
+ p_hash_table_remove (table, PINT_TO_POINTER (22));
+
+ P_TEST_REQUIRE (p_hash_table_keys (table) == NULL);
+ P_TEST_REQUIRE (p_hash_table_values (table) == NULL);
+
+ p_hash_table_free (table);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (phashtable_stress_test)
+{
+ p_libsys_init ();
+
+ PHashTable *table = p_hash_table_new ();
+ P_TEST_REQUIRE (table != NULL);
+
+ srand ((unsigned int) time (NULL));
+
+ int counter = 0;
+
+ pint *keys = (pint *) p_malloc0 (PHASHTABLE_STRESS_COUNT * sizeof (pint));
+ pint *values = (pint *) p_malloc0 (PHASHTABLE_STRESS_COUNT * sizeof (pint));
+
+ P_TEST_REQUIRE (keys != NULL);
+ P_TEST_REQUIRE (values != NULL);
+
+ while (counter != PHASHTABLE_STRESS_COUNT) {
+ pint rand_number = rand ();
+
+ if (p_hash_table_lookup (table, PINT_TO_POINTER (rand_number)) != (ppointer) (-1))
+ continue;
+
+ keys[counter] = rand_number;
+ values[counter] = rand () + 1;
+
+ p_hash_table_remove (table, PINT_TO_POINTER (keys[counter]));
+ p_hash_table_insert (table, PINT_TO_POINTER (keys[counter]), PINT_TO_POINTER (values[counter]));
+
+ ++counter;
+ }
+
+ for (int i = 0; i < PHASHTABLE_STRESS_COUNT; ++i) {
+ P_TEST_CHECK (p_hash_table_lookup (table, PINT_TO_POINTER (keys[i])) ==
+ PINT_TO_POINTER (values[i]));
+
+ p_hash_table_remove (table, PINT_TO_POINTER (keys[i]));
+ P_TEST_CHECK (p_hash_table_lookup (table, PINT_TO_POINTER (keys[i])) == (ppointer) (-1));
+ }
+
+ P_TEST_CHECK (p_hash_table_keys (table) == NULL);
+ P_TEST_CHECK (p_hash_table_values (table) == NULL);
+
+ p_free (keys);
+ p_free (values);
+
+ p_hash_table_free (table);
+
+ /* Try to free at once */
+ table = p_hash_table_new ();
+ P_TEST_REQUIRE (table != NULL);
+
+ counter = 0;
+
+ while (counter != PHASHTABLE_STRESS_COUNT) {
+ pint rand_number = rand ();
+
+ if (p_hash_table_lookup (table, PINT_TO_POINTER (rand_number)) != (ppointer) (-1))
+ continue;
+
+ p_hash_table_insert (table, PINT_TO_POINTER (rand_number), PINT_TO_POINTER (rand () + 1));
+
+ ++counter;
+ }
+
+ p_hash_table_free (table);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (phashtable_nomem_test);
+ P_TEST_SUITE_RUN_CASE (phashtable_invalid_test);
+ P_TEST_SUITE_RUN_CASE (phashtable_general_test);
+ P_TEST_SUITE_RUN_CASE (phashtable_stress_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pinifile_test.cpp b/3rdparty/plibsys/tests/pinifile_test.cpp
new file mode 100644
index 0000000..3d4d4c8
--- /dev/null
+++ b/3rdparty/plibsys/tests/pinifile_test.cpp
@@ -0,0 +1,357 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <float.h>
+
+P_TEST_MODULE_INIT ();
+
+#define PINIFILE_STRESS_LINE 2048
+#define PINIFILE_MAX_LINE 1024
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+static bool create_test_ini_file (bool last_empty_section)
+{
+ FILE *file = fopen ("." P_DIR_SEPARATOR "p_ini_test_file.ini", "w");
+
+ if (file == NULL)
+ return false;
+
+ pchar *buf = (pchar *) p_malloc0 (PINIFILE_STRESS_LINE + 1);
+
+ for (int i = 0; i < PINIFILE_STRESS_LINE; ++i)
+ buf[i] = (pchar) (97 + i % 20);
+
+ /* Empty section */
+ fprintf (file, "[empty_section]\n");
+
+ /* Numeric section */
+ fprintf (file, "[numeric_section]\n");
+ fprintf (file, "int_parameter_1 = 4\n");
+ fprintf (file, "int_parameter_2 = 5 ;This is a comment\n");
+ fprintf (file, "int_parameter_3 = 6 #This is another type of a comment\n");
+ fprintf (file, "# Whole line is a comment\n");
+ fprintf (file, "; Yet another comment line\n");
+ fprintf (file, "float_parameter_1 = 3.24\n");
+ fprintf (file, "float_parameter_2 = 0.15\n");
+
+ /* String section */
+ fprintf (file, "[string_section]\n");
+ fprintf (file, "string_parameter_1 = Test string\n");
+ fprintf (file, "string_parameter_2 = \"Test string with #'\"\n");
+ fprintf (file, "string_parameter_3 = \n");
+ fprintf (file, "string_parameter_4 = 12345 ;Comment\n");
+ fprintf (file, "string_parameter_4 = 54321\n");
+ fprintf (file, "string_parameter_5 = 'Test string'\n");
+ fprintf (file, "string_parameter_6 = %s\n", buf);
+ fprintf (file, "string_parameter_7 = ''\n");
+ fprintf (file, "string_parameter_8 = \"\"\n");
+ fprintf (file, "%s = stress line\n", buf);
+
+ /* Boolean section */
+ fprintf (file, "[boolean_section]\n");
+ fprintf (file, "boolean_parameter_1 = TRUE ;True value\n");
+ fprintf (file, "boolean_parameter_2 = 0 ;False value\n");
+ fprintf (file, "boolean_parameter_3 = false ;False value\n");
+ fprintf (file, "boolean_parameter_4 = 1 ;True value\n");
+
+ /* List section */
+ fprintf (file, "[list_section]\n");
+ fprintf (file, "list_parameter_1 = {1\t2\t5\t10} ;First list\n");
+ fprintf (file, "list_parameter_2 = {2.0 3.0 5.0} #Second list\n");
+ fprintf (file, "list_parameter_3 = {true FALSE 1} #Last list\n");
+
+ /* Empty section */
+ if (last_empty_section)
+ fprintf (file, "[empty_section_2]\n");
+
+ p_free (buf);
+
+ return fclose (file) == 0;
+}
+
+P_TEST_CASE_BEGIN (pinifile_nomem_test)
+{
+ p_libsys_init ();
+
+ P_TEST_REQUIRE (create_test_ini_file (false));
+
+ PIniFile *ini = p_ini_file_new ("." P_DIR_SEPARATOR "p_ini_test_file.ini");
+ P_TEST_CHECK (ini != NULL);
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_ini_file_new ("." P_DIR_SEPARATOR "p_ini_test_file.ini") == NULL);
+ P_TEST_CHECK (p_ini_file_parse (ini, NULL) == TRUE);
+ P_TEST_CHECK (p_ini_file_sections (ini) == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_ini_file_free (ini);
+
+ ini = p_ini_file_new ("." P_DIR_SEPARATOR "p_ini_test_file.ini");
+ P_TEST_CHECK (ini != NULL);
+
+ P_TEST_CHECK (p_ini_file_parse (ini, NULL) == TRUE);
+ PList *section_list = p_ini_file_sections (ini);
+ P_TEST_CHECK (section_list != NULL);
+ P_TEST_CHECK (p_list_length (section_list) == 4);
+
+ p_list_foreach (section_list, (PFunc) p_free, NULL);
+ p_list_free (section_list);
+ p_ini_file_free (ini);
+
+ P_TEST_CHECK (p_file_remove ("." P_DIR_SEPARATOR "p_ini_test_file.ini", NULL) == TRUE);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pinifile_bad_input_test)
+{
+ PIniFile *ini = NULL;
+
+ p_libsys_init ();
+
+ p_ini_file_free (ini);
+ P_TEST_CHECK (p_ini_file_new (NULL) == NULL);
+ P_TEST_CHECK (p_ini_file_parse (ini, NULL) == FALSE);
+ P_TEST_CHECK (p_ini_file_is_parsed (ini) == FALSE);
+ P_TEST_CHECK (p_ini_file_is_key_exists (ini, "string_section", "string_paramter_1") == FALSE);
+ P_TEST_CHECK (p_ini_file_sections (ini) == NULL);
+ P_TEST_CHECK (p_ini_file_keys (ini, "string_section") == NULL);
+ P_TEST_CHECK (p_ini_file_parameter_boolean (ini, "boolean_section", "boolean_parameter_1", FALSE) == FALSE);
+ P_TEST_CHECK_CLOSE (p_ini_file_parameter_double (ini, "numeric_section", "float_parameter_1", 1.0), 1.0, 0.0001);
+ P_TEST_CHECK (p_ini_file_parameter_int (ini, "numeric_section", "int_parameter_1", 0) == 0);
+ P_TEST_CHECK (p_ini_file_parameter_list (ini, "list_section", "list_parameter_1") == NULL);
+ P_TEST_CHECK (p_ini_file_parameter_string (ini, "string_section", "string_parameter_1", NULL) == NULL);
+
+ ini = p_ini_file_new ("./bad_file_path/fake.ini");
+ P_TEST_CHECK (ini != NULL);
+ P_TEST_CHECK (p_ini_file_parse (ini, NULL) == FALSE);
+ p_ini_file_free (ini);
+
+ P_TEST_REQUIRE (create_test_ini_file (true));
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pinifile_read_test)
+{
+ p_libsys_init ();
+
+ PIniFile *ini = p_ini_file_new ("." P_DIR_SEPARATOR "p_ini_test_file.ini");
+ P_TEST_REQUIRE (ini != NULL);
+ P_TEST_CHECK (p_ini_file_is_parsed (ini) == FALSE);
+
+ P_TEST_REQUIRE (p_ini_file_parse (ini, NULL) == TRUE);
+ P_TEST_CHECK (p_ini_file_is_parsed (ini) == TRUE);
+ P_TEST_REQUIRE (p_ini_file_parse (ini, NULL) == TRUE);
+ P_TEST_CHECK (p_ini_file_is_parsed (ini) == TRUE);
+
+ /* Test list of sections */
+ PList *list = p_ini_file_sections (ini);
+ P_TEST_CHECK (list != NULL);
+ P_TEST_CHECK (p_list_length (list) == 4);
+
+ p_list_foreach (list, (PFunc) p_free, NULL);
+ p_list_free (list);
+
+ /* Test empty section */
+ list = p_ini_file_keys (ini, "empty_section");
+ P_TEST_CHECK (list == NULL);
+
+ /* Test numeric section */
+ list = p_ini_file_keys (ini, "numeric_section");
+ P_TEST_CHECK (p_list_length (list) == 5);
+ p_list_foreach (list, (PFunc) p_free, NULL);
+ p_list_free (list);
+
+ P_TEST_CHECK (p_ini_file_parameter_list (ini, "numeric_section", "int_parameter_1") == NULL);
+ P_TEST_CHECK (p_ini_file_parameter_int (ini, "numeric_section", "int_parameter_1", -1) == 4);
+ P_TEST_CHECK (p_ini_file_parameter_int (ini, "numeric_section", "int_parameter_2", -1) == 5);
+ P_TEST_CHECK (p_ini_file_parameter_int (ini, "numeric_section", "int_parameter_3", -1) == 6);
+ P_TEST_CHECK (p_ini_file_parameter_int (ini, "numeric_section", "int_parameter_def", 10) == 10);
+ P_TEST_CHECK_CLOSE (p_ini_file_parameter_double (ini, "numeric_section", "float_parameter_1", -1.0), 3.24, 0.0001);
+ P_TEST_CHECK_CLOSE (p_ini_file_parameter_double (ini, "numeric_section", "float_parameter_2", -1.0), 0.15, 0.0001);
+ P_TEST_CHECK_CLOSE (p_ini_file_parameter_double (ini, "numeric_section_no", "float_parameter_def", 10.0), 10.0, 0.0001);
+ P_TEST_CHECK (p_ini_file_is_key_exists (ini, "numeric_section", "int_parameter_1") == TRUE);
+ P_TEST_CHECK (p_ini_file_is_key_exists (ini, "numeric_section", "float_parameter_1") == TRUE);
+ P_TEST_CHECK (p_ini_file_is_key_exists (ini, "numeric_section_false", "float_parameter_1") == FALSE);
+
+ /* Test string section */
+ list = p_ini_file_keys (ini, "string_section");
+ P_TEST_CHECK (p_list_length (list) == 8);
+ p_list_foreach (list, (PFunc) p_free, NULL);
+ p_list_free (list);
+
+ pchar *str = p_ini_file_parameter_string (ini, "string_section", "string_parameter_1", NULL);
+ P_TEST_REQUIRE (str != NULL);
+ P_TEST_CHECK (strcmp (str, "Test string") == 0);
+ p_free (str);
+
+ str = p_ini_file_parameter_string (ini, "string_section", "string_parameter_2", NULL);
+ P_TEST_REQUIRE (str != NULL);
+ P_TEST_CHECK (strcmp (str, "Test string with #'") == 0);
+ p_free (str);
+
+ str = p_ini_file_parameter_string (ini, "string_section", "string_parameter_3", NULL);
+ P_TEST_REQUIRE (str == NULL);
+ P_TEST_CHECK (p_ini_file_is_key_exists (ini, "string_section", "string_parameter_3") == FALSE);
+
+ str = p_ini_file_parameter_string (ini, "string_section", "string_parameter_4", NULL);
+ P_TEST_REQUIRE (str != NULL);
+ P_TEST_CHECK (strcmp (str, "54321") == 0);
+ p_free (str);
+
+ str = p_ini_file_parameter_string (ini, "string_section", "string_parameter_5", NULL);
+ P_TEST_REQUIRE (str != NULL);
+ P_TEST_CHECK (strcmp (str, "Test string") == 0);
+ p_free (str);
+
+ str = p_ini_file_parameter_string (ini, "string_section", "string_parameter_6", NULL);
+ P_TEST_REQUIRE (str != NULL);
+ P_TEST_CHECK (strlen (str) > 0 && strlen (str) < PINIFILE_MAX_LINE);
+ p_free (str);
+
+ str = p_ini_file_parameter_string (ini, "string_section", "string_parameter_7", NULL);
+ P_TEST_REQUIRE (str != NULL);
+ P_TEST_CHECK (strcmp (str, "") == 0);
+ p_free (str);
+
+ str = p_ini_file_parameter_string (ini, "string_section", "string_parameter_8", NULL);
+ P_TEST_REQUIRE (str != NULL);
+ P_TEST_CHECK (strcmp (str, "") == 0);
+ p_free (str);
+
+ str = p_ini_file_parameter_string (ini, "string_section", "string_parameter_def", "default_value");
+ P_TEST_REQUIRE (str != NULL);
+ P_TEST_CHECK (strcmp (str, "default_value") == 0);
+ p_free (str);
+
+ /* Test boolean section */
+ list = p_ini_file_keys (ini, "boolean_section");
+ P_TEST_CHECK (p_list_length (list) == 4);
+ p_list_foreach (list, (PFunc) p_free, NULL);
+ p_list_free (list);
+
+ P_TEST_CHECK (p_ini_file_parameter_boolean (ini, "boolean_section", "boolean_parameter_1", FALSE) == TRUE);
+ P_TEST_CHECK (p_ini_file_parameter_boolean (ini, "boolean_section", "boolean_parameter_2", TRUE) == FALSE);
+ P_TEST_CHECK (p_ini_file_parameter_boolean (ini, "boolean_section", "boolean_parameter_3", TRUE) == FALSE);
+ P_TEST_CHECK (p_ini_file_parameter_boolean (ini, "boolean_section", "boolean_parameter_4", FALSE) == TRUE);
+ P_TEST_CHECK (p_ini_file_parameter_boolean (ini, "boolean_section", "boolean_section_def", TRUE) == TRUE);
+
+ /* Test list section */
+ list = p_ini_file_keys (ini, "list_section");
+ P_TEST_CHECK (p_list_length (list) == 3);
+ p_list_foreach (list, (PFunc) p_free, NULL);
+ p_list_free (list);
+
+ /* -- First list parameter */
+ PList *list_val = p_ini_file_parameter_list (ini, "list_section", "list_parameter_1");
+ P_TEST_CHECK (list_val != NULL);
+ P_TEST_CHECK (p_list_length (list_val) == 4);
+
+ pint int_sum = 0;
+ for (PList *iter = list_val; iter != NULL; iter = iter->next)
+ int_sum += atoi ((const pchar *) (iter->data));
+
+ P_TEST_CHECK (int_sum == 18);
+ p_list_foreach (list_val, (PFunc) p_free, NULL);
+ p_list_free (list_val);
+
+ /* -- Second list parameter */
+ list_val = p_ini_file_parameter_list (ini, "list_section", "list_parameter_2");
+ P_TEST_CHECK (list_val != NULL);
+ P_TEST_CHECK (p_list_length (list_val) == 3);
+
+ double flt_sum = 0;
+ for (PList *iter = list_val; iter != NULL; iter = iter->next)
+ flt_sum += atof ((const pchar *) (iter->data));
+
+ P_TEST_CHECK_CLOSE (flt_sum, 10.0, 0.0001);
+ p_list_foreach (list_val, (PFunc) p_free, NULL);
+ p_list_free (list_val);
+
+ /* -- Third list parameter */
+ list_val = p_ini_file_parameter_list (ini, "list_section", "list_parameter_3");
+ P_TEST_CHECK (list_val != NULL);
+ P_TEST_CHECK (p_list_length (list_val) == 3);
+
+ pboolean bool_sum = TRUE;
+ for (PList *iter = list_val; iter != NULL; iter = iter->next)
+ bool_sum = bool_sum && atoi ((const pchar *) (iter->data));
+
+ P_TEST_CHECK (bool_sum == FALSE);
+ p_list_foreach (list_val, (PFunc) p_free, NULL);
+ p_list_free (list_val);
+
+ /* -- False list parameter */
+ P_TEST_CHECK (p_ini_file_parameter_list (ini, "list_section_no", "list_parameter_def") == NULL);
+
+ p_ini_file_free (ini);
+
+ P_TEST_CHECK (p_file_remove ("." P_DIR_SEPARATOR "p_ini_test_file.ini", NULL) == TRUE);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pinifile_nomem_test);
+ P_TEST_SUITE_RUN_CASE (pinifile_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (pinifile_read_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/plibraryloader_test.cpp b/3rdparty/plibsys/tests/plibraryloader_test.cpp
new file mode 100644
index 0000000..52ce1b0
--- /dev/null
+++ b/3rdparty/plibsys/tests/plibraryloader_test.cpp
@@ -0,0 +1,179 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2015-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <stdio.h>
+
+P_TEST_MODULE_INIT ();
+
+static int g_argc = 0;
+static char **g_argv = NULL;
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+P_TEST_CASE_BEGIN (plibraryloader_nomem_test)
+{
+ p_libsys_init ();
+
+ if (P_UNLIKELY (p_library_loader_is_ref_counted () == FALSE)) {
+ p_libsys_shutdown ();
+ P_TEST_CASE_RETURN ();
+ }
+
+ /* We assume that 3rd argument is ourself library path */
+ P_TEST_REQUIRE (g_argc > 1);
+
+ /* Cleanup from previous run */
+ p_file_remove ("." P_DIR_SEPARATOR "p_empty_file.txt", NULL);
+
+ FILE *file = fopen ("." P_DIR_SEPARATOR "p_empty_file.txt", "w");
+ P_TEST_CHECK (file != NULL);
+ P_TEST_CHECK (fclose (file) == 0);
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+#ifdef P_OS_WIN
+ SetErrorMode (SEM_FAILCRITICALERRORS);
+#endif
+
+ P_TEST_CHECK (p_library_loader_new ("." P_DIR_SEPARATOR "p_empty_file.txt") == NULL);
+ P_TEST_CHECK (p_library_loader_new (g_argv[g_argc - 1]) == NULL);
+
+#ifdef P_OS_WIN
+ SetErrorMode (0);
+#endif
+
+ p_mem_restore_vtable ();
+
+ P_TEST_CHECK (p_file_remove ("." P_DIR_SEPARATOR "p_empty_file.txt", NULL) == TRUE);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (plibraryloader_general_test)
+{
+ PLibraryLoader *loader;
+ pchar *err_msg;
+ void (*shutdown_func) (void);
+
+ p_libsys_init ();
+
+ /* We assume that 3rd argument is ourself library path */
+ P_TEST_REQUIRE (g_argc > 1);
+
+ /* Invalid usage */
+ P_TEST_CHECK (p_library_loader_new (NULL) == NULL);
+ P_TEST_CHECK (p_library_loader_new ("./unexistent_file.nofile") == NULL);
+ P_TEST_CHECK (p_library_loader_get_symbol (NULL, NULL) == NULL);
+ P_TEST_CHECK (p_library_loader_get_symbol (NULL, "unexistent_symbol") == NULL);
+
+ p_library_loader_free (NULL);
+
+ /* General tests */
+
+ /* At least not on HP-UX it should be true */
+#if !defined (P_OS_HPUX)
+ P_TEST_CHECK (p_library_loader_is_ref_counted () == TRUE);
+#else
+ p_library_loader_is_ref_counted ();
+#endif
+
+ err_msg = p_library_loader_get_last_error (NULL);
+ p_free (err_msg);
+
+ if (P_UNLIKELY (p_library_loader_is_ref_counted () == FALSE)) {
+ p_libsys_shutdown ();
+ P_TEST_CASE_RETURN ();
+ }
+
+ loader = p_library_loader_new (g_argv[g_argc - 1]);
+ P_TEST_REQUIRE (loader != NULL);
+
+ P_TEST_CHECK (p_library_loader_get_symbol (loader, "there_is_no_such_a_symbol") == (PFuncAddr) NULL);
+
+ err_msg = p_library_loader_get_last_error (loader);
+ P_TEST_CHECK (err_msg != NULL);
+ p_free (err_msg);
+
+ shutdown_func = (void (*) (void)) p_library_loader_get_symbol (loader, "p_libsys_shutdown");
+
+ if (shutdown_func == NULL)
+ shutdown_func = (void (*) (void)) p_library_loader_get_symbol (loader, "_p_libsys_shutdown");
+
+ /* For Watcom C */
+
+ if (shutdown_func == NULL)
+ shutdown_func = (void (*) (void)) p_library_loader_get_symbol (loader, "p_libsys_shutdown_");
+
+ P_TEST_REQUIRE (shutdown_func != NULL);
+
+ err_msg = p_library_loader_get_last_error (loader);
+ p_free (err_msg);
+
+ p_library_loader_free (loader);
+
+#ifdef P_OS_BEOS
+ p_libsys_shutdown ();
+#else
+ /* We have already loaded reference to ourself library, it's OK */
+ shutdown_func ();
+#endif
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_ARGS_BEGIN()
+{
+ g_argc = argc;
+ g_argv = argv;
+
+ P_TEST_SUITE_RUN_CASE (plibraryloader_nomem_test);
+ P_TEST_SUITE_RUN_CASE (plibraryloader_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/plist_test.cpp b/3rdparty/plibsys/tests/plist_test.cpp
new file mode 100644
index 0000000..87933ae
--- /dev/null
+++ b/3rdparty/plibsys/tests/plist_test.cpp
@@ -0,0 +1,200 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <string.h>
+
+P_TEST_MODULE_INIT ();
+
+typedef struct _TestData {
+ pint test_array[3];
+ pint index;
+} TestData;
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+static void foreach_test_func (ppointer data, ppointer user_data)
+{
+ if (user_data == NULL)
+ return;
+
+ TestData *test_data = (TestData *) user_data;
+
+ if (test_data->index < 0 || test_data->index > 2)
+ return;
+
+ test_data->test_array[test_data->index] = P_POINTER_TO_INT (data);
+ ++test_data->index;
+}
+
+P_TEST_CASE_BEGIN (plist_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_list_append (NULL, PINT_TO_POINTER (10)) == NULL);
+ P_TEST_CHECK (p_list_prepend (NULL, PINT_TO_POINTER (10)) == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (plist_invalid_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_list_remove (NULL, NULL) == NULL);
+ P_TEST_CHECK (p_list_last (NULL) == NULL);
+ P_TEST_CHECK (p_list_length (NULL) == 0);
+ P_TEST_CHECK (p_list_reverse (NULL) == NULL);
+
+ p_list_free (NULL);
+ p_list_foreach (NULL, NULL, NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (plist_general_test)
+{
+ PList *list = NULL;
+ TestData test_data;
+
+ p_libsys_init ();
+
+ /* Testing append */
+ list = p_list_append (list, P_INT_TO_POINTER (32));
+ list = p_list_append (list, P_INT_TO_POINTER (64));
+
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_CHECK (p_list_length (list) == 2);
+
+ /* Testing data access */
+ P_TEST_CHECK (P_POINTER_TO_INT (list->data) == 32);
+ P_TEST_CHECK (P_POINTER_TO_INT (p_list_last(list)->data) == 64);
+
+ /* Testing prepend */
+ list = p_list_prepend (list, P_INT_TO_POINTER (128));
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_CHECK (p_list_length (list) == 3);
+ P_TEST_CHECK (P_POINTER_TO_INT (list->data) == 128);
+ P_TEST_CHECK (P_POINTER_TO_INT (p_list_last(list)->data) == 64);
+
+ /* Testing for each loop */
+ memset (&test_data, 0, sizeof (test_data));
+
+ P_TEST_REQUIRE (test_data.test_array[0] == 0);
+ P_TEST_REQUIRE (test_data.test_array[1] == 0);
+ P_TEST_REQUIRE (test_data.test_array[2] == 0);
+ P_TEST_REQUIRE (test_data.index == 0);
+
+ p_list_foreach (list, (PFunc) foreach_test_func, (ppointer) &test_data);
+
+ P_TEST_CHECK (test_data.index == 3);
+ P_TEST_CHECK (test_data.test_array[0] == 128);
+ P_TEST_CHECK (test_data.test_array[1] == 32);
+ P_TEST_CHECK (test_data.test_array[2] == 64);
+
+ /* Testing reverse */
+
+ list = p_list_reverse (list);
+
+ P_TEST_CHECK (list != NULL);
+ P_TEST_CHECK (p_list_length (list) == 3);
+ P_TEST_CHECK (P_POINTER_TO_INT (list->data) == 64);
+ P_TEST_CHECK (P_POINTER_TO_INT (p_list_last(list)->data) == 128);
+
+ /* Testing for each loop */
+ memset (&test_data, 0, sizeof (test_data));
+
+ P_TEST_REQUIRE (test_data.test_array[0] == 0);
+ P_TEST_REQUIRE (test_data.test_array[1] == 0);
+ P_TEST_REQUIRE (test_data.test_array[2] == 0);
+ P_TEST_REQUIRE (test_data.index == 0);
+
+ p_list_foreach (list, (PFunc) foreach_test_func, (ppointer) &test_data);
+
+ P_TEST_CHECK (test_data.index == 3);
+ P_TEST_CHECK (test_data.test_array[0] == 64);
+ P_TEST_CHECK (test_data.test_array[1] == 32);
+ P_TEST_CHECK (test_data.test_array[2] == 128);
+
+ /* Testing remove */
+ list = p_list_remove (list, P_INT_TO_POINTER (32));
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_CHECK (p_list_length (list) == 2);
+
+ list = p_list_remove (list, P_INT_TO_POINTER (128));
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_CHECK (p_list_length (list) == 1);
+
+ list = p_list_remove (list, P_INT_TO_POINTER (256));
+ P_TEST_REQUIRE (list != NULL);
+ P_TEST_CHECK (p_list_length (list) == 1);
+
+ list = p_list_remove (list, P_INT_TO_POINTER (64));
+ P_TEST_REQUIRE (list == NULL);
+ P_TEST_CHECK (p_list_length (list) == 0);
+
+ p_list_free (list);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (plist_nomem_test);
+ P_TEST_SUITE_RUN_CASE (plist_invalid_test);
+ P_TEST_SUITE_RUN_CASE (plist_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pmacros_test.cpp b/3rdparty/plibsys/tests/pmacros_test.cpp
new file mode 100644
index 0000000..fed35a2
--- /dev/null
+++ b/3rdparty/plibsys/tests/pmacros_test.cpp
@@ -0,0 +1,646 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2014-2018 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <stdlib.h>
+#include <time.h>
+
+P_TEST_MODULE_INIT ();
+
+static P_GNUC_WARN_UNUSED_RESULT pint unused_result_test_func ()
+{
+ return 0;
+}
+
+P_LIB_INTERNAL_API int internal_api_test ()
+{
+ return 0;
+}
+
+P_LIB_GLOBAL_API int global_api_test ()
+{
+ return 0;
+}
+
+P_TEST_CASE_BEGIN (pmacros_general_test)
+{
+ p_libsys_init ();
+
+ /* Test OS detection macros */
+#if !defined (P_OS_DARWIN) && !defined (P_OS_MAC9) && !defined (P_OS_BSD4) && \
+ !defined (P_OS_AIX) && !defined (P_OS_HPUX) && !defined (P_OS_SOLARIS) && \
+ !defined (P_OS_QNX) && !defined (P_OS_QNX6) && !defined (P_OS_UNIX) && \
+ !defined (P_OS_LINUX) && !defined (P_OS_WIN) && !defined (P_OS_CYGWIN) && \
+ !defined (P_OS_SCO) && !defined (P_OS_UNIXWARE) && !defined (P_OS_VMS) && \
+ !defined (P_OS_IRIX) && !defined (P_OS_MSYS) && !defined (P_OS_DRAGONFLY) && \
+ !defined (P_OS_HAIKU) && !defined (P_OS_TRU64) && !defined (P_OS_SYLLABLE) && \
+ !defined (P_OS_BEOS) && !defined (P_OS_OS2) && !defined (P_OS_AMIGA)
+ P_TEST_CHECK (false);
+#endif
+
+ /* Test for Mac OS */
+#if defined (P_OS_MAC9) && defined (P_OS_UNIX)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_OS_MAC9) && defined (P_OS_MAC)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_OS_MAC) && !defined (P_OS_MAC32) && !defined (P_OS_MAC64)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_OS_MAC) && (!defined (P_OS_DARWIN) || !defined (P_OS_BSD4))
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_OS_MAC32) && !defined (P_OS_DARWIN32)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_OS_MAC64) && !defined (P_OS_DARWIN64)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_OS_MAC32) && defined (P_OS_MAC64)
+ P_TEST_CHECK (false);
+#endif
+
+ /* Test for Windows */
+#if defined (P_OS_WIN64) && !defined (P_OS_WIN)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_OS_WIN) && defined (P_OS_UNIX)
+ P_TEST_CHECK (false);
+#endif
+
+ /* Test for FreeBSD */
+#if defined (P_OS_FREEBSD) && !defined (P_OS_BSD4)
+ P_TEST_CHECK (false);
+#endif
+
+ /* Test for DragonFlyBSD */
+#if defined (P_OS_DRAGONFLY) && !defined (P_OS_BSD4)
+ P_TEST_CHECK (false);
+#endif
+
+ /* Test for NetBSD */
+#if defined (P_OS_NETBSD) && !defined (P_OS_BSD4)
+ P_TEST_CHECK (false);
+#endif
+
+ /* Test for OpenBSD */
+#if defined (P_OS_OPENBSD) && !defined (P_OS_BSD4)
+ P_TEST_CHECK (false);
+#endif
+
+ /* Test for Android */
+#if defined (P_OS_ANDROID) && !defined (P_OS_LINUX)
+ P_TEST_CHECK (false);
+#endif
+
+ /* Test for others */
+#if defined (P_OS_HAIKU) || defined (P_OS_BEOS) || defined (P_OS_OS2) || defined (P_OS_VMS) || \
+ defined (P_OS_AMIGA)
+# if defined (P_OS_UNIX)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+ /* Test for compiler detection macros */
+#if !defined (P_CC_MSVC) && !defined (P_CC_GNU) && !defined (P_CC_MINGW) && \
+ !defined (P_CC_INTEL) && !defined (P_CC_CLANG) && !defined (P_CC_SUN) && \
+ !defined (P_CC_XLC) && !defined (P_CC_HP) && !defined (P_CC_WATCOM) && \
+ !defined (P_CC_BORLAND) && !defined (P_CC_MIPS) && !defined (P_CC_USLC) && \
+ !defined (P_CC_DEC) && !defined (P_CC_PGI) && !defined (P_CC_CRAY)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_CC_MSVC)
+# if !defined (P_OS_WIN)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_INTEL)
+# if !defined (P_OS_WIN) && !defined (P_OS_MAC) && \
+ !defined (P_OS_LINUX) && !defined (P_OS_FREEBSD) && \
+ !defined (P_OS_QNX6)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_SUN)
+# if !defined (P_OS_SOLARIS) && !defined (P_OS_LINUX)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_XLC)
+# if !defined (P_OS_AIX) && !defined (P_OS_LINUX)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_HP)
+# if !defined (P_OS_HPUX)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_WATCOM)
+# if !defined (P_OS_WIN) && !defined (P_OS_LINUX) && \
+ !defined (P_OS_OS2) && !defined (P_OS_QNX)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_BORLAND)
+# if !defined (P_OS_WIN)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_MIPS)
+# if !defined (P_OS_IRIX)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_USLC)
+# if !defined (P_OS_SCO) && !defined (P_OS_UNIXWARE)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_DEC)
+# if !defined (P_OS_VMS) && !defined (P_OS_TRU64)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_PGI)
+# if !defined (P_OS_WIN) && !defined (P_OS_MAC) && !defined (P_OS_LINUX)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_CRAY)
+# if !defined (P_OS_LINUX)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+ /* Test for CPU architecture detection macros */
+#if defined (P_OS_VMS)
+# if !defined (P_CPU_ALPHA) && !defined (P_CPU_IA64)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_AMIGA)
+# if !defined (P_CPU_POWER)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_TRU64)
+# if !defined (P_CPU_ALPHA)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_AIX)
+# if !defined (P_CPU_POWER)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_HPUX)
+# if !defined (P_CPU_HPPA) && !defined (P_CPU_IA64)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_SOLARIS)
+# if !defined (P_CPU_X86) && !defined (P_CPU_SPARC) && !defined (P_CPU_POWER)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_QNX)
+# if !defined (P_CPU_X86)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_QNX6)
+# if !defined (P_CPU_X86) && !defined (P_CPU_ARM) && \
+ !defined (P_CPU_MIPS) && !defined (P_CPU_POWER)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_BB10)
+# if !defined(P_CPU_X86) && !defined (P_CPU_ARM)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_SCO)
+# if !defined (P_CPU_X86)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_UNIXWARE)
+# if !defined (P_CPU_X86)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_IRIX)
+# if !defined (P_CPU_MIPS)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_HAIKU)
+# if !defined (P_CPU_X86) && !defined (P_CPU_ARM)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_SYLLABLE)
+# if !defined (P_CPU_X86)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_BEOS)
+# if !defined (P_CPU_X86) && !defined (P_CPU_POWER)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_OS2)
+# if !defined (P_CPU_X86)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_MAC9)
+# if !defined (P_CPU_POWER)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_MAC)
+# if !defined (P_CPU_X86) && !defined (P_CPU_POWER)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_WIN)
+# if !defined (P_CPU_X86) && !defined (P_CPU_ARM) && !defined (P_CPU_IA64) && \
+ !defined (P_CPU_MIPS) && !defined (P_CPU_POWER) && !defined (P_CPU_ALPHA)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_OS_ANDROID)
+# if !defined (P_CPU_X86) && !defined (P_CPU_ARM) && !defined (P_CPU_MIPS)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_MSVC)
+# if !defined (P_CPU_X86) && !defined (P_CPU_ARM) && !defined (P_CPU_IA64) && \
+ !defined (P_CPU_MIPS) && !defined (P_CPU_POWER) && !defined (P_CPU_ALPHA)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_SUN)
+# if !defined (P_CPU_X86) && !defined (P_CPU_SPARC)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_XLC)
+# if !defined (P_CPU_POWER)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_HP)
+# if !defined (P_CPU_HPPA) && !defined (P_CPU_IA64)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_DEC)
+# if !defined (P_CPU_ALPHA) && !defined (P_CPU_IA64)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_MIPS)
+# if !defined (P_CPU_MIPS)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_USLC)
+# if !defined (P_CPU_X86)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_WATCOM)
+# if !defined (P_CPU_X86)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_BORLAND)
+# if !defined (P_CPU_X86)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CC_PGI)
+# if !defined (P_CPU_X86) && !defined (P_CPU_POWER)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM)
+# if !defined (P_CPU_ARM_V2) && !defined (P_CPU_ARM_V3) && !defined (P_CPU_ARM_V4) && \
+ !defined (P_CPU_ARM_V5) && !defined (P_CPU_ARM_V6) && !defined (P_CPU_ARM_V7) && \
+ !defined (P_CPU_ARM_V8)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM_V2)
+# if !defined (P_CPU_ARM) || !(P_CPU_ARM - 0 == 2)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM_V3)
+# if !defined (P_CPU_ARM) || !(P_CPU_ARM - 0 == 3)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM_V4)
+# if !defined (P_CPU_ARM) || !(P_CPU_ARM - 0 == 4)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM_V5)
+# if !defined (P_CPU_ARM) || !(P_CPU_ARM - 0 == 5)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM_V6)
+# if !defined (P_CPU_ARM) || !(P_CPU_ARM - 0 == 6)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM_V7)
+# if !defined (P_CPU_ARM) || !(P_CPU_ARM - 0 == 7)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM_V8)
+# if !defined (P_CPU_ARM) || !(P_CPU_ARM - 0 == 8)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM) && !(P_CPU_ARM - 0 > 0)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_CPU_ARM)
+# if !defined (P_CPU_ARM_32) && !defined (P_CPU_ARM_64)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM_32) || defined (P_CPU_ARM_64)
+# if !defined (P_CPU_ARM)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM_32)
+# ifdef P_CPU_ARM_64
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_ARM_64)
+# ifdef P_CPU_ARM_32
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_X86)
+# if !((P_CPU_X86 >= 3) && (P_CPU_X86 <= 6))
+ P_TEST_CHECK (false);
+# endif
+# if !defined (P_CPU_X86_32) && !defined (P_CPU_X86_64)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_X86_32) || defined (P_CPU_X86_64)
+# if !defined (P_CPU_X86)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_X86_32) && defined (P_CPU_X86_64)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_CPU_X86_64)
+# if !defined (P_CPU_X86) || !(P_CPU_X86 - 0 == 6)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_MIPS)
+# if !defined (P_CPU_MIPS_I) && !defined (P_CPU_MIPS_II) && !defined (P_CPU_MIPS_III) && \
+ !defined (P_CPU_MIPS_IV) && !defined (P_CPU_MIPS_V) && !defined (P_CPU_MIPS_32) && \
+ !defined (P_CPU_MIPS_64)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_MIPS_I) || defined (P_CPU_MIPS_II) || defined (P_CPU_MIPS_III) || \
+ defined (P_CPU_MIPS_IV) || defined (P_CPU_MIPS_V) || defined (P_CPU_MIPS_32) || \
+ defined (P_CPU_MIPS_64)
+# if !defined (P_CPU_MIPS)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_MIPS_II)
+# if !defined (P_CPU_MIPS_I)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_MIPS_III)
+# if !defined (P_CPU_MIPS_II)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_MIPS_IV)
+# if !defined (P_CPU_MIPS_III)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_MIPS_V)
+# if !defined (P_CPU_MIPS_IV)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_MIPS_32)
+# if !defined (P_CPU_MIPS_II)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_MIPS_64)
+# if !defined (P_CPU_MIPS_V)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_POWER)
+# if !defined (P_CPU_POWER_32) && !defined (P_CPU_POWER_64)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_POWER_32) || defined (P_CPU_POWER_64)
+# if !defined (P_CPU_POWER)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_POWER_32) && defined (P_CPU_POWER_64)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_CPU_SPARC_V8) || defined (P_CPU_SPARC_V9)
+# if !defined (P_CPU_SPARC)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_SPARC_V8) && defined (P_CPU_SPARC_V9)
+ P_TEST_CHECK (false);
+#endif
+
+#if defined (P_CPU_HPPA)
+# if !defined (P_CPU_HPPA_32) && !defined (P_CPU_HPPA_64)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_HPPA_32) || defined (P_CPU_HPPA_64)
+# if !defined (P_CPU_HPPA)
+ P_TEST_CHECK (false);
+# endif
+#endif
+
+#if defined (P_CPU_HPPA_32) && defined (P_CPU_HPPA_64)
+ P_TEST_CHECK (false);
+#endif
+
+ /* Test other macros */
+ pint unused;
+ P_UNUSED (unused);
+
+ pint result = unused_result_test_func ();
+
+ P_UNUSED (result);
+
+ P_TEST_CHECK (internal_api_test () == 0);
+ P_TEST_CHECK (global_api_test () == 0);
+
+ P_WARNING ("Test warning output");
+ P_ERROR ("Test error output");
+ P_DEBUG ("Test debug output");
+
+ srand ((unsigned int) time (NULL));
+
+ pint rand_number = rand ();
+
+ if (P_LIKELY (rand_number > 0))
+ P_DEBUG ("Likely condition triggered");
+
+ if (P_UNLIKELY (rand_number == 0))
+ P_DEBUG ("Unlikely condition triggered");
+
+ /* Test version macros */
+ P_TEST_CHECK (PLIBSYS_VERSION_MAJOR >= 0);
+ P_TEST_CHECK (PLIBSYS_VERSION_MINOR >= 0);
+ P_TEST_CHECK (PLIBSYS_VERSION_PATCH >= 0);
+ P_TEST_CHECK (PLIBSYS_VERSION >= 0);
+
+#if !defined (PLIBSYS_VERSION_STR)
+ P_TEST_CHECK (false);
+#endif
+
+ P_TEST_CHECK (PLIBSYS_VERSION >= PLIBSYS_VERSION_CHECK (0, 0, 1));
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pmacros_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pmain_test.cpp b/3rdparty/plibsys/tests/pmain_test.cpp
new file mode 100644
index 0000000..ec1b553
--- /dev/null
+++ b/3rdparty/plibsys/tests/pmain_test.cpp
@@ -0,0 +1,111 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+P_TEST_MODULE_INIT ();
+
+static pint alloc_counter = 0;
+static pint realloc_counter = 0;
+static pint free_counter = 0;
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ ++alloc_counter;
+ return (ppointer) malloc (nbytes);
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ ++realloc_counter;
+ return (ppointer) realloc (block, nbytes);
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ ++free_counter;
+ free (block);
+}
+
+P_TEST_CASE_BEGIN (pmain_general_test)
+{
+ p_libsys_init ();
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pmain_double_test)
+{
+ p_libsys_init_full (NULL);
+ p_libsys_init ();
+ p_libsys_shutdown ();
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pmain_vtable_test)
+{
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ p_libsys_init_full (&vtable);
+
+ alloc_counter = 0;
+ realloc_counter = 0;
+ free_counter = 0;
+
+ pchar *buf = (pchar *) p_malloc0 (10);
+ pchar *new_buf = (pchar *) p_realloc ((ppointer) buf, 20);
+
+ P_TEST_REQUIRE (new_buf != NULL);
+
+ buf = new_buf;
+
+ p_free (buf);
+
+ P_TEST_CHECK (alloc_counter > 0);
+ P_TEST_CHECK (realloc_counter > 0);
+ P_TEST_CHECK (free_counter > 0);
+
+ P_TEST_CHECK (strcmp (p_libsys_version (), PLIBSYS_VERSION_STR) == 0);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pmain_general_test);
+ P_TEST_SUITE_RUN_CASE (pmain_double_test);
+ P_TEST_SUITE_RUN_CASE (pmain_vtable_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pmem_test.cpp b/3rdparty/plibsys/tests/pmem_test.cpp
new file mode 100644
index 0000000..c9504b6
--- /dev/null
+++ b/3rdparty/plibsys/tests/pmem_test.cpp
@@ -0,0 +1,171 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+P_TEST_MODULE_INIT ();
+
+static pint alloc_counter = 0;
+static pint realloc_counter = 0;
+static pint free_counter = 0;
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ ++alloc_counter;
+ return (ppointer) malloc (nbytes);
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ ++realloc_counter;
+ return (ppointer) realloc (block, nbytes);
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ ++free_counter;
+ free (block);
+}
+
+P_TEST_CASE_BEGIN (pmem_bad_input_test)
+{
+ PMemVTable vtable;
+
+ p_libsys_init ();
+
+ vtable.free = NULL;
+ vtable.malloc = NULL;
+ vtable.realloc = NULL;
+
+ P_TEST_CHECK (p_malloc (0) == NULL);
+ P_TEST_CHECK (p_malloc0 (0) == NULL);
+ P_TEST_CHECK (p_realloc (NULL, 0) == NULL);
+ P_TEST_CHECK (p_mem_set_vtable (NULL) == FALSE);
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == FALSE);
+ p_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pmem_general_test)
+{
+ PMemVTable vtable;
+ ppointer ptr = NULL;
+ pint i;
+
+ p_libsys_init ();
+
+ alloc_counter = 0;
+ realloc_counter = 0;
+ free_counter = 0;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ /* Test memory allocation using system functions */
+ ptr = p_malloc (1024);
+ P_TEST_REQUIRE (ptr != NULL);
+
+ for (int i = 0; i < 1024; ++i)
+ *(((pchar *) ptr) + i) = (pchar) (i % 127);
+
+ for (int i = 0; i < 1024; ++i)
+ P_TEST_CHECK (*(((pchar *) ptr) + i) == (pchar) (i % 127));
+
+ p_free (ptr);
+
+ ptr = p_malloc0 (2048);
+ P_TEST_REQUIRE (ptr != NULL);
+
+ for (int i = 0; i < 2048; ++i)
+ P_TEST_CHECK (*(((pchar *) ptr) + i) == 0);
+
+ for (int i = 0; i < 2048; ++i)
+ *(((pchar *) ptr) + i) = (pchar) (i % 127);
+
+ for (int i = 0; i < 2048; ++i)
+ P_TEST_CHECK (*(((pchar *) ptr) + i) == (pchar) (i % 127));
+
+ p_free (ptr);
+
+ ptr = p_realloc (NULL, 1024);
+ P_TEST_REQUIRE (ptr != NULL);
+
+ for (int i = 0; i < 1024; ++i)
+ *(((pchar *) ptr) + i) = (pchar) (i % 127);
+
+ ptr = p_realloc (ptr, 2048);
+
+ for (int i = 1024; i < 2048; ++i)
+ *(((pchar *) ptr) + i) = (pchar) ((i - 1) % 127);
+
+ for (int i = 0; i < 1024; ++i)
+ P_TEST_CHECK (*(((pchar *) ptr) + i) == (pchar) (i % 127));
+
+ for (int i = 1024; i < 2048; ++i)
+ P_TEST_CHECK (*(((pchar *) ptr) + i) == (pchar) ((i - 1) % 127));
+
+ p_free (ptr);
+
+ P_TEST_CHECK (alloc_counter > 0);
+ P_TEST_CHECK (realloc_counter > 0);
+ P_TEST_CHECK (free_counter > 0);
+
+ p_mem_restore_vtable ();
+
+ /* Test memory mapping */
+ ptr = p_mem_mmap (0, NULL);
+ P_TEST_CHECK (ptr == NULL);
+
+ ptr = p_mem_mmap (1024, NULL);
+ P_TEST_REQUIRE (ptr != NULL);
+
+ for (i = 0; i < 1024; ++i)
+ *(((pchar *) ptr) + i) = i % 127;
+
+ for (i = 0; i < 1024; ++i)
+ P_TEST_CHECK (*(((pchar *) ptr) + i) == i % 127);
+
+ P_TEST_CHECK (p_mem_munmap (NULL, 1024, NULL) == FALSE);
+ P_TEST_CHECK (p_mem_munmap (ptr, 1024, NULL) == TRUE);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pmem_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (pmem_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pmutex_test.cpp b/3rdparty/plibsys/tests/pmutex_test.cpp
new file mode 100644
index 0000000..4d16909
--- /dev/null
+++ b/3rdparty/plibsys/tests/pmutex_test.cpp
@@ -0,0 +1,146 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2019 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+P_TEST_MODULE_INIT ();
+
+static pint mutex_test_val = 0;
+static PMutex *global_mutex = NULL;
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+static void * mutex_test_thread (void *)
+{
+ pint i;
+
+ for (i = 0; i < 1000; ++i) {
+ if (!p_mutex_trylock (global_mutex)) {
+ if (!p_mutex_lock (global_mutex))
+ p_uthread_exit (1);
+ }
+
+ if (mutex_test_val == 10)
+ --mutex_test_val;
+ else {
+ p_uthread_sleep (1);
+ ++mutex_test_val;
+ }
+
+ if (!p_mutex_unlock (global_mutex))
+ p_uthread_exit (1);
+ }
+
+ p_uthread_exit (0);
+
+ return NULL;
+}
+
+P_TEST_CASE_BEGIN (pmutex_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+ P_TEST_CHECK (p_mutex_new () == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pmutex_bad_input_test)
+{
+ p_libsys_init ();
+
+ P_TEST_REQUIRE (p_mutex_lock (NULL) == FALSE);
+ P_TEST_REQUIRE (p_mutex_unlock (NULL) == FALSE);
+ P_TEST_REQUIRE (p_mutex_trylock (NULL) == FALSE);
+ p_mutex_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pmutex_general_test)
+{
+ PUThread *thr1, *thr2;
+
+ p_libsys_init ();
+
+ global_mutex = p_mutex_new ();
+ P_TEST_REQUIRE (global_mutex != NULL);
+
+ mutex_test_val = 10;
+
+ thr1 = p_uthread_create ((PUThreadFunc) mutex_test_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr1 != NULL);
+
+ thr2 = p_uthread_create ((PUThreadFunc) mutex_test_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr2 != NULL);
+
+ P_TEST_CHECK (p_uthread_join (thr1) == 0);
+ P_TEST_CHECK (p_uthread_join (thr2) == 0);
+
+ P_TEST_REQUIRE (mutex_test_val == 10);
+
+ p_uthread_unref (thr1);
+ p_uthread_unref (thr2);
+ p_mutex_free (global_mutex);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pmutex_nomem_test);
+ P_TEST_SUITE_RUN_CASE (pmutex_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (pmutex_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pprocess_test.cpp b/3rdparty/plibsys/tests/pprocess_test.cpp
new file mode 100644
index 0000000..c58cf13
--- /dev/null
+++ b/3rdparty/plibsys/tests/pprocess_test.cpp
@@ -0,0 +1,49 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+P_TEST_MODULE_INIT ();
+
+P_TEST_CASE_BEGIN (pprocess_general_test)
+{
+ puint32 pid;
+
+ p_libsys_init ();
+
+ pid = p_process_get_current_pid ();
+ P_TEST_CHECK (pid > 0);
+ P_TEST_REQUIRE (p_process_is_running (pid) == TRUE);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pprocess_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/prwlock_test.cpp b/3rdparty/plibsys/tests/prwlock_test.cpp
new file mode 100644
index 0000000..c8bce38
--- /dev/null
+++ b/3rdparty/plibsys/tests/prwlock_test.cpp
@@ -0,0 +1,224 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2016-2019 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <string.h>
+
+P_TEST_MODULE_INIT ();
+
+#define PRWLOCK_TEST_STRING_1 "This is a test string."
+#define PRWLOCK_TEST_STRING_2 "Ouh, yet another string to check!"
+
+static PRWLock * test_rwlock = NULL;
+static volatile pboolean is_threads_working = FALSE;
+static volatile pint writers_counter = 0;
+static pchar string_buf[50];
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+static void * reader_thread_func (void *data)
+{
+ P_UNUSED (data);
+
+ pint counter = 0;
+
+ while (p_atomic_int_get (&writers_counter) == 0)
+ p_uthread_sleep (10);
+
+ while (is_threads_working == TRUE) {
+ p_uthread_sleep (10);
+
+ if (p_rwlock_reader_trylock (test_rwlock) == FALSE) {
+ if (p_rwlock_reader_lock (test_rwlock) == FALSE)
+ p_uthread_exit (-1);
+ }
+
+ if (strcmp (string_buf, PRWLOCK_TEST_STRING_1) != 0 &&
+ strcmp (string_buf, PRWLOCK_TEST_STRING_2) != 0) {
+ p_rwlock_reader_unlock (test_rwlock);
+ p_uthread_exit (-1);
+ }
+
+ if (p_rwlock_reader_unlock (test_rwlock) == FALSE)
+ p_uthread_exit (-1);
+
+ ++counter;
+ }
+
+ p_uthread_exit (counter);
+
+ return NULL;
+}
+
+static void * writer_thread_func (void *data)
+{
+ pint string_num = PPOINTER_TO_INT (data);
+ pint counter = 0;
+
+ while (is_threads_working == TRUE) {
+ p_uthread_sleep (10);
+
+ if (p_rwlock_writer_trylock (test_rwlock) == FALSE) {
+ if (p_rwlock_writer_lock (test_rwlock) == FALSE)
+ p_uthread_exit (-1);
+ }
+
+ memset (string_buf, 0, sizeof (string_buf));
+
+ if (string_num == 1)
+ strcpy (string_buf, PRWLOCK_TEST_STRING_1);
+ else
+ strcpy (string_buf, PRWLOCK_TEST_STRING_1);
+
+ if (p_rwlock_writer_unlock (test_rwlock) == FALSE)
+ p_uthread_exit (-1);
+
+ ++counter;
+
+ p_atomic_int_inc ((&writers_counter));
+ }
+
+ p_uthread_exit (counter);
+
+ return NULL;
+}
+
+P_TEST_CASE_BEGIN (prwlock_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_rwlock_new () == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (prwlock_bad_input_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_rwlock_reader_lock (NULL) == FALSE);
+ P_TEST_CHECK (p_rwlock_reader_trylock (NULL) == FALSE);
+ P_TEST_CHECK (p_rwlock_reader_unlock (NULL) == FALSE);
+ P_TEST_CHECK (p_rwlock_writer_lock (NULL) == FALSE);
+ P_TEST_CHECK (p_rwlock_writer_trylock (NULL) == FALSE);
+ P_TEST_CHECK (p_rwlock_writer_unlock (NULL) == FALSE);
+ p_rwlock_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (prwlock_general_test)
+{
+ p_libsys_init ();
+
+ test_rwlock = p_rwlock_new ();
+
+ P_TEST_REQUIRE (test_rwlock != NULL);
+
+ is_threads_working = TRUE;
+ writers_counter = 0;
+
+ PUThread *reader_thr1 = p_uthread_create ((PUThreadFunc) reader_thread_func,
+ NULL,
+ TRUE,
+ NULL);
+
+ PUThread *reader_thr2 = p_uthread_create ((PUThreadFunc) reader_thread_func,
+ NULL,
+ TRUE,
+ NULL);
+
+ PUThread *writer_thr1 = p_uthread_create ((PUThreadFunc) writer_thread_func,
+ NULL,
+ TRUE,
+ NULL);
+
+ PUThread *writer_thr2 = p_uthread_create ((PUThreadFunc) writer_thread_func,
+ NULL,
+ TRUE,
+ NULL);
+
+ P_TEST_REQUIRE (reader_thr1 != NULL);
+ P_TEST_REQUIRE (reader_thr2 != NULL);
+ P_TEST_REQUIRE (writer_thr1 != NULL);
+ P_TEST_REQUIRE (writer_thr2 != NULL);
+
+ p_uthread_sleep (10000);
+
+ is_threads_working = FALSE;
+
+ P_TEST_CHECK (p_uthread_join (reader_thr1) > 0);
+ P_TEST_CHECK (p_uthread_join (reader_thr2) > 0);
+ P_TEST_CHECK (p_uthread_join (writer_thr1) > 0);
+ P_TEST_CHECK (p_uthread_join (writer_thr2) > 0);
+
+ p_uthread_unref (reader_thr1);
+ p_uthread_unref (reader_thr2);
+ p_uthread_unref (writer_thr1);
+ p_uthread_unref (writer_thr2);
+
+ p_rwlock_free (test_rwlock);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (prwlock_nomem_test);
+ P_TEST_SUITE_RUN_CASE (prwlock_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (prwlock_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/psemaphore_test.cpp b/3rdparty/plibsys/tests/psemaphore_test.cpp
new file mode 100644
index 0000000..0b445bd
--- /dev/null
+++ b/3rdparty/plibsys/tests/psemaphore_test.cpp
@@ -0,0 +1,226 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2019 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+P_TEST_MODULE_INIT ();
+
+#define PSEMAPHORE_MAX_VAL 10
+
+static pint semaphore_test_val = 0;
+static pint is_thread_exit = 0;
+
+static void clean_error (PError **error)
+{
+ if (error == NULL || *error == NULL)
+ return;
+
+ p_error_free (*error);
+ *error = NULL;
+}
+
+static void * semaphore_test_thread (void *)
+{
+ PSemaphore *sem;
+ pint i;
+
+ sem = p_semaphore_new ("p_semaphore_test_object", 1, P_SEM_ACCESS_OPEN, NULL);
+
+ if (sem == NULL)
+ p_uthread_exit (1);
+
+ for (i = 0; i < 1000; ++i) {
+ if (!p_semaphore_acquire (sem, NULL)) {
+ if (is_thread_exit > 0) {
+ semaphore_test_val = PSEMAPHORE_MAX_VAL;
+ break;
+ }
+
+ p_uthread_exit (1);
+ }
+
+ if (semaphore_test_val == PSEMAPHORE_MAX_VAL)
+ --semaphore_test_val;
+ else {
+ p_uthread_sleep (1);
+ ++semaphore_test_val;
+ }
+
+ if (!p_semaphore_release (sem, NULL)) {
+ if (is_thread_exit > 0) {
+ semaphore_test_val = PSEMAPHORE_MAX_VAL;
+ break;
+ }
+
+ p_uthread_exit (1);
+ }
+ }
+
+ ++is_thread_exit;
+
+ p_semaphore_free (sem);
+ p_uthread_exit (0);
+
+ return NULL;
+}
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+P_TEST_CASE_BEGIN (psemaphore_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_semaphore_new ("p_semaphore_test_object", 1, P_SEM_ACCESS_CREATE, NULL) == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (psemaphore_general_test)
+{
+ PSemaphore *sem = NULL;
+ PError *error = NULL;
+ pint i;
+
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_semaphore_new (NULL, 0, P_SEM_ACCESS_CREATE, &error) == NULL);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_REQUIRE (p_semaphore_acquire (sem, &error) == FALSE);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_REQUIRE (p_semaphore_release (sem, &error) == FALSE);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ p_semaphore_take_ownership (sem);
+ p_semaphore_free (NULL);
+
+ sem = p_semaphore_new ("p_semaphore_test_object", 10, P_SEM_ACCESS_CREATE, NULL);
+ P_TEST_REQUIRE (sem != NULL);
+ p_semaphore_take_ownership (sem);
+ p_semaphore_free (sem);
+
+ sem = p_semaphore_new ("p_semaphore_test_object", 10, P_SEM_ACCESS_CREATE, NULL);
+ P_TEST_REQUIRE (sem != NULL);
+
+ for (i = 0; i < 10; ++i)
+ P_TEST_CHECK (p_semaphore_acquire (sem, NULL));
+
+ for (i = 0; i < 10; ++i)
+ P_TEST_CHECK (p_semaphore_release (sem, NULL));
+
+ for (i = 0; i < 1000; ++i) {
+ P_TEST_CHECK (p_semaphore_acquire (sem, NULL));
+ P_TEST_CHECK (p_semaphore_release (sem, NULL));
+ }
+
+ p_semaphore_free (sem);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (psemaphore_thread_test)
+{
+ PUThread *thr1, *thr2;
+ PSemaphore *sem = NULL;
+
+ p_libsys_init ();
+
+ sem = p_semaphore_new ("p_semaphore_test_object", 10, P_SEM_ACCESS_CREATE, NULL);
+ P_TEST_REQUIRE (sem != NULL);
+ p_semaphore_take_ownership (sem);
+ p_semaphore_free (sem);
+
+ sem = NULL;
+ is_thread_exit = 0;
+ semaphore_test_val = PSEMAPHORE_MAX_VAL;
+
+ thr1 = p_uthread_create ((PUThreadFunc) semaphore_test_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr1 != NULL);
+
+ thr2 = p_uthread_create ((PUThreadFunc) semaphore_test_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr2 != NULL);
+
+ P_TEST_CHECK (p_uthread_join (thr1) == 0);
+ P_TEST_CHECK (p_uthread_join (thr2) == 0);
+
+ P_TEST_REQUIRE (semaphore_test_val == PSEMAPHORE_MAX_VAL);
+
+ P_TEST_REQUIRE (p_semaphore_acquire (sem, NULL) == FALSE);
+ P_TEST_REQUIRE (p_semaphore_release (sem, NULL) == FALSE);
+ p_semaphore_free (sem);
+ p_semaphore_take_ownership (sem);
+
+ sem = p_semaphore_new ("p_semaphore_test_object", 1, P_SEM_ACCESS_OPEN, NULL);
+ P_TEST_REQUIRE (sem != NULL);
+ p_semaphore_take_ownership (sem);
+ p_semaphore_free (sem);
+
+ p_uthread_unref (thr1);
+ p_uthread_unref (thr2);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (psemaphore_nomem_test);
+ P_TEST_SUITE_RUN_CASE (psemaphore_general_test);
+ P_TEST_SUITE_RUN_CASE (psemaphore_thread_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pshm_test.cpp b/3rdparty/plibsys/tests/pshm_test.cpp
new file mode 100644
index 0000000..bc89692
--- /dev/null
+++ b/3rdparty/plibsys/tests/pshm_test.cpp
@@ -0,0 +1,313 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2019 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <stdlib.h>
+#include <time.h>
+
+P_TEST_MODULE_INIT ();
+
+static void * shm_test_thread (void *arg)
+{
+ pint rand_num;
+ psize shm_size;
+ ppointer addr;
+ PShm *shm;
+
+ if (arg == NULL)
+ p_uthread_exit (1);
+
+ shm = (PShm *) arg;
+ rand_num = rand () % 127;
+ shm_size = p_shm_get_size (shm);
+ addr = p_shm_get_address (shm);
+
+ if (shm_size == 0 || addr == NULL)
+ p_uthread_exit (1);
+
+ if (!p_shm_lock (shm, NULL))
+ p_uthread_exit (1);
+
+ for (puint i = 0; i < shm_size; ++i)
+ *(((pchar *) addr) + i) = (pchar) rand_num;
+
+ if (!p_shm_unlock (shm, NULL))
+ p_uthread_exit (1);
+
+ p_uthread_exit (0);
+
+ return NULL;
+}
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+P_TEST_CASE_BEGIN (pshm_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL) == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pshm_invalid_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_shm_new (NULL, 0, P_SHM_ACCESS_READWRITE, NULL) == NULL);
+ P_TEST_CHECK (p_shm_lock (NULL, NULL) == FALSE);
+ P_TEST_CHECK (p_shm_unlock (NULL, NULL) == FALSE);
+ P_TEST_CHECK (p_shm_get_address (NULL) == NULL);
+ P_TEST_CHECK (p_shm_get_size (NULL) == 0);
+ p_shm_take_ownership (NULL);
+
+ PShm *shm = p_shm_new ("p_shm_invalid_test", 0, P_SHM_ACCESS_READWRITE, NULL);
+ p_shm_take_ownership (shm);
+ p_shm_free (shm);
+
+ shm = p_shm_new ("p_shm_invalid_test", 10, (PShmAccessPerms) -1, NULL);
+ p_shm_take_ownership (shm);
+ p_shm_free (shm);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pshm_general_test)
+{
+ PShm *shm = NULL;
+#ifndef P_OS_HPUX
+ PShm *shm2 = NULL;
+#endif
+ ppointer addr, addr2;
+ pint i;
+
+ p_libsys_init ();
+
+ shm = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL);
+ P_TEST_REQUIRE (shm != NULL);
+ p_shm_take_ownership (shm);
+ p_shm_free (shm);
+
+ shm = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL);
+ P_TEST_REQUIRE (shm != NULL);
+ P_TEST_REQUIRE (p_shm_get_size (shm) == 1024);
+
+ addr = p_shm_get_address (shm);
+ P_TEST_REQUIRE (addr != NULL);
+
+#ifndef P_OS_HPUX
+ shm2 = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READONLY, NULL);
+
+ if (shm2 == NULL) {
+ /* OK, some systems may want exactly the same permissions */
+ shm2 = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL);
+ }
+
+ P_TEST_REQUIRE (shm2 != NULL);
+ P_TEST_REQUIRE (p_shm_get_size (shm2) == 1024);
+
+ addr2 = p_shm_get_address (shm2);
+ P_TEST_REQUIRE (addr2 != NULL);
+#endif
+
+ for (i = 0; i < 512; ++i) {
+ P_TEST_CHECK (p_shm_lock (shm, NULL));
+ *(((pchar *) addr) + i) = 'a';
+ P_TEST_CHECK (p_shm_unlock (shm, NULL));
+ }
+
+#ifndef P_OS_HPUX
+ for (i = 0; i < 512; ++i) {
+ P_TEST_CHECK (p_shm_lock (shm2, NULL));
+ P_TEST_CHECK (*(((pchar *) addr) + i) == 'a');
+ P_TEST_CHECK (p_shm_unlock (shm2, NULL));
+ }
+#else
+ for (i = 0; i < 512; ++i) {
+ P_TEST_CHECK (p_shm_lock (shm, NULL));
+ P_TEST_CHECK (*(((pchar *) addr) + i) == 'a');
+ P_TEST_CHECK (p_shm_unlock (shm, NULL));
+ }
+#endif
+
+ for (i = 0; i < 1024; ++i) {
+ P_TEST_CHECK (p_shm_lock (shm, NULL));
+ *(((pchar *) addr) + i) = 'b';
+ P_TEST_CHECK (p_shm_unlock (shm, NULL));
+ }
+
+#ifndef P_OS_HPUX
+ for (i = 0; i < 1024; ++i) {
+ P_TEST_CHECK (p_shm_lock (shm2, NULL));
+ P_TEST_CHECK (*(((pchar *) addr) + i) != 'c');
+ P_TEST_CHECK (p_shm_unlock (shm2, NULL));
+ }
+
+ for (i = 0; i < 1024; ++i) {
+ P_TEST_CHECK (p_shm_lock (shm2, NULL));
+ P_TEST_CHECK (*(((pchar *) addr) + i) == 'b');
+ P_TEST_CHECK (p_shm_unlock (shm2, NULL));
+ }
+#else
+ for (i = 0; i < 1024; ++i) {
+ P_TEST_CHECK (p_shm_lock (shm, NULL));
+ P_TEST_CHECK (*(((pchar *) addr) + i) != 'c');
+ P_TEST_CHECK (p_shm_unlock (shm, NULL));
+ }
+
+ for (i = 0; i < 1024; ++i) {
+ P_TEST_CHECK (p_shm_lock (shm, NULL));
+ P_TEST_CHECK (*(((pchar *) addr) + i) == 'b');
+ P_TEST_CHECK (p_shm_unlock (shm, NULL));
+ }
+#endif
+
+ p_shm_free (shm);
+
+ shm = p_shm_new ("p_shm_test_memory_block_2", 1024, P_SHM_ACCESS_READWRITE, NULL);
+ P_TEST_REQUIRE (shm != NULL);
+ P_TEST_REQUIRE (p_shm_get_size (shm) == 1024);
+
+ addr = p_shm_get_address (shm);
+ P_TEST_REQUIRE (addr != NULL);
+
+ for (i = 0; i < 1024; ++i) {
+ P_TEST_CHECK (p_shm_lock (shm, NULL));
+ P_TEST_CHECK (*(((pchar *) addr) + i) != 'b');
+ P_TEST_CHECK (p_shm_unlock (shm, NULL));
+ }
+
+ p_shm_free (shm);
+
+#ifndef P_OS_HPUX
+ p_shm_free (shm2);
+#endif
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pshm_thread_test)
+{
+ PShm *shm;
+ PUThread *thr1, *thr2, *thr3;
+ ppointer addr;
+ pint i, val;
+ pboolean test_ok;
+
+ p_libsys_init ();
+
+ srand ((puint) time (NULL));
+
+ shm = p_shm_new ("p_shm_test_memory_block", 1024 * 1024, P_SHM_ACCESS_READWRITE, NULL);
+ P_TEST_REQUIRE (shm != NULL);
+ p_shm_take_ownership (shm);
+ p_shm_free (shm);
+
+ shm = p_shm_new ("p_shm_test_memory_block", 1024 * 1024, P_SHM_ACCESS_READWRITE, NULL);
+ P_TEST_REQUIRE (shm != NULL);
+
+ if (p_shm_get_size (shm) != 1024 * 1024) {
+ p_shm_free (shm);
+ shm = p_shm_new ("p_shm_test_memory_block", 1024 * 1024, P_SHM_ACCESS_READWRITE, NULL);
+ P_TEST_REQUIRE (shm != NULL);
+ }
+
+ P_TEST_REQUIRE (p_shm_get_size (shm) == 1024 * 1024);
+
+ addr = p_shm_get_address (shm);
+ P_TEST_REQUIRE (addr != NULL);
+
+ thr1 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, TRUE, NULL);
+ P_TEST_REQUIRE (thr1 != NULL);
+
+ thr2 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, TRUE, NULL);
+ P_TEST_REQUIRE (thr2 != NULL);
+
+ thr3 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, TRUE, NULL);
+ P_TEST_REQUIRE (thr3 != NULL);
+
+ P_TEST_CHECK (p_uthread_join (thr1) == 0);
+ P_TEST_CHECK (p_uthread_join (thr2) == 0);
+ P_TEST_CHECK (p_uthread_join (thr3) == 0);
+
+ test_ok = TRUE;
+ val = *((pchar *) addr);
+
+ for (i = 1; i < 1024 * 1024; ++i)
+ if (*(((pchar *) addr) + i) != val) {
+ test_ok = FALSE;
+ break;
+ }
+
+ P_TEST_REQUIRE (test_ok == TRUE);
+
+ p_uthread_unref (thr1);
+ p_uthread_unref (thr2);
+ p_uthread_unref (thr3);
+ p_shm_free (shm);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pshm_nomem_test);
+ P_TEST_SUITE_RUN_CASE (pshm_invalid_test);
+ P_TEST_SUITE_RUN_CASE (pshm_general_test);
+ P_TEST_SUITE_RUN_CASE (pshm_thread_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pshmbuffer_test.cpp b/3rdparty/plibsys/tests/pshmbuffer_test.cpp
new file mode 100644
index 0000000..7e48f56
--- /dev/null
+++ b/3rdparty/plibsys/tests/pshmbuffer_test.cpp
@@ -0,0 +1,352 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2020 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <string.h>
+
+P_TEST_MODULE_INIT ();
+
+static pchar test_str[] = "This is a test string!";
+static pchar test_str_sm[] = "Small";
+static pint is_thread_exit = 0;
+static pint read_count = 0;
+static pint write_count = 0;
+
+#ifndef P_OS_HPUX
+volatile static pboolean is_working = FALSE;
+
+static void * shm_buffer_test_write_thread (void *)
+{
+ PShmBuffer *buffer = p_shm_buffer_new ("pshm_test_buffer", 1024, NULL);
+
+ if (buffer == NULL)
+ p_uthread_exit (1);
+
+ while (is_working == TRUE) {
+ p_uthread_sleep (3);
+
+ pssize op_result = p_shm_buffer_get_free_space (buffer, NULL);
+
+ if (op_result < 0) {
+ if (is_thread_exit > 0)
+ break;
+ else {
+ ++is_thread_exit;
+ p_shm_buffer_free (buffer);
+ p_uthread_exit (1);
+ }
+ }
+
+ if ((psize) op_result < sizeof (test_str))
+ continue;
+
+ op_result = p_shm_buffer_write (buffer, (ppointer) test_str, sizeof (test_str), NULL);
+
+ if (op_result < 0) {
+ if (is_thread_exit > 0)
+ break;
+ else {
+ ++is_thread_exit;
+ p_shm_buffer_free (buffer);
+ p_uthread_exit (1);
+ }
+ }
+
+ if (op_result != sizeof (test_str)) {
+ ++is_thread_exit;
+ p_shm_buffer_free (buffer);
+ p_uthread_exit (1);
+ }
+
+ ++read_count;
+ }
+
+ ++is_thread_exit;
+
+ p_shm_buffer_free (buffer);
+ p_uthread_exit (0);
+
+ return NULL;
+}
+
+static void * shm_buffer_test_read_thread (void *)
+{
+ PShmBuffer *buffer = p_shm_buffer_new ("pshm_test_buffer", 1024, NULL);
+ pchar test_buf[sizeof (test_str)];
+
+ if (buffer == NULL)
+ p_uthread_exit (1);
+
+ while (is_working == TRUE) {
+ p_uthread_sleep (3);
+
+ pssize op_result = p_shm_buffer_get_used_space (buffer, NULL);
+
+ if (op_result < 0) {
+ if (is_thread_exit > 0)
+ break;
+ else {
+ ++is_thread_exit;
+ p_shm_buffer_free (buffer);
+ p_uthread_exit (1);
+ }
+ }
+
+ if ((psize) op_result < sizeof (test_str))
+ continue;
+
+ op_result = p_shm_buffer_read (buffer, (ppointer) test_buf, sizeof (test_buf), NULL);
+
+ if (op_result < 0) {
+ if (is_thread_exit > 0)
+ break;
+ else {
+ ++is_thread_exit;
+ p_shm_buffer_free (buffer);
+ p_uthread_exit (1);
+ }
+ }
+
+ if (op_result != sizeof (test_buf)) {
+ ++is_thread_exit;
+ p_shm_buffer_free (buffer);
+ p_uthread_exit (1);
+ }
+
+ if (strncmp (test_buf, test_str, sizeof (test_buf)) != 0) {
+ ++is_thread_exit;
+ p_shm_buffer_free (buffer);
+ p_uthread_exit (1);
+ }
+
+ ++write_count;
+ }
+
+ ++is_thread_exit;
+
+ p_shm_buffer_free (buffer);
+ p_uthread_exit (0);
+
+ return NULL;
+}
+#endif /* !P_OS_HPUX */
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+P_TEST_CASE_BEGIN (pshmbuffer_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_shm_buffer_new ("pshm_test_buffer", 1024, NULL) == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pshmbuffer_bad_input_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_shm_buffer_new (NULL, 0, NULL) == NULL);
+ P_TEST_CHECK (p_shm_buffer_read (NULL, NULL, 0, NULL) == -1);
+ P_TEST_CHECK (p_shm_buffer_write (NULL, NULL, 0, NULL) == -1);
+ P_TEST_CHECK (p_shm_buffer_get_free_space (NULL, NULL) == -1);
+ P_TEST_CHECK (p_shm_buffer_get_used_space (NULL, NULL) == -1);
+
+ PShmBuffer *buf = p_shm_buffer_new ("pshm_invalid_buffer", 0, NULL);
+ p_shm_buffer_take_ownership (buf);
+ p_shm_buffer_free (buf);
+
+ p_shm_buffer_clear (NULL);
+ p_shm_buffer_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pshmbuffer_general_test)
+{
+ p_libsys_init ();
+
+ pchar test_buf[sizeof (test_str)];
+ pchar *large_buf;
+ PShmBuffer *buffer = NULL;
+
+ /* Buffer may be from the previous test on UNIX systems */
+ buffer = p_shm_buffer_new ("pshm_test_buffer", 1024, NULL);
+ P_TEST_REQUIRE (buffer != NULL);
+ p_shm_buffer_take_ownership (buffer);
+ p_shm_buffer_free (buffer);
+ buffer = p_shm_buffer_new ("pshm_test_buffer", 1024, NULL);
+ P_TEST_REQUIRE (buffer != NULL);
+
+ P_TEST_CHECK (p_shm_buffer_get_free_space (buffer, NULL) == 1024);
+ P_TEST_CHECK (p_shm_buffer_get_used_space (buffer, NULL) == 0);
+ p_shm_buffer_clear (buffer);
+ P_TEST_CHECK (p_shm_buffer_get_free_space (buffer, NULL) == 1024);
+ P_TEST_CHECK (p_shm_buffer_get_used_space (buffer, NULL) == 0);
+
+ memset (test_buf, 0, sizeof (test_buf));
+
+ P_TEST_CHECK (p_shm_buffer_write (buffer, (ppointer) test_str, sizeof (test_str), NULL) == sizeof (test_str));
+ P_TEST_CHECK (p_shm_buffer_get_free_space (buffer, NULL) == (1024 - sizeof (test_str)));
+ P_TEST_CHECK (p_shm_buffer_get_used_space (buffer, NULL) == sizeof (test_str));
+ P_TEST_CHECK (p_shm_buffer_read (buffer, (ppointer) test_buf, sizeof (test_buf), NULL) == sizeof (test_str));
+ P_TEST_CHECK (p_shm_buffer_read (buffer, (ppointer) test_buf, sizeof (test_buf), NULL) == 0);
+
+ P_TEST_CHECK (strncmp (test_buf, test_str, sizeof (test_str)) == 0);
+ P_TEST_CHECK (p_shm_buffer_get_free_space (buffer, NULL) == 1024);
+ P_TEST_CHECK (p_shm_buffer_get_used_space (buffer, NULL) == 0);
+
+ p_shm_buffer_clear (buffer);
+
+ large_buf = (pchar *) p_malloc0 (2048);
+ P_TEST_REQUIRE (large_buf != NULL);
+ P_TEST_CHECK (p_shm_buffer_write (buffer, (ppointer) large_buf, 2048, NULL) == 0);
+
+ p_free (large_buf);
+ p_shm_buffer_free (buffer);
+
+ /* Test read-write positions */
+
+ buffer = p_shm_buffer_new ("pshm_test_buffer_small", 10, NULL);
+ P_TEST_REQUIRE (buffer != NULL);
+ p_shm_buffer_take_ownership (buffer);
+ p_shm_buffer_free (buffer);
+ buffer = p_shm_buffer_new ("pshm_test_buffer_small", 10, NULL);
+ P_TEST_REQUIRE (buffer != NULL);
+
+ P_TEST_CHECK (p_shm_buffer_get_free_space (buffer, NULL) == 10);
+ P_TEST_CHECK (p_shm_buffer_get_used_space (buffer, NULL) == 0);
+
+ /* Case 1: write position > read position */
+ P_TEST_CHECK (p_shm_buffer_write (buffer, (ppointer) test_str_sm, sizeof (test_str_sm), NULL) == sizeof (test_str_sm));
+ P_TEST_CHECK (p_shm_buffer_get_free_space (buffer, NULL) == (10 - sizeof (test_str_sm)));
+ P_TEST_CHECK (p_shm_buffer_get_used_space (buffer, NULL) == sizeof (test_str_sm));
+
+ /* Case 2: write position == read position */
+ memset (test_buf, 0, sizeof (test_buf));
+ P_TEST_CHECK (p_shm_buffer_read (buffer, (ppointer) test_buf, sizeof (test_buf), NULL) == sizeof (test_str_sm));
+ P_TEST_CHECK (strncmp (test_buf, test_str_sm, sizeof (test_str_sm)) == 0);
+ P_TEST_CHECK (p_shm_buffer_get_free_space (buffer, NULL) == 10);
+ P_TEST_CHECK (p_shm_buffer_get_used_space (buffer, NULL) == 0);
+
+ /* Case 3: write position < read position */
+ P_TEST_CHECK (p_shm_buffer_write (buffer, (ppointer) test_str_sm, sizeof (test_str_sm), NULL) == sizeof (test_str_sm));
+ P_TEST_CHECK (p_shm_buffer_get_free_space (buffer, NULL) == (10 - sizeof (test_str_sm)));
+ P_TEST_CHECK (p_shm_buffer_get_used_space (buffer, NULL) == sizeof (test_str_sm));
+
+ p_shm_buffer_free (buffer);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+#ifndef P_OS_HPUX
+P_TEST_CASE_BEGIN (pshmbuffer_thread_test)
+{
+ p_libsys_init ();
+
+ PShmBuffer *buffer = NULL;
+ PUThread *thr1, *thr2;
+
+ /* Buffer may be from the previous test on UNIX systems */
+ buffer = p_shm_buffer_new ("pshm_test_buffer", 1024, NULL);
+ P_TEST_REQUIRE (buffer != NULL);
+ p_shm_buffer_take_ownership (buffer);
+ p_shm_buffer_free (buffer);
+
+ is_thread_exit = 0;
+ read_count = 0;
+ write_count = 0;
+ is_working = TRUE;
+
+ buffer = p_shm_buffer_new ("pshm_test_buffer", 1024, NULL);
+ P_TEST_REQUIRE (buffer != NULL);
+
+ thr1 = p_uthread_create ((PUThreadFunc) shm_buffer_test_write_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr1 != NULL);
+
+ thr2 = p_uthread_create ((PUThreadFunc) shm_buffer_test_read_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr1 != NULL);
+
+ p_uthread_sleep (5000);
+
+ is_working = FALSE;
+
+ P_TEST_CHECK (p_uthread_join (thr1) == 0);
+ P_TEST_CHECK (p_uthread_join (thr2) == 0);
+
+ P_TEST_CHECK (read_count > 0);
+ P_TEST_CHECK (write_count > 0);
+
+ p_shm_buffer_free (buffer);
+ p_uthread_unref (thr1);
+ p_uthread_unref (thr2);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+#endif /* !P_OS_HPUX */
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pshmbuffer_nomem_test);
+ P_TEST_SUITE_RUN_CASE (pshmbuffer_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (pshmbuffer_general_test);
+
+#ifndef P_OS_HPUX
+ P_TEST_SUITE_RUN_CASE (pshmbuffer_thread_test);
+#endif
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/psocket_test.cpp b/3rdparty/plibsys/tests/psocket_test.cpp
new file mode 100644
index 0000000..c1a44a4
--- /dev/null
+++ b/3rdparty/plibsys/tests/psocket_test.cpp
@@ -0,0 +1,1131 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2019 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <string.h>
+
+P_TEST_MODULE_INIT ();
+
+static pchar socket_data[] = "This is a socket test data!";
+volatile static pboolean is_sender_working = FALSE;
+volatile static pboolean is_receiver_working = FALSE;
+
+typedef struct _SocketTestData {
+ puint16 sender_port;
+ puint16 receiver_port;
+ pboolean shutdown_channel;
+} SocketTestData;
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+static void clean_error (PError **error)
+{
+ if (error == NULL || *error == NULL)
+ return;
+
+ p_error_free (*error);
+ *error = NULL;
+}
+
+static pboolean test_socket_address_directly (const PSocketAddress *addr, puint16 port)
+{
+ if (addr == NULL)
+ return FALSE;
+
+ pchar *addr_str = p_socket_address_get_address (addr);
+ PSocketFamily remote_family = p_socket_address_get_family (addr);
+ puint16 remote_port = p_socket_address_get_port (addr);
+ psize remote_size = p_socket_address_get_native_size (addr);
+
+ pboolean ret = (strcmp (addr_str, "127.0.0.1") == 0 && remote_family == P_SOCKET_FAMILY_INET &&
+ remote_port == port && remote_size > 0) ? TRUE : FALSE;
+
+ p_free (addr_str);
+
+ return ret;
+}
+
+static pboolean test_socket_address (PSocket *socket, puint16 port)
+{
+ /* Test remote address */
+ PSocketAddress *remote_addr = p_socket_get_remote_address (socket, NULL);
+
+ if (remote_addr == NULL)
+ return FALSE;
+
+ pboolean ret = test_socket_address_directly (remote_addr, port);
+
+ p_socket_address_free (remote_addr);
+
+ return ret;
+}
+
+static pboolean compare_socket_addresses (const PSocketAddress *addr1, const PSocketAddress *addr2)
+{
+ if (addr1 == NULL || addr2 == NULL)
+ return FALSE;
+
+ pchar *addr_str1 = p_socket_address_get_address (addr1);
+ pchar *addr_str2 = p_socket_address_get_address (addr2);
+
+ if (addr_str1 == NULL || addr_str2 == NULL) {
+ p_free (addr_str1);
+ p_free (addr_str2);
+
+ return FALSE;
+ }
+
+ pboolean addr_cmp = (strcmp (addr_str1, addr_str2) == 0 ? TRUE : FALSE);
+
+ p_free (addr_str1);
+ p_free (addr_str2);
+
+ if (addr_cmp == FALSE)
+ return FALSE;
+
+ if (p_socket_address_get_family (addr1) != p_socket_address_get_family (addr2))
+ return FALSE;
+
+ if (p_socket_address_get_native_size (addr1) != p_socket_address_get_native_size (addr2))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void * udp_socket_sender_thread (void *arg)
+{
+ pint send_counter = 0;
+
+ if (arg == NULL)
+ p_uthread_exit (-1);
+
+ SocketTestData *data = (SocketTestData *) (arg);
+
+ /* Create sender socket */
+ PSocket *skt_sender = p_socket_new (P_SOCKET_FAMILY_INET,
+ P_SOCKET_TYPE_DATAGRAM,
+ P_SOCKET_PROTOCOL_UDP,
+ NULL);
+
+ if (skt_sender == NULL)
+ p_uthread_exit (-1);
+
+ PSocketAddress *addr_sender = p_socket_address_new ("127.0.0.1", data->sender_port);
+
+ if (addr_sender == NULL) {
+ p_socket_free (skt_sender);
+ p_uthread_exit (-1);
+ }
+
+ if (p_socket_bind (skt_sender, addr_sender, FALSE, NULL) == FALSE) {
+ p_socket_free (skt_sender);
+ p_socket_address_free (addr_sender);
+ p_uthread_exit (-1);
+ } else {
+ p_socket_address_free (addr_sender);
+
+ PSocketAddress *local_addr = p_socket_get_local_address (skt_sender, NULL);
+
+ if (local_addr == NULL) {
+ p_socket_free (skt_sender);
+ p_uthread_exit (-1);
+ }
+
+ data->sender_port = p_socket_address_get_port (local_addr);
+
+ p_socket_address_free (local_addr);
+ }
+
+ p_socket_set_timeout (skt_sender, 50);
+
+ /* Test that remote address is NULL */
+ PSocketAddress *remote_addr = p_socket_get_remote_address (skt_sender, NULL);
+
+ if (remote_addr != NULL) {
+ if (p_socket_address_is_any (remote_addr) == FALSE) {
+ p_socket_address_free (remote_addr);
+ p_socket_free (skt_sender);
+ p_uthread_exit (-1);
+ } else {
+ p_socket_address_free (remote_addr);
+ remote_addr = NULL;
+ }
+ }
+
+ /* Test that we are not connected */
+ if (p_socket_is_connected (skt_sender) == TRUE) {
+ p_socket_free (skt_sender);
+ p_uthread_exit (-1);
+ }
+
+ while (is_sender_working == TRUE && data->receiver_port == 0) {
+ p_uthread_sleep (1);
+ continue;
+ }
+
+ PSocketAddress *addr_receiver = NULL;
+
+ if (data->receiver_port != 0)
+ addr_receiver = p_socket_address_new ("127.0.0.1", data->receiver_port);
+
+ while (is_sender_working == TRUE) {
+ if (data->receiver_port == 0)
+ break;
+
+ if (p_socket_send_to (skt_sender,
+ addr_receiver,
+ socket_data,
+ sizeof (socket_data),
+ NULL) == sizeof (socket_data))
+ ++send_counter;
+
+ p_uthread_sleep (1);
+ }
+
+ p_socket_address_free (addr_receiver);
+ p_socket_free (skt_sender);
+ p_uthread_exit (send_counter);
+
+ return NULL;
+}
+
+static void * udp_socket_receiver_thread (void *arg)
+{
+ pchar recv_buffer[sizeof (socket_data) * 3];
+ pint recv_counter = 0;
+
+ if (arg == NULL)
+ p_uthread_exit (-1);
+
+ SocketTestData *data = (SocketTestData *) (arg);
+
+ /* Create receiving socket */
+ PSocket *skt_receiver = p_socket_new (P_SOCKET_FAMILY_INET,
+ P_SOCKET_TYPE_DATAGRAM,
+ P_SOCKET_PROTOCOL_UDP,
+ NULL);
+
+ if (skt_receiver == NULL)
+ p_uthread_exit (-1);
+
+ p_socket_set_blocking (skt_receiver, FALSE);
+
+ PSocketAddress *addr_receiver = p_socket_address_new ("127.0.0.1", data->receiver_port);
+
+ if (addr_receiver == NULL) {
+ p_socket_free (skt_receiver);
+ p_uthread_exit (-1);
+ }
+
+ if (p_socket_bind (skt_receiver, addr_receiver, TRUE, NULL) == FALSE) {
+ p_socket_free (skt_receiver);
+ p_socket_address_free (addr_receiver);
+ p_uthread_exit (-1);
+ } else {
+ p_socket_address_free (addr_receiver);
+
+ PSocketAddress *local_addr = p_socket_get_local_address (skt_receiver, NULL);
+
+ if (local_addr == NULL) {
+ p_socket_free (skt_receiver);
+ p_uthread_exit (-1);
+ }
+
+ data->receiver_port = p_socket_address_get_port (local_addr);
+
+ p_socket_address_free (local_addr);
+ }
+
+ p_socket_set_timeout (skt_receiver, 50);
+
+ /* Test that remote address is NULL */
+ PSocketAddress *remote_addr = p_socket_get_remote_address (skt_receiver, NULL);
+
+ if (remote_addr != NULL) {
+ if (p_socket_address_is_any (remote_addr) == FALSE) {
+ p_socket_address_free (remote_addr);
+ p_socket_free (skt_receiver);
+ p_uthread_exit (-1);
+ } else {
+ p_socket_address_free (remote_addr);
+ remote_addr = NULL;
+ }
+ }
+
+ /* Test that we are not connected */
+ if (p_socket_is_connected (skt_receiver) == TRUE) {
+ p_socket_free (skt_receiver);
+ p_uthread_exit (-1);
+ }
+
+ while (is_receiver_working == TRUE) {
+ PSocketAddress *remote_addr = NULL;
+
+ pssize received = p_socket_receive_from (skt_receiver,
+ &remote_addr,
+ recv_buffer,
+ sizeof (recv_buffer),
+ NULL);
+
+ if (remote_addr != NULL && test_socket_address_directly (remote_addr, data->sender_port) == FALSE) {
+ p_socket_address_free (remote_addr);
+ break;
+ }
+
+ p_socket_address_free (remote_addr);
+
+ if (received == sizeof (socket_data))
+ ++recv_counter;
+ else if (received > 0) {
+ p_socket_free (skt_receiver);
+ p_uthread_exit (-1);
+ }
+
+ p_uthread_sleep (1);
+ }
+
+ p_socket_free (skt_receiver);
+ p_uthread_exit (recv_counter);
+
+ return NULL;
+}
+
+static void * tcp_socket_sender_thread (void *arg)
+{
+ pint send_counter = 0;
+ psize send_total;
+ pssize send_now;
+ pboolean is_connected = FALSE;
+
+ if (arg == NULL)
+ p_uthread_exit (-1);
+
+ SocketTestData *data = (SocketTestData *) (arg);
+
+ /* Create sender socket */
+ PSocket *skt_sender = p_socket_new (P_SOCKET_FAMILY_INET,
+ P_SOCKET_TYPE_STREAM,
+ P_SOCKET_PROTOCOL_DEFAULT,
+ NULL);
+
+ if (skt_sender == NULL)
+ p_uthread_exit (-1);
+
+ p_socket_set_timeout (skt_sender, 2000);
+
+ if (p_socket_get_fd (skt_sender) < 0) {
+ p_socket_free (skt_sender);
+ p_uthread_exit (-1);
+ }
+
+ while (is_sender_working == TRUE && data->receiver_port == 0) {
+ p_uthread_sleep (1);
+ continue;
+ }
+
+ PSocketAddress *addr_sender = p_socket_address_new ("127.0.0.1", data->sender_port);
+
+ if (addr_sender == NULL) {
+ p_socket_free (skt_sender);
+ p_uthread_exit (-1);
+ }
+
+ if (p_socket_bind (skt_sender, addr_sender, FALSE, NULL) == FALSE) {
+ p_socket_free (skt_sender);
+ p_socket_address_free (addr_sender);
+ p_uthread_exit (-1);
+ } else {
+ p_socket_address_free (addr_sender);
+
+ PSocketAddress *local_addr = p_socket_get_local_address (skt_sender, NULL);
+
+ if (local_addr == NULL) {
+ p_socket_free (skt_sender);
+ p_uthread_exit (-1);
+ }
+
+ data->sender_port = p_socket_address_get_port (local_addr);
+
+ p_socket_address_free (local_addr);
+ }
+
+ send_total = 0;
+ send_now = 0;
+
+ while (is_sender_working == TRUE && data->receiver_port == 0) {
+ p_uthread_sleep (1);
+ continue;
+ }
+
+ PSocketAddress *addr_receiver = NULL;
+
+ /* Try to connect in non-blocking mode */
+ p_socket_set_blocking (skt_sender, FALSE);
+
+ if (data->receiver_port != 0) {
+ addr_receiver = p_socket_address_new ("127.0.0.1", data->receiver_port);
+ is_connected = p_socket_connect (skt_sender, addr_receiver, NULL);
+
+ if (is_connected == FALSE) {
+ if (p_socket_io_condition_wait (skt_sender, P_SOCKET_IO_CONDITION_POLLOUT, NULL) == TRUE &&
+ p_socket_check_connect_result (skt_sender, NULL) == FALSE) {
+ p_socket_address_free (addr_receiver);
+ p_socket_free (skt_sender);
+ p_uthread_exit (-1);
+ }
+ }
+
+ is_connected = p_socket_is_connected (skt_sender);
+
+ if (is_connected == TRUE && p_socket_shutdown (skt_sender,
+ FALSE,
+ data->shutdown_channel,
+ NULL) == FALSE)
+ is_connected = FALSE;
+ }
+
+ if (data->shutdown_channel == TRUE && p_socket_is_closed (skt_sender) == TRUE) {
+ p_socket_address_free (addr_receiver);
+ p_socket_free (skt_sender);
+ p_uthread_exit (-1);
+ }
+
+ p_socket_set_blocking (skt_sender, TRUE);
+
+ while (is_sender_working == TRUE) {
+ if (data->receiver_port == 0 || is_connected == FALSE)
+ break;
+
+ if (test_socket_address (skt_sender, data->receiver_port) == FALSE)
+ break;
+
+ if (data->shutdown_channel == FALSE && p_socket_is_connected (skt_sender) == FALSE) {
+ p_socket_address_free (addr_receiver);
+ p_socket_free (skt_sender);
+ p_uthread_exit (-1);
+ }
+
+ send_now = p_socket_send (skt_sender,
+ socket_data + send_total,
+ sizeof (socket_data) - send_total,
+ NULL);
+
+ if (send_now > 0)
+ send_total += (psize) send_now;
+
+ if (send_total == sizeof (socket_data)) {
+ send_total = 0;
+ ++send_counter;
+ }
+
+ p_uthread_sleep (1);
+ }
+
+ if (p_socket_close (skt_sender, NULL) == FALSE)
+ send_counter = -1;
+
+ p_socket_address_free (addr_receiver);
+ p_socket_free (skt_sender);
+ p_uthread_exit (send_counter);
+
+ return NULL;
+}
+
+static void * tcp_socket_receiver_thread (void *arg)
+{
+ pchar recv_buffer[sizeof (socket_data)];
+ pint recv_counter = 0;
+ psize recv_total;
+ pssize recv_now;
+
+ if (arg == NULL)
+ p_uthread_exit (-1);
+
+ SocketTestData *data = (SocketTestData *) (arg);
+
+ /* Create receiving socket */
+ PSocket *skt_receiver = p_socket_new (P_SOCKET_FAMILY_INET,
+ P_SOCKET_TYPE_STREAM,
+ P_SOCKET_PROTOCOL_TCP,
+ NULL);
+
+ if (skt_receiver == NULL)
+ p_uthread_exit (-1);
+
+ PSocketAddress *addr_receiver = p_socket_address_new ("127.0.0.1", data->receiver_port);
+
+ if (addr_receiver == NULL) {
+ p_socket_free (skt_receiver);
+ p_uthread_exit (-1);
+ }
+
+ p_socket_set_timeout (skt_receiver, 2000);
+
+ if (p_socket_bind (skt_receiver, addr_receiver, TRUE, NULL) == FALSE ||
+ p_socket_listen (skt_receiver, NULL) == FALSE) {
+ p_socket_free (skt_receiver);
+ p_socket_address_free (addr_receiver);
+ p_uthread_exit (-1);
+ } else {
+ p_socket_address_free (addr_receiver);
+
+ PSocketAddress *local_addr = p_socket_get_local_address (skt_receiver, NULL);
+
+ if (local_addr == NULL) {
+ p_socket_free (skt_receiver);
+ p_uthread_exit (-1);
+ }
+
+ data->receiver_port = p_socket_address_get_port (local_addr);
+
+ p_socket_address_free (local_addr);
+ }
+
+ PSocket *conn_socket = NULL;
+ recv_total = 0;
+ recv_now = 0;
+
+ while (is_receiver_working == TRUE) {
+ if (conn_socket == NULL) {
+ conn_socket = p_socket_accept (skt_receiver, NULL);
+
+ if (conn_socket == NULL) {
+ p_uthread_sleep (1);
+ continue;
+ } else {
+ /* On Syllable there is a bug in TCP which changes a local port
+ * of the client socket which connects to a server */
+#ifndef P_OS_SYLLABLE
+ if (test_socket_address (conn_socket, data->sender_port) == FALSE)
+ break;
+#endif
+
+ if (p_socket_shutdown (conn_socket, data->shutdown_channel, FALSE, NULL) == FALSE)
+ break;
+
+ p_socket_set_timeout (conn_socket, 2000);
+ }
+ }
+
+ if ((data->shutdown_channel == FALSE && p_socket_is_connected (conn_socket) == FALSE) ||
+ (data->shutdown_channel == TRUE && p_socket_is_closed (conn_socket) == TRUE)) {
+ p_socket_free (conn_socket);
+ p_socket_free (skt_receiver);
+ p_uthread_exit (-1);
+ }
+
+ recv_now = p_socket_receive (conn_socket,
+ recv_buffer + recv_total,
+ sizeof (recv_buffer) - recv_total,
+ NULL);
+
+ if (recv_now > 0)
+ recv_total += (psize) recv_now;
+
+ if (recv_total == sizeof (recv_buffer)) {
+ recv_total = 0;
+
+ if (strncmp (recv_buffer, socket_data, sizeof (recv_buffer)) == 0)
+ ++recv_counter;
+
+ memset (recv_buffer, 0, sizeof (recv_buffer));
+ }
+
+ p_uthread_sleep (1);
+ }
+
+ if (p_socket_close (skt_receiver, NULL) == FALSE)
+ recv_counter = -1;
+
+ p_socket_free (conn_socket);
+ p_socket_free (skt_receiver);
+
+ p_uthread_exit (recv_counter);
+
+ return NULL;
+}
+
+P_TEST_CASE_BEGIN (psocket_nomem_test)
+{
+ p_libsys_init ();
+
+ PSocket *socket = p_socket_new (P_SOCKET_FAMILY_INET,
+ P_SOCKET_TYPE_DATAGRAM,
+ P_SOCKET_PROTOCOL_UDP,
+ NULL);
+ P_TEST_CHECK (socket != NULL);
+
+ PSocketAddress *sock_addr = p_socket_address_new ("127.0.0.1", 32211);
+
+ P_TEST_CHECK (sock_addr != NULL);
+ P_TEST_CHECK (p_socket_bind (socket, sock_addr, TRUE, NULL) == TRUE);
+
+ p_socket_address_free (sock_addr);
+
+ p_socket_set_timeout (socket, 1000);
+ sock_addr = p_socket_address_new ("127.0.0.1", 32215);
+ P_TEST_CHECK (sock_addr != NULL);
+ P_TEST_CHECK (p_socket_connect (socket, sock_addr, NULL) == TRUE);
+
+ p_socket_address_free (sock_addr);
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_socket_new (P_SOCKET_FAMILY_INET,
+ P_SOCKET_TYPE_DATAGRAM,
+ P_SOCKET_PROTOCOL_UDP,
+ NULL) == NULL);
+ P_TEST_CHECK (p_socket_new_from_fd (p_socket_get_fd (socket), NULL) == NULL);
+ P_TEST_CHECK (p_socket_get_local_address (socket, NULL) == NULL);
+ P_TEST_CHECK (p_socket_get_remote_address (socket, NULL) == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_socket_close (socket, NULL);
+ p_socket_free (socket);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (psocket_bad_input_test)
+{
+ p_libsys_init ();
+
+ PError *error = NULL;
+
+ P_TEST_CHECK (p_socket_new_from_fd (-1, &error) == NULL);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_new (P_SOCKET_FAMILY_INET,
+ (PSocketType) -1,
+ P_SOCKET_PROTOCOL_TCP,
+ NULL) == NULL);
+ /* Syllable doesn't validate socket family */
+#ifndef P_OS_SYLLABLE
+ P_TEST_CHECK (p_socket_new ((PSocketFamily) -1,
+ P_SOCKET_TYPE_SEQPACKET,
+ P_SOCKET_PROTOCOL_TCP,
+ NULL) == NULL);
+#endif
+ P_TEST_CHECK (p_socket_new (P_SOCKET_FAMILY_UNKNOWN,
+ P_SOCKET_TYPE_UNKNOWN,
+ P_SOCKET_PROTOCOL_UNKNOWN,
+ &error) == NULL);
+ P_TEST_CHECK (p_socket_new_from_fd (1, NULL) == NULL);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_get_fd (NULL) == -1);
+ P_TEST_CHECK (p_socket_get_family (NULL) == P_SOCKET_FAMILY_UNKNOWN);
+ P_TEST_CHECK (p_socket_get_type (NULL) == P_SOCKET_TYPE_UNKNOWN);
+ P_TEST_CHECK (p_socket_get_protocol (NULL) == P_SOCKET_PROTOCOL_UNKNOWN);
+ P_TEST_CHECK (p_socket_get_keepalive (NULL) == FALSE);
+ P_TEST_CHECK (p_socket_get_blocking (NULL) == FALSE);
+ P_TEST_CHECK (p_socket_get_timeout (NULL) == -1);
+ P_TEST_CHECK (p_socket_get_listen_backlog (NULL) == -1);
+ P_TEST_CHECK (p_socket_io_condition_wait (NULL, P_SOCKET_IO_CONDITION_POLLIN, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_io_condition_wait (NULL, P_SOCKET_IO_CONDITION_POLLOUT, NULL) == FALSE);
+
+ P_TEST_CHECK (p_socket_get_local_address (NULL, &error) == NULL);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_get_remote_address (NULL, &error) == NULL);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_is_connected (NULL) == FALSE);
+ P_TEST_CHECK (p_socket_is_closed (NULL) == TRUE);
+
+ P_TEST_CHECK (p_socket_check_connect_result (NULL, &error) == FALSE);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ p_socket_set_keepalive (NULL, FALSE);
+ p_socket_set_blocking (NULL, FALSE);
+ p_socket_set_timeout (NULL, 0);
+ p_socket_set_listen_backlog (NULL, 0);
+
+ P_TEST_CHECK (p_socket_bind (NULL, NULL, FALSE, &error) == FALSE);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_connect (NULL, NULL, &error) == FALSE);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_listen (NULL, &error) == FALSE);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_accept (NULL, &error) == NULL);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_receive (NULL, NULL, 0, &error) == -1);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_receive_from (NULL, NULL, NULL, 0, &error) == -1);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_send (NULL, NULL, 0, &error) == -1);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_send_to (NULL, NULL, NULL, 0, &error) == -1);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_close (NULL, &error) == FALSE);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_shutdown (NULL, FALSE, FALSE, &error) == FALSE);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_set_buffer_size (NULL, P_SOCKET_DIRECTION_RCV, 0, &error) == FALSE);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ P_TEST_CHECK (p_socket_set_buffer_size (NULL, P_SOCKET_DIRECTION_SND, 0, &error) == FALSE);
+ P_TEST_CHECK (error != NULL);
+ clean_error (&error);
+
+ p_socket_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (psocket_general_udp_test)
+{
+ p_libsys_init ();
+
+ /* Test UDP socket */
+ PSocket *socket = p_socket_new (P_SOCKET_FAMILY_INET,
+ P_SOCKET_TYPE_DATAGRAM,
+ P_SOCKET_PROTOCOL_UDP,
+ NULL);
+
+ P_TEST_CHECK (socket != NULL);
+ P_TEST_CHECK (p_socket_get_family (socket) == P_SOCKET_FAMILY_INET);
+ P_TEST_CHECK (p_socket_get_fd (socket) >= 0);
+ P_TEST_CHECK (p_socket_get_listen_backlog (socket) == 5);
+ P_TEST_CHECK (p_socket_get_timeout (socket) == 0);
+
+ /* On some operating systems (i.e. OpenVMS) remote address is not NULL */
+ PSocketAddress *remote_addr = p_socket_get_remote_address (socket, NULL);
+
+ if (remote_addr != NULL) {
+ P_TEST_CHECK (p_socket_address_is_any (remote_addr) == TRUE);
+ p_socket_address_free (remote_addr);
+ remote_addr = NULL;
+ }
+
+ P_TEST_CHECK (p_socket_get_protocol (socket) == P_SOCKET_PROTOCOL_UDP);
+ P_TEST_CHECK (p_socket_get_blocking (socket) == TRUE);
+ P_TEST_CHECK (p_socket_get_type (socket) == P_SOCKET_TYPE_DATAGRAM);
+ P_TEST_CHECK (p_socket_get_keepalive (socket) == FALSE);
+ P_TEST_CHECK (p_socket_is_closed (socket) == FALSE);
+
+ p_socket_set_listen_backlog (socket, 12);
+ p_socket_set_timeout (socket, -10);
+ P_TEST_CHECK (p_socket_get_timeout (socket) == 0);
+ p_socket_set_timeout (socket, 10);
+
+ P_TEST_CHECK (p_socket_get_listen_backlog (socket) == 12);
+ P_TEST_CHECK (p_socket_get_timeout (socket) == 10);
+
+ PSocketAddress *sock_addr = p_socket_address_new ("127.0.0.1", 32111);
+ P_TEST_CHECK (sock_addr != NULL);
+
+ P_TEST_CHECK (p_socket_bind (socket, sock_addr, TRUE, NULL) == TRUE);
+
+ /* Test creating socket from descriptor */
+ PSocket *fd_socket = p_socket_new_from_fd (p_socket_get_fd (socket), NULL);
+ P_TEST_CHECK (fd_socket != NULL);
+ P_TEST_CHECK (p_socket_get_family (fd_socket) == P_SOCKET_FAMILY_INET);
+ P_TEST_CHECK (p_socket_get_fd (fd_socket) >= 0);
+ P_TEST_CHECK (p_socket_get_listen_backlog (fd_socket) == 5);
+ P_TEST_CHECK (p_socket_get_timeout (fd_socket) == 0);
+
+ remote_addr = p_socket_get_remote_address (fd_socket, NULL);
+
+ if (remote_addr != NULL) {
+ P_TEST_CHECK (p_socket_address_is_any (remote_addr) == TRUE);
+ p_socket_address_free (remote_addr);
+ remote_addr = NULL;
+ }
+
+ P_TEST_CHECK (p_socket_get_protocol (fd_socket) == P_SOCKET_PROTOCOL_UDP);
+ P_TEST_CHECK (p_socket_get_blocking (fd_socket) == TRUE);
+ P_TEST_CHECK (p_socket_get_type (fd_socket) == P_SOCKET_TYPE_DATAGRAM);
+ P_TEST_CHECK (p_socket_get_keepalive (fd_socket) == FALSE);
+ P_TEST_CHECK (p_socket_is_closed (fd_socket) == FALSE);
+
+ p_socket_set_keepalive (fd_socket, FALSE);
+ P_TEST_CHECK (p_socket_get_keepalive (fd_socket) == FALSE);
+
+ p_socket_set_keepalive (fd_socket, TRUE);
+ p_socket_set_keepalive (fd_socket, FALSE);
+ P_TEST_CHECK (p_socket_get_keepalive (fd_socket) == FALSE);
+
+ /* Test UDP local address */
+ PSocketAddress *addr = p_socket_get_local_address (socket, NULL);
+ P_TEST_CHECK (addr != NULL);
+
+ P_TEST_CHECK (compare_socket_addresses (sock_addr, addr) == TRUE);
+
+ p_socket_address_free (sock_addr);
+ p_socket_address_free (addr);
+
+ /* Test UDP connecting to remote address */
+ p_socket_set_timeout (socket, 1000);
+ addr = p_socket_address_new ("127.0.0.1", 32115);
+ P_TEST_CHECK (addr != NULL);
+ P_TEST_CHECK (p_socket_connect (socket, addr, NULL) == TRUE);
+
+ P_TEST_CHECK (p_socket_io_condition_wait (socket, P_SOCKET_IO_CONDITION_POLLIN, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_io_condition_wait (socket, P_SOCKET_IO_CONDITION_POLLOUT, NULL) == TRUE);
+
+ sock_addr = p_socket_get_remote_address (socket, NULL);
+
+ /* Syllable doesn't support getpeername() for UDP sockets */
+#ifdef P_OS_SYLLABLE
+ P_TEST_CHECK (sock_addr == NULL);
+ sock_addr = p_socket_address_new ("127.0.0.1", 32115);
+ P_TEST_CHECK (addr != NULL);
+#else
+ P_TEST_CHECK (sock_addr != NULL);
+ P_TEST_CHECK (compare_socket_addresses (sock_addr, addr) == TRUE);
+#endif
+
+ /* Not supported on Syllable */
+#ifndef P_OS_SYLLABLE
+ P_TEST_CHECK (p_socket_set_buffer_size (socket, P_SOCKET_DIRECTION_RCV, 72 * 1024, NULL) == TRUE);
+ P_TEST_CHECK (p_socket_set_buffer_size (socket, P_SOCKET_DIRECTION_SND, 72 * 1024, NULL) == TRUE);
+ P_TEST_CHECK (p_socket_check_connect_result (socket, NULL) == TRUE);
+#endif
+
+ P_TEST_CHECK (p_socket_is_connected (socket) == TRUE);
+ P_TEST_CHECK (p_socket_close (socket, NULL) == TRUE);
+
+ pchar sock_buf[10];
+
+ P_TEST_CHECK (p_socket_bind (socket, sock_addr, TRUE, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_connect (socket, addr, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_listen (socket, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_accept (socket, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_receive (socket, sock_buf, sizeof (sock_buf), NULL) == -1);
+ P_TEST_CHECK (p_socket_receive_from (socket, NULL, sock_buf, sizeof (sock_buf), NULL) == -1);
+ P_TEST_CHECK (p_socket_send (socket, sock_buf, sizeof (sock_buf), NULL) == -1);
+ P_TEST_CHECK (p_socket_send_to (socket, addr, sock_buf, sizeof (sock_buf), NULL) == -1);
+ P_TEST_CHECK (p_socket_shutdown (socket, TRUE, TRUE, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_get_local_address (socket, NULL) == NULL);
+ P_TEST_CHECK (p_socket_check_connect_result (socket, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_get_fd (socket) == -1);
+ P_TEST_CHECK (p_socket_is_connected (socket) == FALSE);
+ P_TEST_CHECK (p_socket_is_closed (socket) == TRUE);
+
+ p_socket_set_keepalive (socket, TRUE);
+ P_TEST_CHECK (p_socket_get_keepalive (socket) == FALSE);
+
+ P_TEST_CHECK (p_socket_io_condition_wait (socket, P_SOCKET_IO_CONDITION_POLLIN, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_io_condition_wait (socket, P_SOCKET_IO_CONDITION_POLLOUT, NULL) == FALSE);
+
+ P_TEST_CHECK (p_socket_set_buffer_size (socket, P_SOCKET_DIRECTION_RCV, 72 * 1024, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_set_buffer_size (socket, P_SOCKET_DIRECTION_SND, 72 * 1024, NULL) == FALSE);
+
+ p_socket_address_free (sock_addr);
+ p_socket_address_free (addr);
+ p_socket_free (socket);
+ p_socket_free (fd_socket);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (psocket_general_tcp_test)
+{
+ p_libsys_init ();
+
+ /* Test TCP socket */
+ PSocket *socket = p_socket_new (P_SOCKET_FAMILY_INET,
+ P_SOCKET_TYPE_STREAM,
+ P_SOCKET_PROTOCOL_TCP,
+ NULL);
+ p_socket_set_blocking (socket, FALSE);
+ p_socket_set_listen_backlog (socket, 11);
+
+ p_socket_set_timeout (socket, -12);
+ P_TEST_CHECK (p_socket_get_timeout (socket) == 0);
+ p_socket_set_timeout (socket, 12);
+
+ P_TEST_CHECK (socket != NULL);
+ P_TEST_CHECK (p_socket_get_family (socket) == P_SOCKET_FAMILY_INET);
+ P_TEST_CHECK (p_socket_get_fd (socket) >= 0);
+ P_TEST_CHECK (p_socket_get_listen_backlog (socket) == 11);
+ P_TEST_CHECK (p_socket_get_timeout (socket) == 12);
+ P_TEST_CHECK (p_socket_get_remote_address (socket, NULL) == NULL);
+ P_TEST_CHECK (p_socket_get_protocol (socket) == P_SOCKET_PROTOCOL_TCP);
+ P_TEST_CHECK (p_socket_get_blocking (socket) == FALSE);
+ P_TEST_CHECK (p_socket_get_type (socket) == P_SOCKET_TYPE_STREAM);
+ P_TEST_CHECK (p_socket_get_keepalive (socket) == FALSE);
+ P_TEST_CHECK (p_socket_is_closed (socket) == FALSE);
+
+ p_socket_set_keepalive (socket, FALSE);
+ P_TEST_CHECK (p_socket_get_keepalive (socket) == FALSE);
+
+ p_socket_set_keepalive (socket, TRUE);
+ p_socket_set_keepalive (socket, FALSE);
+ P_TEST_CHECK (p_socket_get_keepalive (socket) == FALSE);
+
+ PSocketAddress *sock_addr = p_socket_address_new ("127.0.0.1", 0);
+ P_TEST_CHECK (sock_addr != NULL);
+
+ P_TEST_CHECK (p_socket_bind (socket, sock_addr, TRUE, NULL) == TRUE);
+
+ PSocketAddress *addr = p_socket_get_local_address (socket, NULL);
+ P_TEST_CHECK (addr != NULL);
+
+ P_TEST_CHECK (compare_socket_addresses (sock_addr, addr) == TRUE);
+
+ P_TEST_CHECK (p_socket_set_buffer_size (socket, P_SOCKET_DIRECTION_RCV, 72 * 1024, NULL) == TRUE);
+ P_TEST_CHECK (p_socket_set_buffer_size (socket, P_SOCKET_DIRECTION_SND, 72 * 1024, NULL) == TRUE);
+
+ /* In case of success p_socket_check_connect_result() marks socket as connected */
+ P_TEST_CHECK (p_socket_is_connected (socket) == FALSE);
+ P_TEST_CHECK (p_socket_check_connect_result (socket, NULL) == TRUE);
+ P_TEST_CHECK (p_socket_close (socket, NULL) == TRUE);
+
+ pchar sock_buf[10];
+
+ P_TEST_CHECK (p_socket_bind (socket, sock_addr, TRUE, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_connect (socket, addr, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_listen (socket, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_accept (socket, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_receive (socket, sock_buf, sizeof (sock_buf), NULL) == -1);
+ P_TEST_CHECK (p_socket_receive_from (socket, NULL, sock_buf, sizeof (sock_buf), NULL) == -1);
+ P_TEST_CHECK (p_socket_send (socket, sock_buf, sizeof (sock_buf), NULL) == -1);
+ P_TEST_CHECK (p_socket_send_to (socket, addr, sock_buf, sizeof (sock_buf), NULL) == -1);
+ P_TEST_CHECK (p_socket_shutdown (socket, TRUE, TRUE, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_get_local_address (socket, NULL) == NULL);
+ P_TEST_CHECK (p_socket_check_connect_result (socket, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_is_closed (socket) == TRUE);
+ P_TEST_CHECK (p_socket_get_fd (socket) == -1);
+
+ p_socket_set_keepalive (socket, TRUE);
+ P_TEST_CHECK (p_socket_get_keepalive (socket) == FALSE);
+
+ P_TEST_CHECK (p_socket_io_condition_wait (socket, P_SOCKET_IO_CONDITION_POLLIN, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_io_condition_wait (socket, P_SOCKET_IO_CONDITION_POLLOUT, NULL) == FALSE);
+
+ P_TEST_CHECK (p_socket_set_buffer_size (socket, P_SOCKET_DIRECTION_RCV, 72 * 1024, NULL) == FALSE);
+ P_TEST_CHECK (p_socket_set_buffer_size (socket, P_SOCKET_DIRECTION_SND, 72 * 1024, NULL) == FALSE);
+
+ p_socket_address_free (sock_addr);
+ p_socket_address_free (addr);
+
+ p_socket_free (socket);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (psocket_udp_test)
+{
+ p_libsys_init ();
+
+ is_sender_working = TRUE;
+ is_receiver_working = TRUE;
+
+ SocketTestData data;
+ data.receiver_port = 0;
+ data.sender_port = 0;
+ data.shutdown_channel = FALSE;
+
+ PUThread *receiver_thr = p_uthread_create ((PUThreadFunc) udp_socket_receiver_thread,
+ (ppointer) &data,
+ TRUE,
+ NULL);
+
+ PUThread *sender_thr = p_uthread_create ((PUThreadFunc) udp_socket_sender_thread,
+ (ppointer) &data,
+ TRUE,
+ NULL);
+
+ P_TEST_CHECK (sender_thr != NULL);
+ P_TEST_CHECK (receiver_thr != NULL);
+
+ p_uthread_sleep (8000);
+
+ is_sender_working = FALSE;
+ pint send_counter = p_uthread_join (sender_thr);
+
+ p_uthread_sleep (2000);
+
+ is_receiver_working = FALSE;
+ pint recv_counter = p_uthread_join (receiver_thr);
+
+ P_TEST_CHECK (send_counter > 0);
+ P_TEST_CHECK (recv_counter > 0);
+
+ p_uthread_unref (sender_thr);
+ p_uthread_unref (receiver_thr);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (psocket_tcp_test)
+{
+ p_libsys_init ();
+
+ is_sender_working = TRUE;
+ is_receiver_working = TRUE;
+
+ SocketTestData data;
+ data.receiver_port = 0;
+ data.sender_port = 0;
+ data.shutdown_channel = FALSE;
+
+ PUThread *receiver_thr = p_uthread_create ((PUThreadFunc) tcp_socket_receiver_thread,
+ (ppointer) &data,
+ TRUE,
+ NULL);
+
+ PUThread *sender_thr = p_uthread_create ((PUThreadFunc) tcp_socket_sender_thread,
+ (ppointer) &data,
+ TRUE,
+ NULL);
+
+ P_TEST_CHECK (receiver_thr != NULL);
+ P_TEST_CHECK (sender_thr != NULL);
+
+ p_uthread_sleep (8000);
+
+ is_sender_working = FALSE;
+ pint send_counter = p_uthread_join (sender_thr);
+
+ p_uthread_sleep (2000);
+
+ is_receiver_working = FALSE;
+ pint recv_counter = p_uthread_join (receiver_thr);
+
+ P_TEST_CHECK (send_counter > 0);
+ P_TEST_CHECK (recv_counter > 0);
+
+ p_uthread_unref (sender_thr);
+ p_uthread_unref (receiver_thr);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (psocket_shutdown_test)
+{
+ p_libsys_init ();
+
+ is_sender_working = TRUE;
+ is_receiver_working = TRUE;
+
+ SocketTestData data;
+ data.receiver_port = 0;
+ data.sender_port = 0;
+ data.shutdown_channel = TRUE;
+
+ PUThread *receiver_thr = p_uthread_create ((PUThreadFunc) tcp_socket_receiver_thread,
+ (ppointer) &data,
+ TRUE,
+ NULL);
+
+ PUThread *sender_thr = p_uthread_create ((PUThreadFunc) tcp_socket_sender_thread,
+ (ppointer) &data,
+ TRUE,
+ NULL);
+
+ P_TEST_CHECK (receiver_thr != NULL);
+ P_TEST_CHECK (sender_thr != NULL);
+
+ p_uthread_sleep (8000);
+
+ is_sender_working = FALSE;
+ pint send_counter = p_uthread_join (sender_thr);
+
+ p_uthread_sleep (2000);
+
+ is_receiver_working = FALSE;
+ pint recv_counter = p_uthread_join (receiver_thr);
+
+ P_TEST_CHECK (send_counter == 0);
+ P_TEST_CHECK (recv_counter == 0);
+
+ p_uthread_unref (sender_thr);
+ p_uthread_unref (receiver_thr);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (psocket_nomem_test);
+ P_TEST_SUITE_RUN_CASE (psocket_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (psocket_general_udp_test);
+ P_TEST_SUITE_RUN_CASE (psocket_general_tcp_test);
+ P_TEST_SUITE_RUN_CASE (psocket_udp_test);
+ P_TEST_SUITE_RUN_CASE (psocket_tcp_test);
+ P_TEST_SUITE_RUN_CASE (psocket_shutdown_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/psocketaddress_test.cpp b/3rdparty/plibsys/tests/psocketaddress_test.cpp
new file mode 100644
index 0000000..2085725
--- /dev/null
+++ b/3rdparty/plibsys/tests/psocketaddress_test.cpp
@@ -0,0 +1,338 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <string.h>
+
+P_TEST_MODULE_INIT ();
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+P_TEST_CASE_BEGIN (psocketaddress_nomem_test)
+{
+ p_libsys_init ();
+
+ PSocketAddress *sock_addr = p_socket_address_new ("192.168.0.1", 1058);
+ P_TEST_CHECK (sock_addr != NULL);
+
+ psize native_size = p_socket_address_get_native_size (sock_addr);
+ P_TEST_CHECK (native_size > 0);
+
+ ppointer addr_buf = p_malloc0 (native_size);
+ P_TEST_CHECK (addr_buf != NULL);
+
+ P_TEST_CHECK (p_socket_address_to_native (sock_addr, addr_buf, native_size - 1) == FALSE);
+ P_TEST_CHECK (p_socket_address_to_native (sock_addr, addr_buf, native_size) == TRUE);
+ p_socket_address_free (sock_addr);
+
+ PSocketAddress *sock_addr6;
+ psize native_size6;
+ ppointer addr_buf6;
+
+ if (p_socket_address_is_ipv6_supported ()) {
+ sock_addr6 = p_socket_address_new ("2001:cdba:345f:24ab:fe45:5423:3257:9652", 1058);
+ P_TEST_CHECK (sock_addr6 != NULL);
+
+ native_size6 = p_socket_address_get_native_size (sock_addr6);
+ P_TEST_CHECK (native_size6 > 0);
+
+ addr_buf6 = p_malloc0 (native_size6);
+ P_TEST_CHECK (addr_buf6 != NULL);
+
+ P_TEST_CHECK (p_socket_address_to_native (sock_addr6, addr_buf6, native_size6 - 1) == FALSE);
+ P_TEST_CHECK (p_socket_address_to_native (sock_addr6, addr_buf6, native_size6) == TRUE);
+ p_socket_address_free (sock_addr6);
+ }
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_socket_address_new ("192.168.0.1", 1058) == NULL);
+ P_TEST_CHECK (p_socket_address_new_any (P_SOCKET_FAMILY_INET, 1058) == NULL);
+ P_TEST_CHECK (p_socket_address_new_loopback (P_SOCKET_FAMILY_INET, 1058) == NULL);
+ P_TEST_CHECK (p_socket_address_new_from_native (addr_buf, native_size) == NULL);
+
+ if (p_socket_address_is_ipv6_supported ())
+ P_TEST_CHECK (p_socket_address_new_from_native (addr_buf6, native_size6) == NULL);
+
+ p_mem_restore_vtable ();
+
+ P_TEST_CHECK (p_socket_address_new_from_native (addr_buf, native_size - 1) == NULL);
+
+ if (p_socket_address_is_ipv6_supported ()) {
+ P_TEST_CHECK (p_socket_address_new_from_native (addr_buf6, native_size6 - 1) == NULL);
+ p_free (addr_buf6);
+ }
+
+ p_free (addr_buf);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (psocketaddress_bad_input_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_socket_address_new_from_native (NULL, 0) == NULL);
+ P_TEST_CHECK (p_socket_address_new (NULL, 0) == NULL);
+ P_TEST_CHECK (p_socket_address_new ("bad_address", 0) == NULL);
+ P_TEST_CHECK (p_socket_address_new_any (P_SOCKET_FAMILY_UNKNOWN, 0) == NULL);
+ P_TEST_CHECK (p_socket_address_new_loopback (P_SOCKET_FAMILY_UNKNOWN, 0) == NULL);
+ P_TEST_CHECK (p_socket_address_to_native (NULL, NULL, 0) == FALSE);
+ P_TEST_CHECK (p_socket_address_get_native_size (NULL) == 0);
+ P_TEST_CHECK (p_socket_address_get_family (NULL) == P_SOCKET_FAMILY_UNKNOWN);
+ P_TEST_CHECK (p_socket_address_get_address (NULL) == NULL);
+ P_TEST_CHECK (p_socket_address_get_port (NULL) == 0);
+ P_TEST_CHECK (p_socket_address_get_flow_info (NULL) == 0);
+ P_TEST_CHECK (p_socket_address_get_scope_id (NULL) == 0);
+ P_TEST_CHECK (p_socket_address_is_any (NULL) == FALSE);
+ P_TEST_CHECK (p_socket_address_is_loopback (NULL) == FALSE);
+
+ p_socket_address_set_flow_info (NULL, 0);
+ p_socket_address_set_scope_id (NULL, 0);
+ p_socket_address_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (psocketaddress_general_test)
+{
+ p_libsys_init ();
+
+ /* Test IPv4 LAN address */
+ PSocketAddress *addr = p_socket_address_new ("192.168.0.1", 2345);
+
+ P_TEST_REQUIRE (addr != NULL);
+ P_TEST_CHECK (p_socket_address_is_loopback (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_is_any (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_get_family (addr) == P_SOCKET_FAMILY_INET);
+ P_TEST_CHECK (p_socket_address_get_port (addr) == 2345);
+ P_TEST_CHECK (p_socket_address_get_native_size (addr) > 0);
+ P_TEST_CHECK (p_socket_address_get_flow_info (addr) == 0);
+ P_TEST_CHECK (p_socket_address_get_scope_id (addr) == 0);
+
+ pchar *addr_str = p_socket_address_get_address (addr);
+
+ P_TEST_REQUIRE (addr_str != NULL);
+ P_TEST_CHECK (strcmp (addr_str, "192.168.0.1") == 0);
+
+ p_free (addr_str);
+ p_socket_address_free (addr);
+
+ if (p_socket_address_is_ipv6_supported ()) {
+ /* Test IPv6 LAN address */
+ addr = p_socket_address_new ("2001:cdba:345f:24ab:fe45:5423:3257:9652", 2345);
+
+ P_TEST_REQUIRE (addr != NULL);
+ P_TEST_CHECK (p_socket_address_is_loopback (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_is_any (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_get_family (addr) == P_SOCKET_FAMILY_INET6);
+ P_TEST_CHECK (p_socket_address_get_port (addr) == 2345);
+ P_TEST_CHECK (p_socket_address_get_native_size (addr) > 0);
+ P_TEST_CHECK (p_socket_address_get_flow_info (addr) == 0);
+ P_TEST_CHECK (p_socket_address_get_scope_id (addr) == 0);
+
+ addr_str = p_socket_address_get_address (addr);
+
+ P_TEST_REQUIRE (addr_str != NULL);
+ P_TEST_CHECK (strcmp (addr_str, "2001:cdba:345f:24ab:fe45:5423:3257:9652") == 0);
+
+ p_free (addr_str);
+ p_socket_address_free (addr);
+ }
+
+ /* Test IPv4 loopback address */
+ addr = p_socket_address_new_loopback (P_SOCKET_FAMILY_INET, 2345);
+
+ P_TEST_REQUIRE (addr != NULL);
+ P_TEST_CHECK (p_socket_address_is_loopback (addr) == TRUE);
+ P_TEST_CHECK (p_socket_address_is_any (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_get_family (addr) == P_SOCKET_FAMILY_INET);
+ P_TEST_CHECK (p_socket_address_get_port (addr) == 2345);
+ P_TEST_CHECK (p_socket_address_get_native_size (addr) > 0);
+ P_TEST_CHECK (p_socket_address_get_flow_info (addr) == 0);
+ P_TEST_CHECK (p_socket_address_get_scope_id (addr) == 0);
+
+ p_socket_address_free (addr);
+
+ if (p_socket_address_is_ipv6_supported ()) {
+ /* Test IPv6 loopback address */
+ addr = p_socket_address_new_loopback (P_SOCKET_FAMILY_INET6, 2345);
+
+ P_TEST_REQUIRE (addr != NULL);
+ P_TEST_CHECK (p_socket_address_is_loopback (addr) == TRUE);
+ P_TEST_CHECK (p_socket_address_is_any (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_get_family (addr) == P_SOCKET_FAMILY_INET6);
+ P_TEST_CHECK (p_socket_address_get_port (addr) == 2345);
+ P_TEST_CHECK (p_socket_address_get_native_size (addr) > 0);
+ P_TEST_CHECK (p_socket_address_get_flow_info (addr) == 0);
+ P_TEST_CHECK (p_socket_address_get_scope_id (addr) == 0);
+
+ p_socket_address_free (addr);
+ }
+
+ /* Test IPv4 any interface */
+ addr = p_socket_address_new_any (P_SOCKET_FAMILY_INET, 2345);
+
+ P_TEST_REQUIRE (addr != NULL);
+ P_TEST_CHECK (p_socket_address_is_loopback (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_is_any (addr) == TRUE);
+ P_TEST_CHECK (p_socket_address_get_family (addr) == P_SOCKET_FAMILY_INET);
+ P_TEST_CHECK (p_socket_address_get_port (addr) == 2345);
+ P_TEST_CHECK (p_socket_address_get_native_size (addr) > 0);
+ P_TEST_CHECK (p_socket_address_get_flow_info (addr) == 0);
+ P_TEST_CHECK (p_socket_address_get_scope_id (addr) == 0);
+
+ psize native_size = p_socket_address_get_native_size (addr);
+
+ p_socket_address_free (addr);
+
+ /* Test IPv4 native raw data */
+ ppointer native_buf = p_malloc0 (native_size);
+ P_TEST_CHECK (native_buf != NULL);
+ P_TEST_CHECK (p_socket_address_new_from_native (native_buf, native_size) == NULL);
+ addr = p_socket_address_new ("192.168.0.2", 2345);
+ P_TEST_REQUIRE (addr != NULL);
+
+ p_socket_address_set_flow_info (addr, 1);
+ p_socket_address_set_scope_id (addr, 1);
+
+ P_TEST_CHECK (p_socket_address_to_native (addr, native_buf, native_size) == TRUE);
+ p_socket_address_free (addr);
+
+ addr = p_socket_address_new_from_native (native_buf, native_size);
+
+ P_TEST_CHECK (addr != NULL);
+ P_TEST_CHECK (p_socket_address_is_loopback (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_is_any (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_get_family (addr) == P_SOCKET_FAMILY_INET);
+ P_TEST_CHECK (p_socket_address_get_port (addr) == 2345);
+ P_TEST_CHECK (p_socket_address_get_native_size (addr) == native_size);
+ P_TEST_CHECK (p_socket_address_get_flow_info (addr) == 0);
+ P_TEST_CHECK (p_socket_address_get_scope_id (addr) == 0);
+
+ addr_str = p_socket_address_get_address (addr);
+
+ P_TEST_REQUIRE (addr_str != NULL);
+ P_TEST_CHECK (strcmp (addr_str, "192.168.0.2") == 0);
+
+ p_free (native_buf);
+ p_free (addr_str);
+ p_socket_address_free (addr);
+
+ if (p_socket_address_is_ipv6_supported ()) {
+ /* Test IPv6 any interface */
+ addr = p_socket_address_new_any (P_SOCKET_FAMILY_INET6, 2345);
+
+ P_TEST_REQUIRE (addr != NULL);
+ P_TEST_CHECK (p_socket_address_is_loopback (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_is_any (addr) == TRUE);
+ P_TEST_CHECK (p_socket_address_get_family (addr) == P_SOCKET_FAMILY_INET6);
+ P_TEST_CHECK (p_socket_address_get_port (addr) == 2345);
+ P_TEST_CHECK (p_socket_address_get_native_size (addr) > 0);
+ P_TEST_CHECK (p_socket_address_get_flow_info (addr) == 0);
+ P_TEST_CHECK (p_socket_address_get_scope_id (addr) == 0);
+
+ native_size = p_socket_address_get_native_size (addr);
+
+ p_socket_address_free (addr);
+
+ /* Test IPv6 native raw data */
+ native_buf = p_malloc0 (native_size);
+ P_TEST_CHECK (native_buf != NULL);
+ P_TEST_CHECK (p_socket_address_new_from_native (native_buf, native_size) == NULL);
+ addr = p_socket_address_new ("2001:cdba:345f:24ab:fe45:5423:3257:9652", 2345);
+ P_TEST_REQUIRE (addr != NULL);
+
+ p_socket_address_set_flow_info (addr, 1);
+ p_socket_address_set_scope_id (addr, 1);
+
+ P_TEST_CHECK (p_socket_address_to_native (addr, native_buf, native_size) == TRUE);
+ p_socket_address_free (addr);
+
+ addr = p_socket_address_new_from_native (native_buf, native_size);
+
+ P_TEST_CHECK (addr != NULL);
+ P_TEST_CHECK (p_socket_address_is_loopback (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_is_any (addr) == FALSE);
+ P_TEST_CHECK (p_socket_address_get_family (addr) == P_SOCKET_FAMILY_INET6);
+ P_TEST_CHECK (p_socket_address_get_port (addr) == 2345);
+ P_TEST_CHECK (p_socket_address_get_native_size (addr) == native_size);
+
+ if (p_socket_address_is_flow_info_supported ())
+ P_TEST_CHECK (p_socket_address_get_flow_info (addr) == 1);
+
+ if (p_socket_address_is_scope_id_supported ())
+ P_TEST_CHECK (p_socket_address_get_scope_id (addr) == 1);
+
+ addr_str = p_socket_address_get_address (addr);
+
+ P_TEST_REQUIRE (addr_str != NULL);
+ P_TEST_CHECK (strcmp (addr_str, "2001:cdba:345f:24ab:fe45:5423:3257:9652") == 0);
+
+ p_free (native_buf);
+ p_free (addr_str);
+ p_socket_address_free (addr);
+ }
+
+ if (p_socket_address_is_flow_info_supported () || p_socket_address_is_scope_id_supported ())
+ P_TEST_CHECK (p_socket_address_is_ipv6_supported () == TRUE);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (psocketaddress_nomem_test);
+ P_TEST_SUITE_RUN_CASE (psocketaddress_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (psocketaddress_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pspinlock_test.cpp b/3rdparty/plibsys/tests/pspinlock_test.cpp
new file mode 100644
index 0000000..1f23dab
--- /dev/null
+++ b/3rdparty/plibsys/tests/pspinlock_test.cpp
@@ -0,0 +1,148 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2016-2019 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+P_TEST_MODULE_INIT ();
+
+#define PSPINLOCK_MAX_VAL 10
+
+static pint spinlock_test_val = 0;
+static PSpinLock * global_spinlock = NULL;
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+static void * spinlock_test_thread (void *)
+{
+ pint i;
+
+ for (i = 0; i < 1000; ++i) {
+ if (!p_spinlock_trylock (global_spinlock)) {
+ if (!p_spinlock_lock (global_spinlock))
+ p_uthread_exit (1);
+ }
+
+ if (spinlock_test_val == PSPINLOCK_MAX_VAL)
+ --spinlock_test_val;
+ else {
+ p_uthread_sleep (1);
+ ++spinlock_test_val;
+ }
+
+ if (!p_spinlock_unlock (global_spinlock))
+ p_uthread_exit (1);
+ }
+
+ p_uthread_exit (0);
+
+ return NULL;
+}
+
+P_TEST_CASE_BEGIN (pspinlock_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+ P_TEST_CHECK (p_spinlock_new () == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pspinlock_bad_input_test)
+{
+ p_libsys_init ();
+
+ P_TEST_REQUIRE (p_spinlock_lock (NULL) == FALSE);
+ P_TEST_REQUIRE (p_spinlock_unlock (NULL) == FALSE);
+ P_TEST_REQUIRE (p_spinlock_trylock (NULL) == FALSE);
+ p_spinlock_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pspinlock_general_test)
+{
+ PUThread *thr1, *thr2;
+
+ p_libsys_init ();
+
+ spinlock_test_val = PSPINLOCK_MAX_VAL;
+ global_spinlock = p_spinlock_new ();
+
+ P_TEST_REQUIRE (global_spinlock != NULL);
+
+ thr1 = p_uthread_create ((PUThreadFunc) spinlock_test_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr1 != NULL);
+
+ thr2 = p_uthread_create ((PUThreadFunc) spinlock_test_thread, NULL, TRUE, NULL);
+ P_TEST_REQUIRE (thr2 != NULL);
+
+ P_TEST_CHECK (p_uthread_join (thr1) == 0);
+ P_TEST_CHECK (p_uthread_join (thr2) == 0);
+
+ P_TEST_REQUIRE (spinlock_test_val == PSPINLOCK_MAX_VAL);
+
+ p_uthread_unref (thr1);
+ p_uthread_unref (thr2);
+ p_spinlock_free (global_spinlock);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pspinlock_nomem_test);
+ P_TEST_SUITE_RUN_CASE (pspinlock_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (pspinlock_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pstdarg_test.cpp b/3rdparty/plibsys/tests/pstdarg_test.cpp
new file mode 100644
index 0000000..7df041f
--- /dev/null
+++ b/3rdparty/plibsys/tests/pstdarg_test.cpp
@@ -0,0 +1,205 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2017 Jean-Damien Durand <jeandamiendurand@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#if defined(P_CC_WATCOM)
+# pragma disable_message (7)
+#endif
+
+P_TEST_MODULE_INIT ();
+
+static void variadic_function (pint unused, ...);
+static void variadic_function_copy_all (pint unused, p_va_list ap);
+static void variadic_function_copy_trail (pint unused, p_va_list ap);
+
+/* The "runtime" thingies here are just to avoid compiler warnings */
+/* In head, In trail */
+static const pint8 pint8_var[2] = { P_MININT8, P_MAXINT8 };
+static const puint8 puint8_var[2] = { 0, P_MAXUINT8 };
+static const pint16 pint16_var[2] = { P_MININT16, P_MAXINT16 };
+static const puint16 puint16_var[2] = { 0, P_MAXUINT16 };
+static pint32 pint32_var[2] = { 0 /* runtime */, 0 /* runtime */ };
+static puint32 puint32_var[2] = { 0, 0 /* runtime */ };
+static pint64 pint64_var[2] = { 0 /* runtime */, 0 /* runtime */ };
+static puint64 puint64_var[2] = { 0, 0 /* runtime */ };
+static const pint pint_var[2] = { P_MININT, P_MAXINT };
+static const puint puint_var[2] = { 0, P_MAXUINT };
+static const pshort pshort_var[2] = { P_MINSHORT, P_MAXSHORT };
+static const plong plong_var[2] = { P_MINLONG, P_MAXLONG };
+static const pchar pchar_var[2] = { '\0', 'z' };
+static const ppointer ppointer_var[2] = { NULL, (ppointer) p_libsys_init };
+static const pfloat pfloat_var[2] = { -1.234f, 1.234f };
+static const pdouble pdouble_var[2] = { -1.567, 1.567 };
+
+/* Macros are used for testing because these tests MUST play with the CURRENT stack. */
+
+#define P_TEST_VA_ARG(ap, type, wantedvalue) do { \
+ P_DEBUG ("Unstacking a " #type); \
+ P_TEST_CHECK (type##_va_arg(ap) == wantedvalue); \
+ } while (0)
+
+#define P_TEST_VA_ARG_HEAD(ap) do { \
+ P_TEST_VA_ARG(ap, pint8, pint8_var[0]); \
+ P_TEST_VA_ARG(ap, puint8, puint8_var[0]); \
+ P_TEST_VA_ARG(ap, pint16, pint16_var[0]); \
+ P_TEST_VA_ARG(ap, puint16, puint16_var[0]); \
+ P_TEST_VA_ARG(ap, pint32, pint32_var[0]); \
+ P_TEST_VA_ARG(ap, puint32, puint32_var[0]); \
+ P_TEST_VA_ARG(ap, pint64, pint64_var[0]); \
+ P_TEST_VA_ARG(ap, puint64, puint64_var[0]); \
+ P_TEST_VA_ARG(ap, pint, pint_var[0]); \
+ P_TEST_VA_ARG(ap, puint, puint_var[0]); \
+ P_TEST_VA_ARG(ap, pshort, pshort_var[0]); \
+ P_TEST_VA_ARG(ap, plong, plong_var[0]); \
+ P_TEST_VA_ARG(ap, pchar, pchar_var[0]); \
+ P_TEST_VA_ARG(ap, ppointer, ppointer_var[0]); \
+ P_TEST_VA_ARG(ap, pfloat, pfloat_var[0]); \
+ P_TEST_VA_ARG(ap, pdouble, pdouble_var[0]); \
+ } while (0)
+
+#define P_TEST_VA_ARG_TRAIL(ap) do { \
+ P_TEST_VA_ARG(ap, pdouble, pdouble_var[1]); \
+ P_TEST_VA_ARG(ap, pfloat, pfloat_var[1]); \
+ P_TEST_VA_ARG(ap, ppointer, ppointer_var[1]); \
+ P_TEST_VA_ARG(ap, pchar, pchar_var[1]); \
+ P_TEST_VA_ARG(ap, plong, plong_var[1]); \
+ P_TEST_VA_ARG(ap, pshort, pshort_var[1]); \
+ P_TEST_VA_ARG(ap, puint, puint_var[1]); \
+ P_TEST_VA_ARG(ap, pint, pint_var[1]); \
+ P_TEST_VA_ARG(ap, puint64, puint64_var[1]); \
+ P_TEST_VA_ARG(ap, pint64, pint64_var[1]); \
+ P_TEST_VA_ARG(ap, puint32, puint32_var[1]); \
+ P_TEST_VA_ARG(ap, pint32, pint32_var[1]); \
+ P_TEST_VA_ARG(ap, puint16, puint16_var[1]); \
+ P_TEST_VA_ARG(ap, pint16, pint16_var[1]); \
+ P_TEST_VA_ARG(ap, puint8, puint8_var[1]); \
+ P_TEST_VA_ARG(ap, pint8, pint8_var[1]); \
+ } while (0)
+
+static void variadic_function_copy_all (pint unused, p_va_list ap)
+{
+ P_UNUSED (unused);
+ P_DEBUG ("Unstacking a copy of all the arguments");
+ P_TEST_VA_ARG_HEAD (ap);
+ P_TEST_VA_ARG_TRAIL (ap);
+}
+
+static void variadic_function_copy_trail (pint unused, p_va_list ap)
+{
+ P_UNUSED (unused);
+ P_DEBUG ("Unstacking second part of the arguments");
+ P_TEST_VA_ARG_TRAIL (ap);
+}
+
+static void variadic_function (pint unused, ...)
+{
+ p_va_list ap;
+ p_va_list ap2;
+
+ p_va_start (ap, unused);
+
+ P_DEBUG ("Copy of arguments");
+ p_va_copy (ap2, ap);
+ variadic_function_copy_all (unused, ap2);
+ p_va_end (ap2);
+
+ P_DEBUG ("Unstacking first part of arguments");
+ P_TEST_VA_ARG_HEAD (ap);
+
+ P_DEBUG ("Copy of arguments at current unstack state, i.e. in the middle");
+ p_va_copy (ap2, ap);
+ variadic_function_copy_trail (unused, ap2);
+ p_va_end (ap2);
+
+ P_DEBUG ("Unstacking second part of arguments");
+ P_TEST_VA_ARG_TRAIL (ap);
+
+ p_va_end (ap);
+}
+
+P_TEST_CASE_BEGIN (pstdarg_general_test)
+{
+ p_libsys_init ();
+
+ pint32_var[0] = P_MININT16;
+ pint32_var[0] <<= 16;
+ pint32_var[1] = P_MAXINT16;
+ pint32_var[1] <<= 16;
+ puint32_var[1] = P_MAXUINT16;
+ puint32_var[1] <<= 16;
+
+ pint64_var[0] = pint32_var[0];
+ pint64_var[0] <<= 32;
+ pint64_var[1] = pint32_var[1];
+ pint64_var[1] <<= 32;
+ puint64_var[1] = puint32_var[1];
+ puint64_var[1] <<= 32;
+
+ variadic_function (0,
+ pint8_var[0],
+ puint8_var[0],
+ pint16_var[0],
+ puint16_var[0],
+ pint32_var[0],
+ puint32_var[0],
+ pint64_var[0],
+ puint64_var[0],
+ pint_var[0],
+ puint_var[0],
+ pshort_var[0],
+ plong_var[0],
+ pchar_var[0],
+ ppointer_var[0],
+ pfloat_var[0],
+ pdouble_var[0],
+ /* Cut is here when testing p_va_copy, we stack in reverse order */
+ pdouble_var[1],
+ pfloat_var[1],
+ ppointer_var[1],
+ pchar_var[1],
+ plong_var[1],
+ pshort_var[1],
+ puint_var[1],
+ pint_var[1],
+ puint64_var[1],
+ pint64_var[1],
+ puint32_var[1],
+ pint32_var[1],
+ puint16_var[1],
+ pint16_var[1],
+ puint8_var[1],
+ pint8_var[1]);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pstdarg_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/pstring_test.cpp b/3rdparty/plibsys/tests/pstring_test.cpp
new file mode 100644
index 0000000..73e5805
--- /dev/null
+++ b/3rdparty/plibsys/tests/pstring_test.cpp
@@ -0,0 +1,289 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <string.h>
+#include <float.h>
+#include <math.h>
+
+P_TEST_MODULE_INIT ();
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+P_TEST_CASE_BEGIN (pstring_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_strdup ("test string") == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pstring_strdup_test)
+{
+ p_libsys_init ();
+
+ const pchar *test_str_1 = "Test string";
+
+ pchar *new_string = p_strdup (test_str_1);
+ P_TEST_CHECK (new_string != NULL);
+ p_free (new_string);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pstring_strchomp_test)
+{
+ p_libsys_init ();
+
+ const pchar *test_chomp_str_orig = "Test chomp string";
+ const pchar *test_chomp_str_1 = "Test chomp string ";
+ const pchar *test_chomp_str_2 = "\n\nTest chomp string ";
+ const pchar *test_chomp_str_3 = "\n\rTest chomp string \n";
+ const pchar *test_chomp_str_4 = "Test chomp string\n\n";
+ const pchar *test_chomp_str_5 = " \rTest chomp string \n\n ";
+ const pchar *test_chomp_str_6 = " \rI\n\n ";
+ const pchar *test_chomp_str_7 = "\n";
+ const pchar *test_chomp_str_8 = "I";
+ const pchar *test_chomp_str_9 = "";
+ const pchar *test_chomp_str_10 = " ";
+ const pchar *test_chomp_str_11 = NULL;
+
+ pchar *new_string = p_strchomp (test_chomp_str_1);
+ P_TEST_REQUIRE (new_string != NULL);
+ P_TEST_CHECK (strcmp (test_chomp_str_orig, new_string) == 0);
+ p_free (new_string);
+
+ new_string = p_strchomp (test_chomp_str_2);
+ P_TEST_REQUIRE (new_string != NULL);
+ P_TEST_CHECK (strcmp (test_chomp_str_orig, new_string) == 0);
+ p_free (new_string);
+
+ new_string = p_strchomp (test_chomp_str_3);
+ P_TEST_REQUIRE (new_string != NULL);
+ P_TEST_CHECK (strcmp (test_chomp_str_orig, new_string) == 0);
+ p_free (new_string);
+
+ new_string = p_strchomp (test_chomp_str_4);
+ P_TEST_REQUIRE (new_string != NULL);
+ P_TEST_CHECK (strcmp (test_chomp_str_orig, new_string) == 0);
+ p_free (new_string);
+
+ new_string = p_strchomp (test_chomp_str_5);
+ P_TEST_REQUIRE (new_string != NULL);
+ P_TEST_CHECK (strcmp (test_chomp_str_orig, new_string) == 0);
+ p_free (new_string);
+
+ new_string = p_strchomp (test_chomp_str_6);
+ P_TEST_REQUIRE (new_string != NULL);
+ P_TEST_CHECK (strcmp ("I", new_string) == 0);
+ p_free (new_string);
+
+ new_string = p_strchomp (test_chomp_str_7);
+ P_TEST_REQUIRE (new_string != NULL);
+ P_TEST_CHECK (*new_string == '\0');
+ p_free (new_string);
+
+ new_string = p_strchomp (test_chomp_str_8);
+ P_TEST_REQUIRE (new_string != NULL);
+ P_TEST_CHECK (strcmp ("I", new_string) == 0);
+ p_free (new_string);
+
+ new_string = p_strchomp (test_chomp_str_9);
+ P_TEST_REQUIRE (new_string != NULL);
+ P_TEST_CHECK (*new_string == '\0');
+ p_free (new_string);
+
+ new_string = p_strchomp (test_chomp_str_10);
+ P_TEST_REQUIRE (new_string != NULL);
+ P_TEST_CHECK (*new_string == '\0');
+ p_free (new_string);
+
+ new_string = p_strchomp (test_chomp_str_11);
+ P_TEST_CHECK (new_string == NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pstring_strtok_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_strtok (NULL, NULL, NULL) == NULL);
+
+ /* First string */
+ pchar test_string[] = "1,2,3";
+ pchar *token, *next_token;
+
+ /* Check third parameter for possible NULL */
+ token = p_strtok (test_string, ",", NULL);
+
+ if (strcmp (token, "1") != 0) {
+ token = p_strtok (test_string, ",", &next_token);
+ P_TEST_CHECK (token != NULL);
+ P_TEST_CHECK (strcmp (token, "1") == 0);
+ }
+
+ token = p_strtok (NULL, ",", &next_token);
+ P_TEST_CHECK (token != NULL);
+ P_TEST_CHECK (strcmp (token, "2") == 0);
+
+ token = p_strtok (NULL, ",", &next_token);
+ P_TEST_CHECK (token != NULL);
+ P_TEST_CHECK (strcmp (token, "3") == 0);
+
+ token = p_strtok (NULL, ",", &next_token);
+ P_TEST_CHECK (token == NULL);
+
+ /* Second string */
+ pchar test_string_2[] = "Test string, to test";
+
+ token = p_strtok (test_string_2, " ", &next_token);
+ P_TEST_CHECK (token != NULL);
+ P_TEST_CHECK (strcmp (token, "Test") == 0);
+
+ token = p_strtok (NULL, ", ", &next_token);
+ P_TEST_CHECK (token != NULL);
+ P_TEST_CHECK (strcmp (token, "string") == 0);
+
+ token = p_strtok (NULL, ", ", &next_token);
+ P_TEST_CHECK (token != NULL);
+ P_TEST_CHECK (strcmp (token, "to") == 0);
+
+ token = p_strtok (NULL, ", \t\n", &next_token);
+ P_TEST_CHECK (token != NULL);
+ P_TEST_CHECK (strcmp (token, "test") == 0);
+
+ token = p_strtok (NULL, ", \t\n", &next_token);
+ P_TEST_CHECK (token == NULL);
+
+ /* Third string */
+ pchar test_string_3[] = "compile\ttest\ndeploy";
+
+ token = p_strtok (test_string_3, "\t\n", &next_token);
+ P_TEST_CHECK (token != NULL);
+ P_TEST_CHECK (strcmp (token, "compile") == 0);
+
+ token = p_strtok (NULL, "\t\n", &next_token);
+ P_TEST_CHECK (token != NULL);
+ P_TEST_CHECK (strcmp (token, "test") == 0);
+
+ token = p_strtok (NULL, "\t\n", &next_token);
+ P_TEST_CHECK (token != NULL);
+ P_TEST_CHECK (strcmp (token, "deploy") == 0);
+
+ token = p_strtok (NULL, ", \t\n", &next_token);
+ P_TEST_CHECK (token == NULL);
+
+ /* Fourth string */
+ pchar test_string_4[] = "\t \t\n \t";
+
+ token = p_strtok (test_string_4, "\t\n ", &next_token);
+ P_TEST_CHECK (token == NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (pstring_strtod_test)
+{
+ p_libsys_init ();
+
+ /* Incorrect input */
+ P_TEST_CHECK_CLOSE (p_strtod (NULL), 0.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("e2"), 0.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("e-2"), 0.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("-e2"), 0.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("-e-2"), 0.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("0,3"), 0.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("12,3"), 12.0, 0.0001);
+
+ /* Correct input */
+ P_TEST_CHECK_CLOSE (p_strtod ("0"), 0.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("0.0"), 0.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("-0"), 0.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("-0.0"), 0.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("3.14"), 3.14, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("+3.14"), 3.14, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("-12.256"), -12.256, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("0.056"), 0.056, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("-0.057"), -0.057, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("1.5423e2"), 154.23, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("1e3"), 1000.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("1e+3"), 1000.0, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("-2.56e1"), -25.6, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("-2.56e+1"), -25.6, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("123e-2"), 1.23, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("3.14e-1"), 0.314, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("3.14e60"), 3.14e60, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("3.14e-60"), 3.14e-60, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("2.14e10"), 2.14e10, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("2.14e-10"), 2.14e-10, 0.0001);
+ P_TEST_CHECK_CLOSE (p_strtod ("1.10e310"), 1.10e308, 0.0001);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (pstring_nomem_test);
+ P_TEST_SUITE_RUN_CASE (pstring_strdup_test);
+ P_TEST_SUITE_RUN_CASE (pstring_strchomp_test);
+ P_TEST_SUITE_RUN_CASE (pstring_strtok_test);
+ P_TEST_SUITE_RUN_CASE (pstring_strtod_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/ptestmacros.h b/3rdparty/plibsys/tests/ptestmacros.h
new file mode 100644
index 0000000..206a8a6
--- /dev/null
+++ b/3rdparty/plibsys/tests/ptestmacros.h
@@ -0,0 +1,131 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file ptestmacros.h
+ * @brief Macros for unit-tests
+ * @author Alexander Saprykin
+ */
+
+#ifndef PLIBSYS_HEADER_PTESTMACROS_H
+#define PLIBSYS_HEADER_PTESTMACROS_H
+
+#include <stdlib.h>
+
+#include <plibsys.h>
+
+#if defined (P_CC_MSVC)
+# pragma warning (push)
+# pragma warning (disable : 4723)
+#elif defined (P_CC_BORLAND)
+# pragma option -w-8008
+# pragma option -w-8066
+#elif defined (P_CC_WATCOM)
+# pragma disable_message (13)
+# pragma disable_message (367)
+# pragma disable_message (368)
+#endif
+
+inline double p_test_safe_division (double f1, double f2)
+{
+ return (f2 < 1.0 && f1 > f2 * P_MAXDOUBLE) ? P_MAXDOUBLE :
+ (((f2 > 1.0 && f1 < f2 * P_MINDOUBLE) || f1 == 0) ? 0 : f1 / f2);
+}
+
+#ifdef P_CC_MSVC
+# pragma warning (pop)
+#endif
+
+#define P_TEST_MODULE_FAIL_COUNTER p_test_module_fail_counter
+#define P_TEST_SUITE_FAIL_COUNTER p_test_suite_fail_counter
+
+#define P_TEST_MODULE_INIT() static pint P_TEST_MODULE_FAIL_COUNTER = 0
+
+#define P_TEST_CASE_BEGIN(test_case_name) \
+ pint p_test_case_##test_case_name (void) \
+ { \
+ P_TEST_MODULE_FAIL_COUNTER = 0;
+
+#define P_TEST_CASE_END() \
+ return (P_TEST_MODULE_FAIL_COUNTER == 0) ? 0 : -1; \
+ }
+
+#define P_TEST_CASE_RETURN() return 0
+
+#define P_TEST_SUITE_BEGIN() \
+ int main (void) \
+ { \
+ pint P_TEST_SUITE_FAIL_COUNTER = 0;
+
+#define P_TEST_SUITE_ARGS_BEGIN() \
+ int main (int argc, char *argv[]) \
+ { \
+ pint P_TEST_SUITE_FAIL_COUNTER = 0;
+
+#define P_TEST_SUITE_END() \
+ if (P_TEST_SUITE_FAIL_COUNTER == 0) \
+ printf ("Test passed\n"); \
+ else \
+ printf ("Test failed\n"); \
+ \
+ return P_TEST_SUITE_FAIL_COUNTER == 0 ? 0 : -1; \
+ }
+
+#define P_TEST_SUITE_RUN_CASE(a) \
+ printf ("Running test case: %s\n", #a); \
+ P_TEST_SUITE_FAIL_COUNTER += (p_test_case_##a)()
+
+#define P_TEST_CHECK(a) \
+ do { \
+ if (!(a)) { \
+ printf ("%s:%d: check failed\n", __FILE__, __LINE__); \
+ p_atomic_int_inc (&P_TEST_MODULE_FAIL_COUNTER); \
+ } \
+ } while (0)
+
+#define P_TEST_CHECK_CLOSE(a, b, eps) \
+ do { \
+ double p_test_eps_diff = (a) > (b) ? (a) - (b) : (b) - (a); \
+ double p_test_d1 = p_test_safe_division (p_test_eps_diff, \
+ ((a) < 0.0 ? (-(a)) : (a))); \
+ double p_test_d2 = p_test_safe_division (p_test_eps_diff, \
+ ((b) < 0.0 ? (-(b)) : (b))); \
+ double p_test_tol = (eps) * 0.01; \
+ \
+ if (!(p_test_d1 <= p_test_tol && p_test_d2 <= p_test_tol)) { \
+ printf ("%s:%d: check failed\n", __FILE__, __LINE__); \
+ p_atomic_int_inc (&P_TEST_MODULE_FAIL_COUNTER); \
+ } \
+ } while (0)
+
+#define P_TEST_REQUIRE(a) \
+ do { \
+ if (!(a)) { \
+ printf ("%s:%d: required check failed\n", __FILE__, __LINE__); \
+ exit (-1); \
+ } \
+ } while (0)
+
+#endif /* PLIBSYS_HEADER_PTESTMACROS_H */
diff --git a/3rdparty/plibsys/tests/ptimeprofiler_test.cpp b/3rdparty/plibsys/tests/ptimeprofiler_test.cpp
new file mode 100644
index 0000000..dd9e2b7
--- /dev/null
+++ b/3rdparty/plibsys/tests/ptimeprofiler_test.cpp
@@ -0,0 +1,126 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+P_TEST_MODULE_INIT ();
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+P_TEST_CASE_BEGIN (ptimeprofiler_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_time_profiler_new () == NULL);
+
+ p_mem_restore_vtable ();
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (ptimeprofiler_bad_input_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_time_profiler_elapsed_usecs (NULL) == 0);
+ p_time_profiler_reset (NULL);
+ p_time_profiler_free (NULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (ptimeprofiler_general_test)
+{
+ PTimeProfiler *profiler = NULL;
+ puint64 prev_val, val;
+
+ p_libsys_init ();
+
+ profiler = p_time_profiler_new ();
+ P_TEST_REQUIRE (profiler != NULL);
+
+ p_uthread_sleep (50);
+ prev_val = p_time_profiler_elapsed_usecs (profiler);
+ P_TEST_CHECK (prev_val > 0);
+
+ p_uthread_sleep (100);
+ val = p_time_profiler_elapsed_usecs (profiler);
+ P_TEST_CHECK (val > prev_val);
+ prev_val = val;
+
+ p_uthread_sleep (1000);
+ val = p_time_profiler_elapsed_usecs (profiler);
+ P_TEST_CHECK (val > prev_val);
+
+ p_time_profiler_reset (profiler);
+
+ p_uthread_sleep (15);
+ prev_val = p_time_profiler_elapsed_usecs (profiler);
+ P_TEST_CHECK (prev_val > 0);
+
+ p_uthread_sleep (178);
+ val = p_time_profiler_elapsed_usecs (profiler);
+ P_TEST_CHECK (val > prev_val);
+
+ p_time_profiler_free (profiler);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (ptimeprofiler_nomem_test);
+ P_TEST_SUITE_RUN_CASE (ptimeprofiler_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (ptimeprofiler_general_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/ptree_test.cpp b/3rdparty/plibsys/tests/ptree_test.cpp
new file mode 100644
index 0000000..e038ebb
--- /dev/null
+++ b/3rdparty/plibsys/tests/ptree_test.cpp
@@ -0,0 +1,633 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2015-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+
+P_TEST_MODULE_INIT ();
+
+#define PTREE_STRESS_ITERATIONS 20
+#define PTREE_STRESS_NODES 10000
+#define PTREE_STRESS_ROOT_MIN 10000
+#define PTREE_STRESS_TRAVS 30
+
+typedef struct _TreeData {
+ pint cmp_counter;
+ pint key_destroy_counter;
+ pint value_destroy_counter;
+ pint traverse_counter;
+ pint traverse_thres;
+ pint key_sum;
+ pint value_sum;
+ pint last_key;
+ pint key_order_errors;
+} TreeData;
+
+static TreeData tree_data = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+static pint
+tree_complexity (PTree *tree)
+{
+ if (tree == NULL || p_tree_get_nnodes (tree) == 0)
+ return 0;
+
+ switch (p_tree_get_type (tree)) {
+ case P_TREE_TYPE_BINARY:
+ return p_tree_get_nnodes (tree);
+ case P_TREE_TYPE_RB:
+ return 2 * ((pint) (log ((double) p_tree_get_nnodes (tree) + 1) / log (2.0)));
+ case P_TREE_TYPE_AVL:
+ {
+ double phi = (1 + sqrt (5.0)) / 2.0;
+ return (pint) (log (sqrt (5.0) * (p_tree_get_nnodes (tree) + 2)) / log (phi) - 2);
+ }
+ default:
+ return p_tree_get_nnodes (tree);
+ }
+}
+
+static pint
+compare_keys (pconstpointer a, pconstpointer b)
+{
+ int p1 = PPOINTER_TO_INT (a);
+ int p2 = PPOINTER_TO_INT (b);
+
+ if (p1 < p2)
+ return -1;
+ else if (p1 > p2)
+ return 1;
+ else
+ return 0;
+}
+
+static pint
+compare_keys_data (pconstpointer a, pconstpointer b, ppointer data)
+{
+ int p1 = PPOINTER_TO_INT (a);
+ int p2 = PPOINTER_TO_INT (b);
+
+ if (data != NULL)
+ ((TreeData *) data)->cmp_counter++;
+
+ if (p1 < p2)
+ return -1;
+ else if (p1 > p2)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+key_destroy_notify (ppointer data)
+{
+ tree_data.key_destroy_counter++;
+ tree_data.key_sum += PPOINTER_TO_INT (data);
+}
+
+static void
+value_destroy_notify (ppointer data)
+{
+ tree_data.value_destroy_counter++;
+ tree_data.value_sum += PPOINTER_TO_INT (data);
+}
+
+static pboolean
+tree_traverse (ppointer key, ppointer value, ppointer data)
+{
+ TreeData* tdata = ((TreeData *) data);
+
+ tdata->key_sum += PPOINTER_TO_INT (key);
+ tdata->value_sum += PPOINTER_TO_INT (value);
+ tdata->traverse_counter++;
+
+ if (tdata->last_key >= PPOINTER_TO_INT (key))
+ tdata->key_order_errors++;
+
+ tdata->last_key = PPOINTER_TO_INT (key);
+
+ return FALSE;
+}
+
+static pboolean
+tree_traverse_thres (ppointer key, ppointer value, ppointer data)
+{
+ TreeData* tdata = ((TreeData *) data);
+
+ tree_traverse (key, value, data);
+
+ return tdata->traverse_counter >= tdata->traverse_thres ? TRUE : FALSE;
+}
+
+static bool
+check_tree_data_is_zero ()
+{
+ return tree_data.cmp_counter == 0 &&
+ tree_data.key_destroy_counter == 0 &&
+ tree_data.value_destroy_counter == 0 &&
+ tree_data.traverse_counter == 0 &&
+ tree_data.traverse_thres == 0 &&
+ tree_data.key_sum == 0 &&
+ tree_data.value_sum == 0 &&
+ tree_data.last_key == 0 &&
+ tree_data.key_order_errors == 0;
+}
+
+static bool
+general_tree_test (PTree *tree, PTreeType type, bool check_cmp, bool check_notify)
+{
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ P_TEST_REQUIRE (tree != NULL);
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 0);
+ P_TEST_CHECK (p_tree_get_type (tree) == type);
+ P_TEST_CHECK (p_tree_lookup (tree, NULL) == NULL);
+ P_TEST_CHECK (p_tree_remove (tree, NULL) == FALSE);
+
+ p_tree_insert (tree, NULL, PINT_TO_POINTER (10));
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 1);
+ P_TEST_CHECK (p_tree_lookup (tree, NULL) == PINT_TO_POINTER (10));
+ P_TEST_CHECK (p_tree_lookup (tree, PINT_TO_POINTER (2)) == NULL);
+ P_TEST_CHECK (p_tree_remove (tree, NULL) == TRUE);
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 0);
+
+ p_tree_foreach (tree, (PTraverseFunc) tree_traverse, &tree_data);
+ P_TEST_CHECK (tree_data.traverse_counter == 0);
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+
+ /* Because we have NULL-key node */
+ P_TEST_CHECK (tree_data.key_sum == 0);
+
+ if (check_notify)
+ P_TEST_CHECK (tree_data.value_sum == 10);
+ else
+ P_TEST_CHECK (tree_data.value_sum == 0);
+
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ p_tree_insert (tree, PINT_TO_POINTER (4), PINT_TO_POINTER (40));
+ p_tree_insert (tree, PINT_TO_POINTER (1), PINT_TO_POINTER (10));
+ p_tree_insert (tree, PINT_TO_POINTER (5), PINT_TO_POINTER (50));
+ p_tree_insert (tree, PINT_TO_POINTER (2), PINT_TO_POINTER (20));
+ p_tree_insert (tree, PINT_TO_POINTER (6), PINT_TO_POINTER (60));
+ p_tree_insert (tree, PINT_TO_POINTER (3), PINT_TO_POINTER (30));
+
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 6);
+
+ p_tree_insert (tree, PINT_TO_POINTER (1), PINT_TO_POINTER (100));
+ p_tree_insert (tree, PINT_TO_POINTER (5), PINT_TO_POINTER (500));
+
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 6);
+
+ p_tree_insert (tree, PINT_TO_POINTER (1), PINT_TO_POINTER (10));
+ p_tree_insert (tree, PINT_TO_POINTER (5), PINT_TO_POINTER (50));
+
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 6);
+
+ if (check_cmp)
+ P_TEST_CHECK (tree_data.cmp_counter > 0);
+ else
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+
+ if (check_notify) {
+ P_TEST_CHECK (tree_data.key_sum == 12);
+ P_TEST_CHECK (tree_data.value_sum == 660);
+ } else {
+ P_TEST_CHECK (tree_data.key_sum == 0);
+ P_TEST_CHECK (tree_data.value_sum == 0);
+ }
+
+ P_TEST_CHECK (tree_data.traverse_counter == 0);
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ p_tree_foreach (tree, (PTraverseFunc) tree_traverse, &tree_data);
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 6);
+
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+ P_TEST_CHECK (tree_data.key_sum == 21);
+ P_TEST_CHECK (tree_data.value_sum == 210);
+ P_TEST_CHECK (tree_data.traverse_counter == 6);
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ for (int i = 0; i < 7; ++i)
+ P_TEST_CHECK (p_tree_lookup (tree, PINT_TO_POINTER (i)) == PINT_TO_POINTER (i * 10));
+
+ if (check_cmp)
+ P_TEST_CHECK (tree_data.cmp_counter > 0);
+ else
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+
+ P_TEST_CHECK (tree_data.key_sum == 0);
+ P_TEST_CHECK (tree_data.value_sum == 0);
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+
+ tree_data.cmp_counter = 0;
+
+ P_TEST_CHECK (p_tree_remove (tree, PINT_TO_POINTER (7)) == FALSE);
+
+ if (check_cmp)
+ P_TEST_CHECK (tree_data.cmp_counter > 0 &&
+ tree_data.cmp_counter <= tree_complexity (tree));
+ else
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+
+ if (check_notify) {
+ P_TEST_CHECK (tree_data.key_sum == 0);
+ P_TEST_CHECK (tree_data.value_sum == 0);
+ }
+
+ tree_data.cmp_counter = 0;
+
+ for (int i = 0; i < 7; ++i)
+ P_TEST_CHECK (p_tree_lookup (tree, PINT_TO_POINTER (i)) == PINT_TO_POINTER (i * 10));
+
+ if (check_cmp)
+ P_TEST_CHECK (tree_data.cmp_counter > 0);
+ else
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+
+ P_TEST_CHECK (tree_data.key_sum == 0);
+ P_TEST_CHECK (tree_data.value_sum == 0);
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ tree_data.traverse_thres = 5;
+
+ p_tree_foreach (tree, (PTraverseFunc) tree_traverse_thres, &tree_data);
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 6);
+
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+ P_TEST_CHECK (tree_data.key_sum == 15);
+ P_TEST_CHECK (tree_data.value_sum == 150);
+ P_TEST_CHECK (tree_data.traverse_counter == 5);
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ tree_data.traverse_thres = 3;
+
+ p_tree_foreach (tree, (PTraverseFunc) tree_traverse_thres, &tree_data);
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 6);
+
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+ P_TEST_CHECK (tree_data.key_sum == 6);
+ P_TEST_CHECK (tree_data.value_sum == 60);
+ P_TEST_CHECK (tree_data.traverse_counter == 3);
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ P_TEST_CHECK (p_tree_remove (tree, PINT_TO_POINTER (1)) == TRUE);
+ P_TEST_CHECK (p_tree_remove (tree, PINT_TO_POINTER (6)) == TRUE);
+ P_TEST_CHECK (p_tree_lookup (tree, PINT_TO_POINTER (1)) == NULL);
+ P_TEST_CHECK (p_tree_lookup (tree, PINT_TO_POINTER (6)) == NULL);
+
+ if (check_cmp)
+ P_TEST_CHECK (tree_data.cmp_counter > 0);
+ else
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+
+ if (check_notify) {
+ P_TEST_CHECK (tree_data.key_sum == 7);
+ P_TEST_CHECK (tree_data.value_sum == 70);
+ } else {
+ P_TEST_CHECK (tree_data.key_sum == 0);
+ P_TEST_CHECK (tree_data.value_sum == 0);
+ }
+
+ tree_data.cmp_counter = 0;
+
+ for (int i = 2; i < 6; ++i)
+ P_TEST_CHECK (p_tree_lookup (tree, PINT_TO_POINTER (i)) == PINT_TO_POINTER (i * 10));
+
+ if (check_cmp)
+ P_TEST_CHECK (tree_data.cmp_counter > 0);
+ else
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+
+ if (check_notify) {
+ P_TEST_CHECK (tree_data.key_sum == 7);
+ P_TEST_CHECK (tree_data.value_sum == 70);
+ } else {
+ P_TEST_CHECK (tree_data.key_sum == 0);
+ P_TEST_CHECK (tree_data.value_sum == 0);
+ }
+
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+
+ tree_data.cmp_counter = 0;
+
+ p_tree_foreach (tree, NULL, NULL);
+
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+
+ p_tree_clear (tree);
+
+ P_TEST_CHECK (tree_data.cmp_counter == 0);
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+
+ if (check_notify) {
+ P_TEST_CHECK (tree_data.key_sum == 21);
+ P_TEST_CHECK (tree_data.value_sum == 210);
+ } else {
+ P_TEST_CHECK (tree_data.key_sum == 0);
+ P_TEST_CHECK (tree_data.value_sum == 0);
+ }
+
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 0);
+
+ return true;
+}
+
+static bool
+stress_tree_test (PTree *tree, int node_count)
+{
+ P_TEST_REQUIRE (tree != NULL);
+ P_TEST_REQUIRE (node_count > 0);
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 0);
+
+ srand ((unsigned int) time (NULL));
+
+ int counter = 0;
+
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ pint *keys = (pint *) p_malloc0 ((psize) node_count * sizeof (pint));
+ pint *values = (pint *) p_malloc0 ((psize) node_count * sizeof (pint));
+
+ P_TEST_REQUIRE (keys != NULL);
+ P_TEST_REQUIRE (values != NULL);
+
+ while (counter != node_count) {
+ pint rand_number = rand ();
+
+ if (counter == 0 && rand_number < PTREE_STRESS_ROOT_MIN)
+ continue;
+
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ if (p_tree_lookup (tree, PINT_TO_POINTER (rand_number)) != NULL)
+ continue;
+
+ if (counter > 0)
+ P_TEST_CHECK (tree_data.cmp_counter > 0 &&
+ tree_data.cmp_counter <= tree_complexity (tree));
+
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ keys[counter] = rand_number;
+ values[counter] = rand () + 1;
+
+ p_tree_insert (tree, PINT_TO_POINTER (keys[counter]), PINT_TO_POINTER (values[counter]));
+
+ if (counter > 0)
+ P_TEST_CHECK (tree_data.cmp_counter > 0 &&
+ tree_data.cmp_counter <= tree_complexity (tree));
+
+ ++counter;
+ }
+
+ for (int i = 0; i < PTREE_STRESS_TRAVS; ++i) {
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ tree_data.traverse_thres = i + 1;
+ tree_data.last_key = -1;
+
+ p_tree_foreach (tree, (PTraverseFunc) tree_traverse_thres, &tree_data);
+
+ P_TEST_CHECK (tree_data.traverse_counter == i + 1);
+ P_TEST_CHECK (tree_data.key_order_errors == 0);
+ }
+
+ for (int i = 0; i < node_count; ++i) {
+ memset (&tree_data, 0, sizeof (tree_data));
+
+ P_TEST_CHECK (p_tree_lookup (tree, PINT_TO_POINTER (keys[i])) ==
+ PINT_TO_POINTER (values[i]));
+
+ P_TEST_CHECK (tree_data.cmp_counter > 0 &&
+ tree_data.cmp_counter <= tree_complexity (tree));
+
+ P_TEST_CHECK (p_tree_remove (tree, PINT_TO_POINTER (keys[i])) == TRUE);
+ P_TEST_CHECK (p_tree_lookup (tree, PINT_TO_POINTER (keys[i])) == NULL);
+ }
+
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 0);
+
+ for (int i = 0; i < node_count; ++i)
+ p_tree_insert (tree, PINT_TO_POINTER (keys[i]), PINT_TO_POINTER (values[i]));
+
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == node_count);
+
+ p_tree_clear (tree);
+
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 0);
+
+ p_free (keys);
+ p_free (values);
+
+ return true;
+}
+
+P_TEST_CASE_BEGIN (ptree_nomem_test)
+{
+ p_libsys_init ();
+
+ PMemVTable vtable;
+
+ for (int i = (int) P_TREE_TYPE_BINARY; i <= (int) P_TREE_TYPE_AVL; ++i) {
+ PTree *tree = p_tree_new ((PTreeType) i, (PCompareFunc) compare_keys);
+ P_TEST_CHECK (tree != NULL);
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ P_TEST_CHECK (p_tree_new ((PTreeType) i, (PCompareFunc) compare_keys) == NULL);
+ p_tree_insert (tree, PINT_TO_POINTER (1), PINT_TO_POINTER (10));
+ P_TEST_CHECK (p_tree_get_nnodes (tree) == 0);
+
+ p_mem_restore_vtable ();
+
+ p_tree_free (tree);
+ }
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (ptree_invalid_test)
+{
+ p_libsys_init ();
+
+ for (int i = (int) P_TREE_TYPE_BINARY; i <= (int) P_TREE_TYPE_AVL; ++i) {
+ /* Invalid usage */
+ P_TEST_CHECK (p_tree_new ((PTreeType) i, NULL) == NULL);
+ P_TEST_CHECK (p_tree_new ((PTreeType) -1, (PCompareFunc) compare_keys) == NULL);
+ P_TEST_CHECK (p_tree_new ((PTreeType) -1, NULL) == NULL);
+
+ P_TEST_CHECK (p_tree_new_with_data ((PTreeType) i, NULL, NULL) == NULL);
+ P_TEST_CHECK (p_tree_new_with_data ((PTreeType) -1, (PCompareDataFunc) compare_keys, NULL) == NULL);
+ P_TEST_CHECK (p_tree_new_with_data ((PTreeType) -1, NULL, NULL) == NULL);
+
+ P_TEST_CHECK (p_tree_new_full ((PTreeType) i,
+ NULL,
+ NULL,
+ NULL,
+ NULL) == NULL);
+ P_TEST_CHECK (p_tree_new_full ((PTreeType) -1,
+ (PCompareDataFunc) compare_keys,
+ NULL,
+ NULL,
+ NULL) == NULL);
+ P_TEST_CHECK (p_tree_new_full ((PTreeType) -1,
+ NULL,
+ NULL,
+ NULL,
+ NULL) == NULL);
+
+ P_TEST_CHECK (p_tree_remove (NULL, NULL) == FALSE);
+ P_TEST_CHECK (p_tree_lookup (NULL, NULL) == NULL);
+ P_TEST_CHECK (p_tree_get_type (NULL) == (PTreeType) -1);
+ P_TEST_CHECK (p_tree_get_nnodes (NULL) == 0);
+
+ p_tree_insert (NULL, NULL, NULL);
+ p_tree_foreach (NULL, NULL, NULL);
+ p_tree_clear (NULL);
+ p_tree_free (NULL);
+ }
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (ptree_general_test)
+{
+ PTree *tree;
+
+ p_libsys_init ();
+
+ for (int i = (int) P_TREE_TYPE_BINARY; i <= (int) P_TREE_TYPE_AVL; ++i) {
+ /* Test 1 */
+ tree = p_tree_new ((PTreeType) i, (PCompareFunc) compare_keys);
+
+ P_TEST_CHECK (general_tree_test (tree, (PTreeType) i, false, false) == true);
+
+ memset (&tree_data, 0, sizeof (tree_data));
+ p_tree_free (tree);
+
+ P_TEST_CHECK (check_tree_data_is_zero () == true);
+
+ /* Test 2 */
+ tree = p_tree_new_with_data ((PTreeType) i,
+ (PCompareDataFunc) compare_keys_data,
+ &tree_data);
+
+ P_TEST_CHECK (general_tree_test (tree, (PTreeType) i, true, false) == true);
+
+ memset (&tree_data, 0, sizeof (tree_data));
+ p_tree_free (tree);
+
+ P_TEST_CHECK (check_tree_data_is_zero () == true);
+
+ /* Test 3 */
+ tree = p_tree_new_full ((PTreeType) i,
+ (PCompareDataFunc) compare_keys_data,
+ &tree_data,
+ (PDestroyFunc) key_destroy_notify,
+ (PDestroyFunc) value_destroy_notify);
+ P_TEST_CHECK (general_tree_test (tree, (PTreeType) i, true, true) == true);
+
+ memset (&tree_data, 0, sizeof (tree_data));
+ p_tree_free (tree);
+
+ P_TEST_CHECK (check_tree_data_is_zero () == true);
+ }
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (ptree_stress_test)
+{
+ PTree *tree;
+
+ p_libsys_init ();
+
+ for (int i = (int) P_TREE_TYPE_BINARY; i <= (int) P_TREE_TYPE_AVL; ++i) {
+ tree = p_tree_new_full ((PTreeType) i,
+ (PCompareDataFunc) compare_keys_data,
+ &tree_data,
+ (PDestroyFunc) key_destroy_notify,
+ (PDestroyFunc) value_destroy_notify);
+
+ for (int j = 0; j < PTREE_STRESS_ITERATIONS; ++j)
+ P_TEST_CHECK (stress_tree_test (tree, PTREE_STRESS_NODES) == true);
+
+ p_tree_free (tree);
+ }
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (ptree_nomem_test);
+ P_TEST_SUITE_RUN_CASE (ptree_invalid_test);
+ P_TEST_SUITE_RUN_CASE (ptree_general_test);
+ P_TEST_SUITE_RUN_CASE (ptree_stress_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/ptypes_test.cpp b/3rdparty/plibsys/tests/ptypes_test.cpp
new file mode 100644
index 0000000..1e9c0e9
--- /dev/null
+++ b/3rdparty/plibsys/tests/ptypes_test.cpp
@@ -0,0 +1,456 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2014-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+P_TEST_MODULE_INIT ();
+
+P_TEST_CASE_BEGIN (ptypes_general_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (P_BYTE_ORDER == P_LITTLE_ENDIAN ||
+ P_BYTE_ORDER == P_BIG_ENDIAN);
+
+ P_TEST_CHECK (sizeof (pint8) == 1);
+ P_TEST_CHECK (sizeof (puint8) == 1);
+ P_TEST_CHECK (sizeof (pint16) == 2);
+ P_TEST_CHECK (sizeof (puint16) == 2);
+ P_TEST_CHECK (sizeof (pint32) == 4);
+ P_TEST_CHECK (sizeof (puint32) == 4);
+ P_TEST_CHECK (sizeof (pint64) == 8);
+ P_TEST_CHECK (sizeof (puint64) == 8);
+ P_TEST_CHECK (sizeof (void *) == sizeof (ppointer));
+ P_TEST_CHECK (sizeof (const void *) == sizeof (pconstpointer));
+ P_TEST_CHECK (sizeof (int) == sizeof (pboolean));
+ P_TEST_CHECK (sizeof (char) == sizeof (pchar));
+ P_TEST_CHECK (sizeof (short) == sizeof (pshort));
+ P_TEST_CHECK (sizeof (int) == sizeof (pint));
+ P_TEST_CHECK (sizeof (long) == sizeof (plong));
+ P_TEST_CHECK (sizeof (unsigned char) == sizeof (puchar));
+ P_TEST_CHECK (sizeof (unsigned short) == sizeof (pushort));
+ P_TEST_CHECK (sizeof (unsigned int) == sizeof (puint));
+ P_TEST_CHECK (sizeof (unsigned long) == sizeof (pulong));
+ P_TEST_CHECK (sizeof (float) == sizeof (pfloat));
+ P_TEST_CHECK (sizeof (double) == sizeof (pdouble));
+ P_TEST_CHECK (sizeof (pintptr) == PLIBSYS_SIZEOF_VOID_P);
+ P_TEST_CHECK (sizeof (puintptr) == PLIBSYS_SIZEOF_VOID_P);
+ P_TEST_CHECK (sizeof (psize) == PLIBSYS_SIZEOF_SIZE_T);
+ P_TEST_CHECK (sizeof (pssize) == PLIBSYS_SIZEOF_SIZE_T);
+ P_TEST_CHECK (sizeof (plong) == PLIBSYS_SIZEOF_LONG);
+ P_TEST_CHECK (sizeof (pulong) == PLIBSYS_SIZEOF_LONG);
+ P_TEST_CHECK (sizeof (poffset) == 8);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (ptypes_pointers_convert_test)
+{
+ p_libsys_init ();
+
+ ppointer pointer = P_INT_TO_POINTER (128);
+ P_TEST_CHECK (P_POINTER_TO_INT (pointer) == 128);
+
+ pint pint_val = -64;
+ pointer = PINT_TO_POINTER (pint_val);
+ P_TEST_CHECK (PPOINTER_TO_INT (pointer) == -64);
+
+ puint puint_val = 64;
+ pointer = PUINT_TO_POINTER (puint_val);
+ P_TEST_CHECK (PPOINTER_TO_UINT (pointer) == 64);
+
+ psize psize_val = 1024;
+ pointer = PSIZE_TO_POINTER (psize_val);
+ P_TEST_CHECK (PPOINTER_TO_PSIZE (psize_val) == 1024);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (ptypes_min_max_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (P_MININT8 == (pint8) 0x80);
+ P_TEST_CHECK (P_MAXINT8 == (pint8) 0x7F);
+ P_TEST_CHECK (P_MAXUINT8 == (puint8) 0xFF);
+ P_TEST_CHECK (P_MININT16 == (pint16) 0x8000);
+ P_TEST_CHECK (P_MAXINT16 == (pint16) 0x7FFF);
+ P_TEST_CHECK (P_MAXUINT16 == (puint16) 0xFFFF);
+ P_TEST_CHECK (P_MININT32 == (pint32) 0x80000000);
+ P_TEST_CHECK (P_MAXINT32 == (pint32) 0x7FFFFFFF);
+ P_TEST_CHECK (P_MAXUINT32 == (puint32) 0xFFFFFFFF);
+ P_TEST_CHECK (P_MININT64 == (pint64) 0x8000000000000000LL);
+ P_TEST_CHECK (P_MAXINT64 == (pint64) 0x7FFFFFFFFFFFFFFFLL);
+ P_TEST_CHECK (P_MAXUINT64 == (puint64) 0xFFFFFFFFFFFFFFFFULL);
+
+ if (PLIBSYS_SIZEOF_SIZE_T == 8) {
+ P_TEST_CHECK (P_MINSSIZE == P_MININT64);
+ P_TEST_CHECK (P_MAXSSIZE == P_MAXINT64);
+ P_TEST_CHECK (P_MAXSIZE == P_MAXUINT64);
+
+ if (PLIBSYS_SIZEOF_LONG == 8) {
+ P_TEST_CHECK (P_MINSSIZE == P_MINLONG);
+ P_TEST_CHECK (P_MAXSSIZE == P_MAXLONG);
+ P_TEST_CHECK (P_MAXSIZE == P_MAXULONG);
+ }
+ } else {
+ P_TEST_CHECK (P_MINSSIZE == P_MININT32);
+ P_TEST_CHECK (P_MAXSSIZE == P_MAXINT32);
+ P_TEST_CHECK (P_MAXSIZE == P_MAXUINT32);
+
+ if (PLIBSYS_SIZEOF_LONG == 4) {
+ P_TEST_CHECK (P_MINSSIZE == P_MINLONG);
+ P_TEST_CHECK (P_MAXSSIZE == P_MAXLONG);
+ P_TEST_CHECK (P_MAXSIZE == P_MAXULONG);
+ }
+ }
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (ptypes_modifiers_test)
+{
+ p_libsys_init ();
+
+ psize size_val = 256;
+ printf ("%#" PSIZE_MODIFIER "x\n", size_val);
+ pssize ssize_val = -256;
+ printf ("%#" PSIZE_MODIFIER "x\n", ssize_val);
+
+ puintptr puintptr_val = 512;
+ printf ("%#" PINTPTR_MODIFIER "x\n", puintptr_val);
+ pintptr pintptr_val = -512;
+ printf ("%#" PINTPTR_MODIFIER "x\n", pintptr_val);
+
+ puint16 puint16_val = 1024;
+ printf ("%#" PINT16_MODIFIER "x\n", puint16_val);
+ pint16 pint16_val = -1024;
+ printf ("%#" PINT16_MODIFIER "x\n", pint16_val);
+
+ puint32 puint32_val = 2048;
+ printf ("%#" PINT32_MODIFIER "x\n", puint32_val);
+ pint32 pint32_val = -2048;
+ printf ("%#" PINT32_MODIFIER "x\n", pint32_val);
+
+ puint64 puint64_val = 4096;
+ printf ("%#" PINT64_MODIFIER "x\n", puint64_val);
+ pint64 pint64_val = -4096;
+ printf ("%#" PINT64_MODIFIER "x\n", pint64_val);
+
+ poffset poffset_val = 8192;
+ printf ("%#" POFFSET_MODIFIER "x\n", poffset_val);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (ptypes_formats_test)
+{
+ p_libsys_init ();
+
+ pssize ssize_val = -256;
+ printf ("%" PSSIZE_FORMAT "\n", ssize_val);
+ psize size_val = 256;
+ printf ("%" PSIZE_FORMAT "\n", size_val);
+
+ puintptr puintptr_val = 512;
+ printf ("%" PUINTPTR_FORMAT "\n", puintptr_val);
+ pintptr pintptr_val = -512;
+ printf ("%" PINTPTR_FORMAT "\n", pintptr_val);
+
+ puint16 puint16_val = 1024;
+ printf ("%" PUINT16_FORMAT "\n", puint16_val);
+ pint16 pint16_val = -1024;
+ printf ("%" PINT16_FORMAT "\n", pint16_val);
+
+ puint32 puint32_val = 2048;
+ printf ("%" PUINT32_FORMAT "\n", puint32_val);
+ pint32 pint32_val = -2048;
+ printf ("%" PINT32_FORMAT "\n", pint32_val);
+
+ puint64 puint64_val = 4096;
+ printf ("%" PUINT64_FORMAT "\n", puint64_val);
+ pint64 pint64_val = -4096;
+ printf ("%" PINT64_FORMAT "\n", pint64_val);
+
+ poffset poffset_val = 8192;
+ printf ("%" POFFSET_FORMAT "\n", poffset_val);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (ptypes_host_network_test)
+{
+ p_libsys_init ();
+
+ if (P_BYTE_ORDER == P_LITTLE_ENDIAN) {
+ pint16 pint16_val = PINT16_TO_BE (0xFFE0);
+ P_TEST_CHECK (pint16_val == (pint16) 0xE0FF);
+ P_TEST_CHECK (PINT16_FROM_BE (pint16_val) == (pint16) 0xFFE0);
+ P_TEST_CHECK (PINT16_TO_LE (pint16_val) == (pint16) 0xE0FF);
+ P_TEST_CHECK (PINT16_FROM_LE (pint16_val) == (pint16) 0xE0FF);
+
+ puint16 puint16_val = PUINT16_TO_BE (0x0020);
+ P_TEST_CHECK (puint16_val == (puint16) 0x2000);
+ P_TEST_CHECK (PUINT16_FROM_BE (puint16_val) == (puint16) 0x0020);
+ P_TEST_CHECK (PUINT16_TO_LE (puint16_val) == (puint16) 0x2000);
+ P_TEST_CHECK (PUINT16_FROM_LE (puint16_val) == (puint16) 0x2000);
+
+ pint32 pint32_val = PINT32_TO_BE (0xFFFFFFC0);
+ P_TEST_CHECK (pint32_val == (pint32) 0xC0FFFFFF);
+ P_TEST_CHECK (PINT32_FROM_BE (pint32_val) == (pint32) 0xFFFFFFC0);
+ P_TEST_CHECK (PINT32_TO_LE (pint32_val) == (pint32) 0xC0FFFFFF);
+ P_TEST_CHECK (PINT32_FROM_LE (pint32_val) == (pint32) 0xC0FFFFFF);
+
+ puint32 puint32_val = PUINT32_TO_BE (0x00000040);
+ P_TEST_CHECK (puint32_val == (puint32) 0x40000000);
+ P_TEST_CHECK (PUINT32_FROM_BE (puint32_val) == (puint32) 0x00000040);
+ P_TEST_CHECK (PUINT32_TO_LE (puint32_val) == (puint32) 0x40000000);
+ P_TEST_CHECK (PUINT32_FROM_LE (puint32_val) == (puint32) 0x40000000);
+
+ pint64 pint64_val = PINT64_TO_BE (0xFFFFFFFFFFFFFF80LL);
+ P_TEST_CHECK (pint64_val == (pint64) 0x80FFFFFFFFFFFFFFLL);
+ P_TEST_CHECK (PINT64_FROM_BE (pint64_val) == (pint64) 0xFFFFFFFFFFFFFF80LL);
+ P_TEST_CHECK (PINT64_TO_LE (pint64_val) == (pint64) 0x80FFFFFFFFFFFFFFLL);
+ P_TEST_CHECK (PINT64_FROM_LE (pint64_val) == (pint64) 0x80FFFFFFFFFFFFFFLL);
+
+ puint64 puint64_val = PUINT64_TO_BE (0x0000000000000080ULL);
+ P_TEST_CHECK (puint64_val == (puint64) 0x8000000000000000ULL);
+ P_TEST_CHECK (PUINT64_FROM_BE (puint64_val) == (puint64) 0x0000000000000080ULL);
+ P_TEST_CHECK (PUINT64_TO_LE (puint64_val) == (puint64) 0x8000000000000000ULL);
+ P_TEST_CHECK (PUINT64_FROM_LE (puint64_val) == (puint64) 0x8000000000000000ULL);
+
+ pint pint_val = PINT_TO_BE (0xFFFFFC00);
+ P_TEST_CHECK (pint_val == (pint) 0x00FCFFFF);
+ P_TEST_CHECK (PINT_FROM_BE (pint_val) == (pint) 0xFFFFFC00);
+ P_TEST_CHECK (PINT_TO_LE (pint_val) == (pint) 0x00FCFFFF);
+ P_TEST_CHECK (PINT_FROM_LE (pint_val) == (pint) 0x00FCFFFF);
+
+ puint puint_val = PUINT_TO_BE (0x00000400);
+ P_TEST_CHECK (puint_val == (puint) 0x00040000);
+ P_TEST_CHECK (PUINT_FROM_BE (puint_val) == (puint) 0x00000400);
+ P_TEST_CHECK (PUINT_TO_LE (puint_val) == (puint) 0x00040000);
+ P_TEST_CHECK (PUINT_FROM_LE (puint_val) == (puint) 0x00040000);
+
+ if (PLIBSYS_SIZEOF_LONG == 8) {
+ plong plong_val = PLONG_TO_BE (0xFFFFFFFFFFFFF800LL);
+ P_TEST_CHECK (plong_val == (plong) 0x00F8FFFFFFFFFFFFLL);
+ P_TEST_CHECK (PLONG_FROM_BE (plong_val) == (plong) 0xFFFFFFFFFFFFF800LL);
+ P_TEST_CHECK (PLONG_TO_LE (plong_val) == (plong) 0x00F8FFFFFFFFFFFFLL);
+ P_TEST_CHECK (PLONG_FROM_LE (plong_val) == (plong) 0x00F8FFFFFFFFFFFFLL);
+
+ pulong pulong_val = PULONG_TO_BE (0x0000000000000800ULL);
+ P_TEST_CHECK (pulong_val == (pulong) 0x0008000000000000ULL);
+ P_TEST_CHECK (PULONG_FROM_BE (pulong_val) == (pulong) 0x0000000000000800ULL);
+ P_TEST_CHECK (PULONG_TO_LE (pulong_val) == (pulong) 0x0008000000000000ULL);
+ P_TEST_CHECK (PULONG_FROM_LE (pulong_val) == (pulong) 0x0008000000000000ULL);
+ } else {
+ plong plong_val = PLONG_TO_BE (0xFFFFF800);
+ P_TEST_CHECK (plong_val == (plong) 0x00F8FFFF);
+ P_TEST_CHECK (PLONG_FROM_BE (plong_val) == (plong) 0xFFFFF800);
+ P_TEST_CHECK (PLONG_TO_LE (plong_val) == (plong) 0x00F8FFFF);
+ P_TEST_CHECK (PLONG_FROM_LE (plong_val) == (plong) 0x00F8FFFF);
+
+ pulong pulong_val = PULONG_TO_BE (0x00000800);
+ P_TEST_CHECK (pulong_val == (pulong) 0x00080000);
+ P_TEST_CHECK (PULONG_FROM_BE (pulong_val) == (pulong) 0x00000800);
+ P_TEST_CHECK (PULONG_TO_LE (pulong_val) == (pulong) 0x00080000);
+ P_TEST_CHECK (PULONG_FROM_LE (pulong_val) == (pulong) 0x00080000);
+ }
+
+ if (PLIBSYS_SIZEOF_SIZE_T == 8) {
+ psize psize_val = PSIZE_TO_BE (0x0000000000001000ULL);
+ P_TEST_CHECK (psize_val == (psize) 0x0010000000000000ULL);
+ P_TEST_CHECK (PSIZE_FROM_BE (psize_val) == (psize) 0x0000000000001000ULL);
+ P_TEST_CHECK (PSIZE_TO_LE (psize_val) == (psize) 0x0010000000000000ULL);
+ P_TEST_CHECK (PSIZE_FROM_LE (psize_val) == (psize) 0x0010000000000000ULL);
+
+ pssize pssize_val = PSSIZE_TO_BE (0x000000000000F000LL);
+ P_TEST_CHECK (pssize_val == (pssize) 0x00F0000000000000LL);
+ P_TEST_CHECK (PSSIZE_FROM_BE (pssize_val) == (pssize) 0x000000000000F000LL);
+ P_TEST_CHECK (PSSIZE_TO_LE (pssize_val) == (pssize) 0x00F0000000000000LL);
+ P_TEST_CHECK (PSSIZE_FROM_LE (pssize_val) == (pssize) 0x00F0000000000000LL);
+ } else {
+ psize psize_val = PSIZE_TO_BE (0x00001000);
+ P_TEST_CHECK (psize_val == (psize) 0x00100000);
+ P_TEST_CHECK (PSIZE_FROM_BE (psize_val) == (psize) 0x00001000);
+ P_TEST_CHECK (PSIZE_TO_LE (psize_val) == (psize) 0x00100000);
+ P_TEST_CHECK (PSIZE_FROM_LE (psize_val) == (psize) 0x00100000);
+
+ pssize pssize_val = PSSIZE_TO_BE (0x0000F000);
+ P_TEST_CHECK (pssize_val == (pssize) 0x00F00000);
+ P_TEST_CHECK (PSSIZE_FROM_BE (pssize_val) == (pssize) 0x0000F000);
+ P_TEST_CHECK (PSSIZE_TO_LE (pssize_val) == (pssize) 0x00F00000);
+ P_TEST_CHECK (PSSIZE_FROM_LE (pssize_val) == (pssize) 0x00F00000);
+ }
+
+ puint16_val = p_htons (0x0020);
+ P_TEST_CHECK (puint16_val == (puint16) 0x2000);
+ P_TEST_CHECK (p_ntohs (puint16_val) == (puint16) 0x0020);
+
+ puint32_val = p_htonl (0x00000040);
+ P_TEST_CHECK (puint32_val == (puint32) 0x40000000);
+ P_TEST_CHECK (p_ntohl (puint32_val) == (puint32) 0x00000040);
+ } else {
+ pint16 pint16_val = PINT16_TO_LE (0xFFE0);
+ P_TEST_CHECK (pint16_val == (pint16) 0xE0FF);
+ P_TEST_CHECK (PINT16_FROM_LE (pint16_val) == (pint16) 0xFFE0);
+ P_TEST_CHECK (PINT16_TO_BE (pint16_val) == (pint16) 0xE0FF);
+ P_TEST_CHECK (PINT16_FROM_BE (pint16_val) == (pint16) 0xE0FF);
+
+ puint16 puint16_val = PUINT16_TO_LE (0x0020);
+ P_TEST_CHECK (puint16_val == (puint16) 0x2000);
+ P_TEST_CHECK (PUINT16_FROM_LE (puint16_val) == (puint16) 0x0020);
+ P_TEST_CHECK (PUINT16_TO_BE (puint16_val) == (puint16) 0x2000);
+ P_TEST_CHECK (PUINT16_FROM_BE (puint16_val) == (puint16) 0x2000);
+
+ pint32 pint32_val = PINT32_TO_LE (0xFFFFFFC0);
+ P_TEST_CHECK (pint32_val == (pint32) 0xC0FFFFFF);
+ P_TEST_CHECK (PINT32_FROM_LE (pint32_val) == (pint32) 0xFFFFFFC0);
+ P_TEST_CHECK (PINT32_TO_BE (pint32_val) == (pint32) 0xC0FFFFFF);
+ P_TEST_CHECK (PINT32_FROM_BE (pint32_val) == (pint32) 0xC0FFFFFF);
+
+ puint32 puint32_val = PUINT32_TO_LE (0x00000040);
+ P_TEST_CHECK (puint32_val == (puint32) 0x40000000);
+ P_TEST_CHECK (PUINT32_FROM_LE (puint32_val) == (puint32) 0x00000040);
+ P_TEST_CHECK (PUINT32_TO_BE (puint32_val) == (puint32) 0x40000000);
+ P_TEST_CHECK (PUINT32_FROM_BE (puint32_val) == (puint32) 0x40000000);
+
+ pint64 pint64_val = PINT64_TO_LE (0xFFFFFFFFFFFFFF80LL);
+ P_TEST_CHECK (pint64_val == (pint64) 0x80FFFFFFFFFFFFFFLL);
+ P_TEST_CHECK (PINT64_FROM_LE (pint64_val) == (pint64) 0xFFFFFFFFFFFFFF80LL);
+ P_TEST_CHECK (PINT64_TO_BE (pint64_val) == (pint64) 0x80FFFFFFFFFFFFFFLL);
+ P_TEST_CHECK (PINT64_FROM_BE (pint64_val) == (pint64) 0x80FFFFFFFFFFFFFFLL);
+
+ puint64 puint64_val = PUINT64_TO_LE (0x0000000000000080ULL);
+ P_TEST_CHECK (puint64_val == (puint64) 0x8000000000000000ULL);
+ P_TEST_CHECK (PUINT64_FROM_LE (puint64_val) == (puint64) 0x0000000000000080ULL);
+ P_TEST_CHECK (PUINT64_TO_BE (puint64_val) == (puint64) 0x8000000000000000ULL);
+ P_TEST_CHECK (PUINT64_FROM_BE (puint64_val) == (puint64) 0x8000000000000000ULL);
+
+ pint pint_val = PINT_TO_LE (0xFFFFFC00);
+ P_TEST_CHECK (pint_val == (pint) 0x00FCFFFF);
+ P_TEST_CHECK (PINT_FROM_LE (pint_val) == (pint) 0xFFFFFC00);
+ P_TEST_CHECK (PINT_TO_BE (pint_val) == (pint) 0x00FCFFFF);
+ P_TEST_CHECK (PINT_FROM_BE (pint_val) == (pint) 0x00FCFFFF);
+
+ puint puint_val = PUINT_TO_LE (0x00000400);
+ P_TEST_CHECK (puint_val == (puint) 0x00040000);
+ P_TEST_CHECK (PUINT_FROM_LE (puint_val) == (puint) 0x00000400);
+ P_TEST_CHECK (PUINT_TO_BE (puint_val) == (puint) 0x00040000);
+ P_TEST_CHECK (PUINT_FROM_BE (puint_val) == (puint) 0x00040000);
+
+ if (PLIBSYS_SIZEOF_LONG == 8) {
+ plong plong_val = PLONG_TO_LE (0xFFFFFFFFFFFFF800LL);
+ P_TEST_CHECK (plong_val == (plong) 0x00F8FFFFFFFFFFFFLL);
+ P_TEST_CHECK (PLONG_FROM_LE (plong_val) == (plong) 0xFFFFFFFFFFFFF800LL);
+ P_TEST_CHECK (PLONG_TO_BE (plong_val) == (plong) 0x00F8FFFFFFFFFFFFLL);
+ P_TEST_CHECK (PLONG_FROM_BE (plong_val) == (plong) 0x00F8FFFFFFFFFFFFLL);
+
+ pulong pulong_val = PULONG_TO_LE (0x0000000000000800ULL);
+ P_TEST_CHECK (pulong_val == (pulong) 0x0008000000000000ULL);
+ P_TEST_CHECK (PULONG_FROM_LE (pulong_val) == (pulong) 0x0000000000000800ULL);
+ P_TEST_CHECK (PULONG_TO_BE (pulong_val) == (pulong) 0x0008000000000000ULL);
+ P_TEST_CHECK (PULONG_FROM_BE (pulong_val) == (pulong) 0x0008000000000000ULL);
+ } else {
+ plong plong_val = PLONG_TO_LE (0xFFFFF800);
+ P_TEST_CHECK (plong_val == (plong) 0x00F8FFFF);
+ P_TEST_CHECK (PLONG_FROM_LE (plong_val) == (plong) 0xFFFFF800);
+ P_TEST_CHECK (PLONG_TO_BE (plong_val) == (plong) 0x00F8FFFF);
+ P_TEST_CHECK (PLONG_FROM_BE (plong_val) == (plong) 0x00F8FFFF);
+
+ pulong pulong_val = PULONG_TO_LE (0x00000800);
+ P_TEST_CHECK (pulong_val == (pulong) 0x00080000);
+ P_TEST_CHECK (PULONG_FROM_LE (pulong_val) == (pulong) 0x00000800);
+ P_TEST_CHECK (PULONG_TO_BE (pulong_val) == (pulong) 0x00080000);
+ P_TEST_CHECK (PULONG_FROM_BE (pulong_val) == (pulong) 0x00080000);
+ }
+
+ if (PLIBSYS_SIZEOF_SIZE_T == 8) {
+ psize psize_val = PSIZE_TO_LE (0x0000000000001000ULL);
+ P_TEST_CHECK (psize_val == (psize) 0x0010000000000000ULL);
+ P_TEST_CHECK (PSIZE_FROM_LE (psize_val) == (psize) 0x0000000000001000ULL);
+ P_TEST_CHECK (PSIZE_TO_BE (psize_val) == (psize) 0x0010000000000000ULL);
+ P_TEST_CHECK (PSIZE_FROM_BE (psize_val) == (psize) 0x0010000000000000ULL);
+
+ pssize pssize_val = PSSIZE_TO_LE (0x000000000000F000LL);
+ P_TEST_CHECK (pssize_val == (pssize) 0x00F0000000000000LL);
+ P_TEST_CHECK (PSSIZE_FROM_LE (pssize_val) == (pssize) 0x000000000000F000LL);
+ P_TEST_CHECK (PSSIZE_TO_BE (pssize_val) == (pssize) 0x00F0000000000000LL);
+ P_TEST_CHECK (PSSIZE_FROM_BE (pssize_val) == (pssize) 0x00F0000000000000LL);
+ } else {
+ psize psize_val = PSIZE_TO_LE (0x00001000);
+ P_TEST_CHECK (psize_val == (psize) 0x00100000);
+ P_TEST_CHECK (PSIZE_FROM_LE (psize_val) == (psize) 0x00001000);
+ P_TEST_CHECK (PSIZE_TO_BE (psize_val) == (psize) 0x00100000);
+ P_TEST_CHECK (PSIZE_FROM_BE (psize_val) == (psize) 0x00100000);
+
+ pssize pssize_val = PSSIZE_TO_LE (0x0000F000);
+ P_TEST_CHECK (pssize_val == (pssize) 0x00F00000);
+ P_TEST_CHECK (PSSIZE_FROM_LE (pssize_val) == (pssize) 0x0000F000);
+ P_TEST_CHECK (PSSIZE_TO_BE (pssize_val) == (pssize) 0x00F00000);
+ P_TEST_CHECK (PSSIZE_FROM_BE (pssize_val) == (pssize) 0x00F00000);
+ }
+
+ puint16_val = p_htons (0x0020);
+ P_TEST_CHECK (puint16_val == (puint16) 0x0020);
+ P_TEST_CHECK (p_ntohs (puint16_val) == (puint16) 0x0020);
+
+ puint32_val = p_htonl (0x00000040);
+ P_TEST_CHECK (puint32_val == (puint32) 0x00000040);
+ P_TEST_CHECK (p_ntohl (puint32_val) == (puint32) 0x00000040);
+ }
+
+ puint16 puint16_val = PUINT16_SWAP_BYTES (0x0020);
+ P_TEST_CHECK (puint16_val == (puint16) 0x2000);
+ P_TEST_CHECK (PUINT16_SWAP_BYTES (puint16_val) == (puint16) 0x0020);
+
+ puint32 puint32_val = PUINT32_SWAP_BYTES (0x00000040);
+ P_TEST_CHECK (puint32_val == (puint32) 0x40000000);
+ P_TEST_CHECK (PUINT32_SWAP_BYTES (puint32_val) == (puint32) 0x00000040);
+
+ puint64 puint64_val = PUINT64_SWAP_BYTES (0x0000000000000080ULL);
+ P_TEST_CHECK (puint64_val == (puint64) 0x8000000000000000ULL);
+ P_TEST_CHECK (PUINT64_SWAP_BYTES (puint64_val) == (puint64) 0x0000000000000080ULL);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (ptypes_general_test);
+ P_TEST_SUITE_RUN_CASE (ptypes_pointers_convert_test);
+ P_TEST_SUITE_RUN_CASE (ptypes_min_max_test);
+ P_TEST_SUITE_RUN_CASE (ptypes_modifiers_test);
+ P_TEST_SUITE_RUN_CASE (ptypes_formats_test);
+ P_TEST_SUITE_RUN_CASE (ptypes_host_network_test);
+}
+P_TEST_SUITE_END()
diff --git a/3rdparty/plibsys/tests/puthread_test.cpp b/3rdparty/plibsys/tests/puthread_test.cpp
new file mode 100644
index 0000000..5c31cd1
--- /dev/null
+++ b/3rdparty/plibsys/tests/puthread_test.cpp
@@ -0,0 +1,481 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2013-2019 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "plibsys.h"
+#include "ptestmacros.h"
+
+P_TEST_MODULE_INIT ();
+
+static pint thread_wakes_1 = 0;
+static pint thread_wakes_2 = 0;
+static pint thread_to_wakes = 0;
+static volatile pboolean is_threads_working = FALSE;
+
+static P_HANDLE thread1_id = (P_HANDLE) NULL;
+static P_HANDLE thread2_id = (P_HANDLE) NULL;
+static PUThread * thread1_obj = NULL;
+static PUThread * thread2_obj = NULL;
+
+static PUThreadKey * tls_key = NULL;
+static PUThreadKey * tls_key_2 = NULL;
+static volatile pint free_counter = 0;
+
+extern "C" ppointer pmem_alloc (psize nbytes)
+{
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
+{
+ P_UNUSED (block);
+ P_UNUSED (nbytes);
+ return (ppointer) NULL;
+}
+
+extern "C" void pmem_free (ppointer block)
+{
+ P_UNUSED (block);
+}
+
+extern "C" void free_with_check (ppointer mem)
+{
+ p_free (mem);
+ p_atomic_int_inc (&free_counter);
+}
+
+static void * test_thread_func (void *data)
+{
+ pint *counter = static_cast < pint * > (data);
+
+ if ((*counter) == 1) {
+ thread1_id = p_uthread_current_id ();
+ thread1_obj = p_uthread_current ();
+ } else {
+ thread2_id = p_uthread_current_id ();
+ thread2_obj = p_uthread_current ();
+ }
+
+ p_uthread_set_local (tls_key, (ppointer) p_uthread_current_id ());
+
+ *counter = 0;
+
+ while (is_threads_working == TRUE) {
+ p_uthread_sleep (10);
+ ++(*counter);
+ p_uthread_yield ();
+
+ if (p_uthread_get_local (tls_key) != (ppointer) p_uthread_current_id ())
+ p_uthread_exit (-1);
+ }
+
+ p_uthread_exit (*counter);
+
+ return NULL;
+}
+
+static void * test_thread_nonjoinable_func (void *data)
+{
+ pint *counter = static_cast < pint * > (data);
+
+ is_threads_working = TRUE;
+
+ for (int i = thread_to_wakes; i > 0; --i) {
+ p_uthread_sleep (10);
+ ++(*counter);
+ p_uthread_yield ();
+ }
+
+ is_threads_working = FALSE;
+
+ p_uthread_exit (0);
+
+ return NULL;
+}
+
+static void * test_thread_tls_func (void *data)
+{
+ pint self_thread_free = *((pint *) data);
+
+ pint *tls_value = (pint *) p_malloc0 (sizeof (pint));
+ *tls_value = 0;
+ p_uthread_set_local (tls_key, (ppointer) tls_value);
+
+ pint prev_tls = 0;
+ pint counter = 0;
+
+ while (is_threads_working == TRUE) {
+ p_uthread_sleep (10);
+
+ pint *last_tls = (pint *) p_uthread_get_local (tls_key);
+
+ if ((*last_tls) != prev_tls)
+ p_uthread_exit (-1);
+
+ pint *tls_new_value = (pint *) p_malloc0 (sizeof (pint));
+
+ *tls_new_value = (*last_tls) + 1;
+ prev_tls = (*last_tls) + 1;
+
+ p_uthread_replace_local (tls_key, (ppointer) tls_new_value);
+
+ if (self_thread_free)
+ p_free (last_tls);
+
+ ++counter;
+
+ p_uthread_yield ();
+ }
+
+ if (self_thread_free) {
+ pint *last_tls = (pint *) p_uthread_get_local (tls_key);
+
+ if ((*last_tls) != prev_tls)
+ p_uthread_exit (-1);
+
+ p_free (last_tls);
+
+ p_uthread_replace_local (tls_key, (ppointer) NULL);
+ }
+
+ p_uthread_exit (counter);
+
+ return NULL;
+}
+
+static void * test_thread_tls_create_func (void *data)
+{
+ P_UNUSED (data);
+
+ pint *tls_value = (pint *) p_malloc0 (sizeof (pint));
+ *tls_value = 0;
+ p_uthread_set_local (tls_key, (ppointer) tls_value);
+
+ pint *tls_value_2 = (pint *) p_malloc0 (sizeof (pint));
+ *tls_value_2 = 0;
+ p_uthread_set_local (tls_key_2, (ppointer) tls_value_2);
+
+ return NULL;
+}
+
+P_TEST_CASE_BEGIN (puthread_nomem_test)
+{
+ p_libsys_init ();
+
+ PUThreadKey *thread_key = p_uthread_local_new (p_free);
+ P_TEST_CHECK (thread_key != NULL);
+
+ PMemVTable vtable;
+
+ vtable.free = pmem_free;
+ vtable.malloc = pmem_alloc;
+ vtable.realloc = pmem_realloc;
+
+ P_TEST_CHECK (p_mem_set_vtable (&vtable) == TRUE);
+
+ thread_wakes_1 = 0;
+ thread_wakes_2 = 0;
+
+ P_TEST_CHECK (p_uthread_create ((PUThreadFunc) test_thread_func,
+ (ppointer) &thread_wakes_1,
+ TRUE,
+ NULL) == NULL);
+
+ P_TEST_CHECK (p_uthread_create_full ((PUThreadFunc) test_thread_func,
+ (ppointer) &thread_wakes_2,
+ TRUE,
+ P_UTHREAD_PRIORITY_NORMAL,
+ 0,
+ NULL) == NULL);
+
+ P_TEST_CHECK (p_uthread_current () == NULL);
+ P_TEST_CHECK (p_uthread_local_new (NULL) == NULL);
+
+ p_uthread_exit (0);
+
+ p_uthread_set_local (thread_key, PINT_TO_POINTER (10));
+
+ ppointer tls_value = p_uthread_get_local (thread_key);
+
+ if (tls_value != NULL) {
+ P_TEST_CHECK (tls_value == PINT_TO_POINTER (10));
+ p_uthread_set_local (thread_key, NULL);
+ }
+
+ p_uthread_replace_local (thread_key, PINT_TO_POINTER (12));
+
+ tls_value = p_uthread_get_local (thread_key);
+
+ if (tls_value != NULL) {
+ P_TEST_CHECK (tls_value == PINT_TO_POINTER (12));
+ p_uthread_set_local (thread_key, NULL);
+ }
+
+ p_mem_restore_vtable ();
+
+ p_uthread_local_free (thread_key);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (puthread_bad_input_test)
+{
+ p_libsys_init ();
+
+ P_TEST_CHECK (p_uthread_create (NULL, NULL, FALSE, NULL) == NULL);
+ P_TEST_CHECK (p_uthread_create_full (NULL, NULL, FALSE, P_UTHREAD_PRIORITY_NORMAL, 0, NULL) == NULL);
+ P_TEST_CHECK (p_uthread_join (NULL) == -1);
+ P_TEST_CHECK (p_uthread_set_priority (NULL, P_UTHREAD_PRIORITY_NORMAL) == FALSE);
+ P_TEST_CHECK (p_uthread_get_local (NULL) == NULL);
+ p_uthread_set_local (NULL, NULL);
+ p_uthread_replace_local (NULL, NULL);
+ p_uthread_ref (NULL);
+ p_uthread_unref (NULL);
+ p_uthread_local_free (NULL);
+ p_uthread_exit (0);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (puthread_general_test)
+{
+ p_libsys_init ();
+
+ thread_wakes_1 = 1;
+ thread_wakes_2 = 2;
+ thread1_id = (P_HANDLE) NULL;
+ thread2_id = (P_HANDLE) NULL;
+ thread1_obj = NULL;
+ thread2_obj = NULL;
+
+ tls_key = p_uthread_local_new (NULL);
+ P_TEST_CHECK (tls_key != NULL);
+
+ /* Threre is no guarantee that we wouldn't get one of the IDs
+ * of the finished test threads */
+
+ P_HANDLE main_id = p_uthread_current_id ();
+
+ is_threads_working = TRUE;
+
+ PUThread *thr1 = p_uthread_create_full ((PUThreadFunc) test_thread_func,
+ (ppointer) &thread_wakes_1,
+ TRUE,
+ P_UTHREAD_PRIORITY_NORMAL,
+ 64 * 1024,
+ "thread_name");
+
+ PUThread *thr2 = p_uthread_create_full ((PUThreadFunc) test_thread_func,
+ (ppointer) &thread_wakes_2,
+ TRUE,
+ P_UTHREAD_PRIORITY_NORMAL,
+ 64 * 1024,
+ "very_long_name_for_thread_testing");
+
+ p_uthread_ref (thr1);
+
+ p_uthread_set_priority (thr1, P_UTHREAD_PRIORITY_NORMAL);
+
+ P_TEST_REQUIRE (thr1 != NULL);
+ P_TEST_REQUIRE (thr2 != NULL);
+
+ p_uthread_sleep (5000);
+
+ is_threads_working = FALSE;
+
+ P_TEST_CHECK (p_uthread_join (thr1) == thread_wakes_1);
+ P_TEST_CHECK (p_uthread_join (thr2) == thread_wakes_2);
+
+ P_TEST_REQUIRE (thread1_id != thread2_id);
+ P_TEST_CHECK (thread1_id != main_id && thread2_id != main_id);
+
+ P_TEST_CHECK (thread1_obj == thr1);
+ P_TEST_CHECK (thread2_obj == thr2);
+
+ p_uthread_local_free (tls_key);
+ p_uthread_unref (thr1);
+ p_uthread_unref (thr2);
+
+ p_uthread_unref (thr1);
+
+ PUThread *cur_thr = p_uthread_current ();
+ P_TEST_CHECK (cur_thr != NULL);
+
+ P_TEST_CHECK (p_uthread_ideal_count () > 0);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (puthread_nonjoinable_test)
+{
+ p_libsys_init ();
+
+ thread_wakes_1 = 0;
+ thread_to_wakes = 100;
+ is_threads_working = TRUE;
+
+ PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_nonjoinable_func,
+ (ppointer) &thread_wakes_1,
+ FALSE,
+ NULL);
+
+ P_TEST_REQUIRE (thr1 != NULL);
+
+ p_uthread_sleep (3000);
+
+ P_TEST_CHECK (p_uthread_join (thr1) == -1);
+
+ while (is_threads_working == TRUE)
+ p_uthread_sleep (10);
+
+ P_TEST_CHECK (thread_wakes_1 == thread_to_wakes);
+
+ p_uthread_unref (thr1);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_CASE_BEGIN (puthread_tls_test)
+{
+ p_libsys_init ();
+
+ /* With destroy notification */
+ tls_key = p_uthread_local_new (free_with_check);
+
+ is_threads_working = TRUE;
+ free_counter = 0;
+
+ pint self_thread_free = 0;
+
+ PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
+ (ppointer) &self_thread_free,
+ TRUE,
+ NULL);
+
+ PUThread *thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
+ (ppointer) &self_thread_free,
+ TRUE,
+ NULL);
+
+ P_TEST_REQUIRE (thr1 != NULL);
+ P_TEST_REQUIRE (thr2 != NULL);
+
+ p_uthread_sleep (5000);
+
+ is_threads_working = FALSE;
+
+ pint total_counter = 0;
+
+ total_counter += (p_uthread_join (thr1) + 1);
+ total_counter += (p_uthread_join (thr2) + 1);
+
+ P_TEST_CHECK (total_counter == free_counter);
+
+ p_uthread_local_free (tls_key);
+ p_uthread_unref (thr1);
+ p_uthread_unref (thr2);
+
+ /* Without destroy notification */
+ tls_key = p_uthread_local_new (NULL);
+
+ free_counter = 0;
+ is_threads_working = TRUE;
+ self_thread_free = 1;
+
+ thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
+ (ppointer) &self_thread_free,
+ TRUE,
+ NULL);
+
+ thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
+ (ppointer) &self_thread_free,
+ TRUE,
+ NULL);
+
+ P_TEST_REQUIRE (thr1 != NULL);
+ P_TEST_REQUIRE (thr2 != NULL);
+
+ p_uthread_sleep (5000);
+
+ is_threads_working = FALSE;
+
+ total_counter = 0;
+
+ total_counter += (p_uthread_join (thr1) + 1);
+ total_counter += (p_uthread_join (thr2) + 1);
+
+ P_TEST_CHECK (total_counter > 0);
+ P_TEST_CHECK (free_counter == 0);
+
+ p_uthread_local_free (tls_key);
+ p_uthread_unref (thr1);
+ p_uthread_unref (thr2);
+
+ /* With implicit thread exit */
+ tls_key = p_uthread_local_new (free_with_check);
+ tls_key_2 = p_uthread_local_new (free_with_check);
+
+ free_counter = 0;
+
+ thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_create_func,
+ NULL,
+ TRUE,
+ NULL);
+
+ thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_create_func,
+ NULL,
+ TRUE,
+ NULL);
+
+ P_TEST_REQUIRE (thr1 != NULL);
+ P_TEST_REQUIRE (thr2 != NULL);
+
+ p_uthread_join (thr1);
+ p_uthread_join (thr2);
+
+ P_TEST_CHECK (free_counter == 4);
+
+ p_uthread_local_free (tls_key);
+ p_uthread_local_free (tls_key_2);
+ p_uthread_unref (thr1);
+ p_uthread_unref (thr2);
+
+ p_libsys_shutdown ();
+}
+P_TEST_CASE_END ()
+
+P_TEST_SUITE_BEGIN()
+{
+ P_TEST_SUITE_RUN_CASE (puthread_nomem_test);
+ P_TEST_SUITE_RUN_CASE (puthread_bad_input_test);
+ P_TEST_SUITE_RUN_CASE (puthread_general_test);
+ P_TEST_SUITE_RUN_CASE (puthread_nonjoinable_test);
+ P_TEST_SUITE_RUN_CASE (puthread_tls_test);
+}
+P_TEST_SUITE_END()