diff --git a/tests/Makefile b/tests/Makefile index 5c9806ab..532fd3bc 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -204,12 +204,13 @@ SYNTHESIS_DATA= M-ALGO test-malgo.c.c test-malgo.synt \ M-RBTREE test-mrbtree.c.c test-mrbtree.synt \ M-SERIAL-BIN ../m-serial-bin.h test-mserial-bin.synt \ M-SERIAL-JSON ../m-serial-json.h test-mserial-json.synt \ + M-SHARED-PTR test-mshared-ptr.c.c test-mshared-ptr.synt \ M-SHARED test-mshared.c.c test-mshared.synt \ M-SNAPSHOT test-msnapshot.c.c test-msnapshot.synt \ M-STRING ../m-string.h test-mstring.synt \ M-TREE test-mtree.c.c test-mtree.synt \ M-THREAD ../m-thread.h test-mmutex.synt \ - M-TRY ../m-try.h test-mtry.synt \ + M-TRY ../m-try.h test-mtry.synt \ M-TUPLE test-mtuple.c.c test-mtuple.synt \ M-VARIANT test-mvariant.c.c test-mvariant.synt \ M-WORKER ../m-worker.h test-mworker.synt diff --git a/tests/test-mshared-ptr.c b/tests/test-mshared-ptr.c index 31ce9e94..60a37e2d 100644 --- a/tests/test-mshared-ptr.c +++ b/tests/test-mshared-ptr.c @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2017-2024, Patrick Pelissier + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include + #include "m-shared-ptr.h" #include "m-string.h" @@ -11,9 +35,14 @@ #include "m-tuple.h" #include "m-variant.h" +#include "coverage.h" + +// TEST WITH INT +SHARED_PTR_DECL_AS(shared_int, SharedInt, M_BASIC_OPLIST) + // TEST WITH DOUBLE SHARED_PTR_DECL_AS(shared_double, SharedDouble, M_BASIC_OPLIST) -SHARED_PTR_DEF_EXTERN_AS(shared_double, SharedDouble, double, M_BASIC_OPLIST) +extern SharedDouble *shared_double_new_from(double); // Workaround for test. static void test_double(void) { @@ -37,8 +66,47 @@ static void test_double(void) } // TEST WITH STRING +static inline void string_add(string_t d, const string_t a, const string_t b) +{ + int ia = atoi(string_get_cstr(a)); + int ib = atoi(string_get_cstr(b)); + string_printf(d, "%d", ia+ib); +} +static inline void string_sub(string_t d, const string_t a, const string_t b) +{ + int ia = atoi(string_get_cstr(a)); + int ib = atoi(string_get_cstr(b)); + string_printf(d, "%d", ia-ib); +} +static inline void string_mul(string_t d, const string_t a, const string_t b) +{ + int ia = atoi(string_get_cstr(a)); + int ib = atoi(string_get_cstr(b)); + string_printf(d, "%d", ia*ib); +} +static inline void string_div(string_t d, const string_t a, const string_t b) +{ + int ia = atoi(string_get_cstr(a)); + int ib = atoi(string_get_cstr(b)); + string_printf(d, "%d", ia/ib); +} -SHARED_PTR_DECL(shared_string, STRING_OPLIST) +#define STR_OPL M_OPEXTEND(STRING_OPLIST, POP(string_pop_u), GET_SIZE(string_length_u), ADD(string_add), SUB(string_sub), MUL(string_mul), DIV(string_div)) +SHARED_PTR_DECL(shared_string, STR_OPL) + +static int str_callback(void *data, const string_unicode_t *u) +{ + string_unicode_t *pu = (string_unicode_t *) data; + *pu += *u; + return 0; +} + +static int str_callback2(void *data, const string_unicode_t *u) +{ + string_unicode_t *pu = (string_unicode_t *) data; + *pu += *u; + return 1; +} static void test_string(void) { @@ -67,6 +135,26 @@ static void test_string(void) assert(shared_string_equal_p(r, q)); assert(shared_string_cmp(r, q) == 0); assert(shared_string_cmp(q, r) == 0); + assert(shared_string_cmp(q, p) == 0); + string_unicode_t u; + b = shared_string_try_pop(&u, p2); + assert(!b); + b = shared_string_try_push(p2, 'X'); + assert(b); + shared_string_push(p2, 'X'); + assert(shared_string_size(p2) == 2); + b = shared_string_try_pop(&u, p2); + assert(b); + assert(shared_string_cmp(q, p2) < 0); + assert(shared_string_cmp(p2, q) > 0); + shared_string_push(p2, 'X'); + u = 0; + int res = shared_string_for_each(p2, str_callback, (void*) &u); + assert(res == 0); + assert(u == 2* 'X'); + res = shared_string_for_each(p2, str_callback2, (void*) &u); + assert(res == 1); + assert(u == 3* 'X'); shared_string_reset(q); assert(!shared_string_equal_p(r2, q)); assert(shared_string_empty_p(q)); @@ -84,8 +172,6 @@ static void test_string(void) shared_string_clear(p2); } -SHARED_PTR_DEF_EXTERN(shared_string, string_t, STRING_OPLIST) - // TEST WITH ARRAY ARRAY_DEF(array, int) @@ -181,10 +267,9 @@ static void test_array(void) shared_array_release(p); } -SHARED_PTR_DEF_EXTERN(shared_array, array_t) ARRAY_DEF(array_str, string_t) -SHARED_PTR_DEF(shared_array_str, array_str_t, ARRAY_OPLIST(array_str, M_STRING_OPLIST)) +SHARED_PTR_DECL(shared_array_str, ARRAY_OPLIST(array_str, M_STRING_OPLIST)) static void test_array_string(void) { @@ -307,9 +392,126 @@ static void test_thread(void) m_thread_join(idx); } +/************************************************************************/ + +// Define effective code when only _DECL was used. +START_COVERAGE +SHARED_PTR_DEF_EXTERN(shared_string, string_t, STR_OPL) +END_COVERAGE +// Non measured code +#include "test-mshared-ptr.h" + +static void test_string2(void) +{ + M_LET( (x, ("Hello")), string_t) { + shared_string_t *p = shared_string_new_from(x); + assert(!shared_string_empty_p(p)); + assert(string_equal_str_p(*shared_string_cref(p), "Hello")); + assert(string_equal_str_p(*shared_string_ref(p), "Hello")); + shared_string_release(p); + } + + shared_string_t *p = shared_string_new(); + shared_string_t *q = shared_string_make("2"); + shared_string_t *r = shared_string_make("1"); + shared_string_t *rr = shared_string_make("3"); + shared_string_add(p, q, r); + assert(shared_string_equal_p(p, rr)); + shared_string_add(p, r, q); + assert(shared_string_equal_p(p, rr)); + shared_string_add(p, r, r); + assert(shared_string_equal_p(p, q)); + shared_string_add(p, p, r); + assert(shared_string_equal_p(p, rr)); + shared_string_add(p, r, r); + assert(shared_string_equal_p(p, q)); + shared_string_add(p, r, p); + assert(shared_string_equal_p(p, rr)); + shared_string_sub(p, q, r); + assert(shared_string_equal_p(p, r)); + shared_string_add(p, p, p); + assert(shared_string_equal_p(p, q)); + shared_string_mul(p, q, r); + assert(shared_string_equal_p(p, q)); + shared_string_div(p, q, r); + assert(shared_string_equal_p(p, q)); + shared_string_reset(p); + shared_string_release(p); + shared_string_release(q); + shared_string_release(r); + shared_string_release(rr); +} + +/************************************************************************/ + +#define MAX_NUM 200 + +static void conso_thread1_string(void *p) +{ + shared_string_t *ptr = (shared_string_t*) p; + bool tmp[MAX_NUM] = {0}; + for(int i = 1; i < MAX_NUM; i++) { + m_string_unicode_t j; + shared_string_pop(&j, ptr); + assert (j > 0 && j < MAX_NUM); + assert(tmp[j] == false); + tmp[j] = true; + } + shared_string_release(ptr); +} + +static void test_thread1_string(void) +{ + m_thread_t idx; + shared_string_t *ptr = shared_string_new(); + m_thread_create (idx, conso_thread1_string, shared_string_acquire(ptr)); + for(int i = 1; i < MAX_NUM; i++) { + shared_string_push (ptr, (m_string_unicode_t) i); + } + shared_string_release(ptr); + m_thread_join(idx); +} + +// This will test the proper handling of the read lock, +// by pushing it to its limit. +#define MAX_READER 8 + +static void conso_thread2_string(void *p) +{ + shared_string_t *ptr = (shared_string_t*) p; + size_t size = shared_string_size(p); + for(int i = 0; i < 1000; i++) { + size_t n = shared_string_size(p); + assert( n >= size); + size = n; + } + shared_string_release(ptr); +} + +static void test_thread2_string(void) +{ + m_thread_t idx[MAX_READER]; + shared_string_t *ptr = shared_string_new(); + for(int i = 0; i < MAX_READER; i++) { + m_thread_create (idx[i], conso_thread2_string, shared_string_acquire(ptr)); + } + for(int i = 1; i < 100000; i++) { + shared_string_push (ptr, (m_string_unicode_t) i); + } + shared_string_release(ptr); + for(int i = 0; i < MAX_READER; i++) { + m_thread_join(idx[i]); + } +} + +/************************************************************************/ + int main(void) { test_string(); + test_string2(); + test_thread1_string(); + test_thread2_string(); test_double(); test_array(); test_array_string(); diff --git a/tests/test-mshared-ptr.h b/tests/test-mshared-ptr.h new file mode 100644 index 00000000..47e74ee7 --- /dev/null +++ b/tests/test-mshared-ptr.h @@ -0,0 +1,7 @@ +// Header for coverage purpose +// Expand here all code that shall not be measured in coverage. +// Since the functions are not declared as static inline, their coverage is measured +SHARED_PTR_DEF_EXTERN_AS(shared_int, SharedInt, int, M_BASIC_OPLIST) +SHARED_PTR_DEF_EXTERN_AS(shared_double, SharedDouble, double, M_OPEXTEND(M_BASIC_OPLIST, TYPE(double))) +SHARED_PTR_DEF_EXTERN(shared_array, array_t) +SHARED_PTR_DEF_EXTERN(shared_array_str, array_str_t, ARRAY_OPLIST(array_str, M_STRING_OPLIST))