ARB
arb_diff.cxx
Go to the documentation of this file.
1 // ================================================================= //
2 // //
3 // File : arb_diff.cxx //
4 // Purpose : code to compare/diff files //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in September 2013 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // ================================================================= //
11 
12 // AISC_MKPT_PROMOTE:#ifndef _GLIBCXX_CSTDLIB
13 // AISC_MKPT_PROMOTE:#include <cstdlib>
14 // AISC_MKPT_PROMOTE:#endif
15 
16 #include "arb_diff.h"
17 #include "arb_match.h"
18 #include "arb_string.h"
19 #include "arb_msg.h"
20 #include "arb_file.h"
21 
22 #include <arb_str.h>
23 #include <arbtools.h>
24 #include <smartptr.h>
25 
26 #include <list>
27 #include <string>
28 
29 #define MAX_REGS 13
30 
31 class difflineMode : virtual Noncopyable {
32  bool ignoreDateTimeChanges;
33 
34  GBS_regex *reg[MAX_REGS];
35  bool wordsOnly[MAX_REGS]; // only match if regexpr hits a word
36  const char *replace[MAX_REGS];
37 
38  int count;
39  mutable GB_ERROR error;
40 
41  void add(bool onlyWords, const char *regEx, GB_CASE case_flag, const char *replacement) {
42  if (!error) {
43  arb_assert(count<MAX_REGS);
44  reg[count] = GBS_compile_regexpr(regEx, case_flag, &error);
45  if (!error) {
46  replace[count] = replacement;
47  wordsOnly[count] = onlyWords;
48  count++;
49  }
50  }
51  }
52 
53  static bool is_word_char(char c) { return isalnum(c) || c == '_'; } // matches posix word def
54 
55  typedef SmartCustomPtr(GBS_regex, GBS_free_regexpr) GBS_regexPtr;
56 
57  mutable bool may_involved;
58  static GBS_regexPtr contains_May;
59 
60  void avoid_may_problems(const char *str) const {
61  if (!may_involved) {
62  if (GBS_regmatch_compiled(str, &*contains_May, NULp)) {
63  // 'May' does not differ between short/long monthname
64  // -> use less accurate tests in May
65  fprintf(stderr, "Loosening month comparison: 'May' involved in '%s'\n", str);
66  const_cast<difflineMode*>(this)->add(false, "<Month>", GB_MIND_CASE, "<MON>");
67  may_involved = true;
68  }
69  }
70  }
71 
72 public:
73  difflineMode(bool ignoreDateTimeChanges_) :
74  ignoreDateTimeChanges(ignoreDateTimeChanges_),
75  count(0),
76  error(NULp),
77  may_involved(false)
78  {
79  memset(reg, 0, sizeof(reg));
80  if (ignoreDateTimeChanges) {
81  add(false, "[0-9]{2}:[0-9]{2}:[0-9]{2}", GB_MIND_CASE, "<TIME>");
82  add(true, "(Mon|Tue|Wed|Thu|Fri|Sat|Sun)", GB_IGNORE_CASE, "<DOW>");
83 
84  add(true, "(January|February|March|April|May|June|July|August|September|October|November|December)", GB_IGNORE_CASE, "<Month>");
85  add(true, "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)", GB_IGNORE_CASE, "<MON>");
86 
87  add(false, "<MON>[ -][0-9]{4}", GB_IGNORE_CASE, "<MON> <YEAR>");
88  add(false, "<Month>[ -][0-9]{4}", GB_IGNORE_CASE, "<Month> <YEAR>");
89 
90  add(false, "<TIME>[ -][0-9]{4}", GB_IGNORE_CASE, "<TIME> <YEAR>");
91 
92  add(false, "<MON>[ -][0-9 ]?[0-9]", GB_IGNORE_CASE, "<MON> <DAY>");
93  add(false, "<Month>[ -][0-9 ]?[0-9]", GB_IGNORE_CASE, "<Month> <DAY>");
94 
95  add(false, "[0-9]{2}[ -\\.]+<MON>", GB_IGNORE_CASE, "<DAY> <MON>");
96  add(false, "[0-9]{2}[ -\\.]+<Month>", GB_IGNORE_CASE, "<DAY> <Month>");
97 
98  add(false, "<DAY>, [0-9]{4}", GB_IGNORE_CASE, "<DAY> <YEAR>");
99  }
100  }
102  for (int i = 0; i<count; ++i) {
103  GBS_free_regexpr(reg[i]);
104  reg[i] = NULp;
105  }
106  }
107 
108  const char *get_error() const { return error; }
109  int get_count() const { return count; }
110 
111 private:
112  void replaceAll(char*& str) const {
113  for (int i = 0; i<count; ++i) {
114  size_t matchlen;
115  const char *matched = GBS_regmatch_compiled(str, reg[i], &matchlen);
116 
117  if (matched) {
118  char *prefix = ARB_strpartdup(str, matched-1);
119  const char *suffix = matched+matchlen;
120 
121  bool do_repl = true;
122  if (wordsOnly[i]) {
123  if (prefix[0] != 0 && is_word_char(matched[-1])) do_repl = false;
124  else if (suffix[0] != 0 && is_word_char(suffix[0])) do_repl = false;
125  }
126 
127  if (do_repl) freeset(str, GBS_global_string_copy("%s%s%s", prefix, replace[i], suffix));
128 
129  free(prefix);
130  }
131  }
132  }
133 public:
134  void replaceAll(char*& str1, char*& str2) const {
135  avoid_may_problems(str1);
136  avoid_may_problems(str2);
137  replaceAll(str1);
138  replaceAll(str2);
139  }
140 };
141 
143 difflineMode::GBS_regexPtr difflineMode::contains_May = GBS_compile_regexpr("May", GB_IGNORE_CASE, &static_error);
144 
145 static void cutEOL(char *s) {
146  char *lf = strchr(s, '\n');
147  if (lf) lf[0] = 0;
148 }
149 
150 static bool test_accept_diff_lines(const char *line1, const char *line2, const difflineMode& mode) {
151  if (*line1++ != '-') return false;
152  if (*line2++ != '+') return false;
153 
154  char *dup1 = ARB_strdup(line1);
155  char *dup2 = ARB_strdup(line2);
156 
157  cutEOL(dup1); // side-effect: accepts missing trailing newline
158  cutEOL(dup2);
159 
160  mode.replaceAll(dup1, dup2);
161 
162  bool equalNow = strcmp(dup1, dup2) == 0;
163 #if defined(DEBUG)
164  // printf("dup1='%s'\ndup2='%s'\n", dup1, dup2); // uncomment this line to trace replaces
165 #endif // DEBUG
166 
167  free(dup2);
168  free(dup1);
169 
170  return equalNow;
171 }
172 
173 class DiffLines {
174  typedef std::list<std::string> Lines;
175  typedef Lines::iterator LinesIter;
176  typedef Lines::const_iterator LinesCIter;
177 
178  Lines added_lines;
179  Lines deleted_lines;
180 
181  LinesIter added_last_checked;
182  LinesIter deleted_last_checked;
183 
184  static LinesIter next(LinesIter iter) { advance(iter, 1); return iter; }
185  static LinesIter last(Lines& lines) { return (++lines.rbegin()).base(); }
186 
187  void set_checked() {
188  added_last_checked = last(added_lines);
189  deleted_last_checked = last(deleted_lines);
190  }
191 
192 public:
193  DiffLines() { set_checked(); }
194 
195  bool add(const char *diffline) {
196  bool did_add = true;
197  switch (diffline[0]) {
198  case '-': deleted_lines.push_back(diffline); break;
199  case '+': added_lines.push_back(diffline); break;
200  default : did_add = false; break;
201  }
202  // fputs(diffline, stdout); // uncomment to show all difflines
203  return did_add;
204  }
205 
206  int added() const { return added_lines.size(); }
207  int deleted() const { return deleted_lines.size(); }
208 
210  LinesIter d = next(deleted_last_checked);
211  LinesIter dEnd = deleted_lines.end();
212  LinesIter a = next(added_last_checked);
213  LinesIter aEnd = added_lines.end();
214 
215 
216  while (d != dEnd && a != aEnd) {
217  if (test_accept_diff_lines(d->c_str(), a->c_str(), mode)) {
218  d = deleted_lines.erase(d);
219  a = added_lines.erase(a);
220  }
221  else {
222  ++d;
223  ++a;
224  }
225  }
226  set_checked();
227  }
228 
229  void print_from(FILE *out, LinesCIter a, LinesCIter d) const {
230  LinesCIter dEnd = deleted_lines.end();
231  LinesCIter aEnd = added_lines.end();
232 
233  while (d != dEnd && a != aEnd) {
234  fputs(d->c_str(), out); ++d;
235  fputs(a->c_str(), out); ++a;
236  }
237  while (d != dEnd) { fputs(d->c_str(), out); ++d; }
238  while (a != aEnd) { fputs(a->c_str(), out); ++a; }
239  }
240 
241  void print(FILE *out) const {
242  LinesCIter d = deleted_lines.begin();
243  LinesCIter a = added_lines.begin();
244  print_from(out, a, d);
245  }
246 };
247 
248 // AISC_MKPT_PROMOTE:enum TextDiffMode { TDM_DIFF_LINECOUNT=0, TDM_IGNORE_TIMESTAMPS=1, TDM_NOT_DIFF_LINECOUNT=2 };
249 
250 bool ARB_textfiles_have_difflines(const char *file1, const char *file2, int expected_difflines, TextDiffMode tdmode) {
251  // tdmode & TDM_IGNORE_TIMESTAMPS -> accept date and time changes as equal
252  //
253  // Warning: also returns true if comparing two EQUAL binary files.
254  // But it always fails if one file is binary and files differ
255  //
256  // Always fails if one or both files are missing.
257 
258  const char *error = NULp;
259 
260  if (!GB_is_regularfile(file1)) error = GBS_global_string("No such file '%s'", file1);
261  else if (!GB_is_regularfile(file2)) error = GBS_global_string("No such file '%s'", file2);
262  else {
263  char *cmd = GBS_global_string_copy("/usr/bin/diff --unified %s %s", file1, file2);
264  FILE *diffout = popen(cmd, "r");
265 
266  if (diffout) {
267 #define BUFSIZE 20000
268  char *buffer = ARB_alloc<char>(BUFSIZE);
269  bool inHunk = false;
270  DiffLines diff_lines;
271  difflineMode mode(tdmode & TDM_IGNORE_TIMESTAMPS);
272 
273  // TEST_EXPECT_NO_ERROR(mode.get_error());
274  error = mode.get_error();
275 
276  while (!error && !feof(diffout)) {
277  char *line = fgets(buffer, BUFSIZE, diffout);
278  if (!line) break;
279 
280 #if defined(ASSERTION_USED)
281  size_t len = strlen(line);
282  arb_assert(len<(BUFSIZE-1)); // increase BUFSIZE
283 #endif
284 
285  if (ARB_strBeginsWith(line, "Binary files")) {
286  if (strstr(line, "differ")) {
287  error = "attempt to compare binary files";
288  }
289  }
290  else {
291  bool remove_now = true;
292  if (strncmp(line, "@@", 2) == 0) inHunk = true;
293  else if (!inHunk && strncmp(line, "Index: ", 7) == 0) inHunk = false;
294  else if (inHunk) {
295  remove_now = !diff_lines.add(line);
296  }
297 
298  if (remove_now) diff_lines.remove_accepted_lines(mode);
299  }
300  }
301 
302  if (!error) {
303  diff_lines.remove_accepted_lines(mode);
304 
305  int added = diff_lines.added();
306  int deleted = diff_lines.deleted();
307  bool dump_diffs = false;
308 
309  if (added != deleted) {
310  error = GBS_global_string("added lines (=%i) differ from deleted lines(=%i)", added, deleted);
311  dump_diffs = true;
312  }
313  else {
314  // here 'added' contains "changed lines"
315  bool matches_expected = added == expected_difflines;
316  bool want_expected = (tdmode & TDM_NOT_DIFF_LINECOUNT) == 0;
317 
318  if (matches_expected != want_expected) { // fail
319  error = GBS_global_string("files differ in %i lines (expected: %s%i)",
320  added,
321  want_expected ? "" : "not ",
322  expected_difflines);
323 
324  dump_diffs = added != 0;
325  }
326  }
327 
328  if (dump_diffs) {
329  fputs("Different lines:\n", stdout);
330  diff_lines.print(stdout);
331  fputc('\n', stdout);
332  }
333  }
334  free(buffer);
335  IF_ASSERTION_USED(int err =) pclose(diffout);
336  arb_assert(err != -1);
337 #undef BUFSIZE
338  }
339  else {
340  error = GBS_global_string("failed to run diff (%s)", cmd);
341  }
342  free(cmd);
343  }
344  // return result;
345  if (error) printf("ARB_textfiles_have_difflines(%s, %s) fails: %s\n", file1, file2, error);
346  return !error;
347 }
348 
349 #ifdef UNIT_TESTS
350 #include <test_unit.h>
351 
352 size_t ARB_test_mem_equal(const unsigned char *buf1, const unsigned char *buf2, size_t common, size_t blockStartAddress) {
353  size_t equal_bytes;
354  if (memcmp(buf1, buf2, common) == 0) {
355  equal_bytes = common;
356  }
357  else {
358  equal_bytes = 0;
359  size_t x = 0; // position inside memory
360  while (buf1[x] == buf2[x]) {
361  x++;
362  equal_bytes++;
363  }
364 
365  const size_t DUMP = 7;
366  size_t y1 = x >= DUMP ? x-DUMP : 0;
367  size_t y2 = (x+2*DUMP)>common ? common : (x+2*DUMP);
368  size_t blockstart = blockStartAddress+equal_bytes-x;
369 
370  for (size_t y = y1; y <= y2; y++) {
371  fprintf(stderr, "[0x%04zx]", blockstart+y);
372  arb_test::print_pair(buf1[y], buf2[y]);
373  fputc(' ', stderr);
374  arb_test::print_hex_pair(buf1[y], buf2[y]);
375  if (buf1[y] != buf2[y]) fputs(" <- diff", stderr);
376  fputc('\n', stderr);
377  }
378  if (y2 == common) {
379  fputs("[end of block - truncated]\n", stderr);
380  }
381  }
382  return equal_bytes;
383 }
384 
385 static GB_ERROR compare_files(const char *file1, const char *file2, bool error_if_different) {
386  const char *error = NULp;
387  FILE *fp1 = fopen(file1, "rb");
388 
389  if (!fp1) {
390  printf("can't open '%s'\n", file1);
391  error = "i/o error";
392  }
393  else {
394  FILE *fp2 = fopen(file2, "rb");
395  if (!fp2) {
396  printf("can't open '%s'\n", file2);
397  error = "i/o error";
398  }
399  else {
400  const int BLOCKSIZE = 4096;
401  unsigned char *buf1 = ARB_alloc<unsigned char>(BLOCKSIZE);
402  unsigned char *buf2 = ARB_alloc<unsigned char>(BLOCKSIZE);
403  size_t equal_bytes = 0;
404 
405  while (!error) {
406  int read1 = fread(buf1, 1, BLOCKSIZE, fp1);
407  int read2 = fread(buf2, 1, BLOCKSIZE, fp2);
408  size_t common = read1<read2 ? read1 : read2;
409 
410  if (!common) {
411  if (read1 != read2) error = "filesize differs";
412  break;
413  }
414 
415  size_t eqCount = ARB_test_mem_equal(buf1, buf2, common, equal_bytes);
416  if (eqCount != common) {
417  error = "content differs";
418  }
419  equal_bytes += eqCount;
420  }
421 
422  if (error) printf("compare_files: equal_bytes=%zu\n", equal_bytes);
423  arb_assert(error || equal_bytes); // comparing empty files is nonsense
424 
425  free(buf2);
426  free(buf1);
427  fclose(fp2);
428 
429  if (!error_if_different) error = error ? NULp : "files are equal";
430  }
431  fclose(fp1);
432  }
433 
434  return error;
435 }
436 
437 
438 bool ARB_files_are_equal(const char *file1, const char *file2) {
439  GB_ERROR error = compare_files(file1, file2, true);
440  if (error) printf("ARB_files_are_equal(%s, %s) fails: %s\n", file1, file2, error);
441  return !error;
442 }
443 bool ARB_files_differ(const char *file1, const char *file2) { // used via unittest macros (e.g. TEST_EXPECT_FILES_DIFFER)
444  GB_ERROR error = compare_files(file1, file2, false);
445  if (error) printf("ARB_files_differ(%s, %s) fails: %s\n", file1, file2, error);
446  return !error;
447 }
448 
449 void TEST_diff_files() {
450  // files are in ../UNIT_TESTER/run/diff
451  const char *file = "diff/base.input";
452  const char *file_swapped = "diff/swapped.input"; // same dates as 'base', but 2 other lines swapped
453  const char *file_date_swapped = "diff/date_swapped.input"; // compared to 'base': 3 pairs of date-lines were swapped
454  // compared to 'swapped': 3 pairs of date-lines were swapped + 2 other lines were swapped
455  const char *file_date_changed = "diff/date_changed.input"; // compared to 'base' only dates were changed;
456  // compared to 'swapped' dates were changed and 2 other lines were swapped
457  // compared to 'date_swapped' dates were changed
458  const char *file_missing = "diff/nosuch.input";
459 
460  TEST_EXPECT(ARB_textfiles_have_difflines(file, file, 0, TDM_DIFF_LINECOUNT)); // check identity
461 
462  TEST_EXPECT(ARB_textfiles_have_difflines(file, file_swapped, 0, TDM_NOT_DIFF_LINECOUNT)); // check difference (will fail when files get equal)
463  TEST_REJECT(ARB_textfiles_have_difflines(file, file, 0, TDM_NOT_DIFF_LINECOUNT)); // failing difference-test (reason: files are equal)
464  TEST_REJECT(ARB_textfiles_have_difflines(file, file_missing, 0, TDM_NOT_DIFF_LINECOUNT)); // failing difference-test (reason: not all files exist)
465 
466  // check if swapped lines are detected properly
469 
470  TEST_EXPECT(ARB_textfiles_have_difflines(file, file_date_swapped, 3, TDM_DIFF_LINECOUNT));
471  TEST_EXPECT(ARB_textfiles_have_difflines(file, file_date_swapped, 3, TDM_IGNORE_TIMESTAMPS));
472 
473  TEST_EXPECT(ARB_textfiles_have_difflines(file, file_date_changed, 6, TDM_DIFF_LINECOUNT));
474  TEST_EXPECT(ARB_textfiles_have_difflines(file, file_date_changed, 0, TDM_IGNORE_TIMESTAMPS));
475 
476  TEST_EXPECT(ARB_textfiles_have_difflines(file_swapped, file_date_swapped, 4, TDM_DIFF_LINECOUNT));
477  TEST_EXPECT(ARB_textfiles_have_difflines(file_swapped, file_date_swapped, 4, TDM_IGNORE_TIMESTAMPS));
478 
479  TEST_EXPECT(ARB_textfiles_have_difflines(file_swapped, file_date_changed, 7, TDM_DIFF_LINECOUNT));
480  TEST_EXPECT(ARB_textfiles_have_difflines(file_swapped, file_date_changed, 1, TDM_IGNORE_TIMESTAMPS));
481 
482  TEST_EXPECT(ARB_textfiles_have_difflines(file_date_swapped, file_date_changed, 6, TDM_DIFF_LINECOUNT));
483  TEST_EXPECT(ARB_textfiles_have_difflines(file_date_swapped, file_date_changed, 0, TDM_IGNORE_TIMESTAMPS));
484 
485  // test combination of TDM_NOT_DIFF_LINECOUNT and TDM_IGNORE_TIMESTAMPS:
486  TEST_EXPECT(ARB_textfiles_have_difflines(file_swapped, file_date_changed, 0, TextDiffMode(TDM_NOT_DIFF_LINECOUNT|TDM_IGNORE_TIMESTAMPS))); // check difference beyond date-lines
487  TEST_REJECT(ARB_textfiles_have_difflines(file, file_date_changed, 0, TextDiffMode(TDM_NOT_DIFF_LINECOUNT|TDM_IGNORE_TIMESTAMPS))); // failing difference-test (reason: only dates differ)
488 
489  const char *binary = "TEST_gpt.arb.expected"; // a binary arb DB
490  const char *binary2 = "TEST_gpt.arb.pt.expected"; // a ptserver index
491  const char *text = file;
492 
493  // diff between text and binary should fail
498 
499  // diff between two binaries shall fails as well ..
502 
503  // when files do not differ, ARB_textfiles_have_difflines always
504  // returns true - even if the files are binary
505  // (unwanted but accepted behavior)
510 }
511 
512 // --------------------------------------------------------------------------------
513 // tests for global code included from central ARB headers (located in $ARBHOME/TEMPLATES)
514 
515 // gcc reports: "warning: logical 'or' of collectively exhaustive tests is always true"
516 // for 'implicated(any, any)'. True, obviously. Nevertheless annoying.
517 #pragma GCC diagnostic ignored "-Wlogical-op"
518 
519 void TEST_logic() {
520 #define FOR_ANY_BOOL(name) for (int name = 0; name<2; ++name)
521 
522  TEST_EXPECT(implicated(true, true));
523  // for (int any = 0; any<2; ++any) {
524  FOR_ANY_BOOL(any) {
525  TEST_EXPECT(implicated(false, any)); // "..aus Falschem folgt Beliebiges.."
526  TEST_EXPECT(implicated(any, any));
527 
528  TEST_EXPECT(correlated(any, any));
529  TEST_REJECT(correlated(any, !any));
530  TEST_REJECT(contradicted(any, any));
531  TEST_EXPECT(contradicted(any, !any));
532  }
533 
534  TEST_EXPECT(correlated(false, false));
535 
536  TEST_EXPECT(contradicted(true, false));
537  TEST_EXPECT(contradicted(false, true));
538 
539  FOR_ANY_BOOL(kermitIsFrog) {
540  FOR_ANY_BOOL(kermitIsGreen) {
541  bool allFrogsAreGreen = implicated(kermitIsFrog, kermitIsGreen);
542  bool onlyFrogsAreGreen = implicated(kermitIsGreen, kermitIsFrog);
543 
544  TEST_EXPECT(implicated( kermitIsFrog && allFrogsAreGreen, kermitIsGreen));
545  TEST_EXPECT(implicated(!kermitIsGreen && allFrogsAreGreen, !kermitIsFrog));
546 
547  TEST_EXPECT(implicated( kermitIsGreen && onlyFrogsAreGreen, kermitIsFrog));
548  TEST_EXPECT(implicated(!kermitIsFrog && onlyFrogsAreGreen, !kermitIsGreen));
549 
550  TEST_EXPECT(implicated(kermitIsFrog && !kermitIsGreen, !allFrogsAreGreen));
551  TEST_EXPECT(implicated(kermitIsGreen && !kermitIsFrog, !onlyFrogsAreGreen));
552 
553  TEST_EXPECT(correlated(
554  correlated(kermitIsGreen, kermitIsFrog),
555  allFrogsAreGreen && onlyFrogsAreGreen
556  ));
557  }
558  }
559 }
560 
561 #include <cmath>
562 // #include <math.h>
563 
564 void TEST_naninf() {
565  double num = 3.1415;
566  double zero = num-num;
567  double inf = num/zero;
568  double ninf = -inf;
569  double nan = 0*inf;
570 
571  TEST_EXPECT_DIFFERENT(inf, ninf);
572  TEST_EXPECT_EQUAL(ninf, -1.0/zero);
573 
574  // decribe how isnan, isinf and isnormal shall behave:
575 #define TEST_ISINF(isinf_fun) \
576  TEST_EXPECT(isinf_fun(inf)); \
577  TEST_EXPECT(!!isinf_fun(ninf)); \
578  TEST_EXPECT(isinf_fun(INFINITY)); \
579  TEST_EXPECT(!isinf_fun(nan)); \
580  TEST_EXPECT(!isinf_fun(NAN)); \
581  TEST_EXPECT(!isinf_fun(num)); \
582  TEST_EXPECT(!isinf_fun(zero))
583 
584 #define TEST_ISNAN(isnan_fun) \
585  TEST_EXPECT(isnan_fun(nan)); \
586  TEST_EXPECT(isnan_fun(NAN)); \
587  TEST_EXPECT(!isnan_fun(inf)); \
588  TEST_EXPECT(!isnan_fun(ninf)); \
589  TEST_EXPECT(!isnan_fun(INFINITY)); \
590  TEST_EXPECT(!isnan_fun(zero)); \
591  TEST_EXPECT(!isnan_fun(num))
592 
593 #define TEST_ISNORMAL(isnormal_fun) \
594  TEST_EXPECT(isnormal_fun(num)); \
595  TEST_EXPECT(!isnormal_fun(zero)); \
596  TEST_EXPECT(!isnormal_fun(inf)); \
597  TEST_EXPECT(!isnormal_fun(ninf)); \
598  TEST_EXPECT(!isnormal_fun(nan)); \
599  TEST_EXPECT(!isnormal_fun(INFINITY)); \
600  TEST_EXPECT(!isnormal_fun(NAN))
601 
602  // check behavior of arb templates:
603  TEST_ISNAN(is_nan);
604  TEST_ISINF(is_inf);
605  TEST_ISNORMAL(is_normal);
606 
607 #if !defined(DARWIN)
608  // TEST_DISABLED_OSX: section fails compilation under OSX
609 # if (GCC_PATCHLEVEL_CODE < 50301)
610  // (section leads to compile error with gcc 5.3.1 - suggesting std::isnan and std::isinf)
611  // document behavior of math.h macros:
612  TEST_ISNAN(isnan);
613 # if (GCC_PATCHLEVEL_CODE >= 40403 && GCC_PATCHLEVEL_CODE <= 40407 && defined(DEBUG))
614  // TEST_ISINF(isinf); // isinf macro is broken (gcc 4.4.3 up to gcc 4.4.7, if compiled with DEBUG)
615  TEST_EXPECT__BROKEN(isinf(ninf)); // broken; contradicts http://www.cplusplus.com/reference/cmath/isinf/
616 # else
617  TEST_ISINF(isinf);
618 # endif
619  // TEST_ISNORMAL(isnormal); // ok if <math.h> included, compile error if <cmath> included
620 # endif
621 #endif // DARWIN
622 
623  // check behavior of std-versions:
624  TEST_ISNAN(std::isnan);
625  TEST_ISINF(std::isinf);
626  TEST_ISNORMAL(std::isnormal);
627 }
628 
629 #endif // UNIT_TESTS
void print(FILE *out) const
Definition: arb_diff.cxx:241
#define arb_assert(cond)
Definition: arb_assert.h:245
#define BUFSIZE
const char * GB_ERROR
Definition: arb_core.h:25
void remove_accepted_lines(const difflineMode &mode)
Definition: arb_diff.cxx:209
#define implicated(hypothesis, conclusion)
Definition: arb_assert.h:289
bool ARB_files_differ(const char *file1, const char *file2)
size_t ARB_test_mem_equal(const unsigned char *buf1, const unsigned char *buf2, size_t common, size_t blockStartAddress)
GBS_regex * GBS_compile_regexpr(const char *regexpr, GB_CASE case_flag, GB_ERROR *error)
Definition: arb_match.cxx:40
static char * y[maxsp+1]
bool ARB_files_are_equal(const char *file1, const char *file2)
int added() const
Definition: arb_diff.cxx:206
TextDiffMode
Definition: arb_diff.h:19
static void cutEOL(char *s)
Definition: arb_diff.cxx:145
const char * get_error() const
Definition: arb_diff.cxx:108
int deleted() const
Definition: arb_diff.cxx:207
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
void replaceAll(char *&str1, char *&str2) const
Definition: arb_diff.cxx:134
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
static GB_ERROR static_error
Definition: arb_diff.cxx:142
CONSTEXPR_INLINE bool is_nan(const T &n)
Definition: arbtools.h:174
char * ARB_strpartdup(const char *start, const char *end)
Definition: arb_string.h:51
CONSTEXPR_INLINE bool is_normal(const T &n)
Definition: arbtools.h:176
char buffer[MESSAGE_BUFFERSIZE]
Definition: seq_search.cxx:34
#define TEST_EXPECT(cond)
Definition: test_unit.h:1313
CONSTEXPR_INLINE bool is_inf(const T &n)
Definition: arbtools.h:177
#define false
Definition: ureadseq.h:13
#define TEST_REJECT(cond)
Definition: test_unit.h:1315
#define MAX_REGS
Definition: arb_diff.cxx:29
bool add(const char *diffline)
Definition: arb_diff.cxx:195
static void error(const char *msg)
Definition: mkptypes.cxx:96
fputc('\n', stderr)
void print_from(FILE *out, LinesCIter a, LinesCIter d) const
Definition: arb_diff.cxx:229
bool ARB_textfiles_have_difflines(const char *file1, const char *file2, int expected_difflines, TextDiffMode tdmode)
Definition: arb_diff.cxx:250
GB_CASE
Definition: arb_core.h:30
const char * GBS_regmatch_compiled(const char *str, GBS_regex *comreg, size_t *matchlen)
Definition: arb_match.cxx:120
fputs(TRACE_PREFIX, stderr)
void print_pair(T1 t1, T2 t2)
Definition: test_unit.h:355
#define IF_ASSERTION_USED(x)
Definition: arb_assert.h:308
difflineMode(bool ignoreDateTimeChanges_)
Definition: arb_diff.cxx:73
static bool test_accept_diff_lines(const char *line1, const char *line2, const difflineMode &mode)
Definition: arb_diff.cxx:150
void GBS_free_regexpr(GBS_regex *toFree)
Definition: arb_match.cxx:62
static int line
Definition: arb_a2ps.c:296
#define NULp
Definition: cxxforward.h:97
bool GB_is_regularfile(const char *path)
Definition: arb_file.cxx:76
#define TEST_EXPECT_DIFFERENT(expr, want)
Definition: test_unit.h:1290
bool ARB_strBeginsWith(const char *str, const char *with)
Definition: arb_str.h:42
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1283
int get_count() const
Definition: arb_diff.cxx:109
#define TEST_EXPECT__BROKEN(cond)
Definition: test_unit.h:1314
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:195
void print_hex_pair(T1 t1, T2 t2)
Definition: test_unit.h:360
GB_write_int const char s
Definition: AW_awar.cxx:156