/* testlib.h: TEST LIBRARY INTERFACE * * $Id$ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. * * .purpose: A library of functions that may be of use to unit tests. */ #ifndef testlib_h #define testlib_h #include "mps.h" #include "misc.h" /* for STR */ #include "mpstd.h" /* Suppress Visual C warnings at /W4 (warning level 4) */ /* This is also done in config.h. */ #ifdef MPS_BUILD_MV /* "constant conditional" (provoked by MPS_END) */ #pragma warning(disable: 4127) #endif /* MPS_BUILD_MV */ /* Suppress Pelles C warnings at /W2 (warning level 2) */ /* This is also done in config.h. */ #ifdef MPS_BUILD_PC /* "Unreachable code" (provoked by AVER, if condition is constantly true). */ #pragma warn(disable: 2154) #endif /* MPS_BUILD_PC */ /* Function attributes */ /* These are also defined in config.h */ #if defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL) /* GCC: * Clang: */ #define ATTRIBUTE_FORMAT(ARGLIST) __attribute__((__format__ ARGLIST)) /* GCC: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html */ #define ATTRIBUTE_NOINLINE __attribute__((__noinline__)) #else #define ATTRIBUTE_FORMAT(ARGLIST) #define ATTRIBUTE_NOINLINE #endif /* alloca -- memory allocator * * Windows calls this function _alloca() instead of alloca(). * */ #if defined(MPS_OS_W3) #define alloca _alloca #endif /* setenv -- set environment variable * * Windows lacks setenv(), but _putenv_s() has similar functionality. * * * This macro version may evaluate the name argument twice. */ #if defined(MPS_OS_W3) #define setenv(name, value, overwrite) \ (((overwrite) || !getenv(name)) ? _putenv_s(name, value) : 0) #endif /* ulongest_t -- longest unsigned integer type * * Define a longest unsigned integer type for testing, scanning, and * printing. We'd like to use C99's uintmax_t and PRIuMAX here, but * the MPS is in C89 and C99 isn't supported by Microsoft. * * We avoid using the types defined in mpstd.h because we want the * tests to root out any incompatible assumptions by breaking. */ #if defined(MPS_ARCH_I6) #define PRIwWORD "16" #elif defined(MPS_ARCH_I3) #define PRIwWORD "8" #else #error "How many beans make five?" #endif #if defined(MPS_OS_W3) && defined(MPS_ARCH_I6) #define PRIuLONGEST "llu" #define SCNuLONGEST "llu" #define SCNXLONGEST "llX" #define PRIXLONGEST "llX" typedef unsigned long long ulongest_t; typedef long long longest_t; #define MPS_WORD_CONST(n) (n##ull) #else #define PRIuLONGEST "lu" #define SCNuLONGEST "lu" #define SCNXLONGEST "lX" #define PRIXLONGEST "lX" typedef unsigned long ulongest_t; typedef long longest_t; #define MPS_WORD_CONST(n) (n##ul) #endif #define PRIXPTR "0"PRIwWORD PRIXLONGEST /* testlib_unused -- declares that a variable is unused * * It should be used to prevent compiler warnings about unused * variables. Care should be exercised; the fact that a variable * is unused may need justification. */ #define testlib_unused(v) ((void)(v)) /* max -- return larger value * * Note: evaluates its arguments twice. */ #undef max #define max(a, b) (((a) > (b)) ? (a) : (b)) /* alignUp -- align word to alignment * * Note: evaluates argument a twice. */ #define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) /* die -- succeed or die * * If the first argument is not ResOK then prints the second * argument on stderr and exits the program. Otherwise does nothing. * * Typical use: * die(mps_ap_create(&ap, pool, mps_rank_exact()), "APCreate"); */ extern void die(mps_res_t res, const char *s); /* die_expect -- get expected result or die * * If the first argument is not the same as the second argument, * prints the third argument on stderr and exits the program. * Otherwise does nothing. * * Typical use: * die_expect(res, MPS_RES_COMMIT_LIMIT, "Commit limit allocation"); */ extern void die_expect(mps_res_t res, mps_res_t expected, const char *s); /* cdie -- succeed or die * * If the first argument is not true (non-zero) then prints the second * argument on stderr and exits the program. Otherwise does nothing. * * Typical use: * cdie(foo != NULL, "No foo"); */ extern void cdie(int res, const char *s); /* assert_die -- always die on assertion * * The MPS assertion handler may not stop in the HOT variety, * preventing tests from detecting defects. This one does. */ void assert_die(const char *file, unsigned line, const char *condition); /* error, verror -- die with message */ ATTRIBUTE_FORMAT((printf, 1, 2)) extern void error(const char *format, ...); ATTRIBUTE_FORMAT((printf, 1, 0)) extern void verror(const char *format, va_list args); /* Insist -- like assert, but even in release varieties */ #define Insist(cond) insist1(cond, #cond) #define insist1(cond, condstring) \ if(cond) \ NOOP; \ else \ cdie(cond, condstring "\n" __FILE__ "\n" STR(__LINE__)) /* fail -- like assert, but (notionally) returns a value, so usable in an expression */ extern int fail(void); /* rnd -- random number generator * * rnd() generates a sequence of integers in the range [1, 2^31-2]. */ extern unsigned long rnd(void); typedef unsigned long rnd_state_t; extern rnd_state_t rnd_state(void); extern void rnd_state_set(rnd_state_t state_v3); extern void rnd_state_set_v2(rnd_state_t seed0_v2); /* legacy */ extern rnd_state_t rnd_seed(void); /* rnd_verify() -- checks behaviour of rnd() */ extern void rnd_verify(int depth); /* rnd_addr -- random number generator * * rnd_addr() generates a sequence of addresses all over the address space. */ extern mps_addr_t rnd_addr(void); /* rnd_double -- uniformly distributed random number between 0.0 and 1.0 */ extern double rnd_double(void); /* rnd_grain -- return a random grain size that's not too big for the * given arena size */ extern size_t rnd_grain(size_t arena_size); /* randomize -- randomize the generator, or initialize to replay * * randomize(argc, argv) randomizes the rnd generator (using time(3)) * and prints out the randomization seed, or takes a seed (as a command- * line argument) and initializes the generator to the same state. */ extern void randomize(int argc, char *argv[]); /* testlib_init -- install assertion handler and seed RNG */ extern void testlib_init(int argc, char *argv[]); #endif /* testlib_h */ /* C. COPYRIGHT AND LICENSE * * Copyright (C) 2001-2014 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. 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. * * 3. Redistributions in any form must be accompanied by information on how * to obtain complete source code for this software and any accompanying * software that uses this software. The source code must either be * included in the distribution or be available for no more than the cost * of distribution plus a nominal fee, and must be freely redistributable * under reasonable conditions. For an executable file, complete source * code means the source code for all modules it contains. It does not * include source code for modules or files that typically accompany the * major components of the operating system on which the executable file * runs. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS 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. */