Changeset 8219

Show
Ignore:
Timestamp:
17/11/11 12:18:01 (6 months ago)
Author:
westram
Message:
  • rewrote unit test code
    • uses expectations (inspired by hamcrest)
    • reasons for failures etc now explained AFTER the failure message
    • expectations can be gathered and nested into groups
      • allows to describe more complex overall behavior, whereas the details of the failure are listed in the explanation
Location:
branches/dev
Files:
6 modified

Legend:

Unmodified
Added
Removed
  • branches/dev/AISC_MKPTPS/Makefile

    r7453 r8219  
    3939mkptypes.o: $(ARBHOME)/INCLUDE/arbtools.h 
    4040mkptypes.o: $(ARBHOME)/INCLUDE/attributes.h 
     41mkptypes.o: $(ARBHOME)/INCLUDE/dupstr.h 
    4142mkptypes.o: $(ARBHOME)/INCLUDE/test_global.h 
    4243mkptypes.o: $(ARBHOME)/INCLUDE/test_unit.h 
  • branches/dev/CORE/Makefile

    r7773 r8219  
    122122arb_string.o: arb_string.h 
    123123arb_string.o: $(ARBHOME)/INCLUDE/arb_assert.h 
     124arb_string.o: $(ARBHOME)/INCLUDE/arbtools.h 
    124125arb_string.o: $(ARBHOME)/INCLUDE/attributes.h 
    125126arb_string.o: $(ARBHOME)/INCLUDE/dupstr.h 
    126127arb_string.o: $(ARBHOME)/INCLUDE/test_global.h 
     128arb_string.o: $(ARBHOME)/INCLUDE/test_unit.h 
  • branches/dev/CORE/arb_string.cxx

    r7300 r8219  
    6969 
    7070 
    71  
    72  
     71// -------------------------------------------------------------------------------- 
     72 
     73 
     74#ifdef UNIT_TESTS 
     75 
     76#include <string> 
     77#include <climits> 
     78 
     79#ifndef TEST_UNIT_H 
     80#include <test_unit.h> 
     81#endif 
     82 
     83using namespace std; 
     84 
     85// ---------------------------------------------- 
     86//      some tests for unit-test-code itself 
     87 
     88#define TEST_ASSERT_HEAPCOPY_EQUAL(copy,expected) do {  \ 
     89        char *theCopy = (copy);                         \ 
     90        TEST_ASSERT_EQUAL(theCopy, expected);           \ 
     91        free(theCopy);                                  \ 
     92    } while(0) 
     93 
     94void TEST_arbtest_strf() { 
     95    // tests string formatter from test_unit.h 
     96    using namespace arb_test; 
     97    TEST_ASSERT_HEAPCOPY_EQUAL(StaticCode::strf("<%i>", 7), "<7>"); 
     98    TEST_ASSERT_HEAPCOPY_EQUAL(StaticCode::strf("<%0*i>", 3, 7), "<007>"); 
     99} 
     100 
     101void TEST_arbtest_readable() { 
     102    using namespace arb_test; 
     103 
     104    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy('x')), "'x'"); 
     105    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy(static_cast<unsigned char>('x'))), "'x'"); 
     106    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy(static_cast<signed char>('x'))), "'x'"); 
     107 
     108    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy(true)), "true"); 
     109    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy(false)), "false"); 
     110     
     111    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy(1)), "1"); 
     112    TEST_ASSERT_HEAPCOPY_EQUAL(val2hex(make_copy(2)), "0x2"); 
     113 
     114    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy(3L)), "3"); 
     115    TEST_ASSERT_HEAPCOPY_EQUAL(val2hex(make_copy(4L)), "0x4"); 
     116 
     117    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy(5U)), "5"); 
     118    TEST_ASSERT_HEAPCOPY_EQUAL(val2hex(make_copy(6U)), "0x6"); 
     119     
     120    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy("some\ntext\twhich\"special\\chars")), "\"some\\ntext\\twhich\\\"special\\\\chars\""); 
     121    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy("a\1\2\x1a\x7e\x7f\x80\xfe\xff")), "\"a\\1\\2\\x1a~\\x7f\\x80\\xfe\\xff\""); 
     122    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy((const char *)NULL)), "(null)"); 
     123    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy((const unsigned char *)NULL)), "(null)"); 
     124    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy((const signed char *)NULL)), "(null)"); 
     125 
     126    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy(1.7)), "1.700000"); 
     127    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy(177.0e20)),  "17699999999999998951424.000000"); 
     128    TEST_ASSERT_HEAPCOPY_EQUAL(val2readable(make_copy(177.0e20F)), "17699999967695435988992.000000"); 
     129} 
     130 
     131void TEST_arbtest_copyable() { 
     132    using namespace arb_test; 
     133 
     134    int         i = 7; 
     135    const char *s = "servas"; 
     136 
     137    TEST_ASSERT(make_copy(i) == make_copy(7)); 
     138 
     139    TEST_ASSERT(strcmp(make_copy(s), make_copy("servas")) == 0); 
     140} 
     141 
     142#define TEST_DESCRIPTIONS(d, tt, tf, ft, ff) do {               \ 
     143        TEST_ASSERT_EQUAL((d).make(true, true), (tt));   \ 
     144        TEST_ASSERT_EQUAL((d).make(true, false), (tf));  \ 
     145        TEST_ASSERT_EQUAL((d).make(false, true), (ft));  \ 
     146        TEST_ASSERT_EQUAL((d).make(false, false), (ff)); \ 
     147    } while(0) 
     148 
     149#define TEST_SIMPLE_DESCRIPTIONS(d, ae, nae) TEST_DESCRIPTIONS(d, ae, nae, nae, ae) 
     150 
     151void TEST_arbtest_predicate_description() { 
     152    TEST_SIMPLE_DESCRIPTIONS(predicate_description("similar"), "is similar", "isnt similar"); 
     153    TEST_SIMPLE_DESCRIPTIONS(predicate_description("repairs"), "repairs", "doesnt repair"); 
     154 
     155    TEST_DESCRIPTIONS(predicate_description("equals", "differs"), 
     156                      "equals", "doesnt equal", 
     157                      "doesnt differ", "differs"); 
     158 
     159    TEST_DESCRIPTIONS(predicate_description("less_than", "more_than"), 
     160                      "is less_than", "isnt less_than", 
     161                      "isnt more_than", "is more_than"); 
     162} 
     163 
     164void TEST_arbtest_expectations() { 
     165    // used to TDD expectations 
     166    using namespace arb_test; 
     167 
     168    string apple       = "Apfel"; 
     169    string pear        = "Birne"; 
     170    string boskop      = apple; 
     171    string pomegranate = "Granatapfel"; 
     172 
     173    TEST_EXPECT(that(apple).equals("Apfel")); 
     174     
     175    TEST_EXPECT(that(apple).differs(pear)); 
     176    TEST_EXPECT(that(apple).equals(boskop)); 
     177    TEST_EXPECT(wrong(that(pomegranate).equals(apple))); 
     178 
     179    match_expectation ff1 = that(1.0).equals(2-1); 
     180    match_expectation ff2 = that(boskop).equals(apple); 
     181    match_expectation ff3 = that(apple).equals(apple); 
     182 
     183    match_expectation nf1 = that(apple).equals(pear); 
     184    match_expectation nf2 = that(pomegranate).equals(apple); 
     185    match_expectation nf3 = that(apple).differs(boskop); 
     186 
     187    match_expectation a1 = all().of(ff1); 
     188    match_expectation a2 = all().of(ff1, ff2); 
     189    match_expectation a3 = all().of(ff1, ff2, ff3); 
     190 
     191    TEST_EXPECT(a1); 
     192    TEST_EXPECT(a2); 
     193    TEST_EXPECT(a3); 
     194 
     195    match_expectation n1 = none().of(ff1); 
     196    match_expectation n2 = none().of(ff1, ff2); 
     197    match_expectation n3 = none().of(ff1, ff2, ff3); 
     198 
     199    TEST_EXPECT(wrong(none().of(that(boskop).equals(apple)))); 
     200    TEST_EXPECT(wrong(n1)); 
     201    TEST_EXPECT(wrong(n2)); 
     202    TEST_EXPECT(wrong(n3)); 
     203 
     204    TEST_EXPECT(atleast(1).of(a1)); 
     205    TEST_EXPECT(atleast(1).of(a1, n1)); 
     206    TEST_EXPECT(atleast(1).of(n2, a1, n1)); 
     207 
     208    TEST_EXPECT(wrong(atleast(2).of(a1, n1, n2))); 
     209    TEST_EXPECT(wrong(atleast(2).of(a1, n1))); 
     210    TEST_EXPECT(wrong(atleast(2).of(a1))); // impossible 
     211 
     212    TEST_EXPECT(atmost(2).of(a1)); 
     213    TEST_EXPECT(atmost(2).of(a1, a2)); 
     214    TEST_EXPECT(atmost(2).of(a1, a2, n1)); 
     215    TEST_EXPECT(atmost(2).of(a1, n1, n2)); 
     216    TEST_EXPECT(atmost(2).of(n1, n2)); 
     217    TEST_EXPECT(wrong(atmost(2).of(a1, a2, a3))); 
     218 
     219    TEST_EXPECT(exacly(1).of(ff1, nf1, nf2)); 
     220    TEST_EXPECT(wrong(exacly(1).of(nf1, nf2))); 
     221    TEST_EXPECT(wrong(exacly(1).of(nf1, nf2, nf3))); 
     222    TEST_EXPECT(wrong(exacly(1).of(ff1, ff2, nf2))); 
     223    TEST_EXPECT(wrong(exacly(1).of(ff1, ff2, ff3))); 
     224 
     225} 
     226 
     227void TEST_replace_old_TEST_ASSERTS_by_expectations() { 
     228    // test various string-types are matchable (w/o casts) 
     229    { 
     230        const char *car_ccp = "Alfa"; 
     231        char       *car_cp  = strdup("Alfa"); 
     232        string      car_str("Alfa"); 
     233 
     234        TEST_ASSERT_EQUAL(car_ccp, "Alfa"); 
     235        TEST_ASSERT_EQUAL(car_cp, "Alfa"); 
     236        TEST_ASSERT_EQUAL(car_str, "Alfa"); 
     237 
     238        TEST_ASSERT_EQUAL("Alfa", car_ccp); 
     239        TEST_ASSERT_EQUAL("Alfa", car_cp); 
     240        TEST_ASSERT_EQUAL("Alfa", car_str); 
     241 
     242        TEST_ASSERT_EQUAL(car_cp, car_ccp); 
     243        TEST_ASSERT_EQUAL(car_cp, car_str); 
     244        TEST_ASSERT_EQUAL(car_ccp, car_cp); 
     245        TEST_ASSERT_EQUAL(car_ccp, car_str); 
     246        TEST_ASSERT_EQUAL(car_str, car_cp); 
     247        TEST_ASSERT_EQUAL(car_str, car_ccp); 
     248 
     249        char *null = NULL; 
     250        TEST_ASSERT_NULL(NULL); 
     251        TEST_ASSERT_NULL(null); 
     252 
     253        TEST_ASSERT_CONTAINS(car_ccp, "lf"); 
     254        TEST_ASSERT_CONTAINS(car_cp, "fa"); 
     255        TEST_ASSERT_CONTAINS(car_str, "Al"); 
     256 
     257        free(car_cp); 
     258    } 
     259 
     260    // test various numeric types are matchable 
     261 
     262    { 
     263        short unsigned su = 7; 
     264        short          s  = -su; 
     265 
     266        unsigned iu = su; 
     267        int      i  = -iu; 
     268 
     269        long unsigned lu = (long unsigned)INT_MAX+3; 
     270        long          l  = -lu; 
     271 
     272        float  f = s; 
     273        double d = i; 
     274 
     275        TEST_ASSERT_EQUAL(s, -7); 
     276        TEST_ASSERT_EQUAL(i, -7); 
     277 
     278        TEST_ASSERT_EQUAL(su, 7);  TEST_ASSERT_EQUAL(iu, 7); 
     279        TEST_ASSERT_EQUAL(su, 7U); TEST_ASSERT_EQUAL(iu, 7U); 
     280        TEST_ASSERT_EQUAL(su, 7L); TEST_ASSERT_EQUAL(iu, 7L); 
     281 
     282        TEST_ASSERT_EQUAL(s, -su); TEST_ASSERT_EQUAL(s, -iu); 
     283        TEST_ASSERT_EQUAL(i, -iu); TEST_ASSERT_EQUAL(i, -su); 
     284        TEST_ASSERT_EQUAL(l, -lu); 
     285 
     286        TEST_ASSERT_EQUAL(f, d); 
     287        TEST_ASSERT_EQUAL(d, f); 
     288    } 
     289 
     290    TEST_ASSERT_ZERO(7-7); 
     291} 
     292 
     293// --- simulate user_type (which may be defined anywhere) --- 
     294class user_type { 
     295    int x, y; 
     296public: 
     297    user_type(int X, int Y) : x(X), y(Y) {} 
     298 
     299    int get_x() const { return x; } 
     300    int get_y() const { return y; } 
     301 
     302    user_type flipped() const { return user_type(y,x); } 
     303 
     304    int quadrant() const { 
     305        if (x == 0 || y == 0) return 0; // on axis 
     306        if (y>0) return x<0 ? 2 : 1; 
     307        return x<0 ? 3 : 4; 
     308    } 
     309}; 
     310// --- end of user_type --- 
     311 
     312// helpers needed for tests: 
     313inline bool operator == (const user_type& u1, const user_type& u2) { return u1.get_x() == u2.get_x() && u1.get_y() == u2.get_y(); } 
     314inline char *val2readable(const user_type& u) { return arb_test::StaticCode::strf("user_type(%i,%i)", u.get_x(), u.get_y()); } 
     315inline bool in_same_quadrant(const user_type& u1, const user_type& u2) { return u1.quadrant() == u2.quadrant(); } 
     316 
     317void TEST_user_type_with_expectations() { 
     318    user_type ut1(3, 4); 
     319    user_type ut12(4, 4); 
     320    user_type ut2(-4, 4); 
     321    user_type ut3(-4, -8); 
     322    user_type ut4(4, -8); 
     323 
     324    TEST_EXPECT(that(ut1).differs(ut12)); 
     325    TEST_EXPECT(that(ut12).equals(ut12.flipped())); 
     326    TEST_EXPECT(that(ut1).differs(ut1.flipped())); 
     327 
     328    TEST_EXPECT(that(ut1).is(in_same_quadrant, ut12)); 
     329    TEST_EXPECT(none().of(that(ut1).is(in_same_quadrant, ut2), 
     330                          that(ut2).is(in_same_quadrant, ut3), 
     331                          that(ut3).is(in_same_quadrant, ut4))); 
     332} 
     333 
     334void TEST_similarity() { 
     335    double d1      = 0.7531; 
     336    double epsilon = 0.00001; 
     337    double d2      = d1-epsilon*0.6; 
     338    double d3      = d1+epsilon*0.6; 
     339 
     340    TEST_EXPECT(that(d1).is(epsilon_similar(epsilon), d2)); 
     341    TEST_EXPECT(that(d1).is(epsilon_similar(epsilon), d3)); 
     342    TEST_EXPECT(that(d2).is_not(epsilon_similar(epsilon), d3)); 
     343 
     344    TEST_ASSERT_SIMILAR(d1, d2, epsilon); 
     345    TEST_ASSERT_SIMILAR(d1, d3, epsilon); 
     346} 
     347 
     348void TEST_less_equal() { 
     349    int x = 7; 
     350    int y = 8; 
     351    int z = 9; 
     352 
     353    // less/more etc 
     354 
     355    TEST_EXPECT(that(x).less_than(y)); 
     356    TEST_EXPECT(that(x).less_or_equal(y)); 
     357    TEST_EXPECT(that(x).less_or_equal(x)); 
     358     
     359    TEST_EXPECT(that(y).more_than(x)); 
     360    TEST_EXPECT(that(y).more_or_equal(x)); 
     361    TEST_EXPECT(that(y).more_or_equal(y)); 
     362 
     363    TEST_ASSERT_LOWER_EQUAL(x, y); 
     364    TEST_ASSERT_LOWER_EQUAL(x, x); 
     365    TEST_ASSERT_LOWER(x, y); 
     366    TEST_ASSERT_IN_RANGE(y, x, z); 
     367} 
     368 
     369#endif // UNIT_TESTS 
     370 
     371// -------------------------------------------------------------------------------- 
     372 
     373 
  • branches/dev/SL/PRONUC/Makefile

    r7419 r8219  
    7979iupac.o: $(ARBHOME)/INCLUDE/arb_core.h 
    8080iupac.o: $(ARBHOME)/INCLUDE/arbdb_base.h 
     81iupac.o: $(ARBHOME)/INCLUDE/arbtools.h 
    8182iupac.o: $(ARBHOME)/INCLUDE/dupstr.h 
    8283iupac.o: $(ARBHOME)/INCLUDE/test_global.h 
  • branches/dev/UNIT_TESTER/TestEnvironment.cxx

    r8006 r8219  
    162162        if (!fp) { 
    163163            GB_ERROR error = GB_IO_error("creating flag", flagfile); 
    164             StaticCode::errorf(__FILE__, __LINE__, "%s\n", error); 
     164            HERE.errorf(true, "%s\n", error); 
    165165        } 
    166166        fclose(fp); 
     
    176176        if (res != 0) { 
    177177            GB_ERROR error = GB_IO_error("unlinking", flagfile); 
    178             StaticCode::errorf(__FILE__, __LINE__, "%s\n", error); 
     178            HERE.errorf(true, "%s\n", error); 
    179179        } 
    180180        env_assert(!flagFileExists()); 
  • branches/dev/UNIT_TESTER/test_unit.h

    r8006 r8219  
    1616#include <arb_assert.h> 
    1717#endif 
     18#ifndef ARBTOOLS_H 
     19#include <arbtools.h> 
     20#endif 
    1821#ifndef _GLIBCXX_CSTDARG 
    1922#include <cstdarg> 
     
    2528#include <errno.h> 
    2629#endif 
     30#ifndef DUPSTR_H 
     31#include <dupstr.h> 
     32#endif 
     33 
     34#if defined(_GLIBCXX_STRING) 
     35#define TESTS_KNOW_STRING 
     36#endif 
     37 
    2738 
    2839#define ENABLE_CRASH_TESTS // comment out this line to get rid of provoked SEGVs (e.g. while debugging test-code) 
    29 // #define TRACE_IS_EQUAL // print calls to numerical is_equal() 
    3040 
    3141/* Note: 
     
    3646 * test is known to fail, but cannot be fixed atm for some reason 
    3747 * 
     48 * Recommended test-assertion is TEST_EXPECT(that(..).xxx()) 
     49 * see examples in test-unit-tests in ../CORE/arb_string.cxx@UNIT_TESTS 
    3850 */ 
    3951 
     
    4254namespace arb_test { 
    4355 
    44     class StaticCode { 
    45         static void vcompiler_msg(const char *filename, int lineno, const char *message_type, const char *format, va_list parg) __attribute__((format(__printf__, 4, 0))) { 
    46             fprintf(stderr, "%s:%i: ", filename, lineno); 
     56    // ------------- 
     57    //      str 
     58 
     59    class str { 
     60        char *s; 
     61    public: 
     62        str() : s(0) {} 
     63        str(const str& other) : s(nulldup(other.s)) {} 
     64        explicit str(char *S) : s(S) {} 
     65        str& operator = (const str& other) { 
     66            freedup(s, other.s); 
     67            return *this; 
     68        } 
     69        str& operator = (char *S) { 
     70            freeset(s, S); 
     71            return *this; 
     72        } 
     73        ~str() { free(s); } 
     74 
     75        bool exists() const { return s; } 
     76        void assign(char *S) { s = S; } 
     77        const char *value() const { return s; } 
     78    }; 
     79 
     80    // ----------------------- 
     81    //      location info 
     82 
     83#define WITHVALISTFROM(format,CODE)  do { va_list parg; va_start(parg, format); CODE; va_end(parg); } while(0) 
     84#define VPRINTFORMAT(format)         WITHVALISTFROM(format, vfprintf(stderr, format, parg)) 
     85#define VCOMPILERMSG(msgtype,format) WITHVALISTFROM(format, vcompiler_msg(msgtype, format, parg)) 
     86 
     87    class locinfo //! stores source code location 
     88    { 
     89        const char *file; 
     90        int         line; 
     91 
     92        __attribute__((format(__printf__, 2, 0))) void vcompiler_msg(const char *message_type, const char *format, va_list parg) const { 
     93            fprintf(stderr, "%s:%i: ", file, line); 
    4794            if (message_type) fprintf(stderr, "%s: ", message_type); 
    4895            vfprintf(stderr, format, parg); 
    4996        } 
    50  
    51 #define WITHVALISTFROM(format,CODE)             do { va_list parg; va_start(parg, format); CODE; va_end(parg); } while(0) 
    52 #define VPRINTFORMAT(format)                    WITHVALISTFROM(format, vfprintf(stderr, format, parg)) 
    53 #define VCOMPILERMSG(file,line,msgtype,format)  WITHVALISTFROM(format, vcompiler_msg(file, line, msgtype, format, parg)) 
    5497         
    5598    public: 
    56  
     99        locinfo() : file(0), line(0) {} 
     100        locinfo(const char *file_, int line_) : file(file_), line(line_) {} 
     101 
     102        bool exists() const { return file; } 
     103 
     104        const char *get_file() const { return file; } 
     105        int get_line() const { return line; } 
     106 
     107        __attribute__((format(printf, 2, 3))) void warningf(const char *format, ...) const { 
     108            GlobalTestData& global = test_data(); 
     109            if (global.show_warnings) { 
     110                FlushedOutput yes; 
     111                VCOMPILERMSG("Warning", format); 
     112                GlobalTestData::print_annotation(); 
     113                global.warnings++; 
     114            } 
     115        } 
     116 
     117        __attribute__((format(printf, 3, 4))) void errorf(bool fail, const char *format, ...) const { 
     118            { 
     119                FlushedOutput yes; 
     120                VCOMPILERMSG("Error", format); 
     121                GlobalTestData::print_annotation(); 
     122            } 
     123            if (fail) TRIGGER_ASSERTION(false); // fake an assertion failure 
     124        } 
     125        __attribute__((format(printf, 3, 4))) void ioerrorf(bool fail, const char *format, ...) const { 
     126            { 
     127                FlushedOutput yes; 
     128                VCOMPILERMSG("Error", format); 
     129                fprintf(stderr, " (errno=%i='%s')", errno, strerror(errno)); 
     130                GlobalTestData::print_annotation(); 
     131            } 
     132            if (fail) TRIGGER_ASSERTION(false); // fake an assertion failure 
     133        } 
     134    }; 
     135 
     136    // -------------------- 
     137    //      StaticCode 
     138 
     139    struct StaticCode { 
    57140        static void printf(const char *format, ...) __attribute__((format(printf, 1, 2))) { 
    58141            FlushedOutputNoLF yes; 
    59142            VPRINTFORMAT(format); 
    60143        } 
    61         static void warningf(const char *filename, int lineno, const char *format, ...) __attribute__((format(printf, 3, 4))) { 
    62             GlobalTestData& global = test_data(); 
    63             if (global.show_warnings) { 
    64                 FlushedOutput yes; 
    65                 VCOMPILERMSG(filename, lineno, "Warning", format); 
    66                 GlobalTestData::print_annotation(); 
    67                 global.warnings++; 
    68             } 
    69         } 
    70         static void errorf(const char *filename, int lineno, const char *format, ...) __attribute__((format(printf, 3, 4))) { 
    71             { 
    72                 FlushedOutput yes; 
    73                 VCOMPILERMSG(filename, lineno, "Error", format); 
    74                 GlobalTestData::print_annotation(); 
    75             } 
    76             TRIGGER_ASSERTION(false); // fake an assertion failure 
    77         } 
    78         static void ioerrorf(const char *filename, int lineno, const char *format, ...) __attribute__((format(printf, 3, 4))) { 
    79             { 
    80                 FlushedOutput yes; 
    81                 VCOMPILERMSG(filename, lineno, "Error", format); 
    82                 fprintf(stderr, " (errno=%i='%s')", errno, strerror(errno)); 
    83                 GlobalTestData::print_annotation(); 
    84             } 
    85             TRIGGER_ASSERTION(false); // fake an assertion failure 
    86         } 
    87144#undef VPRINTFORMAT 
    88145#undef VCOMPILERMSG 
    89146#undef WITHVALISTFROM 
    90147 
    91         static void print_readable_string(const char *s, FILE *out) { 
     148        static char *readable_string(const char *s) { 
    92149            // quote like C does! 
    93150            if (s) { 
    94                 fputc('\"', out); 
    95                 for (int i_ = 0; s[i_]; ++i_) { 
    96                     switch (s[i_]) { 
    97                         case '\n': fputs("\\n", out); break; 
    98                         case '\t': fputs("\\t", out); break; 
    99                         case '\"': fputs("\\\"", out); break; 
    100                         case '\\': fputs("\\\\", out); break; 
    101                         default: fputc(s[i_], out); break; 
     151                size_t  len    = strlen(s)*4; 
     152                char   *res = (char*)malloc(len+2+1); 
     153 
     154                int j     = 0; 
     155                res[j++] = '\"'; 
     156                for (int i = 0; s[i]; ++i) { 
     157                    unsigned char c = static_cast<unsigned char>(s[i]); 
     158                    char esc = 0; 
     159                    switch (c) { 
     160                        case '\n': esc = 'n'; break; 
     161                        case '\t': esc = 't'; break; 
     162                        case '\"': esc = '\"'; break; 
     163                        case '\\': esc = '\\'; break; 
     164                        default: if (c<10) esc = c-1+'1'; break; 
     165                    } 
     166                    if (esc) { 
     167                        res[j++] = '\\'; 
     168                        res[j++] = esc; 
     169                    } 
     170                    else { 
     171                        if (c >= 32 && c<127) { 
     172                            res[j++] = c; 
     173                        } 
     174                        else { 
     175                            j += sprintf(res+j, "\\x%02x", int(c)); 
     176                        } 
    102177                    } 
    103178                } 
    104                 fputc('\"', out); 
     179                res[j++] = '\"'; 
     180                res[j++] = 0; 
     181                return res; 
    105182            } 
    106183            else { 
    107                 fputs("(null)", out); 
    108             } 
    109         } 
    110     }; 
    111  
    112     inline void print(int i)                 { fprintf(stderr, "%i", i); } 
    113     inline void print_hex(int i)             { fprintf(stderr, "0x%x", i); } 
    114  
    115     inline void print(long L)                { fprintf(stderr, "%li", L); } 
    116     inline void print_hex(long L)            { fprintf(stderr, "0x%lx", L); } 
    117  
    118     inline void print(const char *s)         { StaticCode::print_readable_string(s, stderr); } 
    119     // no print_hex for strings 
    120  
    121     inline void print(size_t z)              { fprintf(stderr, "%zu", z); } 
    122     inline void print_hex(size_t z)          { fprintf(stderr, "0x%zx", z); } 
    123  
    124     inline void print(unsigned char c)       { fprintf(stderr, "'%c'", c); } 
    125     inline void print_hex(unsigned char c)   { print_hex(size_t(c)); } 
    126  
    127     inline void print(char c)                { print((unsigned char)c); } 
    128     inline void print_hex(char c)            { print_hex((unsigned char)c); } 
     184                return strdup("(null)"); 
     185            } 
     186        } 
     187        static void print_readable_string(const char *s, FILE *out) { 
     188            fputs(str(readable_string(s)).value(), out); 
     189        } 
     190 
     191        static char *vstrf(const char *format, va_list& parg) __attribute__((format(__printf__, 1, 0))) { 
     192            static const size_t max_vstrf_size = 10000; 
     193            static char         vstrf_buf[max_vstrf_size]; 
     194 
     195            int printed = vsnprintf(vstrf_buf, max_vstrf_size, format, parg); 
     196            arb_assert(printed >= 0 && size_t(printed)<max_vstrf_size); 
     197 
     198            char *result    = (char*)malloc(printed+1); 
     199            memcpy(result, vstrf_buf, printed); 
     200            result[printed] = 0; 
     201            return result; 
     202        } 
     203 
     204        static char *strf(const char *format, ...) __attribute__((format(__printf__, 1, 2))) { 
     205            va_list  parg; 
     206            va_start(parg, format); 
     207            char *result = vstrf(format, parg); 
     208            va_end(parg); 
     209            return result; 
     210        } 
     211 
     212    }; 
     213 
     214    inline char *val2readable(bool b) { return strdup(b ? "true" : "false"); } 
     215     
     216    inline char *val2readable(int i) { return StaticCode::strf("%i", i); } 
     217    inline char *val2hex(int i) { return StaticCode::strf("0x%x", i); } 
     218 
     219    inline char *val2readable(long L) { return StaticCode::strf("%li", L); } 
     220    inline char *val2hex(long L) { return StaticCode::strf("0x%lx", L); } 
     221 
     222    inline char *val2readable(size_t z) { return StaticCode::strf("%zu", z); } 
     223    inline char *val2hex(size_t z) { return StaticCode::strf("0x%zx", z); } 
    129224 
    130225    // dont dup size_t: 
    131226#ifdef ARB_64 
    132     inline void print(unsigned u)            { fprintf(stderr, "%u", u); } 
    133     inline void print_hex(unsigned u)        { fprintf(stderr, "0x%x", u); } 
     227    inline char *val2readable(unsigned u) { return StaticCode::strf("%u", u); } 
     228    inline char *val2hex(unsigned u) { return StaticCode::strf("0x%x", u); } 
    134229#else 
    135     inline void print(long unsigned u)       { fprintf(stderr, "%lu", u); } 
    136     inline void print_hex(long unsigned u)   { fprintf(stderr, "0x%lx", u); } 
     230    inline char *val2readable(long unsigned u) { return StaticCode::strf("%lu", u); } 
     231    inline char *val2hex(long unsigned u) { return StaticCode::strf("0x%lx", u); } 
    137232#endif 
     233 
     234    inline char *val2readable(double d) { return StaticCode::strf("%f", d); } 
     235 
     236    inline char *val2readable(unsigned char c) { arb_assert(c); return StaticCode::strf("'%c'", c); } 
     237    inline char *val2readable(const char *s) { return StaticCode::readable_string(s); } 
     238 
     239#ifdef TESTS_KNOW_STRING 
     240    inline char *val2readable(const std::string& s) { return StaticCode::readable_string(s.c_str()); } 
     241#endif 
     242 
     243    template <typename T> inline void print(const T& t) { fputs(val2readable(make_copy(t)), stderr); } 
     244    template <typename T> inline void print_hex(const T& t) { fputs(val2hex(make_copy(t)), stderr); } 
    138245 
    139246    template <typename T1, typename T2> inline void print_pair(T1 t1, T2 t2) { 
    140247        print(t1); 
    141         fputs(", ", stderr); 
     248        fputs(",", stderr); 
    142249        print(t2); 
    143250    } 
     
    148255    } 
    149256 
    150     template <typename T> inline const char *nameoftype(T unspecialized) { 
    151         return specialized_nameoftype(unspecialized);  // define instanciating type below! 
    152     } 
    153  
    154 #define NAMEOFTYPE(type) template <> inline const char * nameoftype<>(type) { return #type; } 
    155     NAMEOFTYPE(bool); 
    156     NAMEOFTYPE(char); 
    157     NAMEOFTYPE(unsigned char); 
    158     NAMEOFTYPE(const char*); 
    159     NAMEOFTYPE(int); 
    160     NAMEOFTYPE(unsigned int); 
    161     NAMEOFTYPE(long int); 
    162     NAMEOFTYPE(long unsigned int); 
    163 #undef NAMEOFTYPE 
    164  
    165  
    166  
    167 #ifdef TRACE_IS_EQUAL 
    168     template <typename T1, typename T2> inline bool bool_traced(const char *name, bool equal, T1 t1, T2 t2) { 
    169         fprintf(stderr, "%-5s = %s(%s ", (equal ? "true" : "false"), name, nameoftype(t1)); 
    170         print(t1); 
    171         fprintf(stderr, ",%s ", nameoftype(t2)); 
    172         print(t2); 
    173         fprintf(stderr, ")\n"); 
    174         return equal; 
    175     } 
    176 #else 
    177     template <typename T1, typename T2> inline bool bool_traced(const char *, bool equal, T1 , T2 ) { 
    178         return equal; 
    179     } 
     257    class epsilon_similar { 
     258        double epsilon; 
     259    public: 
     260        epsilon_similar(double epsilon_) : epsilon(epsilon_) {} 
     261        bool operator()(const double& d1, const double& d2) const { 
     262            double diff = d1-d2; 
     263            if (diff<0.0) diff = -diff; // do not use fabs() here 
     264            return diff <= epsilon; 
     265        } 
     266    }; 
     267 
     268    struct containing { 
     269        bool operator()(const char *str, const char *part) const { return strstr(str, part); } 
     270#if defined(TESTS_KNOW_STRING) 
     271        bool operator()(const std::string& str, const std::string& part) const { return strstr(str.c_str(), part.c_str()); } 
    180272#endif 
    181  
    182     template <typename T1, typename T2> inline bool is_equal(T1 t1, T2 t2) { 
    183         return bool_traced("is_equal", t1 == t2, t1, t2); 
    184     } 
    185     template<> inline bool is_equal<>(const char *s1, const char *s2) { 
    186         return bool_traced("is_equal", (s1 == s2) || (s1 && s2 && strcmp(s1, s2) == 0), s1, s2); 
    187     } 
    188     template <typename T1, typename T2> inline bool is_less(T1 t1, T2 t2) { 
    189         return bool_traced("is_less", t1 < t2, t1, t2); 
    190     } 
    191  
    192  
    193     template <typename T1, typename T2> inline void print_failed_compare(T1 t1, T2 t2, const char *prefix, const char *infix, const char *suffix) { 
    194         FlushedOutput yes; 
    195         fputs(prefix, stderr); 
    196         print_pair(t1, t2); 
    197         fputs(infix, stderr); 
    198         print_hex_pair(t1, t2); 
    199         fputs(suffix, stderr); 
    200     } 
    201     template <typename T1, typename T2> inline void print_failed_equal(T1 t1, T2 t2) { 
    202         print_failed_compare(t1, t2, "test_equal(", ") (", ") returns false"); 
    203     } 
    204     template <typename T1, typename T2> inline void print_failed_less_equal(T1 t1, T2 t2) { 
    205         print_failed_compare(t1, t2, "test_less_equal(", ") (", ") returns false"); 
    206     } 
    207     template <typename T1, typename T2> inline void print_failed_different(T1 t1, T2 t2) { 
    208         print_failed_compare(t1, t2, "test_different(", ") (", ") returns false"); 
    209     } 
    210  
    211     template<> inline void print_failed_equal<>(const char *s1, const char *s2) { 
    212         FlushedOutput yes; 
    213         fputs("test_equal(", stderr); 
    214         print(s1); 
    215         fputs(",\n           ", stderr); 
    216         print(s2); 
    217         fputs(") returns false", stderr); 
    218     } 
    219     template<> inline void print_failed_different<>(const char *s1, const char *) { 
    220         FlushedOutput yes; 
    221         fputs("test_different(", stderr); 
    222         print(s1); 
    223         fputs(", <same>", stderr); 
    224         fputs(") returns false", stderr); 
    225     } 
    226  
    227     template <typename T1, typename T2> inline bool test_equal(T1 t1, T2 t2) { 
    228         bool equal = is_equal(t1, t2); 
    229         if (!equal) print_failed_equal(t1, t2); 
    230         return equal; 
    231     } 
    232     template <typename T1, typename T2> inline bool test_less_equal(T1 lower, T2 upper) { 
    233         bool less_equal = is_equal(lower, upper) || is_less(lower, upper); 
    234         if (!less_equal) print_failed_less_equal(lower, upper); 
    235         return less_equal; 
    236     } 
    237     template <typename T1, typename T2> inline bool test_different(T1 t1, T2 t2) { 
    238         bool different = !is_equal(t1, t2); 
    239         if (!different) print_failed_different(t1, t2); 
    240         return different; 
    241     } 
    242  
    243 #define ACCEPT_NON_CONST_ARGUMENTS(FUN,TYPE) \ 
    244     template<> inline bool FUN<>(TYPE p1, TYPE p2) { return FUN((const TYPE)p1, (const TYPE)p2); } \ 
    245         template<> inline bool FUN<>(TYPE p1, const TYPE p2) { return FUN((const TYPE)p1, p2); } \ 
    246         template<> inline bool FUN<>(const TYPE p1, TYPE p2) { return FUN(p1, (const TYPE)p2); } 
    247  
    248     ACCEPT_NON_CONST_ARGUMENTS(test_equal, char*); 
    249     ACCEPT_NON_CONST_ARGUMENTS(test_different, char*); 
    250  
    251 #ifdef ARB_64 
    252     typedef long int NULLPTR; 
    253 #else 
    254     typedef int      NULLPTR; 
    255 #endif 
    256      
    257 #define ACCEPT_NULLPTR_ARGUMENTS(FUN,TYPE)         \ 
    258     template<> inline bool FUN<>(TYPE p1, NULLPTR p2) { TEST_ASSERT(!p2); return FUN((const TYPE)p1, (const TYPE)p2); } \ 
    259         template<> inline bool FUN<>(const TYPE p1, NULLPTR p2) { TEST_ASSERT(!p2); return FUN((const TYPE)p1, (const TYPE)p2); } \ 
    260         template<> inline bool FUN<>(NULLPTR p1, TYPE p2) { TEST_ASSERT(!p1); return FUN((const TYPE)p1, (const TYPE)p2); } \ 
    261         template<> inline bool FUN<>(NULLPTR p1, const TYPE p2) { TEST_ASSERT(!p1); return FUN((const TYPE)p1, (const TYPE)p2); } 
    262  
    263     ACCEPT_NULLPTR_ARGUMENTS(test_equal, char*); 
    264     ACCEPT_NULLPTR_ARGUMENTS(test_different, char*); 
    265  
    266     inline bool test_similar(double d1, double d2, double epsilon) { 
    267         double diff = d1-d2; 
    268         if (diff<0.0) diff = -diff; // do not use fabs() here 
    269  
    270         bool in_epsilon_range = diff < epsilon; 
    271         if (!in_epsilon_range) { 
    272             StaticCode::printf("test_similar(%f,%f,%f) returns false\n", d1, d2, epsilon); 
    273         } 
    274         return in_epsilon_range; 
    275     } 
    276  
    277     inline bool test_equal(double d1, double d2) { return test_similar(d1, d2, 0.000001); } 
    278  
    279     inline bool test_strcontains(const char *str, const char *part)  { 
    280         const char *found = strstr(str, part); 
    281         if (!found) StaticCode::printf("string '%s'\ndoes not contain '%s'\n", str, part); 
    282         return found; 
    283     } 
    284      
    285     // inline bool is_equal(double d1, double d2) { 
    286         // return is_similar(d1, d2, 0.000001); 
    287     // } 
     273    }; 
    288274 
    289275    inline bool files_are_equal(const char *file1, const char *file2) { 
     
    362348        return !error; 
    363349    } 
     350 
     351 
     352    // ------------------ 
     353    //      copy 
     354 
     355 
     356    template <typename T> 
     357    class copy //! makes char* copyable, so it can be handled like most other types 
     358    { 
     359        T t; 
     360    public: 
     361        copy(const T& t_) : t(t_) {} 
     362        operator const T&() const { return t; } 
     363    }; 
     364 
     365    template <> 
     366    class copy<const char *> { 
     367        str t; 
     368    public: 
     369        copy(const char *t_) : t(str(t_ ? strdup(t_) : NULL)) {} 
     370        operator const char *() const { return t.value(); } 
     371    }; 
     372 
     373    template <typename T> class copy< copy<T> > { copy(const copy<T>& t_); }; // avoid copies of copies 
     374 
     375    template <typename T> inline copy<T> make_copy(const T& t) { return copy<T>(t); } 
     376 
     377    inline copy<const char *> make_copy(const char *p) { return copy<const char *>(p); } 
     378    inline copy<const char *> make_copy(char *p) { return copy<const char *>(p); } 
     379    inline copy<const char *> make_copy(const unsigned char *p) { return copy<const char *>(reinterpret_cast<const char *>(p)); } 
     380    inline copy<const char *> make_copy(unsigned char *p) { return copy<const char *>(reinterpret_cast<const char *>(p)); } 
     381    inline copy<const char *> make_copy(const signed char *p) { return copy<const char *>(reinterpret_cast<const char *>(p)); } 
     382    inline copy<const char *> make_copy(signed char *p) { return copy<const char *>(reinterpret_cast<const char *>(p)); } 
     383 
     384    inline copy<unsigned char> make_copy(char p) { return copy<unsigned char>(p); } 
     385    inline copy<unsigned char> make_copy(unsigned char p) { return copy<unsigned char>(p); } 
     386    inline copy<unsigned char> make_copy(signed char p) { return copy<unsigned char>(p); } 
     387 
     388    template <typename T> str readable(const copy<T>& v) { return str(val2readable(v)); } 
     389    template <typename T> str readableHex(const copy<T>& v) { return str(val2readableHex(v)); } 
     390 
     391    template <typename T> bool operator == (const copy<T>& v1, const copy<T>& v2) { return static_cast<const T&>(v1) == static_cast<const T&>(v2); } 
     392    template <typename T> bool operator != (const copy<T>& v1, const copy<T>& v2) { return !(v1 == v2); } 
     393 
     394    template <> inline bool operator == <const char *>(const copy<const char *>& v1, const copy<const char *>& v2) { 
     395        const char *val1 = v1; 
     396        const char *val2 = v2; 
     397 
     398        return (val1 == val2) || (val1 && val2 && (strcmp(val1, val2) == 0)); 
     399    } 
     400 
     401 
     402 
     403    // ------------------------------- 
     404    //      some output functions 
     405 
     406    inline void print(const char *s) { fputs(s, stderr); } 
     407    inline void print(char c) { fputc(c, stderr); } 
     408    inline void print(int i) { fprintf(stderr, "%i", i); } 
     409 
     410    inline void space() { print(' '); } 
     411    inline void nl() { print('\n'); } 
     412     
     413    inline void print_indent(int indent) { while (indent--) space(); } 
     414 
     415    inline void spaced(const char *word) { space(); print(word); space(); } 
     416    inline void select_spaced(bool first, const char *singular, const char *plural) { spaced(first ? singular : plural); } 
     417     
     418 
     419#define HASTOBE_CLONABLE(type) virtual type *clone() const = 0 
     420#define MAKE_CLONABLE(type)    type *clone() const { return new type(*this); } 
     421 
     422    // ------------------------------ 
     423    //      abstract expectation 
     424 
     425    struct expectation //! something expected. can be fulfilled or not (and can explain why/not) 
     426    { 
     427        virtual ~expectation() {} 
     428        HASTOBE_CLONABLE(expectation); 
     429 
     430        virtual bool fulfilled() const              = 0; 
     431        virtual void explain(int indent) const      = 0; 
     432        virtual void dump_brief_description() const = 0; 
     433    }; 
     434 
     435    // ------------------- 
     436    //      asserters 
     437 
     438    class asserter : virtual Noncopyable { 
     439        expectation *expected; 
     440        locinfo      loc; 
     441        const char  *code; 
     442 
     443        virtual void announce_failure() const { TRIGGER_ASSERTION(false); } 
     444 
     445        void err(const char *format) const { loc.errorf(false, format, code); } 
     446        void warn(const char *format) const { loc.warningf(format, code); } 
     447         
     448    public: 
     449        asserter(const expectation& e, const char *nontmp_code, const char *file, int line) 
     450            : expected(e.clone()), 
     451              loc(file, line), 
     452              code(nontmp_code) 
     453        {} 
     454        virtual ~asserter() { delete expected; } 
     455 
     456        const char *get_code() const { return code; } 
     457 
     458        void expect_that() const { 
     459            if (!expected->fulfilled()) { 
     460                err("Failed expectation '%s'"); 
     461                print("expectation fails because\n"); 
     462                expected->explain(2); print('\n'); 
     463                announce_failure(); 
     464            } 
     465        } 
     466        void expect_broken() const { 
     467            if (expected->fulfilled()) { 
     468                err("Previously broken expectation '%s' succeeds"); 
     469                announce_failure(); 
     470            } 
     471            else { 
     472                warn("Expectation '%s' known as broken (accepted until fixed)"); 
     473                print("Broken because\n"); 
     474                expected->explain(2); print('\n'); 
     475            } 
     476        } 
     477        void expect_wanted_behavior() const { 
     478            if (expected->fulfilled()) { 
     479                err("Wanted behavior '%s' reached"); 
     480                announce_failure(); 
     481            } 
     482            else { 
     483                warn("Wanted behavior: '%s'"); 
     484                print("Unsatisfied because\n"); 
     485                expected->explain(2); print('\n'); 
     486            } 
     487        } 
     488 
     489    }; 
     490 
     491    class debug_asserter : public asserter { 
     492        virtual void announce_failure() const { 
     493            print("<<< would trigger assertion now! >>>\n"); 
     494        } 
     495    public: 
     496        debug_asserter(const expectation& e, const char *code_, const char *file, int line) 
     497            : asserter(e, code_, file, line) 
     498        {} 
     499 
     500        void debug_expectations() { 
     501            fprintf(stderr, "-------------------- [Debugging expectations for '%s']\n", get_code()); 
     502            expect_that(); 
     503            expect_broken(); 
     504            expect_wanted_behavior(); 
     505        } 
     506    }; 
     507 
     508    // ---------------------------------------- 
     509    //      matchable + matcher (abstract) 
     510 
     511    struct matchable //! can be matched with corresponding matcher. 
     512    { 
     513        virtual ~matchable() {} 
     514        HASTOBE_CLONABLE(matchable); 
     515 
     516        virtual const char *name() const           = 0; 
     517        virtual const char *readable_value() const = 0; 
     518    }; 
     519 
     520    struct matcher //! can match things. 
     521    { 
     522        virtual ~matcher() {} 
     523        HASTOBE_CLONABLE(matcher); 
     524 
     525        virtual bool matches(const matchable& thing) const                      = 0; 
     526        virtual void dump_expectation(const matchable& thing, int indent) const = 0; 
     527        virtual void dump_brief_description(const matchable& thing) const       = 0; 
     528    }; 
     529 
     530    // ---------------------------------------------- 
     531    //      expectation from matchable + matcher 
     532 
     533 
     534    class match_expectation : public expectation //! expectation composed from matcher and corresponding matchable. 
     535    { 
     536        matchable *thing; 
     537        matcher   *condition; 
     538    public: 
     539        match_expectation(const matchable& thing_, const matcher& condition_) 
     540            : thing(thing_.clone()), 
     541              condition(condition_.clone()) 
     542        {} 
     543        match_expectation(const match_expectation& other) 
     544            : thing(other.thing->clone()), 
     545              condition(other.condition->clone()) 
     546        {} 
     547        DECLARE_ASSIGNMENT_OPERATOR(match_expectation); 
     548        MAKE_CLONABLE(match_expectation); 
     549        ~match_expectation() { 
     550            delete thing; 
     551            delete condition; 
     552        } 
     553 
     554        bool fulfilled() const { return condition->matches(*thing); } 
     555        void explain(int indent) const { condition->dump_expectation(*thing, indent); } 
     556        void dump_brief_description() const { condition->dump_brief_description(*thing); } 
     557    }; 
     558 
     559    // ------------------- 
     560    //      predicate 
     561 
     562 
     563    class predicate_description { 
     564        const char  *primary; 
     565        const char  *inverse; 
     566        mutable str  tmp; 
     567 
     568        void erase_last_from_tmp() const { 
     569            char *t   = const_cast<char*>(tmp.value()); 
     570            int   len = strlen(t); 
     571            t[len-1]  = 0; 
     572        } 
     573 
     574        static bool ends_with_s(const char *s) { 
     575            int len          = strlen(s); 
     576            return s[len-1] == 's'; 
     577        } 
     578 
     579        const char *make(const char *desc, bool got) const { 
     580            if (ends_with_s(desc)) { 
     581                if (got) return desc; 
     582                tmp = StaticCode::strf("doesnt %s", desc); 
     583                erase_last_from_tmp(); 
     584            } 
     585            else { 
     586                tmp = StaticCode::strf("%s %s", got ? "is" : "isnt", desc); 
     587            } 
     588            return tmp.value(); 
     589        } 
     590 
     591    public: 
     592        predicate_description(const char *primary_) : primary(primary_), inverse(NULL) {} 
     593        predicate_description(const char *primary_, const char *inverse_) : primary(primary_), inverse(inverse_) {} 
     594        predicate_description(const predicate_description& other) : primary(other.primary), inverse(other.inverse) {} 
     595        DECLARE_ASSIGNMENT_OPERATOR(predicate_description); 
     596 
     597        const char *make(bool expected, bool got) const { 
     598            if (expected) return make(primary, got); 
     599            if (inverse) return make(inverse, !got); 
     600            return make(primary, !got); 
     601        } 
     602    }; 
     603 
     604    template <typename FUNC> 
     605    class predicate { 
     606        FUNC                  pred; 
     607        predicate_description description; 
     608    public: 
     609        predicate(FUNC pred_, const char *name) : pred(pred_), description(name) {} 
     610        predicate(FUNC pred_, const char *name, const char *inverse) : pred(pred_), description(name, inverse) {} 
     611 
     612        template <typename T> bool matches(const copy<T>& v1, const copy<T>& v2) const { return pred(v1, v2); } 
     613        const char *describe(bool expected, bool got) const { return description.make(expected, got); } 
     614    }; 
     615 
     616    template <typename FUNC> predicate<FUNC> make_predicate(FUNC func, const char *primary, const char *inverse) { 
     617        return predicate<FUNC>(func, primary, inverse); 
     618    } 
     619 
     620    // ------------------------------------------ 
     621    //      matchable + matcher (for values) 
     622 
     623    template <typename T> inline bool equals(const copy<T>& t1, const copy<T>& t2) { return t1 == t2; } 
     624    template <typename T> inline bool less(const copy<T>& t1, const copy<T>& t2) { return t1 < t2; } 
     625    template <typename T> inline bool more(const copy<T>& t1, const copy<T>& t2) { return t1 > t2; } 
     626 
     627    template <typename T> 
     628    class matchable_value : public matchable //! matchable for values 
     629    { 
     630        copy<T>      val; 
     631        mutable str  readable; 
     632        const char * code; 
     633    public: 
     634        matchable_value(copy<T> val_, const char *nontemp_code) : val(val_), code(nontemp_code) {} 
     635        matchable_value(const matchable_value<T>& other) : val(other.val), readable(other.readable), code(other.code) {} 
     636        DECLARE_ASSIGNMENT_OPERATOR(matchable_value); 
     637        MAKE_CLONABLE(matchable_value<T>); 
     638 
     639        const copy<T>& value() const { return val; } 
     640        char *gen_description() const { return StaticCode::strf("%s (=%s)", code, val.readable()); } 
     641 
     642        const char *name() const { return code; } 
     643        const char *readable_value() const { 
     644            if (!readable.exists()) readable = arb_test::readable(val); 
     645            return readable.value(); 
     646        } 
     647 
     648        template <typename U> inline match_expectation equals_expectation(bool invert, const U& other, const char *code) const; 
     649        template <typename U> inline match_expectation lessThan_expectation(bool invert, const U& other, const char *code) const; 
     650        template <typename U> inline match_expectation moreThan_expectation(bool invert, const U& other, const char *code) const; 
     651         
     652        template <typename FUNC> inline match_expectation predicate_expectation(bool wanted, predicate<FUNC> pred, matchable_value<T> arg) const; 
     653        template <typename U, typename FUNC> inline match_expectation predicate_expectation(bool wanted, FUNC pred, const char *pred_code, const U& arg, const char *arg_code) const; 
     654    }; 
     655 
     656    template <typename T, typename U> 
     657    inline const matchable_value<T> make_matchable_value(const U& other, const char *code_) { 
     658        return matchable_value<T>(T(other), code_); 
     659    } 
     660#if defined(TESTS_KNOW_STRING) 
     661    template<> 
     662    inline const matchable_value<const char*> make_matchable_value<const char *, std::string>(const std::string& other, const char *code_) { 
     663        return matchable_value<const char *>(other.c_str(), code_); 
     664    } 
     665#endif 
     666     
     667    template <typename T> template <typename U> 
     668    inline match_expectation matchable_value<T>::equals_expectation(bool wanted, const U& other, const char *code_) const { 
     669        return predicate_expectation(wanted, make_predicate(equals<T>, "equals", "differs"), make_matchable_value<T,U>(other, code_)); 
     670    } 
     671    template <typename T> template <typename U> 
     672    inline match_expectation matchable_value<T>::lessThan_expectation(bool wanted, const U& other, const char *code_) const { 
     673        return predicate_expectation(wanted, make_predicate(less<T>, "less than", "more or equal"), make_matchable_value<T,U>(other, code_)); 
     674    } 
     675    template <typename T> template <typename U> 
     676    inline match_expectation matchable_value<T>::moreThan_expectation(bool wanted, const U& other, const char *code_) const { 
     677        return predicate_expectation(wanted, make_predicate(more<T>, "more than", "less or equal"), make_matchable_value<T,U>(other, code_)); 
     678    } 
     679     
     680    template <typename T> 
     681    class value_matcher : public matcher //! matcher for values 
     682    { 
     683        matchable_value<T> expected; 
     684    public: 
     685        value_matcher(const matchable_value<T>& expected_) : expected(expected_) {} 
     686        virtual ~value_matcher() {} 
     687 
     688        virtual bool matches(const copy<T>& v1, const copy<T>& v2) const       = 0; 
     689        virtual const char *relation(bool isMatch) const                       = 0; 
     690 
     691        const matchable_value<T>& get_expected() const { return expected; } 
     692 
     693        bool matches(const matchable& thing) const { 
     694            const matchable_value<T>& value_thing = dynamic_cast<const matchable_value<T>&>(thing); 
     695            return matches(value_thing.value(), expected.value()); 
     696        } 
     697 
     698        void dump_expectation(const matchable& thing, int indent) const { 
     699            bool isMatch = matches(thing); 
     700            print_indent(indent); 
     701            fprintf(stderr, "'%s' %s '%s'", thing.name(), relation(isMatch), expected.name()); 
     702 
     703            const matchable_value<T>& value_thing = dynamic_cast<const matchable_value<T>&>(thing); 
     704            if (equals<T>(value_thing.value(), expected.value())) { 
     705                fprintf(stderr, " (both are %s)", value_thing.readable_value()); 
     706            } 
     707            else { 
     708                int diff = strlen(thing.name())-strlen(expected.name()); 
     709 
     710                print(", where\n"); 
     711                indent += 2;; 
     712                print_indent(indent); fprintf(stderr, "'%s'%*s is %s, and\n", thing.name(),    (diff>0 ? 0 : -diff), "", thing.readable_value()); 
     713                print_indent(indent); fprintf(stderr, "'%s'%*s is %s",        expected.name(), (diff<0 ? 0 : diff),  "", expected.readable_value()); 
     714            } 
     715        } 
     716        void dump_brief_description(const matchable& thing) const { 
     717            print(thing.name()); 
     718            print('.'); 
     719            print(relation(true)); 
     720            print('('); print(expected.name()); print(')'); 
     721        } 
     722 
     723    }; 
     724 
     725    // --------------------------- 
     726    //      predicate_matcher 
     727 
     728 
     729    template <typename T, typename FUNC> 
     730    class predicate_matcher : public value_matcher<T> { 
     731        predicate<FUNC> pred; 
     732        bool            expected_result; 
     733 
     734    public: 
     735        predicate_matcher(bool wanted, predicate<FUNC> pred_, const matchable_value<T>& arg) 
     736            : value_matcher<T>(arg), 
     737              pred(pred_), 
     738              expected_result(wanted) 
     739        {} 
     740        MAKE_CLONABLE(predicate_matcher); 
     741 
     742        bool matches(const copy<T>& v1, const copy<T>& v2) const { return correlated(pred.matches(v1, v2), expected_result); } 
     743        const char *relation(bool isMatch) const { return pred.describe(expected_result, correlated(isMatch, expected_result)); } 
     744    }; 
     745 
     746    template <typename T> template <typename FUNC> 
     747    inline match_expectation matchable_value<T>::predicate_expectation(bool wanted, predicate<FUNC> pred, matchable_value<T> arg) const { 
     748        return match_expectation(*this, predicate_matcher<T,FUNC>(wanted, pred, arg)); 
     749    } 
     750    template <typename T> template <typename U, typename FUNC> 
     751    inline match_expectation matchable_value<T>::predicate_expectation(bool wanted, FUNC pred, const char *pred_code, const U& arg, const char *arg_code) const { 
     752        return match_expectation(*this, predicate_matcher<T,FUNC>(wanted, predicate<FUNC>(pred, pred_code), make_matchable_value<T,U>(arg, arg_code))); 
     753    } 
     754 
     755    // ------------------------------------------------ 
     756    //      matchable + matcher (for expectations) 
     757 
     758    const int MAX_GROUP_SIZE = 3; 
     759    class expectation_group : public matchable //! group of expectation. matchable with group_matcher 
     760    { 
     761        int          count; 
     762        expectation *depend_on[MAX_GROUP_SIZE]; 
     763 
     764        expectation_group& operator = (const expectation_group&); // forbidden 
     765    protected: 
     766 
     767    public: 
     768        expectation_group(const expectation& e) : count(1) { 
     769            depend_on[0] = e.clone(); 
     770        } 
     771        expectation_group(const expectation& e1, const expectation& e2) : count(2) { 
     772            depend_on[0] = e1.clone(); 
     773            depend_on[1] = e2.clone(); 
     774        } 
     775        expectation_group(const expectation_group& other) : count(other.count) { 
     776            for (int i = 0; i<count; ++i) { 
     777                depend_on[i] = other.depend_on[i]->clone(); 
     778            } 
     779        } 
     780        virtual ~expectation_group() { 
     781            for (int i = 0; i<count; ++i) { 
     782                delete depend_on[i]; 
     783            } 
     784        } 
     785        MAKE_CLONABLE(expectation_group); 
     786 
     787        expectation_group& add(const expectation& e) { depend_on[count++] = e.clone(); return *this; } 
     788 
     789        const char *name() const { 
     790            return "<expectation_group>"; 
     791        } 
     792        const char *readable_value() const { 
     793            return "<value of expectation_group>"; 
     794        } 
     795 
     796        const expectation& dependent(int i) const { arb_assert(i<count); return *depend_on[i]; } 
     797        int size() const { return count; } 
     798        int count_fulfilled() const { 
     799            int ff = 0; 
     800            for (int i = 0; i<count; ++i) { 
     801                ff += dependent(i).fulfilled(); 
     802            } 
     803            return ff; 
     804        } 
     805        void dump_some_expectations(int indent, bool fulfilled, bool unfulfilled) const { 
     806            if (fulfilled||unfulfilled) { 
     807                bool all    = fulfilled && unfulfilled; 
     808                bool wanted = fulfilled; 
     809 
     810                bool printed = false; 
     811                for (int i = 0; i<size(); ++i) { 
     812                    const expectation& e = dependent(i); 
     813 
     814                    bool is_fulfilled = e.fulfilled(); 
     815                    if (all || is_fulfilled == wanted) { 
     816                        if (printed) print('\n'); 
     817                        e.explain(indent); 
     818                        printed = true; 
     819                    } 
     820                } 
     821            } 
     822        } 
     823        void dump_brief_description() const { 
     824            print("of("); 
     825            bool printed = false; 
     826            for (int i = 0; i<size(); ++i) { 
     827                if (printed) print(", "); 
     828                const expectation& e = dependent(i); 
     829                e.dump_brief_description(); 
     830                printed = true; 
     831            } 
     832            print(')'); 
     833        } 
     834    }; 
     835 
     836    struct group_match //! result of matching an expectation_group with a group_matcher 
     837    { 
     838        const int count; 
     839        const int fulfilled; 
     840        const int min_req; 
     841        const int max_req; 
     842        const int diff; 
     843 
     844        int required(int what) const { return what == -1 ? count : what; } 
     845        group_match(const expectation_group& group, int min, int max) 
     846            : count(group.size()), 
     847              fulfilled(group.count_fulfilled()), 
     848              min_req(required(min)), 
     849              max_req(required(max)), 
     850              diff(fulfilled<min_req 
     851                   ? fulfilled-min_req 
     852                   : (fulfilled>max_req ? fulfilled-max_req : 0)) 
     853        {} 
     854 
     855 
     856        inline static void is(int a) { select_spaced(a == 1, "is", "are"); } 
     857        inline static void was(int a) { select_spaced(a < 2, "was", "were"); } 
     858        inline static void amountzero(int a, const char *zero) { a ? print(a) : print(zero); } 
     859 
     860        void dump_num_of(int amount, const char *thing) const { 
     861            amountzero(amount, "no"); 
     862            space(); 
     863            print(thing); 
     864            if (amount != 1) print('s'); 
     865        } 
     866 
     867        void dump(const expectation_group& group, int indent) const { 
     868            print_indent(indent); 
     869            if (count == 1) { 
     870                print("expectation "); 
     871                print("'"); 
     872                group.dependent(0).dump_brief_description(); 
     873                print("' "); 
     874                print(fulfilled ? "fulfilled" : "fails"); 
     875                print(diff ? " unexpectedly" : " as expected"); 
     876            } 
     877            else { 
     878                print("expected "); 
     879                int that_many; 
     880                if (min_req == max_req) { 
     881                    if (diff>0 && min_req>0) print("only "); 
     882                    that_many = min_req; 
     883                } 
     884                else { 
     885                    if (diff) { 
     886                        print("at"); select_spaced(diff<0, "least", "most"); 
     887                        that_many = diff<0 ? min_req : max_req; 
     888                    } 
     889                    else { 
     890                        fprintf(stderr, "%i-", min_req); 
     891                        that_many = max_req; 
     892                    } 
     893                } 
     894                dump_num_of(that_many, "fulfilled expectation"); 
     895                space(); 
     896                group.dump_brief_description(); 
     897                nl(); 
     898 
     899                indent += 2; 
     900                print_indent(indent); 
     901                if (diff == 0) print("and "); else print("but "); 
     902 
     903                if (diff<0 && fulfilled>0) print("only "); 
     904                amountzero(fulfilled, "none"); is(fulfilled); print("fulfilled"); 
     905            } 
     906 
     907            print(", because\n"); 
     908            bool show_fulfilled   = diff >= 0; 
     909            bool show_unfulfilled = diff <= 0; 
     910            group.dump_some_expectations(indent+2, show_fulfilled, show_unfulfilled); 
     911        } 
     912    }; 
     913 
     914    class group_matcher : public matcher //! matches expectation_group for degree of fulfilledness 
     915    { 
     916        int min, max; 
     917        group_matcher(int min_, int max_) : min(min_), max(max_) {} 
     918    public: 
     919        MAKE_CLONABLE(group_matcher); 
     920 
     921        bool matches(const matchable& thing) const { 
     922            return group_match(dynamic_cast<const expectation_group&>(thing), min, max).diff == 0; 
     923        } 
     924 
     925        void dump_expectation(const matchable& thing, int indent) const { 
     926            const expectation_group& group = dynamic_cast<const expectation_group&>(thing); 
     927            group_match matching(group, min, max); 
     928            matching.dump(group, indent); 
     929        } 
     930 
     931        // factories 
     932        static group_matcher all() { return group_matcher(-1, -1); } 
     933        static group_matcher none() { return group_matcher(0, 0); } 
     934        static group_matcher atleast(int min_) { return group_matcher(min_, -1); } 
     935        static group_matcher atmost(int max_) { return group_matcher(0, max_); } 
     936        static group_matcher exacly(int amount) { return group_matcher(amount, amount); } 
     937 
     938        // match_expectation factories 
     939        match_expectation of(const expectation& e) const { 
     940            return match_expectation(expectation_group(e), *this); 
     941        } 
     942        match_expectation of(const expectation& e1, const expectation& e2) const { 
     943            return match_expectation(expectation_group(e1, e2), *this); 
     944        } 
     945        match_expectation of(const expectation& e1, const expectation& e2, const expectation& e3) const { 
     946            return match_expectation(expectation_group(e1, e2).add(e3), *this); 
     947        } 
     948 
     949        void dump_brief_description(const matchable& thing) const { 
     950            if (max == -1) { 
     951                if (min == -1) { 
     952                    print("all"); 
     953                } 
     954                else { 
     955                    fprintf(stderr, "atleast(%i)", min); 
     956                } 
     957            } 
     958            else if (max == 0) { 
     959                print("none"); 
     960            } 
     961            else if (min == max) { 
     962                fprintf(stderr, "exactly(%i)", min); 
     963            } 
     964            else { 
     965                fprintf(stderr, "[%i-%i]", min, max); 
     966            } 
     967 
     968            print('.'); 
     969 
     970            const expectation_group& group = dynamic_cast<const expectation_group&>(thing); 
     971            group.dump_brief_description(); 
     972        } 
     973    }; 
     974 
     975    // -------------------------- 
     976    //      helper functions 
     977 
     978     
     979    template <typename T> const matchable_value<T> CREATE_matchable(const copy<T>& val, const char *code) { return matchable_value<T>(val, code); } 
     980 
     981    inline group_matcher all() { return group_matcher::all(); } 
     982    inline group_matcher none() { return group_matcher::none(); } 
     983    inline group_matcher atleast(int min) { return group_matcher::atleast(min); } 
     984    inline group_matcher atmost(int max) { return group_matcher::atmost(max); } 
     985    inline group_matcher exacly(int amount) { return group_matcher::exacly(amount); } 
     986 
     987    inline match_expectation wrong(const expectation& e) { return none().of(e); } 
    364988}; 
    365989 
    366990// -------------------------------------------------------------------------------- 
    367991 
    368 #define TEST_WARNING(format,strarg)           arb_test::StaticCode::warningf(__FILE__, __LINE__, format, (strarg)) 
    369 #define TEST_WARNING2(format,strarg1,strarg2) arb_test::StaticCode::warningf(__FILE__, __LINE__, format, (strarg1), (strarg2)) 
    370  
    371 #define TEST_ERROR(format,strarg)           arb_test::StaticCode::errorf(__FILE__, __LINE__, format, (strarg)) 
    372 #define TEST_ERROR2(format,strarg1,strarg2) arb_test::StaticCode::errorf(__FILE__, __LINE__, format, (strarg1), (strarg2)) 
    373 #define TEST_IOERROR(format,strarg)         arb_test::StaticCode::ioerrorf(__FILE__, __LINE__, format, (strarg)) 
     992#define MATCHABLE_ARGS_UNTYPED(val) val, #val 
     993#define MATCHABLE_ARGS_TYPED(val)   make_copy(val), #val 
     994 
     995#define equals(val)  equals_expectation(true, MATCHABLE_ARGS_UNTYPED(val)) 
     996#define differs(val) equals_expectation(false, MATCHABLE_ARGS_UNTYPED(val)) 
     997 
     998#define less_than(val) lessThan_expectation(true, MATCHABLE_ARGS_UNTYPED(val)) 
     999#define more_than(val) moreThan_expectation(true, MATCHABLE_ARGS_UNTYPED(val)) 
     1000 
     1001#define less_or_equal(val) moreThan_expectation(false, MATCHABLE_ARGS_UNTYPED(val)) 
     1002#define more_or_equal(val) lessThan_expectation(false, MATCHABLE_ARGS_UNTYPED(val)) 
     1003 
     1004#define is(pred,arg)     predicate_expectation(true, MATCHABLE_ARGS_UNTYPED(pred), MATCHABLE_ARGS_UNTYPED(arg)) 
     1005#define is_not(pred,arg) predicate_expectation(false, MATCHABLE_ARGS_UNTYPED(pred), MATCHABLE_ARGS_UNTYPED(arg)) 
     1006 
     1007#define that(thing) CREATE_matchable(MATCHABLE_ARGS_TYPED(thing)) 
     1008 
     1009#define TEST_EXPECT(EXPCTN) do { using namespace arb_test; asserter(EXPCTN, #EXPCTN, __FILE__, __LINE__).expect_that(); } while(0) 
     1010#define TEST_EXPECT__BROKEN(EXPCTN) do { using namespace arb_test; asserter(EXPCTN, #EXPCTN, __FILE__, __LINE__).expect_broken(); } while(0) 
     1011#define TEST_EXPECT__WANTED(EXPCTN) do { using namespace arb_test; asserter(EXPCTN, #EXPCTN, __FILE__, __LINE__).expect_wanted_behavior(); } while(0) 
     1012 
     1013#define DEBUG_TEST_EXPECT(EXPCTN) do {                                                  \ 
     1014        using namespace arb_test;                                                       \ 
     1015        debug_asserter(EXPCTN, #EXPCTN, __FILE__, __LINE__).                            \ 
     1016            debug_expectations();                                                       \ 
     1017        debug_asserter(wrong(EXPCTN), "wrong(" #EXPCTN ")", __FILE__, __LINE__).        \ 
     1018            debug_expectations();                                                       \ 
     1019    } while(0) 
     1020 
     1021// -------------------------------------------------------------------------------- 
     1022 
     1023#define HERE arb_test::locinfo(__FILE__, __LINE__) 
     1024 
     1025#define TEST_WARNING(format,strarg)           HERE.warningf(format, (strarg)) 
     1026#define TEST_WARNING2(format,strarg1,strarg2) HERE.warningf(format, (strarg1), (strarg2)) 
     1027#define TEST_ERROR(format,strarg)             HERE.errorf(true, format, (strarg)) 
     1028#define TEST_ERROR2(format,strarg1,strarg2)   HERE.errorf(true, format, (strarg1), (strarg2)) 
     1029#define TEST_IOERROR(format,strarg)           HERE.ioerrorf(true, format, (strarg)) 
    3741030 
    3751031// -------------------------------------------------------------------------------- 
     
    3921048    } while (0) 
    3931049 
    394  
    395 #define TEST_ASSERT_ZERO(cond)         TEST_ASSERT((cond)         == 0) 
    396 #define TEST_ASSERT_ZERO__BROKEN(cond) TEST_ASSERT__BROKEN((cond) == 0) 
     1050#define TEST_ASSERT_ZERO(cond)         TEST_EXPECT(that(cond).equals(0)) 
     1051#define TEST_ASSERT_ZERO__BROKEN(cond) TEST_EXPECT__BROKEN(that(cond).equals(0)) 
    3971052 
    3981053#define TEST_ASSERT_ZERO_OR_SHOW_ERRNO(iocond)                  \ 
     
    5441199// -------------------------------------------------------------------------------- 
    5451200 
    546 #define TEST_ASSERT_NULL(n)         TEST_ASSERT(arb_test::test_equal(n, (typeof(n))NULL)) 
    547 #define TEST_ASSERT_NULL__BROKEN(n) TEST_ASSERT__BROKEN(arb_test::test_equal(n, (typeof(n))NULL)) 
    548  
    549 #define TEST_ASSERT_EQUAL(e1,t2)         TEST_ASSERT(arb_test::test_equal(e1, t2)) 
    550 #define TEST_ASSERT_EQUAL__BROKEN(e1,t2) TEST_ASSERT__BROKEN(arb_test::test_equal(e1, t2)) 
    551  
    552 #define TEST_ASSERT_SIMILAR(e1,t2,epsilon)         TEST_ASSERT(arb_test::test_similar(e1, t2, epsilon)) 
    553 #define TEST_ASSERT_SIMILAR__BROKEN(e1,t2,epsilon) TEST_ASSERT__BROKEN(arb_test::test_similar(e1, t2, epsilon)) 
    554  
    555 #define TEST_ASSERT_DIFFERENT(e1,t2)         TEST_ASSERT(arb_test::test_different(e1, t2)) 
    556 #define TEST_ASSERT_DIFFERENT__BROKEN(e1,t2) TEST_ASSERT__BROKEN(arb_test::test_different(e1, t2)) 
    557  
    558 #define TEST_ASSERT_LOWER_EQUAL(lower,upper)  TEST_ASSERT(arb_test::test_less_equal(lower, upper)) 
    559 #define TEST_ASSERT_LOWER(lower,upper) do { TEST_ASSERT_LOWER_EQUAL(lower, upper); TEST_ASSERT_DIFFERENT(lower, upper); } while(0) 
    560 #define TEST_ASSERT_IN_RANGE(val,lower,upper) do { TEST_ASSERT_LOWER_EQUAL(lower, val); TEST_ASSERT_LOWER_EQUAL(val, upper); } while(0) 
    561  
    562  
    563 #define TEST_ASSERT_CONTAINS(str, part) TEST_ASSERT(arb_test::test_strcontains(str, part)) 
     1201#define TEST_ASSERT_EQUAL(e1,t2)         TEST_EXPECT(that(e1).equals(t2)) 
     1202#define TEST_ASSERT_EQUAL__BROKEN(e1,t2) TEST_EXPECT__BROKEN(that(e1).equals(t2)) 
     1203 
     1204#define TEST_ASSERT_NULL(n)         TEST_ASSERT_EQUAL(n, NULL) 
     1205#define TEST_ASSERT_NULL__BROKEN(n) TEST_ASSERT_EQUAL__BROKEN(n, NULL) 
     1206 
     1207#define TEST_ASSERT_SIMILAR(e1,t2,epsilon)         TEST_EXPECT(that(e1).is(epsilon_similar(epsilon), t2)) 
     1208#define TEST_ASSERT_SIMILAR__BROKEN(e1,t2,epsilon) TEST_EXPECT__BROKEN(that(e1).is(epsilon_similar(epsilon), t2)) 
     1209 
     1210#define TEST_ASSERT_DIFFERENT(e1,t2)         TEST_EXPECT(that(e1).differs(t2)); 
     1211#define TEST_ASSERT_DIFFERENT__BROKEN(e1,t2) TEST_EXPECT__BROKEN(that(e1).differs(t2)); 
     1212 
     1213#define TEST_ASSERT_LOWER_EQUAL(lower,upper)  TEST_EXPECT(that(lower).less_or_equal(upper)) 
     1214#define TEST_ASSERT_LOWER(lower,upper)        TEST_EXPECT(that(lower).less_than(upper)) 
     1215#define TEST_ASSERT_IN_RANGE(val,lower,upper) TEST_EXPECT(all().of(that(val).more_or_equal(lower), that(val).less_or_equal(upper))) 
     1216 
     1217#define TEST_ASSERT_CONTAINS(str, part) TEST_EXPECT(that(str).is(containing(), part)) 
    5641218 
    5651219// --------------------------------------------------------------------------------