635 lines
16 KiB
C++
635 lines
16 KiB
C++
/*
|
|
* Copyright (c) 2021-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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <time.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
|
|
|
|
// Type used for M*LIB container. Default is the same as C++
|
|
#ifndef BASE_TYPE
|
|
# define BASE_TYPE BASE_CLASS
|
|
#endif
|
|
|
|
// Compare the M*LIB base object to the C++ base object
|
|
#ifndef CMP_BASE
|
|
# define CMP_BASE(a, b) assert( (a) == (b) )
|
|
#endif
|
|
|
|
/* Get the affectation if needed to transform an integer into C++ class (resp. M*LIB type) */
|
|
#ifndef CLASS_SET_INT
|
|
# define CLASS_SET_INT(a, i) (a) = (i)
|
|
#endif
|
|
#ifndef TYPE_SET_INT
|
|
# define TYPE_SET_INT(a, i) (a) = (i)
|
|
#endif
|
|
|
|
/* Get the affectation if needed to transform a C++ iterator (resp. M*LIB) to an int */
|
|
#ifndef CLASS_IT_TO_INT
|
|
# define CLASS_IT_TO_INT(it) *(it)
|
|
#endif
|
|
#ifndef TYPE_IT_TO_INT
|
|
# define TYPE_IT_TO_INT(it) *(it)
|
|
#endif
|
|
|
|
/* Global properties of the container */
|
|
// Use find to perform GET_KEY for C++
|
|
//#define HAVE_GET_KEY_THROUGH_FIND
|
|
// Container are nor ordered
|
|
//#define DONT_HAVE_SEQUENCE_IT
|
|
// associative array container
|
|
//#define HAVE_SET_KEY
|
|
// Container is in reverse
|
|
//#define HAVE_REVERSE_IT
|
|
// Have PUSH_FRONT operator
|
|
//#define HAVE_PUSH_FRONT
|
|
// Have POP_FRONT operator
|
|
//#define HAVE_POP_FRONT
|
|
|
|
/*********************************************************************************/
|
|
|
|
// Define the container name, extracting it from its oplist
|
|
#define CONT_NAME_(CONT_OPL) M_GET_NAME CONT_OPL
|
|
#define CONT_NAME CONT_NAME_(CONT_OPL)
|
|
|
|
// Define the maximum number of tests
|
|
#define MAX_TEST 28
|
|
|
|
#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
|
|
|
|
#ifdef HAVE_POP_BACK
|
|
case 2:
|
|
if (!c1.empty()) {
|
|
M_C(CONT_NAME, _pop_back)(&b0, c0);
|
|
b1 = c1.back();
|
|
c1.pop_back();
|
|
}
|
|
break;
|
|
#elif 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(RESET, CONT_OPL)
|
|
case 5:
|
|
M_CALL_RESET(CONT_OPL, c0);
|
|
c1.clear();
|
|
break;
|
|
#endif
|
|
|
|
#if M_TEST_METHOD_P(GET_KEY, CONT_OPL)
|
|
case 6:
|
|
if (!c1.empty()) {
|
|
#ifndef HAVE_GET_KEY_THROUGH_FIND
|
|
// GET_KEY takes an index which shall be within the range of the container
|
|
index = index % c1.size();
|
|
M_CALL_SET(M_GET_OPLIST CONT_OPL, b0, *M_CALL_GET_KEY(CONT_OPL, c0, index));
|
|
b1 = c1[index];
|
|
#else
|
|
// GET_KEY takes a key
|
|
index = index % (DEFAULT_NUMBER/4);
|
|
BASE_TYPE *p = M_CALL_GET_KEY(CONT_OPL, c0, index);
|
|
if (p!= NULL) {
|
|
// Key found
|
|
M_CALL_SET(M_GET_OPLIST CONT_OPL, b0, *p);
|
|
auto i = c1.find(index);
|
|
assert(i != c1.end());
|
|
b1 = CLASS_IT_TO_INT(i);
|
|
} else {
|
|
// Key not found
|
|
auto i = c1.find(index);
|
|
assert(i == c1.end());
|
|
TYPE_SET_INT(b0, 0);
|
|
CLASS_SET_INT(b1, 0);
|
|
}
|
|
#endif
|
|
} else {
|
|
assert( M_CALL_EMPTY_P(CONT_OPL, c0) == true);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if M_TEST_METHOD_P(SET_KEY, CONT_OPL)
|
|
case 7:
|
|
TYPE_SET_INT(b0, index);
|
|
CLASS_SET_INT(b1, index);
|
|
#ifndef HAVE_SET_KEY
|
|
if (!c1.empty())
|
|
{
|
|
index = index % c1.size();
|
|
M_CALL_SET_KEY(CONT_OPL, c0, index, b0);
|
|
c1[index] = b1;
|
|
}
|
|
#else
|
|
index = index % (DEFAULT_NUMBER/4);
|
|
M_CALL_SET_KEY(CONT_OPL, c0, index, b0);
|
|
c1[index] = b1;
|
|
#endif
|
|
break;
|
|
|
|
case 21:
|
|
{
|
|
unsigned n = index % 1000;
|
|
unsigned offset = (index / 1027) % 1000;
|
|
#ifndef HAVE_SET_KEY
|
|
// If it is a sequence container, check it it fits, otherwise resize
|
|
// without resize which may not be available, but push is assumed to be.
|
|
if ((size_t) n+offset > c1.size() ) {
|
|
TYPE_SET_INT(b0, 0);
|
|
CLASS_SET_INT(b1, 0);
|
|
for(unsigned i = c1.size() ; i < (size_t) n+offset; i++) {
|
|
M_CALL_PUSH(CONT_OPL, c0, b0);
|
|
c1.push_back(b1);
|
|
}
|
|
assert(c1.size() == (size_t) n+offset);
|
|
}
|
|
#endif
|
|
for(unsigned i = 0; i < n; i++) {
|
|
TYPE_SET_INT(b0, 3*i);
|
|
CLASS_SET_INT(b1, 3*i);
|
|
M_CALL_SET_KEY(CONT_OPL, c0, offset + i, b0);
|
|
c1[offset + i] = 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);
|
|
#ifndef HAVE_GET_KEY_THROUGH_FIND
|
|
c1.erase(c1.begin() + index);
|
|
p1 = true;
|
|
#else
|
|
auto i = c1.find(index);
|
|
if (i != c1.end()) {
|
|
c1.erase(i);
|
|
p1 = true;
|
|
} else {
|
|
p1 = false;
|
|
}
|
|
#endif
|
|
}
|
|
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(SAFE_GET_KEY, CONT_OPL)
|
|
case 14:
|
|
index = (1 + (c1.size() < 1000000)) * (index % ( c1.size() + 1) );
|
|
M_CALL_SET(M_GET_OPLIST CONT_OPL, b0, *M_CALL_SAFE_GET_KEY(CONT_OPL, c0, index));
|
|
#ifndef HAVE_GET_KEY_THROUGH_FIND
|
|
if ((size_t) index >= c1.size() ) {
|
|
c1.resize(index+1);
|
|
}
|
|
b1 = c1[index];
|
|
#else
|
|
{
|
|
auto i = c1.find(index);
|
|
if (i == c1.end()) {
|
|
#ifdef HAVE_SET_KEY
|
|
c1[index] = 0;
|
|
#else
|
|
c1.insert(index);
|
|
#endif
|
|
i = c1.find(index);
|
|
assert(i != c1.end());
|
|
}
|
|
b1 = CLASS_IT_TO_INT(i);
|
|
}
|
|
#endif
|
|
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 (!M_CALL_IT_END_P(CONT_OPL, it0)) {
|
|
#ifdef HAVE_KEY_PTR
|
|
// Containers are key / value (through ptr)
|
|
index = *M_CALL_IT_CREF(CONT_OPL, it0)->key_ptr;
|
|
M_CALL_SET(M_GET_OPLIST CONT_OPL, b0, *M_CALL_IT_CREF(CONT_OPL, it0)->value_ptr);
|
|
#elif defined(HAVE_SET_KEY)
|
|
// Containers are key / value
|
|
index = M_CALL_IT_CREF(CONT_OPL, it0)->key;
|
|
M_CALL_SET(M_GET_OPLIST CONT_OPL, b0, M_CALL_IT_CREF(CONT_OPL, it0)->value);
|
|
#else
|
|
// Containers are single key
|
|
M_CALL_SET(M_GET_OPLIST CONT_OPL, b0, *M_CALL_IT_CREF(CONT_OPL, it0));
|
|
index = b0;
|
|
#endif
|
|
#ifndef DONT_HAVE_SEQUENCE_IT
|
|
// Container are ordered
|
|
assert(it1 != c1.end());
|
|
b1 = CLASS_IT_TO_INT(it1);
|
|
it1++;
|
|
#else
|
|
// Containers are not ordered.
|
|
it1 = c1.find(index);
|
|
assert(it1 != c1.end());
|
|
b1 = CLASS_IT_TO_INT(it1);
|
|
#endif
|
|
CMP_BASE(b0, b1);
|
|
M_CALL_IT_NEXT(CONT_OPL, it0);
|
|
}
|
|
#ifndef DONT_HAVE_SEQUENCE_IT
|
|
assert(it1 == c1.end());
|
|
#endif
|
|
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, TYPE_IT_TO_INT(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, TYPE_IT_TO_INT(M_CALL_IT_CREF(CONT_OPL, it0)));
|
|
b1 = CLASS_IT_TO_INT(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;
|
|
// 21 is above
|
|
#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
|
|
|
|
#ifdef HAVE_RESIZE
|
|
case 25:
|
|
index = (1 + (c1.size() < 1000000)) * (index % ( c1.size() + 1) );
|
|
M_C(CONT_NAME, _resize)(c0, index);
|
|
c1.resize(index);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef HAVE_RESERVE
|
|
case 26:
|
|
index = c1.size() + ( index % (c1.size() + 1) );
|
|
M_C(CONT_NAME, _reserve)(c0, index);
|
|
c1.reserve(index);
|
|
break;
|
|
|
|
case 27:
|
|
M_C(CONT_NAME, _reserve)(c0, 0);
|
|
c1.shrink_to_fit();
|
|
break;
|
|
#endif
|
|
|
|
// SPLICE_BACK
|
|
// SPLICE_AT
|
|
// Needs SPLICE ?
|
|
|
|
default:
|
|
M_STATIC_ASSERT( 28 == MAX_TEST, MLIB_INTERNAL_ERROR, "Constant MAX_TEST is no coherent with the effective number of tests");
|
|
// Nothing to do
|
|
break;
|
|
}
|
|
CMP_BASE(b0, b1);
|
|
CMP_CONT(c0, c1);
|
|
assert(p0 == p1);
|
|
assert(s0 == s1);
|
|
}
|
|
|
|
static void init_rand(void)
|
|
{
|
|
const char *seed = getenv("CHECK_RANDOMIZE");
|
|
if (seed == NULL) {
|
|
// No check randomize requested.
|
|
// Initialize with a common value
|
|
srand(0x45856525U);
|
|
} else {
|
|
unsigned int seed_value = strtoul (seed, NULL, 10);
|
|
if (seed_value > 1) {
|
|
// Seed has been set by the user. Use it.
|
|
printf("Using seed = %u\n", seed_value);
|
|
} else {
|
|
time_t tv;
|
|
time (&tv);
|
|
seed_value = tv;
|
|
printf("Generating seed = %u\n", seed_value);
|
|
}
|
|
srand(seed_value);
|
|
}
|
|
}
|
|
|
|
static int read_int(FILE *f)
|
|
{
|
|
int c = 0;
|
|
while (true) {
|
|
int n = fscanf(f, " %d", &c);
|
|
if (n == 1) {
|
|
return c;
|
|
}
|
|
if (feof(f)) {
|
|
return 0;
|
|
}
|
|
// Skip next character
|
|
c = fgetc(f);
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
init_rand();
|
|
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);
|
|
|
|
if (loop < 0) {
|
|
/* test input is provided from stdin */
|
|
while (!feof(stdin)) {
|
|
int t = read_int(stdin);
|
|
int s = read_int(stdin);
|
|
test(t, s, b0, b1, c0, c1);
|
|
}
|
|
} else {
|
|
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;
|
|
}
|