Changeset 8219
- Timestamp:
- 17/11/11 12:18:01 (6 months ago)
- Location:
- branches/dev
- Files:
-
- 6 modified
-
AISC_MKPTPS/Makefile (modified) (1 diff)
-
CORE/Makefile (modified) (1 diff)
-
CORE/arb_string.cxx (modified) (1 diff)
-
SL/PRONUC/Makefile (modified) (1 diff)
-
UNIT_TESTER/TestEnvironment.cxx (modified) (2 diffs)
-
UNIT_TESTER/test_unit.h (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/dev/AISC_MKPTPS/Makefile
r7453 r8219 39 39 mkptypes.o: $(ARBHOME)/INCLUDE/arbtools.h 40 40 mkptypes.o: $(ARBHOME)/INCLUDE/attributes.h 41 mkptypes.o: $(ARBHOME)/INCLUDE/dupstr.h 41 42 mkptypes.o: $(ARBHOME)/INCLUDE/test_global.h 42 43 mkptypes.o: $(ARBHOME)/INCLUDE/test_unit.h -
branches/dev/CORE/Makefile
r7773 r8219 122 122 arb_string.o: arb_string.h 123 123 arb_string.o: $(ARBHOME)/INCLUDE/arb_assert.h 124 arb_string.o: $(ARBHOME)/INCLUDE/arbtools.h 124 125 arb_string.o: $(ARBHOME)/INCLUDE/attributes.h 125 126 arb_string.o: $(ARBHOME)/INCLUDE/dupstr.h 126 127 arb_string.o: $(ARBHOME)/INCLUDE/test_global.h 128 arb_string.o: $(ARBHOME)/INCLUDE/test_unit.h -
branches/dev/CORE/arb_string.cxx
r7300 r8219 69 69 70 70 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 83 using 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 94 void 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 101 void 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 131 void 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 151 void 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 164 void 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 227 void 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) --- 294 class user_type { 295 int x, y; 296 public: 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: 313 inline bool operator == (const user_type& u1, const user_type& u2) { return u1.get_x() == u2.get_x() && u1.get_y() == u2.get_y(); } 314 inline char *val2readable(const user_type& u) { return arb_test::StaticCode::strf("user_type(%i,%i)", u.get_x(), u.get_y()); } 315 inline bool in_same_quadrant(const user_type& u1, const user_type& u2) { return u1.quadrant() == u2.quadrant(); } 316 317 void 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 334 void 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 348 void 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 79 79 iupac.o: $(ARBHOME)/INCLUDE/arb_core.h 80 80 iupac.o: $(ARBHOME)/INCLUDE/arbdb_base.h 81 iupac.o: $(ARBHOME)/INCLUDE/arbtools.h 81 82 iupac.o: $(ARBHOME)/INCLUDE/dupstr.h 82 83 iupac.o: $(ARBHOME)/INCLUDE/test_global.h -
branches/dev/UNIT_TESTER/TestEnvironment.cxx
r8006 r8219 162 162 if (!fp) { 163 163 GB_ERROR error = GB_IO_error("creating flag", flagfile); 164 StaticCode::errorf(__FILE__, __LINE__, "%s\n", error);164 HERE.errorf(true, "%s\n", error); 165 165 } 166 166 fclose(fp); … … 176 176 if (res != 0) { 177 177 GB_ERROR error = GB_IO_error("unlinking", flagfile); 178 StaticCode::errorf(__FILE__, __LINE__, "%s\n", error);178 HERE.errorf(true, "%s\n", error); 179 179 } 180 180 env_assert(!flagFileExists()); -
branches/dev/UNIT_TESTER/test_unit.h
r8006 r8219 16 16 #include <arb_assert.h> 17 17 #endif 18 #ifndef ARBTOOLS_H 19 #include <arbtools.h> 20 #endif 18 21 #ifndef _GLIBCXX_CSTDARG 19 22 #include <cstdarg> … … 25 28 #include <errno.h> 26 29 #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 27 38 28 39 #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()30 40 31 41 /* Note: … … 36 46 * test is known to fail, but cannot be fixed atm for some reason 37 47 * 48 * Recommended test-assertion is TEST_EXPECT(that(..).xxx()) 49 * see examples in test-unit-tests in ../CORE/arb_string.cxx@UNIT_TESTS 38 50 */ 39 51 … … 42 54 namespace arb_test { 43 55 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); 47 94 if (message_type) fprintf(stderr, "%s: ", message_type); 48 95 vfprintf(stderr, format, parg); 49 96 } 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))54 97 55 98 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 { 57 140 static void printf(const char *format, ...) __attribute__((format(printf, 1, 2))) { 58 141 FlushedOutputNoLF yes; 59 142 VPRINTFORMAT(format); 60 143 } 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 failure77 }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 failure86 }87 144 #undef VPRINTFORMAT 88 145 #undef VCOMPILERMSG 89 146 #undef WITHVALISTFROM 90 147 91 static void print_readable_string(const char *s, FILE *out) {148 static char *readable_string(const char *s) { 92 149 // quote like C does! 93 150 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 } 102 177 } 103 178 } 104 fputc('\"', out); 179 res[j++] = '\"'; 180 res[j++] = 0; 181 return res; 105 182 } 106 183 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); } 129 224 130 225 // dont dup size_t: 131 226 #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); } 134 229 #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); } 137 232 #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); } 138 245 139 246 template <typename T1, typename T2> inline void print_pair(T1 t1, T2 t2) { 140 247 print(t1); 141 fputs(", ", stderr);248 fputs(",", stderr); 142 249 print(t2); 143 250 } … … 148 255 } 149 256 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()); } 180 272 #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 }; 288 274 289 275 inline bool files_are_equal(const char *file1, const char *file2) { … … 362 348 return !error; 363 349 } 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); } 364 988 }; 365 989 366 990 // -------------------------------------------------------------------------------- 367 991 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)) 374 1030 375 1031 // -------------------------------------------------------------------------------- … … 392 1048 } while (0) 393 1049 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)) 397 1052 398 1053 #define TEST_ASSERT_ZERO_OR_SHOW_ERRNO(iocond) \ … … 544 1199 // -------------------------------------------------------------------------------- 545 1200 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)) 564 1218 565 1219 // --------------------------------------------------------------------------------
