Add framework to test containers againts C++ library

This commit is contained in:
Patrick Pelissier committed 2021-10-09 16:55:51 +02:00
1 parent 4409f613e0
commit fdfff0c5c5
6 files changed
+703 -5

No files matched your search

+9 -5
View File
@@ -21,6 +21,7 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
CC=cc -std=c99
CXX=c++ -std=c++11
WCFLAGS_GCC=-Wall -W -pedantic -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wswitch-default -Wswitch-enum -Wcast-align -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 -Wundef -Wnested-externs -Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op -Wstrict-aliasing=2 -Wredundant-decls -Wold-style-definition -Wunused-function -ftrapv -Wsign-conversion -Wdate-time -Wconversion -Wformat=2 -Winit-self -Wjump-misses-init -Wstack-protector -Wtrampolines -Wwrite-strings -Wformat-security -Wno-float-conversion -O
WCFLAGS_CLANG=-Wall -W -pedantic -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wswitch-default -Wswitch-enum -Wcast-align -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 -Winline -Wundef -Wnested-externs -Wcast-qual -Wshadow -Wunreachable-code -Wstrict-aliasing=2 -Wredundant-decls -Wold-style-definition -Wunused-function -ftrapv -Wsign-conversion -O
WCFLAGS_CPP=-Wall -W -pedantic -Wshadow -Wpointer-arith -Wcast-qual -Wswitch-default -Wswitch-enum -Wcast-align -Wpointer-arith -Wstrict-overflow=5 -Winline -Wundef -Wcast-qual -Wshadow -Wunreachable-code -Wstrict-aliasing=2 -Wredundant-decls -Wunused-function -ftrapv -Wsign-conversion
@@ -44,12 +45,15 @@ all:
.POSIX:
.PHONY: scan-build sanitize check clean *.log coverage synthesis
.SUFFIXES:
.SUFFIXES: .c .exe .log .depend .gcov .analyzer
.SUFFIXES: .c .exe .log .depend .gcov .analyzer .cpp
.SECONDARY:
.c.exe:
$(CC) $(CFLAGS) $(CPPFLAGS) -g $(LDFLAGS) $< -o $@
.cpp.exe:
$(CXX) $(WCFLAGS_CPP) $(XCFLAGS) $(CPPFLAGS) -g $(LDFLAGS) $< -o $@
.c.depend:
$(CC) $(CFLAGS) $(CPPFLAGS) -MM -MT `echo $< |$(SED) 's/\.c/\.exe/g'` $< > $@
@@ -82,14 +86,14 @@ depend:
# Clean
#####################################################################################################
exe: depend
$(MAKE) `ls test-*.c|$(SED) 's/\.c/\.exe/g'` CC="$(CC)" CFLAGS="$(CFLAGS)"
@echo All executable generated
check: depend
$(MAKE) `ls test-*.c|$(SED) 's/\.c/\.log/g'` `ls fail-*.c|$(SED) 's/\.c/\.log/g'` CC="$(CC)" CFLAGS="$(CFLAGS)"
@echo All tests passed
check-stl: depend
$(MAKE) `ls check-*.cpp|$(SED) 's/\.cpp/\.log/g'` CXX="$(CXX)" XCFLAGS="-O2 -fsanitize=address,undefined,leak -Wno-sign-conversion -Wno-inline"
@echo All comparison against C++ STL passed
clean:
$(RM) *.exe *.s *~ *.o *.log a*.dat
$(RM) *.gcda *.gcno *.gcov all.info test.tar *.synt clang_output_* *.c.c *.end.c *.first.c *.middle.c *.analyzer
+61
View File
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2021, 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 <vector>
#include "m-array.h"
ARRAY_DEF(array_int, int)
// Transform an integer 'i' into a M*LIB base item 'a'
#define TYPE_SET_INT(a, i) (a) = (i)
// Container OPLIST
#define CONT_OPL ARRAY_OPLIST(array_int, M_OPL_int())
// C++ Base class of the item in the container
#define BASE_CLASS int
// Transform an integer 'i' into a C++ base item 'a'
#define CLASS_SET_INT(a, i) (a) = (i)
// C++ Container class
#define CONT_CLASS std::vector<int>
// Compare the M*LIB container a to the C++ container b
#define CMP_CONT(a, b) cmp_cont(a, b)
// Compate the M*LIB base object to the C++ base object
#define CMP_BASE(a, b) assert( (a) == (b) )
void cmp_cont(array_int_t a, std::vector<int> b)
{
size_t s = array_int_size(a);
assert (s == b.size());
for(size_t i = 0; i < s; i++) {
int *b0 = array_int_get(a, i);
int &b1 = b.at(i);
CMP_BASE(*b0, b1);
}
}
#define DEFAULT_NUMBER 1000000
#include "check-generic.hpp"
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2021, 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 <deque>
#include "m-deque.h"
DEQUE_DEF(deque_float, float)
// Transform an integer 'i' into a M*LIB base item 'a'
#define TYPE_SET_INT(a, i) (a) = (i)
// Container OPLIST
#define CONT_OPL DEQUE_OPLIST(deque_float, M_OPL_float())
// C++ Base class of the item in the container
#define BASE_CLASS float
// Transform an integer 'i' into a C++ base item 'a'
#define CLASS_SET_INT(a, i) (a) = (i)
// C++ Container class
#define CONT_CLASS std::deque<float>
// Compare the M*LIB container a to the C++ container b
#define CMP_CONT(a, b) cmp_cont(a, b)
// Compate the M*LIB base object to the C++ base object
#define CMP_BASE(a, b) assert( (a) == (b) )
void cmp_cont(deque_float_t a, std::deque<float> b)
{
deque_float_it_t ita;
deque_float_it(ita, a);
auto itb = b.begin();
while (itb != b.end()) {
assert(!deque_float_end_p(ita));
const float *b0 = deque_float_cref(ita);
float &b1 = *itb;
CMP_BASE(*b0, b1);
itb++;
deque_float_next(ita);
}
assert(deque_float_end_p(ita));
}
#define DEFAULT_NUMBER 1000000
#define HAVE_PUSH_FRONT
#define HAVE_POP_FRONT
#include "check-generic.hpp"
+71
View File
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2021, 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 <list>
#include "m-list.h"
LIST_DUAL_PUSH_DEF(list_int, int)
// Transform an integer 'i' into a M*LIB base item 'a'
#define TYPE_SET_INT(a, i) (a) = (i)
// Container OPLIST
#define CONT_OPL LIST_OPLIST(list_int, M_OPL_int())
// C++ Base class of the item in the container
#define BASE_CLASS int
// Transform an integer 'i' into a C++ base item 'a'
#define CLASS_SET_INT(a, i) (a) = (i)
// C++ Container class
#define CONT_CLASS std::list<int>
// Compare the M*LIB container a to the C++ container b
#define CMP_CONT(a, b) cmp_cont(a, b)
// Compate the M*LIB base object to the C++ base object
#define CMP_BASE(a, b) assert( (a) == (b) )
void cmp_cont(const list_int_t a, const std::list<int> &b)
{
list_int_it_t ita;
list_int_it(ita, a);
auto itb = b.rbegin();
while (itb != b.rend()) {
assert(!list_int_end_p(ita));
const int *b0 = list_int_cref(ita);
const int &b1 = *itb;
//printf("%d VS %d\n", *b0, b1);
CMP_BASE(*b0, b1);
itb++;
list_int_next(ita);
}
assert(list_int_end_p(ita));
}
#define DEFAULT_NUMBER 100000
#define HAVE_PUSH_FRONT
#define HAVE_REVERSE_IT
#include "check-generic.hpp"
+421
View File
@@ -0,0 +1,421 @@
/*
* Copyright (c) 2021, 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 <stdio.h>
#include <stdlib.h>
#include <assert.h>
/* This test will perform random generic operations on the
M*LIB container and compares it to the same operation on the
C++ equivalent container.
If there are some differences, it reports an error.
It is therefore quite generic and based on the properties of the container
*/
/* Get the types from the container oplist if needed */
#ifndef CONT_TYPE
# define CONT_TYPE_(CONT_OPL) M_GET_TYPE CONT_OPL
# define CONT_TYPE CONT_TYPE_(CONT_OPL)
#endif
#ifndef BASE_TYPE
# define BASE_TYPE_(CONT_OPL) M_GET_SUBTYPE CONT_OPL
# define BASE_TYPE BASE_TYPE_(CONT_OPL)
#endif
#define CONT_NAME_(CONT_OPL) M_GET_NAME CONT_OPL
#define CONT_NAME CONT_NAME_(CONT_OPL)
#define MAX_TEST 25
#ifdef HAVE_REVERSE_IT
// Scan the C++ sequence in reverse
# define begin rbegin
# define end rend
# define IT(x) std::prev(x.base(), 1)
#else
# define IT(x) x
#endif
volatile int test_case;
void test(int select_test, int index,
BASE_TYPE &b0, BASE_CLASS &b1, CONT_TYPE &c0, CONT_CLASS &c1)
{
bool p0 = false, p1 = false;
size_t s0 = 0, s1 = 0;
CONT_TYPE tmp;
#if M_TEST_METHOD_P(IT_TYPE, CONT_OPL)
M_ID(M_GET_IT_TYPE CONT_OPL) it0;
auto it1 = c1.begin();
#endif
// Save in a volatile variable the last test for debug purpose
test_case = select_test % MAX_TEST;
#ifdef DEBUG
printf("Case=%d\n", test_case);
#endif
switch (test_case) {
#if M_TEST_METHOD_P(PUSH, CONT_OPL)
case 0:
TYPE_SET_INT(b0, index);
CLASS_SET_INT(b1, index);
M_CALL_PUSH(CONT_OPL, c0, b0);
c1.push_back(b1);
break;
case 1:
index = index % 1000;
for(int i = 0; i < index; i++) {
TYPE_SET_INT(b0, i);
CLASS_SET_INT(b1, i);
M_CALL_PUSH(CONT_OPL, c0, b0);
c1.push_back(b1);
}
break;
#endif
#if M_TEST_METHOD_P(POP, CONT_OPL)
case 2:
if (!c1.empty()) {
M_CALL_POP(CONT_OPL, &b0, c0);
b1 = c1.back();
c1.pop_back();
}
break;
#endif
#if M_TEST_METHOD_P(EMPTY_P, CONT_OPL)
case 3:
p0 = M_CALL_EMPTY_P(CONT_OPL, c0);
p1 = c1.empty();
break;
#endif
#if M_TEST_METHOD_P(SIZE, CONT_OPL)
case 4:
s0 = M_CALL_SIZE(CONT_OPL, c0);
s1 = c1.size();
break;
#endif
#if M_TEST_METHOD_P(CLEAN, CONT_OPL)
case 5:
M_CALL_CLEAN(CONT_OPL, c0);
c1.clear();
break;
#endif
#if M_TEST_METHOD_P(GET_KEY, CONT_OPL)
case 6:
if (!c1.empty()) {
// To rework for dict
index = index % c1.size();
M_CALL_SET(M_GET_OPLIST CONT_OPL, b0, *M_CALL_GET_KEY(CONT_OPL, c0, index));
b1 = c1[index];
}
break;
#endif
#if M_TEST_METHOD_P(SET_KEY, CONT_OPL)
case 7:
if (!c1.empty()) {
TYPE_SET_INT(b0, index);
CLASS_SET_INT(b1, index);
index = index % c1.size();
M_CALL_SET_KEY(CONT_OPL, c0, index, b0);
c1[index] = b1;
}
break;
#endif
#if M_TEST_METHOD_P(ERASE_KEY, CONT_OPL)
case 8:
if (!c1.empty()) {
index = index % c1.size();
p0 = M_CALL_ERASE_KEY(CONT_OPL, c0, index);
c1.erase(c1.begin() + index);
p1 = true;
}
break;
#endif
#if M_TEST_METHOD_P(SET, CONT_OPL) && M_TEST_METHOD_P(INIT_SET, CONT_OPL)
case 9:
M_CALL_INIT_SET(CONT_OPL, tmp, c0);
#if M_TEST_METHOD_P(EQUAL_P, CONT_OPL)
assert( M_CALL_EQUAL_P(CONT_OPL, tmp, c0) );
#endif
M_CALL_SET(CONT_OPL, c0, tmp);
M_CALL_CLEAR(CONT_OPL, tmp);
break;
#endif
#if M_TEST_METHOD_P(INIT_MOVE, CONT_OPL)
case 10:
M_CALL_INIT_MOVE(CONT_OPL, tmp, c0);
M_CALL_INIT_MOVE(CONT_OPL, c0, tmp);
break;
#endif
#if M_TEST_METHOD_P(MOVE, CONT_OPL) && M_TEST_METHOD_P(INIT_MOVE, CONT_OPL)
case 11:
M_CALL_INIT_SET(CONT_OPL, tmp, c0);
M_CALL_MOVE(CONT_OPL, tmp, c0);
M_CALL_INIT_MOVE(CONT_OPL, c0, tmp);
break;
#endif
#if M_TEST_METHOD_P(SWAP, CONT_OPL) && M_TEST_METHOD_P(GET_SIZE, CONT_OPL)
case 12:
s0 = M_CALL_GET_SIZE(CONT_OPL, c0);
M_CALL_INIT(CONT_OPL, tmp);
M_CALL_SWAP(CONT_OPL, tmp, c0);
s1 = M_CALL_GET_SIZE(CONT_OPL, tmp);
M_CALL_SWAP(CONT_OPL, tmp, c0);
M_CALL_CLEAR(CONT_OPL, tmp);
break;
case 13:
M_CALL_INIT_SET(CONT_OPL, tmp, c0);
M_CALL_SWAP(CONT_OPL, tmp, c0);
M_CALL_CLEAR(CONT_OPL, tmp);
break;
#endif
#if M_TEST_METHOD_P(GET_SET_KEY, CONT_OPL)
case 14:
// To rework for dict
index = (1 + (c1.size() < 1000000)) * (index % ( c1.size() + 1) );
M_CALL_SET(M_GET_OPLIST CONT_OPL, b0, *M_CALL_GET_SET_KEY(CONT_OPL, c0, index));
if ((size_t) index >= c1.size() ) {
c1.resize(index+1);
}
b1 = c1[index];
break;
#endif
#if M_TEST_METHOD_P(IT_CREF, CONT_OPL)
case 15:
M_CALL_IT_FIRST(CONT_OPL, it0, c0);
it1 = c1.begin();
while (it1 != c1.end()) {
assert( !M_CALL_IT_END_P(CONT_OPL, it0));
M_CALL_SET(M_GET_OPLIST CONT_OPL, b0, *M_CALL_IT_CREF(CONT_OPL, it0));
b1 = *it1;
CMP_BASE(b0, b1);
M_CALL_IT_NEXT(CONT_OPL, it0);
it1++;
}
assert(M_CALL_IT_END_P(CONT_OPL, it0));
break;
#endif
#if M_TEST_METHOD_P(IT_REF, CONT_OPL)
case 16:
M_CALL_IT_FIRST(CONT_OPL, it0, c0);
it1 = c1.begin();
while (it1 != c1.end()) {
assert( !M_CALL_IT_END_P(CONT_OPL, it0));
TYPE_SET_INT(b0, index);
CLASS_SET_INT(b1, index);
M_CALL_SET(M_GET_OPLIST CONT_OPL, *M_CALL_IT_REF(CONT_OPL, it0), b0);
*it1 = b1;
M_CALL_IT_NEXT(CONT_OPL, it0);
it1++;
index = 1457857U * index + 458741U;
}
assert(M_CALL_IT_END_P(CONT_OPL, it0));
break;
#endif
#if M_TEST_METHOD_P(IT_LAST, CONT_OPL)
case 17:
{
M_CALL_IT_LAST(CONT_OPL, it0, c0);
auto it1b = c1.rbegin();
while (it1b != c1.rend()) {
assert( !M_CALL_IT_END_P(CONT_OPL, it0));
M_CALL_SET(M_GET_OPLIST CONT_OPL, b0, *M_CALL_IT_CREF(CONT_OPL, it0));
b1 = *it1b;
CMP_BASE(b0, b1);
M_CALL_IT_PREVIOUS(CONT_OPL, it0);
it1b++;
}
assert(M_CALL_IT_END_P(CONT_OPL, it0));
}
break;
#endif
#if M_TEST_METHOD_P(IT_INSERT, CONT_OPL)
case 18:
M_CALL_IT_FIRST(CONT_OPL, it0, c0);
it1 = c1.begin();
TYPE_SET_INT(b0, index);
CLASS_SET_INT(b1, index);
#ifdef HAVE_INSERT_AFTER
while (it1 != c1.end() ) {
if (rand() > index)
break;
M_CALL_IT_NEXT(CONT_OPL, it0);
it1++;
}
if (it1 != c1.end() ) {
M_CALL_IT_INSERT(CONT_OPL, c0, it0, b0);
c1.insert_after(it1, b1);
}
#else
if (!c1.empty() ){
index = index % c1.size();
if (index == 0) {
M_CALL_IT_END(CONT_OPL, it0, c0);
} else {
for(int i = 0; i < index; i++) {
assert( it1 != c1.end());
assert( !M_CALL_IT_END_P(CONT_OPL, it0));
M_CALL_IT_NEXT(CONT_OPL, it0);
it1++;
}
it1++;
}
}
M_CALL_IT_INSERT(CONT_OPL, c0, it0, b0);
#ifdef HAVE_REVERSE_IT
// in cases of reverse iterator, fix iterator.
it1 = std::prev(it1, 1);
#endif
c1.insert(IT(it1), b1);
#endif
break;
#endif
#if M_TEST_METHOD_P(IT_REMOVE, CONT_OPL)
case 19:
M_CALL_IT_FIRST(CONT_OPL, it0, c0);
it1 = c1.begin();
#ifdef HAVE_ERASE_AFTER
while (it1 != c1.end() ) {
M_CALL_IT_NEXT(CONT_OPL, it0);
if (rand() > index)
break;
it1++;
}
if (it1 != c1.end() && !M_CALL_IT_END_P(CONT_OPL, it0) ) {
M_CALL_IT_REMOVE(CONT_OPL, c0, it0);
c1.erase_after(it1);
}
#else
if (!c1.empty() ){
index = index % c1.size();
for(int i = 0; i < index; i++) {
assert( it1 != c1.end());
assert( !M_CALL_IT_END_P(CONT_OPL, it0));
M_CALL_IT_NEXT(CONT_OPL, it0);
it1++;
}
M_CALL_IT_REMOVE(CONT_OPL, c0, it0);
c1.erase(IT(it1));
}
#endif
break;
#endif
#if M_TEST_METHOD_P(REVERSE, CONT_OPL)
case 20:
M_CALL_REVERSE(CONT_OPL, c0);
c1.reverse();
break;
#endif
#if M_TEST_METHOD_P(SPLICE_BACK, CONT_OPL)
case 21:
M_CALL_REVERSE(CONT_OPL, c0);
c1.reverse();
break;
#endif
#ifdef HAVE_PUSH_FRONT
case 22:
TYPE_SET_INT(b0, index);
CLASS_SET_INT(b1, index);
M_C(CONT_NAME, _push_front)(c0, b0);
c1.push_front(b1);
break;
case 23:
index = index % 1000;
for(int i = 0; i < index; i++) {
TYPE_SET_INT(b0, i);
CLASS_SET_INT(b1, i);
M_C(CONT_NAME, _push_front)(c0, b0);
c1.push_front(b1);
}
break;
#endif
#ifdef HAVE_POP_FRONT
case 24:
if (!c1.empty()) {
M_C(CONT_NAME, _pop_front)(&b0, c0);
b1 = c1.front();
c1.pop_front();
}
break;
#endif
// SPLICE_BACK
// SPLICE_AT
// Needs SPLICE ?
default:
// Nothing to do
break;
}
CMP_BASE(b0, b1);
CMP_CONT(c0, c1);
assert(p0 == p1);
assert(s0 == s1);
}
int main(int argc, const char *argv[])
{
int loop = argc >= 2 ? atoi(argv[1]) : DEFAULT_NUMBER;
BASE_TYPE b0;
BASE_CLASS b1;
CONT_TYPE c0;
CONT_CLASS c1;
M_CALL_INIT(CONT_OPL, c0);
M_CALL_INIT(M_GET_OPLIST CONT_OPL, b0);
TYPE_SET_INT(b0, 0);
CLASS_SET_INT(b1, 0);
for(int i = 0; i < loop; i++) {
int t = rand();
int s = rand();
test(t, s, b0, b1, c0, c1);
}
M_CALL_CLEAR(M_GET_OPLIST CONT_OPL, b0);
M_CALL_CLEAR(CONT_OPL, c0);
return 0;
}
+73
View File
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2021, 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 <forward_list>
#include "m-list.h"
LIST_DEF(list_int, int)
// Transform an integer 'i' into a M*LIB base item 'a'
#define TYPE_SET_INT(a, i) (a) = (i)
// Container OPLIST
#define CONT_OPL LIST_OPLIST(list_int, M_OPL_int())
// C++ Base class of the item in the container
#define BASE_CLASS int
// Transform an integer 'i' into a C++ base item 'a'
#define CLASS_SET_INT(a, i) (a) = (i)
// C++ Container class
#define CONT_CLASS std::forward_list<int>
// Compare the M*LIB container a to the C++ container b
#define CMP_CONT(a, b) cmp_cont(a, b)
// Compate the M*LIB base object to the C++ base object
#define CMP_BASE(a, b) assert( (a) == (b) )
void cmp_cont(list_int_t a, std::forward_list<int> b)
{
list_int_it_t ita;
list_int_it(ita, a);
auto itb = b.begin();
while (itb != b.end()) {
assert(!list_int_end_p(ita));
const int *b0 = list_int_cref(ita);
int &b1 = *itb;
CMP_BASE(*b0, b1);
itb++;
list_int_next(ita);
}
assert(list_int_end_p(ita));
}
#define HAVE_INSERT_AFTER
#define HAVE_ERASE_AFTER
#define DEFAULT_NUMBER 100000
// C++ forward_list pushs in front instead of in back
#define push_back push_front
#define pop_back pop_front
#define back front
#include "check-generic.hpp"