source: branches/stable/CORE/arb_string.cxx

Last change on this file was 17491, checked in by westram, 6 years ago
  • partial merge from 'fix' into 'trunk'
    • fix OSX build (was broken by [17387]):
      • uses wrapper ARB_strchrnul instead of directly using strchrnul
      • OSX version uses replacement code
  • adds: log:branches/fix@17486:17490
File size: 17.2 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : arb_string.cxx                                     //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Coded by Ralf Westram (coder@reallysoft.de) in November 2010   //
7//   Institute of Microbiology (Technical University Munich)        //
8//   http://www.arb-home.de/                                        //
9//                                                                  //
10// ================================================================ //
11
12#include "arb_string.h"
13
14#include <ctime>
15#include <sys/time.h>
16#include <Keeper.h>
17
18inline tm *get_current_time() {
19    timeval  date;
20    tm      *p;
21
22    gettimeofday(&date, NULp);
23
24#if defined(DARWIN)
25    struct timespec local;
26    TIMEVAL_TO_TIMESPEC(&date, &local); // not avail in time.h of Linux gcc 2.95.3
27    p = localtime(&local.tv_sec);
28#else
29    p = localtime(&date.tv_sec);
30#endif // DARWIN
31
32    return p;
33}
34
35const char *ARB_date_string() {
36    tm   *p        = get_current_time();
37    char *readable = asctime(p); // points to a static buffer
38    char *cr       = strchr(readable, '\n');
39    arb_assert(cr);
40    cr[0]          = 0;          // cut of \n
41
42    return readable;
43}
44
45const char *ARB_dateTime_suffix() {
46    /*! returns "YYYYMMDD_HHMMSS" */
47    const  unsigned  SUFFIXLEN = 8+1+6;
48    static char      buffer[SUFFIXLEN+1];
49    tm              *p         = get_current_time();
50
51#if defined(ASSERTION_USED)
52    size_t printed =
53#endif
54        strftime(buffer, SUFFIXLEN+1, "%Y%m%d_%H%M%S", p);
55    arb_assert(printed == SUFFIXLEN);
56    buffer[SUFFIXLEN] = 0;
57
58    return buffer;
59}
60
61// --------------------------------------------------------------------------------
62
63const char *ARB_keep_string(char *str) {
64    /*! keep an allocated string until program termination
65     * useful to avoid valgrind reporting leaks e.g for callback parameters
66     */
67    static Keeper<char*> stringKeeper;
68    stringKeeper.keep(str);
69    return str;
70}
71
72
73// --------------------------------------------------------------------------------
74
75
76#ifdef UNIT_TESTS
77
78#include <string>
79#include <climits>
80
81#ifndef TEST_UNIT_H
82#include <test_unit.h>
83#endif
84
85using namespace std;
86
87// ----------------------------------------------
88//      some tests for unit-test-code itself
89
90#define TEST_EXPECT_HEAPCOPY_EQUAL(copy,expected) do {  \
91        char *theCopy = (copy);                         \
92        TEST_EXPECT_EQUAL(theCopy, expected);           \
93        free(theCopy);                                  \
94    } while(0)
95
96void TEST_arbtest_strf() {
97    // tests string formatter from test_unit.h
98    using namespace arb_test;
99    TEST_EXPECT_HEAPCOPY_EQUAL(StaticCode::strf("<%i>", 7), "<7>");
100    TEST_EXPECT_HEAPCOPY_EQUAL(StaticCode::strf("<%0*i>", 3, 7), "<007>");
101}
102
103void TEST_arbtest_readable() {
104    using namespace arb_test;
105
106    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy('x')), "'x' (=0x78)");
107    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(static_cast<unsigned char>('x'))), "'x' (=0x78)");
108    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(static_cast<signed char>('x'))), "'x' (=0x78)");
109
110    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(true)), "true");
111    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(false)), "false");
112   
113    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(1)), "1");
114    TEST_EXPECT_HEAPCOPY_EQUAL(val2hex(make_copy(2)), "0x2");
115
116    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(3L)), "3");
117    TEST_EXPECT_HEAPCOPY_EQUAL(val2hex(make_copy(4L)), "0x4");
118
119    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(5U)), "5");
120    TEST_EXPECT_HEAPCOPY_EQUAL(val2hex(make_copy(6U)), "0x6");
121   
122    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy("some\ntext\twhich\"special\\chars")), "\"some\\ntext\\twhich\\\"special\\\\chars\"");
123    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy("a\x01\x02\x07\x08\x09\x0b\x0c\x0d\x1a\x22\x27\x5c\x7e\x7f\x80\xfe\xff")),
124                               /*                  */ "\"a\\x01\\x02\\a\\b\\t\\v\\f\\r\\x1a\\\"'\\\\~\\x7f\\x80\\xfe\\xff\"");
125    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy((const char *)NULp)), "(null)");
126    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy((const unsigned char *)NULp)), "(null)");
127    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy((const signed char *)NULp)), "(null)");
128
129    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(1.7)), "1.700000");
130    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(177.0e20)),  "17699999999999998951424.000000");
131    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(177.0e20F)), "17699999967695435988992.000000");
132}
133
134void TEST_arbtest_copyable() {
135    using namespace arb_test;
136
137    int         i = 7;
138    const char *s = "servas";
139
140    TEST_EXPECT(make_copy(i) == make_copy(7));
141    TEST_EXPECT_ZERO(strcmp(make_copy(s), make_copy("servas")));
142}
143
144#define TEST_DESCRIPTIONS(d, tt, tf, ft, ff) do {        \
145        TEST_EXPECT_EQUAL((d).make(true, true), (tt));   \
146        TEST_EXPECT_EQUAL((d).make(true, false), (tf));  \
147        TEST_EXPECT_EQUAL((d).make(false, true), (ft));  \
148        TEST_EXPECT_EQUAL((d).make(false, false), (ff)); \
149    } while(0)
150
151#define TEST_SIMPLE_DESCRIPTIONS(d, ae, nae) TEST_DESCRIPTIONS(d, ae, nae, ae, nae)
152
153void TEST_arbtest_predicate_description() {
154    TEST_SIMPLE_DESCRIPTIONS(predicate_description("similar"), "is similar", "isnt similar");
155    TEST_SIMPLE_DESCRIPTIONS(predicate_description("repairs"), "repairs", "doesnt repair");
156
157    TEST_DESCRIPTIONS(predicate_description("equals", "differs"),
158                      "equals", "doesnt equal",
159                      "doesnt differ", "differs");
160
161    TEST_DESCRIPTIONS(predicate_description("less_than", "more_than"),
162                      "is less_than", "isnt less_than",
163                      "isnt more_than", "is more_than");
164}
165
166void TEST_arbtest_expectations() {
167    // used to TDD expectations
168    using namespace arb_test;
169
170    string apple       = "Apfel";
171    string pear        = "Birne";
172    string boskop      = apple;
173    string pomegranate = "Granatapfel";
174
175    TEST_EXPECTATION(that(apple).is_equal_to("Apfel"));
176   
177    TEST_EXPECTATION(that(apple).does_differ_from(pear));
178    TEST_EXPECTATION(that(apple).is_equal_to(boskop));
179    TEST_EXPECTATION(wrong(that(pomegranate).is_equal_to(apple)));
180
181    match_expectation ff1 = that(1.0).is_equal_to(2-1);
182    match_expectation ff2 = that(boskop).is_equal_to(apple);
183    match_expectation ff3 = that(apple).is_equal_to(apple);
184
185    match_expectation nf1 = that(apple).is_equal_to(pear);
186    match_expectation nf2 = that(pomegranate).is_equal_to(apple);
187    match_expectation nf3 = that(apple).does_differ_from(boskop);
188
189    match_expectation a1 = all().of(ff1);
190    match_expectation a2 = all().of(ff1, ff2);
191    match_expectation a3 = all().of(ff1, ff2, ff3);
192
193    TEST_EXPECTATION(a1);
194    TEST_EXPECTATION(a2);
195    TEST_EXPECTATION(a3);
196
197    match_expectation n1 = none().of(ff1);
198    match_expectation n2 = none().of(ff1, ff2);
199    match_expectation n3 = none().of(ff1, ff2, ff3);
200
201    TEST_EXPECTATION(wrong(none().of(that(boskop).is_equal_to(apple))));
202    TEST_EXPECTATION(wrong(n1));
203    TEST_EXPECTATION(wrong(n2));
204    TEST_EXPECTATION(wrong(n3));
205
206    TEST_EXPECTATION(atleast(1).of(a1));
207    TEST_EXPECTATION(atleast(1).of(a1, n1));
208    TEST_EXPECTATION(atleast(1).of(n2, a1, n1));
209
210    TEST_EXPECTATION(wrong(atleast(2).of(a1, n1, n2)));
211    TEST_EXPECTATION(wrong(atleast(2).of(a1, n1)));
212    TEST_EXPECTATION(wrong(atleast(2).of(a1))); // impossible
213
214    TEST_EXPECTATION(atmost(2).of(a1));
215    TEST_EXPECTATION(atmost(2).of(a1, a2));
216    TEST_EXPECTATION(atmost(2).of(a1, a2, n1));
217    TEST_EXPECTATION(atmost(2).of(a1, n1, n2));
218    TEST_EXPECTATION(atmost(2).of(n1, n2));
219    TEST_EXPECTATION(wrong(atmost(2).of(a1, a2, a3)));
220
221    TEST_EXPECTATION(exactly(1).of(ff1, nf1, nf2));
222    TEST_EXPECTATION(wrong(exactly(1).of(nf1, nf2)));
223    TEST_EXPECTATION(wrong(exactly(1).of(nf1, nf2, nf3)));
224    TEST_EXPECTATION(wrong(exactly(1).of(ff1, ff2, nf2)));
225    TEST_EXPECTATION(wrong(exactly(1).of(ff1, ff2, ff3)));
226
227}
228
229void TEST_expectation_groups() {
230    using namespace arb_test;
231
232    expectation_group no_expectations;
233    TEST_EXPECTATION(all().ofgroup(no_expectations));
234    TEST_EXPECTATION(none().ofgroup(no_expectations));
235
236    expectation_group fulfilled_expectation  (that(1).is_equal_to(1));
237    expectation_group unfulfilled_expectation(that(1).is_equal_to(0));
238    expectation_group some_fulfilled_expectations(that(1).is_equal_to(0), that(1).is_equal_to(1));
239
240    TEST_EXPECTATION(all().ofgroup(fulfilled_expectation));
241    TEST_EXPECTATION(none().ofgroup(unfulfilled_expectation));
242
243    TEST_EXPECT(none().ofgroup(fulfilled_expectation).unfulfilled());
244    TEST_EXPECT(all().ofgroup(unfulfilled_expectation).unfulfilled());
245   
246    TEST_EXPECT(all().ofgroup(some_fulfilled_expectations).unfulfilled());
247    TEST_EXPECT(none().ofgroup(some_fulfilled_expectations).unfulfilled());
248}
249
250void TEST_replace_old_TEST_EXPECTS_by_expectations() {
251    // test various string-types are matchable (w/o casts)
252    {
253        const char *car_ccp = "Alfa";
254        char       *car_cp  = ARB_strdup("Alfa");
255        string      car_str("Alfa");
256
257        TEST_EXPECT_EQUAL(car_ccp, "Alfa");
258        TEST_EXPECT_EQUAL(car_cp, "Alfa");
259        TEST_EXPECT_EQUAL(car_str, "Alfa");
260
261        TEST_EXPECT_EQUAL("Alfa", car_ccp);
262        TEST_EXPECT_EQUAL("Alfa", car_cp);
263        TEST_EXPECT_EQUAL("Alfa", car_str);
264
265        TEST_EXPECT_EQUAL(car_cp, car_ccp);
266        TEST_EXPECT_EQUAL(car_cp, car_str);
267        TEST_EXPECT_EQUAL(car_ccp, car_cp);
268        TEST_EXPECT_EQUAL(car_ccp, car_str);
269        TEST_EXPECT_EQUAL(car_str, car_cp);
270        TEST_EXPECT_EQUAL(car_str, car_ccp);
271
272        char *null = NULp;
273        TEST_EXPECT_NULL((void*)NULp);
274        TEST_EXPECT_NULL(null);
275
276        TEST_EXPECT_CONTAINS(car_ccp, "lf");
277        TEST_EXPECT_CONTAINS(car_cp, "fa");
278        TEST_EXPECT_CONTAINS(car_str, "Al");
279
280        free(car_cp);
281    }
282
283    // test various numeric types are matchable
284
285    {
286        short unsigned su = 7;
287        short          s  = -su;
288
289        unsigned iu = su;
290        int      i  = -iu;
291
292        long unsigned lu = (long unsigned)INT_MAX+3;
293        long          l  = -lu;
294
295        float  f = s;
296        double d = i;
297
298        TEST_EXPECT_EQUAL(s, -7);
299        TEST_EXPECT_EQUAL(i, -7);
300
301        TEST_EXPECT_EQUAL(su, 7);  TEST_EXPECT_EQUAL(iu, 7);
302        TEST_EXPECT_EQUAL(su, 7U); TEST_EXPECT_EQUAL(iu, 7U);
303        TEST_EXPECT_EQUAL(su, 7L); TEST_EXPECT_EQUAL(iu, 7L);
304
305        TEST_EXPECT_EQUAL(s, -su); TEST_EXPECT_EQUAL(s, -iu);
306        TEST_EXPECT_EQUAL(i, -iu); TEST_EXPECT_EQUAL(i, -su);
307        TEST_EXPECT_EQUAL(l, -lu);
308
309        TEST_EXPECT_EQUAL(f, d);
310        TEST_EXPECT_EQUAL(d, f);
311    }
312
313    TEST_EXPECT_ZERO(7-7);
314}
315
316// --- simulate user_type (which may be defined anywhere) ---
317class user_type {
318    int x, y;
319public:
320    user_type(int X, int Y) : x(X), y(Y) {}
321
322    int get_x() const { return x; }
323    int get_y() const { return y; }
324
325    user_type flipped() const { return user_type(y,x); }
326
327    int quadrant() const {
328        if (x == 0 || y == 0) return 0; // on axis
329        if (y>0) return x<0 ? 2 : 1;
330        return x<0 ? 3 : 4;
331    }
332};
333// --- end of user_type ---
334
335// helpers needed for tests:
336inline bool operator == (const user_type& u1, const user_type& u2) { return u1.get_x() == u2.get_x() && u1.get_y() == u2.get_y(); }
337inline char *val2readable(const user_type& u) { return arb_test::StaticCode::strf("user_type(%i,%i)", u.get_x(), u.get_y()); }
338inline bool in_same_quadrant(const user_type& u1, const user_type& u2) { return u1.quadrant() == u2.quadrant(); }
339
340void TEST_user_type_with_expectations() {
341    user_type ut1(3, 4);
342    user_type ut12(4, 4);
343    user_type ut2(-4, 4);
344    user_type ut3(-4, -8);
345    user_type ut4(4, -8);
346
347    TEST_EXPECTATION(that(ut1).does_differ_from(ut12));
348    TEST_EXPECTATION(that(ut12).is_equal_to(ut12.flipped()));
349    TEST_EXPECTATION(that(ut1).does_differ_from(ut1.flipped()));
350
351    TEST_EXPECTATION(that(ut1).fulfills(in_same_quadrant, ut12));
352    TEST_EXPECTATION(none().of(that(ut1).fulfills(in_same_quadrant, ut2),
353                          that(ut2).fulfills(in_same_quadrant, ut3),
354                          that(ut3).fulfills(in_same_quadrant, ut4)));
355}
356TEST_PUBLISH(TEST_user_type_with_expectations);
357
358void TEST_similarity() {
359    double d1      = 0.7531;
360    double epsilon = 0.00001;
361    double d2      = d1-epsilon*0.6;
362    double d3      = d1+epsilon*0.6;
363
364    TEST_EXPECTATION(that(d1).fulfills(epsilon_similar(epsilon), d2));
365    TEST_EXPECTATION(that(d1).fulfills(epsilon_similar(epsilon), d3));
366    TEST_EXPECTATION(that(d2).contradicts(epsilon_similar(epsilon), d3));
367
368    TEST_EXPECT_SIMILAR(d1, d2, epsilon);
369    TEST_EXPECT_SIMILAR(d1, d3, epsilon);
370}
371
372void TEST_less_equal() {
373    int x = 7;
374    int y = 8;
375    int z = 9;
376
377    // less/more etc
378
379    TEST_EXPECTATION(that(x).is_less_than(y));
380    TEST_EXPECTATION(that(x).is_less_or_equal(y));
381    TEST_EXPECTATION(that(x).is_less_or_equal(x));
382   
383    TEST_EXPECTATION(that(y).is_more_than(x));
384    TEST_EXPECTATION(that(y).is_more_or_equal(x));
385    TEST_EXPECTATION(that(y).is_more_or_equal(y));
386
387    TEST_EXPECT_LESS_EQUAL(x, y);
388    TEST_EXPECT_LESS_EQUAL(x, x);
389    TEST_EXPECT_LESS(x, y);
390    TEST_EXPECT_IN_RANGE(y, x, z);
391}
392TEST_PUBLISH(TEST_less_equal);
393
394class readModified { // modifies on "read" (used to test unwanted double-evaluation)
395    int val;
396public:
397    readModified(int v) : val(v) {}
398    void set(int n) { val = n; }
399    int getAndMod(int n) {
400        int v = val;
401        set(n);
402        return v;
403    }
404};
405
406#if !defined(__clang__)
407// TEST_DISABLED_CLANG: evaluation order differs under clang
408void TEST_single_eval() {
409    readModified mod(5);
410    TEST_EXPECT_EQUAL__BROKEN(mod.getAndMod(2), 2, 5); // now succeeds (this is no broken test; it tests behavior of TEST_EXPECT_EQUAL__BROKEN!)
411
412    mod.set(5);
413    TEST_EXPECT_IN_RANGE(mod.getAndMod(10), 4, 6);
414    TEST_EXPECT_EQUAL(mod.getAndMod(10), 10);
415    TEST_EXPECT_IN_RANGE__BROKEN(mod.getAndMod(2), 8, 12); // @@@ tested expression is evaluated twice
416    TEST_EXPECT_EQUAL(mod.getAndMod(2), 2);
417    TEST_EXPECT_IN_RANGE(mod.getAndMod(33), 1, 3);
418    TEST_EXPECT_EQUAL(mod.getAndMod(33), 33);
419    TEST_EXPECT_IN_RANGE__BROKEN(mod.getAndMod(20), 32, 34); // @@@ tested expression is evaluated twice
420    TEST_EXPECT_EQUAL(mod.getAndMod(20), 20);
421}
422#endif
423
424enum MyEnum {
425    MY_UNKNOWN,
426    MY_RNA,
427    MY_DNA,
428    MY_AA,
429};
430
431void TEST_MyEnum_loop() {
432    int loops_performed = 0;
433    const char *db_name[]=  { NULp, "TEST_trees.arb", "TEST_realign.arb", "TEST_realign.arb", NULp };
434    for (int iat = MY_RNA; iat<=MY_AA; ++iat) {
435        MyEnum at = MyEnum(iat);
436        TEST_EXPECT(at>=1 && at<=3);
437        fprintf(stderr, "at=%i db_name[%i]='%s'\n", at, at, db_name[at]);
438        TEST_REJECT_NULL(db_name[at]);
439        loops_performed++;
440    }
441    TEST_EXPECT_EQUAL(loops_performed, 3);
442}
443
444
445void TEST_ARB_strchrnul() {
446    const char *check = "check";
447
448    TEST_EXPECT_EQUAL(ARB_strchrnul("check", 'c'),  "check");
449    TEST_EXPECT_EQUAL(ARB_strchrnul("check", 'e'),  "eck");
450    TEST_EXPECT_EQUAL(ARB_strchrnul("check", 'i'),  "");
451    TEST_EXPECT_EQUAL(ARB_strchrnul("check", '\0'), "");
452
453    TEST_EXPECT_EQUAL(ARB_strchrnul(check, 'c'),  "check");
454    TEST_EXPECT_EQUAL(ARB_strchrnul(check, 'e'),  "eck");
455    TEST_EXPECT_EQUAL(ARB_strchrnul(check, 'i'),  "");
456    TEST_EXPECT_EQUAL(ARB_strchrnul(check, '\0'), "");
457
458    TEST_EXPECT(ARB_strchrnul(check, 'c')  == check);
459    TEST_EXPECT(ARB_strchrnul(check, 'e')  == (check+2));
460    TEST_EXPECT(ARB_strchrnul(check, 'i')  == (check+5));
461    TEST_EXPECT(ARB_strchrnul(check, '\0') == (check+5));
462}
463
464static const char *keepOne(char *s) {
465    static char *s2 = NULp;
466    reassign(s2, s);
467    return s2;
468}
469
470#define TEST_EXPECT_STRPARTDUP_TO(start,end,expected) TEST_EXPECT_EQUAL(keepOne(ARB_strpartdup(start,end)),expected)
471#define TEST_EXPECT_STRNDUP_TO(start,len,expected)    TEST_EXPECT_EQUAL(keepOne(ARB_strndup(start,len)),expected)
472
473void TEST_string_duppers() {
474    const char *text  = "text";
475    const char *empty = "";
476
477    TEST_EXPECT_STRPARTDUP_TO(text, text+4, text); // dup with 0-byte
478    TEST_EXPECT_STRPARTDUP_TO(text, text+3, text); // dup w/o 0-byte (afterwards append 0-byte)
479    TEST_EXPECT_STRPARTDUP_TO(text, text,   "t");
480    TEST_EXPECT_STRPARTDUP_TO(text, text-1, empty);
481
482    // copy whole string
483    TEST_EXPECT_STRPARTDUP_TO(text,  NULp, text);
484    TEST_EXPECT_STRPARTDUP_TO(empty, NULp, empty);
485
486    TEST_EXPECT_STRNDUP_TO(text, 5, text); // dup with 0-byte
487    TEST_EXPECT_STRNDUP_TO(text, 4, text); // dup w/o 0-byte (afterwards append 0-byte)
488    TEST_EXPECT_STRNDUP_TO(text, 1, "t");
489    TEST_EXPECT_STRNDUP_TO(text, 0, empty);
490
491    // error cases:
492    // a. "less" than empty string
493    TEST_EXPECT_NULL(ARB_strpartdup(text, text-2));
494    TEST_EXPECT_NULL(ARB_strpartdup(text, text-200));
495
496    TEST_EXPECT_NULL(ARB_strndup(text, -1));
497    TEST_EXPECT_NULL(ARB_strndup(text, -1000));
498
499    // b. no source -> no result
500    TEST_EXPECT_STRPARTDUP_TO(NULp, empty, NULp);
501    TEST_EXPECT_STRPARTDUP_TO(NULp, text,  NULp);
502    TEST_EXPECT_STRPARTDUP_TO(NULp, NULp,  NULp);
503
504    keepOne(NULp); // =free
505}
506TEST_PUBLISH(TEST_string_duppers);
507
508#endif // UNIT_TESTS
509
510// --------------------------------------------------------------------------------
511
512
Note: See TracBrowser for help on using the repository browser.