/* * Copyright (c) 2017-2025, 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 #include "coverage.h" // Override M_F for testing purpose #define M_F(a,b) M_OVERRIDE_F(a,b) #define M_OVERRIDE__method() , _get_method , #define M_OVERRIDE__method2() , _get_method2 #include "test-obj.h" #include "m-core.h" static bool tmp_init(void) { return true; } static bool tmp_get_method(void) { return true; } static bool tmp_get_method2(void) { return true; } static bool tmp_clear(void) { return true; } static void test_cat(void) { #define AandB true #define AandBandC true assert (M_C(A,andB)); assert (M_C3(A,and,B)); assert (M_C4(A,and,B,andC)); assert (M_C3_EMPTY(A,and,B)); assert (M_C3_EMPTY(Aand,,B)); assert (M_C3_EMPTY(AandB,,)); assert (M_C5_EMPTY(A,a,n,d,B)); assert (M_C5_EMPTY(Aand,,,,B)); assert( M_F(tmp, _init)()); assert( M_F(tmp, _method)()); assert( M_F(tmp, _method2)()); assert( M_F(tmp, _clear)()); } static void test_power2(void) { assert (M_POWEROF2_P(1)); assert (M_POWEROF2_P(2)); assert (!M_POWEROF2_P(3)); assert (M_POWEROF2_P(4)); assert (!M_POWEROF2_P(5)); assert (!M_POWEROF2_P(6)); assert (!M_POWEROF2_P(7)); assert (M_POWEROF2_P(8)); } static void test_incdec(void) { assert (M_INC(0) == 1); assert (M_INC(1) == 2); assert (M_INC(2) == 3); assert (M_INC(3) == 4); assert (M_INC(4) == 5); assert (M_INC(5) == 6); assert (M_INC(6) == 7); assert (M_INC(7) == 8); assert (M_INC(8) == 9); assert (M_INC(9) == 10); assert (M_INC(10) == 11); assert (M_INC(11) == 12); assert (M_INC(12) == 13); assert (M_INC(13) == 14); assert (M_INC(14) == 15); assert (M_INC(15) == 16); assert (M_INC(16) == 17); assert (M_INC(17) == 18); assert (M_INC(18) == 19); assert (M_INC(19) == 20); assert (M_INC(20) == 21); assert (M_INC(21) == 22); assert (M_INC(22) == 23); assert (M_INC(23) == 24); assert (M_INC(24) == 25); assert (M_INC(25) == 26); assert (M_INC(26) == 27); assert (M_INC(27) == 28); assert (M_INC(28) == 29); assert ((0) == M_DEC(1)); assert ((1) == M_DEC(2)); assert ((2) == M_DEC(3)); assert ((3) == M_DEC(4)); assert ((4) == M_DEC(5)); assert ((5) == M_DEC(6)); assert ((6) == M_DEC(7)); assert ((7) == M_DEC(8)); assert ((8) == M_DEC(9)); assert ((9) == M_DEC(10)); assert ((10) == M_DEC(11)); assert ((11) == M_DEC(12)); assert ((12) == M_DEC(13)); assert ((13) == M_DEC(14)); assert ((14) == M_DEC(15)); assert ((15) == M_DEC(16)); assert ((16) == M_DEC(17)); assert ((17) == M_DEC(18)); assert ((18) == M_DEC(19)); assert ((19) == M_DEC(20)); assert ((20) == M_DEC(21)); assert ((21) == M_DEC(22)); assert ((22) == M_DEC(23)); assert ((23) == M_DEC(24)); assert ((24) == M_DEC(25)); assert ((25) == M_DEC(26)); assert ((26) == M_DEC(27)); assert ((27) == M_DEC(28)); assert ((28) == M_DEC(29)); assert( M_ADD(2,5) == M_SUB(10,3)); assert( M_ADD(5,15) == M_SUB(25,5)); assert(M_EQUAL(2, 2)); assert(!M_EQUAL(1, 2)); assert(M_EQUAL(52, 52)); assert(!M_NOTEQUAL(2, 2)); assert(M_NOTEQUAL(1, 2)); assert(!M_NOTEQUAL(52, 52)); assert(!M_LESS_THAN_P(4, 2)); assert(!M_LESS_THAN_P(4, 3)); assert(!M_LESS_THAN_P(4, 4)); assert(M_LESS_THAN_P(4, 5)); assert(M_LESS_THAN_P(4, 6)); assert(M_LESS_THAN_P(4, 7)); assert(M_GREATER_OR_EQUAL_P(4, 2)); assert(M_GREATER_OR_EQUAL_P(4, 3)); assert(M_GREATER_OR_EQUAL_P(4, 4)); assert(!M_GREATER_OR_EQUAL_P(4, 5)); assert(!M_GREATER_OR_EQUAL_P(4, 6)); assert(!M_GREATER_OR_EQUAL_P(4, 7)); assert(M_GREATER_THAN_P(4, 2)); assert(M_GREATER_THAN_P(4, 3)); assert(!M_GREATER_THAN_P(4, 4)); assert(!M_GREATER_THAN_P(4, 5)); assert(!M_GREATER_THAN_P(4, 6)); assert(!M_GREATER_THAN_P(4, 7)); assert(!M_LESS_OR_EQUAL_P(4, 2)); assert(!M_LESS_OR_EQUAL_P(4, 3)); assert(M_LESS_OR_EQUAL_P(4, 4)); assert(M_LESS_OR_EQUAL_P(4, 5)); assert(M_LESS_OR_EQUAL_P(4, 6)); assert(M_LESS_OR_EQUAL_P(4, 7)); assert(!M_KEYWORD_P(M_UNDERFLOW, M_SUB(1, 1))); assert(M_KEYWORD_P(M_UNDERFLOW, M_SUB(1, 2))); assert(M_KEYWORD_P(M_UNDERFLOW, M_SUB(1, 6))); assert(M_KEYWORD_P(M_UNDERFLOW, M_SUB(1, 5))); assert(!M_KEYWORD_P(M_OVERFLOW, M_ADD(M_MAX_NB_ARGUMENT, 1))); assert(M_KEYWORD_P(M_OVERFLOW, M_ADD(M_MAX_NB_ARGUMENT, 2))); assert(M_KEYWORD_P(M_OVERFLOW, M_ADD(M_MAX_NB_ARGUMENT, 3))); // Test if the initial error is not lost in translation assert(M_KEYWORD_P(M_UNDERFLOW, M_INC(M_UNDERFLOW))); assert(M_KEYWORD_P(M_OVERFLOW, M_DEC(M_OVERFLOW))); assert(M_AND(0, 0) == 0); assert(M_AND(0, 1) == 0); assert(M_AND(1, 0) == 0); assert(M_AND(1, 1) == 1); assert(M_OR(0, 0) == 0); assert(M_OR(0, 1) == 1); assert(M_OR(1, 0) == 1); assert(M_OR(1, 1) == 1); assert(M_AND3(0, 0, 0) == 0); assert(M_AND3(0, 0, 1) == 0); assert(M_AND3(0, 1, 0) == 0); assert(M_AND3(0, 1, 1) == 0); assert(M_AND3(1, 0, 0) == 0); assert(M_AND3(1, 0, 1) == 0); assert(M_AND3(1, 1, 0) == 0); assert(M_AND3(1, 1, 1) == 1); assert(M_OR3(0, 0, 0) == 0); assert(M_OR3(0, 0, 1) == 1); assert(M_OR3(0, 1, 0) == 1); assert(M_OR3(0, 1, 1) == 1); assert(M_OR3(1, 0, 0) == 1); assert(M_OR3(1, 0, 1) == 1); assert(M_OR3(1, 1, 0) == 1); assert(M_OR3(1, 1, 1) == 1); } static void test_return(void) { assert (M_RET_ARG1(1, 0)); assert (M_RET_ARG2(0, 1, 0)); assert (M_RET_ARG3(0, 0, 1, 0)); assert (M_RET_ARG27(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0)); assert (M_GET_AT((0,1,0),1)); assert (M_GET_AT((1,0,0),0)); assert (M_GET_AT((0,0,0,1),3)); } static void test_invert(void) { assert (M_RET_ARG1 (M_REVERSE(0,1))); assert (M_RET_ARG1 (M_REVERSE(0,0,1))); assert (M_RET_ARG1 (M_REVERSE(0,0,0,1))); assert (M_RET_ARG1 (M_REVERSE(0,0,0,0,1))); } static void test_min(void) { assert (M_MIN(1,2) == 1); assert (M_MIN(1,-2) == -2); assert (M_MAX(1,2) == 2); assert (M_MAX(1,-2) == 1); } static void test_empty(void) { assert (M_EMPTY_P() == true); assert (M_EMPTY_P(1) == false); assert (M_EMPTY_P(,) == false); assert (M_EMPTY_P(()) == false); assert (M_EMPTY_P("123") == false); assert (M_EMPTY_P(,1,2,3) == false); assert (M_EMPTY_P(+2) == false); assert (M_EMPTY_P(-2) == false); assert (M_EMPTY_P( () ) == false); #define F0() int #define F1() (void) #define F2(x) x #define F3() #define F4() 1,2 assert (M_EMPTY_P(F0) == false); #ifndef M_COMMA_P_WORKAROUND // Disable tests on platform with a non working preprocessor assert (M_EMPTY_P(F1) == false); assert (M_EMPTY_P(F2) == false); assert (M_EMPTY_P(F3) == false); #endif assert (M_EMPTY_P(F4) == false); #define G0 int #define G1 (void) #define G2 x #define G3 #define G4 1,2 assert (M_EMPTY_P(G0) == false); assert (M_EMPTY_P(G1) == false); assert (M_EMPTY_P(G2) == false); assert (M_EMPTY_P(G3) == true); assert (M_EMPTY_P(G4) == false); } #define f(n) (n)*(n) + #define f2(d,n) (d)*(n) + #define f3(d,i,n) (d)*(i)*(n) + static void test_map(void) { assert (M_MAP (f, 1) 0 == 1); assert (M_MAP (f, 1, 2) 0 == 5); assert (M_MAP (f, 1, 2, 3) 0 == 14); assert (M_MAP (f, M_SEQ(1, 4)) 0 == 1+4+9+16); assert (M_MAP2 (f2, 2, 1) 0 == 2); assert (M_MAP2 (f2, 3, 1, 2) 0 == 9); assert (M_MAP2 (f2, 4, 1, 2, 3) 0 == 24); assert (M_MAP3 (f3, 2, 2) 0 == 4); assert (M_MAP3 (f3, 3, 2, 4) 0 == 30); assert (M_MAP3 (f3, 4, 2, 4, 6) 0 == 8+32+12*6); assert (M_CROSS_MAP(f2, (1), (2)) 0 == 1*2); assert (M_CROSS_MAP(f2, (1), (2, 3)) 0 == 1*2+1*3); assert (M_CROSS_MAP(f2, (1, 3), (2)) 0 == 1*2+3*2); assert (M_CROSS_MAP(f2, (1, 3), (2,4)) 0 == 1*2 + 1*4 + 3*2 + 3*4); assert (M_CROSS_MAP(f2, (1, 3, 5), (2,4)) 0 == 1*2 + 1*4 + 3*2 + 3*4 + 5*2 + 5*4); assert (M_CROSS_MAP2(f3, 2, (1), (2)) 0 == (1*2) * 2); assert (M_CROSS_MAP2(f3, 2, (1), (2, 3)) 0 == (1*2+1*3) * 2); assert (M_CROSS_MAP2(f3, 2, (1, 3), (2)) 0 == (1*2+3*2) * 2); assert (M_CROSS_MAP2(f3, 2, (1, 3), (2,4)) 0 == (1*2 + 1*4 + 3*2 + 3*4) * 2); assert (M_CROSS_MAP2(f3, 2, (1, 3, 5), (2,4)) 0 == (1*2 + 1*4 + 3*2 + 3*4 + 5*2 + 5*4)*2); } static void test_let(void) { bool b = false; M_LET(z, M_CLASSIC_OPLIST(testobj)) { testobj_set_ui(z, 12); M_LET((zz,z), M_CLASSIC_OPLIST(testobj)) { assert( testobj_cmp_ui(zz, 12) == 0); } M_LET((zz,(42)), M_OPEXTEND(M_CLASSIC_OPLIST(testobj), INIT_WITH(testobj_init_set_ui))) { assert( testobj_cmp_ui(zz, 42) == 0); } M_LET((zz,z), z2, M_CLASSIC_OPLIST(testobj)) { assert( testobj_cmp_ui(zz, 12) == 0); } M_LET(z3, (zz,(42)), M_OPEXTEND(M_CLASSIC_OPLIST(testobj), INIT_WITH(testobj_init_set_ui))) { assert( testobj_cmp_ui(zz, 42) == 0); } b = true; break; assert(0); } assert(b); // Test of recursive INIT_WITH within M_LET #define OPL1 (TYPE(int), INIT_WITH(OPL1_F)) #define OPL1_F(d, x) ((d) = (x)) #define OPL2 (TYPE(int), INIT_WITH(API_1(OPL2_F)), OPLIST(OPL1) ) #define OPL2_F(opl, d, x) M_APPLY_API(M_GET_INIT_WITH M_GET_OPLIST opl, M_GET_OPLIST opl, d, x) #define OPL3 (TYPE(int), INIT_WITH(API_1(OPL3_F)), OPLIST(OPL2) ) #define OPL3_F(opl, d, x) M_APPLY_API(M_GET_INIT_WITH M_GET_OPLIST opl, M_GET_OPLIST opl, d, x) #define OPL4 (TYPE(int), INIT_WITH(API_1(OPL4_F)), OPLIST(OPL3) ) #define OPL4_F(opl, d, x) M_APPLY_API(M_GET_INIT_WITH M_GET_OPLIST opl, M_GET_OPLIST opl, d, x) #define OPL5 (TYPE(int), INIT_WITH(API_1(OPL5_F)), OPLIST(OPL4) ) #define OPL5_F(opl, d, x) M_APPLY_API(M_GET_INIT_WITH M_GET_OPLIST opl, M_GET_OPLIST opl, d, x) #define OPL6 (TYPE(int), INIT_WITH(API_1(OPL6_F)), OPLIST(OPL5) ) #define OPL6_F(opl, d, x) M_APPLY_API(M_GET_INIT_WITH M_GET_OPLIST opl, M_GET_OPLIST opl, d, x) M_LET( (x, 4585) , OPL1) assert (x == 4585); M_LET( (x, 4586) , OPL2) assert (x == 4586); M_LET( (x, 4587) , OPL3) assert (x == 4587); M_LET( (x, 4588) , OPL4) assert (x == 4588); M_LET( (x, 4589) , OPL5) assert (x == 4589); M_LET( (x, 4590) , OPL6) assert (x == 4590); // Test of M_LET_IF int c = 0; M_LET_IF( assert(c++ == 0), (assert(c++ == 1), true), assert(c++ == 3)) { assert(c++ == 2); } M_LET_IF( assert(c++ == 4), (assert(c++ == 5), false), assert(0)) { assert(0); } assert(c++ == 6); M_LET_IF(int *p = (int*) malloc(sizeof(int)), p!=0, free(p)) { assert(p != NULL); *p = 4; } M_LET_IF( assert(c++ == 7), (assert(c++ == 8), true), assert(c++ == 10), assert(0) ) { assert(c++ == 9); } M_LET_IF( assert(c++ == 11), (assert(c++ == 12), false), assert(0), assert(c++ == 13) ) { assert(0); } assert(c++ == 14); M_LET_IF( assert(c++ == 15), (assert(c++ == 16), true), assert(c++ == 18) ) { assert(c++ == 17); break; assert(0); } assert(c++ == 19); c = 7; int *p = (int*)malloc(sizeof(int)); assert(p != NULL); M_DEFER ( (assert(c++ == 8), free(p)) ) { *p = 4; assert(c++ == 7); } assert(c++ == 9); M_DEFER ( assert(c++ == 11) ) { assert(c++ == 10); break; assert(0); } assert(c++ == 12); } static void test_va(void) { assert (M_RET_ARG1 (M_VA(a),zz) == 1); assert (M_RET_ARG2 (M_VA(17),zz) == 17); assert (M_RET_ARG1 (M_VA(a,b,c),zz) == 3); assert (M_RET_ARG2 (M_VA(17,42,59),zz) == 17); } static void test_if(void) { assert (M_IF(1)(true, false)); assert (!M_IF(0)(true, false)); assert (M_IF(x)(true, false)); } static void test_test(void) { assert(M_COMMA_P(,)); assert(M_COMMA_P(1,2)); assert(M_COMMA_P(1,2,aa)); assert(!M_COMMA_P(1)); assert(!M_COMMA_P(())); assert(!M_COMMA_P("aa")); assert(!M_COMMA_P("")); assert(!M_COMMA_P((,))); assert(M_PARENTHESIS_P(())); assert(M_PARENTHESIS_P((aa))); assert(M_PARENTHESIS_P((aa,bb))); assert(!M_PARENTHESIS_P(a())); assert(!M_PARENTHESIS_P(a(ada))); assert(!M_PARENTHESIS_P(a,b)); assert(!M_PARENTHESIS_P(a)); assert(!M_PARENTHESIS_P()); assert(!M_PARENTHESIS_P(,)); assert(!M_PARENTHESIS_P((),)); assert(!M_PARENTHESIS_P(()x)); assert(!M_KEYWORD_P(sum, sul)); assert(M_KEYWORD_P(sum, sum)); assert(M_KEYWORD_P(sum, add)); assert(M_KEYWORD_P(product, product)); assert(M_KEYWORD_P(product, mul)); assert(!M_KEYWORD_P(product, mul2)); assert(M_KEYWORD_P(_, _)); assert(M_KEYWORD_P(_, _() )); assert(M_KEYWORD_P(LIST, LIST)); assert(M_KEYWORD_P(LIST, LIST(1,23,4) )); assert(!M_KEYWORD_P(LIST, SEQ(1,23,4) )); assert(M_KEYWORD_TO_VA_ARGS(LIST, LIST(16)) == 16); assert(M_KEYWORD_TO_VA_ARGS(LIST, LIST(14)) == 14); assert(M_GET_AT( ( M_KEYWORD_TO_VA_ARGS(LIST, LIST(11, 22, 33)) ), 0) == 11); assert(M_GET_AT( ( M_KEYWORD_TO_VA_ARGS(LIST, LIST(11, 22, 33)) ), 1) == 22); assert(M_GET_AT( ( M_KEYWORD_TO_VA_ARGS(LIST, LIST(11, 22, 33)) ), 2) == 33); assert(M_KEYWORD_TO_VA_ARGS(_, _(10)) == 10); } static void test_list(void) { assert(M_KEEP_ARGS(1, 1, 0, 0, 0, 0)); assert(M_SKIP_ARGS(4, 0, 0, 0, 0, 1)); assert(M_MID_ARGS(2, 1, 0, 0, 1, 0)); const int tab[] = { M_REPLICATE_C(5, 1) }; assert(sizeof tab == 5 * sizeof (int) ); for(int i = 0; i < 5; i++) assert(tab[i] == 1); const char str[] = M_REPLICATE(10, "N"); assert(strcmp(str, "NNNNNNNNNN") == 0); assert(M_EQUAL(M_REMOVE_PARENTHESIS( 17 ), 17)); assert(M_EQUAL(M_REMOVE_PARENTHESIS( (17) ), 17)); assert( M_FILTER(M_EQUAL, 17, 1, 42, 17, 89) ); assert( M_FILTER_C(M_EQUAL, 17, 1, 42, 17, 89) ); const int tab2[] = { M_FILTER_C(M_NOTEQUAL, 8, 1, 3, 4, 8, 9, 8, 10) }; assert(sizeof tab2 == 5 * sizeof (int) ); const int tabref[] = { 1, 3, 4, 9, 10 }; assert (sizeof tab2 == sizeof tabref); for(int i = 0; i < 5 ; i++) assert(tab2[i] == tabref[i]); #define TEST_MUL(a) M_PAIR_1 a * M_PAIR_2 a #define TEST_ADD(a,b) a + b int red = M_REDUCE(TEST_MUL, TEST_ADD, M_OPFLAT M_MERGE_ARGLIST( (1, 2, 3), (4, 5, 6) ) ); assert(red == 1 * 4 + 2 * 5 + 3 * 6); red = M_REDUCE(TEST_MUL, TEST_ADD, M_OPFLAT M_MERGE_ARGLIST( (1), (4) ) ); assert(red == 1 * 4); red = M_REDUCE(TEST_MUL, TEST_ADD, M_OPFLAT M_MERGE_ARGLIST( (3, 5), (7, 11) ) ); assert(red == 3 * 7 + 5 * 11); red = M_REDUCE(M_ID, TEST_ADD, M_OPFLAT M_CAT_ARGLIST( , (3))); assert(red == 3); red = M_REDUCE(M_ID, TEST_ADD, M_OPFLAT M_CAT_ARGLIST((5, 4), )); assert(red == 5 + 4); red = M_REDUCE(M_ID, TEST_ADD, M_OPFLAT M_CAT_ARGLIST((5, 4), ( 9, 25, 111) )); assert(red == 5 + 4 + 9 + 25 + 111); } static void test_oplist(void) { #define TEST_OPLIST(op, oplist) \ M_C(M_GET_, op) oplist assert (TEST_OPLIST(INIT, (INIT(true)))); assert (TEST_OPLIST(INIT, (INIT(true),CLEAR(false)))); assert (TEST_OPLIST(INIT, (INIT_SET(false), INIT(true),CLEAR(false)))); assert (TEST_OPLIST(INIT, (INIT_SET(false), INIT(true)))); assert (M_TEST_METHOD_P(INIT, (INIT(empty)))); assert (M_TEST_METHOD_P(INIT, (INIT(empty),CLEAR(empty)))); assert (M_TEST_METHOD_P(INIT, (INIT_SET(empty), INIT(empty),CLEAR(empty)))); assert (M_TEST_METHOD_P(INIT, (INIT_SET(empty), INIT(empty)))); assert (M_TEST_METHOD_P(OPLIST, (INIT_SET(empty), INIT(empty), OPLIST(a(INIT(empty), CLEAR(empty))), CLEAR(empty)))); // True oplist are not supported for TEST_METHOD_P + OPLIST... assert (M_TEST_METHOD_P(OPLIST, (INIT_SET(empty), OPLIST(a(INIT(empty), CLEAR(empty)))))); assert (M_TEST_METHOD_P(OPLIST, (INIT_SET(empty), M_IF_METHOD(CLEAR, (INIT(empty), CLEAR(empty)))(OPLIST(empty),)))); assert (!M_TEST_METHOD_P(INIT2, (INIT(empty)))); assert (!M_TEST_METHOD_P(INIT2, (INIT(empty),CLEAR(empty)))); assert (!M_TEST_METHOD_P(INIT2, (INIT_SET(empty), INIT(empty),CLEAR(empty)))); assert (!M_TEST_METHOD_P(INIT2, (INIT_SET(empty), INIT(empty)))); #define CHECK_OPLIST(op, oplist) \ M_IF_METHOD(op, oplist) (true, false) assert (CHECK_OPLIST (INIT, M_BASIC_OPLIST)); assert (CHECK_OPLIST (INIT_SET, M_BASIC_OPLIST)); assert (CHECK_OPLIST (SET, M_BASIC_OPLIST)); assert (CHECK_OPLIST (CLEAR, M_BASIC_OPLIST)); assert (!CHECK_OPLIST (CLEAR_TOOT, M_BASIC_OPLIST)); assert (M_OPLIST_P(())); assert (M_OPLIST_P((INIT(init)))); assert (M_OPLIST_P((INIT(init),CLEAR(clear)))); assert (M_OPLIST_P((INIT(init),CLEAR(clear),))); assert (!M_OPLIST_P()); assert (!M_OPLIST_P((()))); assert (!M_OPLIST_P(INIT(init))); assert (!M_OPLIST_P((INIT(init)) a)); assert (!M_OPLIST_P(func(INIT(init)) a)); assert (!M_OPLIST_P(func(INIT(init),) a)); #define aop (INIT(0), CLEAR(clear)) assert (M_TEST_DISABLED_METHOD_P(INIT, aop)); assert (!M_TEST_DISABLED_METHOD_P(INIT2, aop)); assert (!M_TEST_DISABLED_METHOD_P(CLEAR, aop)); assert (!M_TEST_DISABLED_METHOD_P(INIT, ())); #define M_OPL_op() (INIT(1), CLEAR(0)) assert(M_ID (M_GET_INIT M_GLOBAL_OPLIST(op))); assert(M_ID (!M_GET_INIT M_GLOBAL_OPLIST(aop))); #define MAKE_OPLIST(op) (OPLIST(M_GLOBAL_OPLIST_OR_DEF(op)())) #define M_OPL_uint() (INIT(0), CLEAR(1)) #define M_OPL_array_uint() (OPLIST(M_GLOBAL_OPLIST_OR_DEF(uint)())) #define M_OPL_list_array_uint() MAKE_OPLIST(array_uint) #define A1 A2(M_OPL_list_array_uint()) #define A2(op) A3(M_GET_OPLIST op) #define A3(op) A4(M_GET_OPLIST op) #define A4(op) M_GET_CLEAR op assert (A1); #define A5 (NAME(1)) assert (M_ID (M_GET_NAME A5)); #define A6 (NAME(A6), INIT_WITH(API_1(M_INIT_WITH_NVAR))) #define A6_init_with__1(x) 1 #define A6_init_with__2(x, y) 0 assert (M_ID(M_CALL_INIT_WITH (A6, 0))); assert (M_ID(!M_CALL_INIT_WITH (A6, 0, 0))); } static void test_cast(void) { float f1 = 1.0; float f2 = M_ASSIGN_CAST(float, f1); int i1 = M_ASSIGN_CAST(int, f2); assert (i1 == 1); int *p1 = &i1; const int *p2 = M_CONST_CAST(int, p1); assert (*p2 == 1); } static void test_reduce(void) { #define id(x,a) a #define add(a,b) a + b assert ( M_REDUCE2(id, add, d, M_SEQ(1, 5)) == 5 * 6 /2); assert ( M_REDUCE2(id, add, d, M_SEQ(1, 10)) == 10 * 11 /2); assert ( M_REDUCE2(id, add, d, M_SEQ(1, 1)) == 1); assert ( M_REDUCE2(id, add, d, M_SEQ(1, 2)) == 1+2); assert ( M_REDUCE(M_ID, add, M_SEQ(1, 5)) + M_REDUCE(M_ID, add, M_SEQ(6, 10)) == M_REDUCE(M_ID, add, M_SEQ(1, 10))); #define add3(a,b,c) (a + b + c) #define mul(a,b) (a) * (b) int d = 42; assert ( M_REDUCE3(add3, mul, d, 20, 4, 5) == (d + 1 + 20) * ( (d + 2 + 4) * ( (d + 3 + 5) ) ) ); } static void test_as_type(void) { #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L int i = 42; float f = 2.5; void *p = (void*) &i; struct as_type { int n; } n = { 17 }; assert (M_AS_TYPE(int, i) == 42); assert (M_AS_TYPE(float, i) == 0.0); assert (M_AS_TYPE(void *, i) == 0); assert (M_AS_TYPE(struct as_type, i).n == 0 ); assert (M_AS_TYPE(int, f) == 0); assert (M_AS_TYPE(float, f) == 2.5); assert (M_AS_TYPE(void *, f) == 0); assert (M_AS_TYPE(struct as_type, f).n == 0 ); assert (M_AS_TYPE(int, p) == 0); assert (M_AS_TYPE(float, p) == 0.0); assert (M_AS_TYPE(void *, p) == &i); assert (M_AS_TYPE(struct as_type, p).n == 0 ); assert (M_AS_TYPE(int, n) == 0); assert (M_AS_TYPE(float, n) == 0.0); assert (M_AS_TYPE(void *, n) == 0); assert (M_AS_TYPE(struct as_type, n).n == 17 ); #endif } static void test_parse_standard_c_type(void) { #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L char c = 0; const char *endp; M_PARSE_DEFAULT_TYPE(&c, "C", NULL); assert (c == 'C'); M_PARSE_DEFAULT_TYPE(&c, "D", &endp); assert (c == 'D'); assert (*endp == 0); bool b = false; M_PARSE_DEFAULT_TYPE(&b, "1", NULL); assert (b == true); M_PARSE_DEFAULT_TYPE(&b, "0", &endp); assert (b == false); assert (*endp == 0); short s = 0; M_PARSE_DEFAULT_TYPE(&s, "-2", NULL); assert (s == -2); M_PARSE_DEFAULT_TYPE(&s, "3", &endp); assert (s == 3); assert (*endp == 0); int i = 0; M_PARSE_DEFAULT_TYPE(&i, "2", NULL); assert (i == 2); M_PARSE_DEFAULT_TYPE(&i, "-3", &endp); assert (i == -3); assert (*endp == 0); long l = 0; M_PARSE_DEFAULT_TYPE(&l, "1742", NULL); assert (l == 1742); M_PARSE_DEFAULT_TYPE(&l, "-421742", &endp); assert (l == -421742); assert (*endp == 0); long long ll = 0; M_PARSE_DEFAULT_TYPE(&ll, "-1742548676843540", NULL); assert (ll == -1742548676843540LL); M_PARSE_DEFAULT_TYPE(&ll, "1742548676843541", &endp); assert (ll == 1742548676843541LL); assert (*endp == 0); unsigned short us = 0; M_PARSE_DEFAULT_TYPE(&us, "3", NULL); assert (us == 3); M_PARSE_DEFAULT_TYPE(&us, "5", &endp); assert (us == 5); assert (*endp == 0); unsigned int ui = 0; M_PARSE_DEFAULT_TYPE(&ui, "2", NULL); assert (ui == 2); M_PARSE_DEFAULT_TYPE(&ui, "25", &endp); assert (ui == 25); assert (*endp == 0); unsigned long ul = 0; M_PARSE_DEFAULT_TYPE(&ul, "1742", NULL); assert (ul == 1742); M_PARSE_DEFAULT_TYPE(&ul, "17412", &endp); assert (ul == 17412); assert (*endp == 0); unsigned long long ull = 0; M_PARSE_DEFAULT_TYPE(&ull, "1742548676843540", NULL); assert (ull == 1742548676843540ULL); M_PARSE_DEFAULT_TYPE(&ull, "1742548676843541", &endp); assert (ull == 1742548676843541ULL); assert (*endp == 0); float f; M_PARSE_DEFAULT_TYPE(&f, "-0.5", NULL); assert (f == -0.5); M_PARSE_DEFAULT_TYPE(&f, "4.5", &endp); assert (f == 4.5); assert (*endp == 0); double d; M_PARSE_DEFAULT_TYPE(&d, "2.5", NULL); assert (d == 2.5); M_PARSE_DEFAULT_TYPE(&d, "-3.5", &endp); assert (d == -3.5); assert (*endp == 0); long double ld; M_PARSE_DEFAULT_TYPE(&ld, "2.5", NULL); assert (ld == 2.5); M_PARSE_DEFAULT_TYPE(&ld, "-5.5", &endp); assert (ld == -5.5); assert (*endp == 0); #endif } typedef int ti[1]; typedef struct { int b,c; } ts; static void f_ti(ti x) { ti y; M_COPY_A1_DEFAULT(y,x); assert(y[0] == 9); } static void f_ts(ts x) { ts y; M_SET_DEFAULT(y,x); assert(y.b == 2); assert(y.c == 3); } static void f_ts2(ts *x) { ts y; M_SET_DEFAULT(y,*x); assert(y.b == 2); assert(y.c == 3); } static void test_move_default(void) { int o, p; o = 9; M_SET_DEFAULT(p, o); assert(p == 9); double u, k; k = -1.0; u = 9.5; M_SET_DEFAULT(k, u); assert(k == 9.5); int *ptr = &o, *m; M_SET_DEFAULT(m, ptr); (void)m; ti x, y; x[0] = 9; M_COPY_A1_DEFAULT(y, x); assert(y[0] == 9); x[0] = 9; f_ti(x); ts y2, x2 = { 2, 3}; M_SET_DEFAULT(y2, x2); assert(y2.b == 2 && y2.c == 3); x2.b = 2; x2.c = 3; f_ts(x2); assert(x2.b == 2); assert(x2.c == 3); f_ts2(&x2); } static void test_builtin(void) { assert(m_core_clz32(0) == 32); for(unsigned i = 0; i < 31; i++) { assert(m_core_clz32((uint32_t) (1UL<= 7 && !defined(__clang__)) \ ||(defined(__clang__) && __clang_major__ >= 18) _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wformat-truncation\"") #endif r = strcmp(M_CSTR("Hello %s %c", "World", '!'), "Hello W"); #if (defined (__GNUC__) && __GNUC__ >= 7 && !defined(__clang__)) \ ||(defined(__clang__) && __clang_major__ >= 18) _Pragma("GCC diagnostic pop") #endif assert (r == 0); } static void test_properties(void) { #define OP_PROP() ( INIT(init), PROPERTIES((INIT(1), IT_TYPE(2), INIT_WITH(priority))) ) assert( M_GET_PROPERTY (OP_PROP(), INIT ) == 1); assert( M_GET_PROPERTY (OP_PROP(), CLEAR ) == 0); assert( M_GET_PROPERTY (OP_PROP(), IT_TYPE ) == 2); assert( M_KEYWORD_P( M_GET_PROPERTY (OP_PROP(), INIT_WITH ), priority)); } static int init3(int *p, int a, int b) { *p = b; return a; } static int cmp1(int a, int b) { return a < b ? -1 : a > b; } static int cmp2(int *a, int *b) { return *a < *b ? -1 : *a > *b; } #define cmp3(a, b) \ (a < b ? -1 : a > b) static void test_generic_api(void) { assert( M_HEAD(17, 0) == 17); assert( M_TAIL(18, 19) == 19); assert( M_HEAD_2(18, 17, 0) == 17); assert( M_TAIL_2(18, 17, 8) == 8); #define GO1 (INIT(API( init3, ARG1, ARGPTR2, 17, ID(-43) ))) #define GO2 (INIT(API( init3, NONE, ARGPTR2, 0, ARG1 ))) #define GO3 (EQUAL(API( cmp2, EQ(0), ARGPTR1, ARGPTR2 ))) #define GO4 (EQUAL(API( cmp1, EQ(0), ARG1, ARG2 ))) #define GO5 (EQUAL(API( cmp3, EQ(0), ARG1, ARG2 ))) #define GO6 (CMP(API(cmp3, NEG, ARG1, ARG2))) int x = 0, y = 0; M_CALL_INIT(GO1, x, y); assert(x == 17); assert(y == -43); x = 89; M_CALL_INIT(GO2, x, y); assert( y == 89); assert( x == 89); x = y = 78; bool b = M_CALL_EQUAL(GO3, x, y); assert(b); x = 77; b = M_CALL_EQUAL(GO4, x, y); assert(!b); x = y = 78; b = M_CALL_EQUAL(GO5, x, y); assert(b); x = 77; b = M_CALL_EQUAL(GO5, x, y); assert(!b); x = 78; y = 77; int r = M_CALL_CMP(GO6, x, y); assert(r < 0); x = 76; y = 77; r = M_CALL_CMP(GO6, x, y); assert(r > 0); x = 76; y = 76; r = M_CALL_CMP(GO6, x, y); assert(r == 0); } static void f_default(int a, int b, int c) { assert( a == 1 ); assert( b == 2 ); assert( c == 3 ); } static void test_default(void) { #define f11(...) f_default(M_DEFAULT_ARGS(3, (1, 2, 3), __VA_ARGS__)) f11(1, 2, 3); f11(1, 2); f11(1); #define f12(...) f_default(M_DEFAULT_ARGS(3, (2, 3), __VA_ARGS__)) f12(1, 2, 3); f12(1, 2); f12(1); #define f13(...) f_default(M_DEFAULT_ARGS(3, (3), __VA_ARGS__)) f13(1, 2, 3); f13(1, 2); } int main(void) { test_cat(); test_power2(); test_incdec(); test_return(); test_invert(); test_min(); test_empty(); test_list(); test_map(); test_let(); test_va(); test_if(); test_test(); test_oplist(); test_cast(); test_reduce(); test_as_type(); test_parse_standard_c_type(); test_move_default(); test_builtin(); test_str_hash(); test_M_CSTR(); test_properties(); test_generic_api(); test_default(); testobj_final_check(); exit(0); }