Files
mlib/tests/test-mcore.c
T

1012 lines
28 KiB
C

/*
* Copyright (c) 2017-2023, 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 <stdbool.h>
#include <assert.h>
#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 "m-core.h"
#include "test-obj.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_MOVE_A1_DEFAULT(y,x);
assert(y[0] == 9);
assert(x[0] == 0);
}
static void f_ts(ts x)
{
ts y;
M_MOVE_DEFAULT(y,x);
assert(y.b == 2);
assert(y.c == 3);
assert(x.b == 0);
assert(x.c == 0);
}
static void f_ts2(ts *x)
{
ts y;
M_MOVE_DEFAULT(y,*x);
assert(y.b == 2);
assert(y.c == 3);
assert(x->b == 0);
assert(x->c == 0);
}
static void test_move_default(void)
{
int o, p;
o = 9;
M_MOVE_DEFAULT(p, o);
assert(p == 9);
assert(o == 0);
double u, k;
k = -1.0;
u = 9.5;
M_MOVE_DEFAULT(k, u);
assert(k == 9.5);
assert(u == 0.0); // NOTE: memset(0) sets an IEEE-754 number to 0.0
int *ptr = &o, *m;
M_MOVE_DEFAULT(m, ptr);
assert( ptr == NULL);
assert( m == &o);
ti x, y;
x[0] = 9;
M_MOVE_A1_DEFAULT(y, x);
assert(y[0] == 9);
assert(x[0] == 0);
x[0] = 9;
f_ti(x);
assert(x[0] == 0);
ts y2, x2 = { 2, 3};
M_MOVE_DEFAULT(y2, x2);
assert(y2.b == 2 && y2.c == 3);
assert(x2.b == 0 && x2.c == 0);
x2.b = 2; x2.c = 3;
f_ts(x2);
assert(x2.b == 2);
assert(x2.c == 3);
f_ts2(&x2);
assert(x2.b == 0);
assert(x2.c == 0);
}
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<<i)) == 31U - i);
assert(m_core_clz32((uint32_t) ((1UL<<i) | 1)) == 31U - i);
}
assert(m_core_clz64(0) == 64);
for(unsigned i = 0; i < 63; i++) {
assert(m_core_clz64((uint64_t) (1ULL<<i)) == 63U - i);
assert(m_core_clz64((uint64_t) ((1ULL<<i) | 1)) == 63U - i);
}
assert(m_core_ctz32(0) == 32);
for(unsigned i = 0; i < 31; i++) {
assert(m_core_ctz32((uint32_t) (1UL<<i)) == i);
assert(m_core_ctz32((uint32_t) ((1UL<<i) | 1UL<<31)) == i);
}
assert(m_core_ctz64(0) == 64);
for(unsigned i = 0; i < 63; i++) {
assert(m_core_ctz64((uint64_t) (1ULL<<i)) == i);
assert(m_core_ctz64((uint64_t) ((1ULL<<i) | 1ULL<<63)) == i);
}
assert ( m_core_roundpow2(0) == 0);
for(unsigned i = 0; i < 62; i++) {
assert ( m_core_roundpow2(1ULL<<i) == 1ULL<<i);
assert ( m_core_roundpow2((1ULL<<i)+1) == 1ULL<<(i+1) );
}
for(unsigned i = 0; i < 3000; i++) {
assert( m_core_rotl32a(i, 1) == i * 2);
assert( m_core_rotl32a(i, 2) == i * 4);
assert( m_core_rotl32a((uint32_t) ((1UL<<31) + i), 1) == i * 2 + 1);
assert( m_core_rotl32a((uint32_t) ((1UL<<31) + i), 2) == i * 4 + 2);
}
for(unsigned i = 0; i < 3000; i++) {
assert( m_core_rotl64a(i, 1) == i * 2);
assert( m_core_rotl64a(i, 2) == i * 4);
assert( m_core_rotl64a((1ULL<<63) + i, 1) == i * 2 + 1);
assert( m_core_rotl64a((1ULL<<63) + i, 2) == i * 4 + 2);
}
}
const char str1[] = "A";
const char str2[] = "AB";
const char str3[] = "Hello";
static void test_str_hash(void)
{
assert (M_CALL_HASH(M_CSTR_OPLIST, str1) != 0);
assert (M_CALL_HASH(M_CSTR_OPLIST, str2) != 0);
assert (M_CALL_HASH(M_CSTR_OPLIST, str3) != 0);
}
static void test_M_CSTR(void)
{
int r;
r = strcmp(M_CSTR("Len=%d", 17), "Len=17");
assert (r == 0);
r = strcmp(M_CSTR("Hello %s %c", "World", '!'), "Hello World !");
assert (r == 0);
// Reduce allocation to test truncation
#undef M_USE_CSTR_ALLOC
#define M_USE_CSTR_ALLOC 8
// Disable GNUC warning as we want to test this behavior.
// this warning is not supported by CLANG
#if defined (__GNUC__) && __GNUC__ >= 7 && !defined(__clang__)
_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__)
_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);
}
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();
testobj_final_check();
exit(0);
}