source: branches/profile/CORE/arb_string.cxx

Last change on this file was 12477, checked in by westram, 10 years ago
  • publish some tests (disappeared with gcc4.8.0 and -Og)
File size: 14.1 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 <arb_assert.h>
15
16#include <cstring>
17#include <cstdlib>
18
19#include <ctime>
20#include <sys/time.h>
21#include <Keeper.h>
22
23char *GB_strduplen(const char *p, unsigned len) {
24    // fast replacement for strdup, if len is known
25    if (p) {
26        char *neu;
27
28        arb_assert(strlen(p) == len);
29        // Note: Common reason for failure: a zero-char was manually printed by a GBS_global_string...-function
30
31        neu = (char*)malloc(len+1);
32        memcpy(neu, p, len+1);
33        return neu;
34    }
35    return 0;
36}
37
38char *GB_strpartdup(const char *start, const char *end) {
39    /* strdup of a part of a string (including 'start' and 'end')
40     * 'end' may point behind end of string -> copy only till zero byte
41     * if 'end'=('start'-1) -> return ""
42     * if 'end'<('start'-1) -> return 0
43     * if 'end' == NULL -> copy whole string
44     */
45
46    char *result;
47    if (end) {
48        int len = end-start+1;
49
50        if (len >= 0) {
51            const char *eos = (const char *)memchr(start, 0, len);
52
53            if (eos) len = eos-start;
54            result = (char*)malloc(len+1);
55            memcpy(result, start, len);
56            result[len] = 0;
57        }
58        else {
59            result = 0;
60        }
61    }
62    else { // end = 0 -> return copy of complete string
63        result = nulldup(start);
64    }
65
66    return result;
67}
68
69char *GB_strndup(const char *start, int len) {
70    return GB_strpartdup(start, start+len-1);
71}
72
73const char *GB_date_string() {
74    timeval  date;
75    tm      *p;
76
77    gettimeofday(&date, 0);
78
79#if defined(DARWIN)
80    struct timespec local;
81    TIMEVAL_TO_TIMESPEC(&date, &local); // not avail in time.h of Linux gcc 2.95.3
82    p = localtime(&local.tv_sec);
83#else
84    p = localtime(&date.tv_sec);
85#endif // DARWIN
86
87    char *readable = asctime(p); // points to a static buffer
88    char *cr       = strchr(readable, '\n');
89    arb_assert(cr);
90    cr[0]          = 0;         // cut of \n
91
92    return readable;
93}
94
95// --------------------------------------------------------------------------------
96
97const char *GB_keep_string(char *str) {
98    /*! keep an allocated string until program termination
99     * useful to avoid valgrind reporting leaks e.g for callback parameters
100     */
101    static Keeper<char*> stringKeeper;
102    stringKeeper.keep(str);
103    return str;
104}
105
106
107// --------------------------------------------------------------------------------
108
109
110#ifdef UNIT_TESTS
111
112#include <string>
113#include <climits>
114
115#ifndef TEST_UNIT_H
116#include <test_unit.h>
117#endif
118
119using namespace std;
120
121// ----------------------------------------------
122//      some tests for unit-test-code itself
123
124#define TEST_EXPECT_HEAPCOPY_EQUAL(copy,expected) do {  \
125        char *theCopy = (copy);                         \
126        TEST_EXPECT_EQUAL(theCopy, expected);           \
127        free(theCopy);                                  \
128    } while(0)
129
130void TEST_arbtest_strf() {
131    // tests string formatter from test_unit.h
132    using namespace arb_test;
133    TEST_EXPECT_HEAPCOPY_EQUAL(StaticCode::strf("<%i>", 7), "<7>");
134    TEST_EXPECT_HEAPCOPY_EQUAL(StaticCode::strf("<%0*i>", 3, 7), "<007>");
135}
136
137void TEST_arbtest_readable() {
138    using namespace arb_test;
139
140    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy('x')), "'x' (=0x78)");
141    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(static_cast<unsigned char>('x'))), "'x' (=0x78)");
142    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(static_cast<signed char>('x'))), "'x' (=0x78)");
143
144    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(true)), "true");
145    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(false)), "false");
146   
147    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(1)), "1");
148    TEST_EXPECT_HEAPCOPY_EQUAL(val2hex(make_copy(2)), "0x2");
149
150    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(3L)), "3");
151    TEST_EXPECT_HEAPCOPY_EQUAL(val2hex(make_copy(4L)), "0x4");
152
153    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(5U)), "5");
154    TEST_EXPECT_HEAPCOPY_EQUAL(val2hex(make_copy(6U)), "0x6");
155   
156    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy("some\ntext\twhich\"special\\chars")), "\"some\\ntext\\twhich\\\"special\\\\chars\"");
157    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy("a\1\2\x1a\x7e\x7f\x80\xfe\xff")), "\"a\\1\\2\\x1a~\\x7f\\x80\\xfe\\xff\"");
158    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy((const char *)NULL)), "(null)");
159    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy((const unsigned char *)NULL)), "(null)");
160    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy((const signed char *)NULL)), "(null)");
161
162    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(1.7)), "1.700000");
163    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(177.0e20)),  "17699999999999998951424.000000");
164    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(177.0e20F)), "17699999967695435988992.000000");
165}
166
167void TEST_arbtest_copyable() {
168    using namespace arb_test;
169
170    int         i = 7;
171    const char *s = "servas";
172
173    TEST_EXPECT(make_copy(i) == make_copy(7));
174    TEST_EXPECT_ZERO(strcmp(make_copy(s), make_copy("servas")));
175}
176
177#define TEST_DESCRIPTIONS(d, tt, tf, ft, ff) do {        \
178        TEST_EXPECT_EQUAL((d).make(true, true), (tt));   \
179        TEST_EXPECT_EQUAL((d).make(true, false), (tf));  \
180        TEST_EXPECT_EQUAL((d).make(false, true), (ft));  \
181        TEST_EXPECT_EQUAL((d).make(false, false), (ff)); \
182    } while(0)
183
184#define TEST_SIMPLE_DESCRIPTIONS(d, ae, nae) TEST_DESCRIPTIONS(d, ae, nae, ae, nae)
185
186void TEST_arbtest_predicate_description() {
187    TEST_SIMPLE_DESCRIPTIONS(predicate_description("similar"), "is similar", "isnt similar");
188    TEST_SIMPLE_DESCRIPTIONS(predicate_description("repairs"), "repairs", "doesnt repair");
189
190    TEST_DESCRIPTIONS(predicate_description("equals", "differs"),
191                      "equals", "doesnt equal",
192                      "doesnt differ", "differs");
193
194    TEST_DESCRIPTIONS(predicate_description("less_than", "more_than"),
195                      "is less_than", "isnt less_than",
196                      "isnt more_than", "is more_than");
197}
198
199void TEST_arbtest_expectations() {
200    // used to TDD expectations
201    using namespace arb_test;
202
203    string apple       = "Apfel";
204    string pear        = "Birne";
205    string boskop      = apple;
206    string pomegranate = "Granatapfel";
207
208    TEST_EXPECTATION(that(apple).is_equal_to("Apfel"));
209   
210    TEST_EXPECTATION(that(apple).does_differ_from(pear));
211    TEST_EXPECTATION(that(apple).is_equal_to(boskop));
212    TEST_EXPECTATION(wrong(that(pomegranate).is_equal_to(apple)));
213
214    match_expectation ff1 = that(1.0).is_equal_to(2-1);
215    match_expectation ff2 = that(boskop).is_equal_to(apple);
216    match_expectation ff3 = that(apple).is_equal_to(apple);
217
218    match_expectation nf1 = that(apple).is_equal_to(pear);
219    match_expectation nf2 = that(pomegranate).is_equal_to(apple);
220    match_expectation nf3 = that(apple).does_differ_from(boskop);
221
222    match_expectation a1 = all().of(ff1);
223    match_expectation a2 = all().of(ff1, ff2);
224    match_expectation a3 = all().of(ff1, ff2, ff3);
225
226    TEST_EXPECTATION(a1);
227    TEST_EXPECTATION(a2);
228    TEST_EXPECTATION(a3);
229
230    match_expectation n1 = none().of(ff1);
231    match_expectation n2 = none().of(ff1, ff2);
232    match_expectation n3 = none().of(ff1, ff2, ff3);
233
234    TEST_EXPECTATION(wrong(none().of(that(boskop).is_equal_to(apple))));
235    TEST_EXPECTATION(wrong(n1));
236    TEST_EXPECTATION(wrong(n2));
237    TEST_EXPECTATION(wrong(n3));
238
239    TEST_EXPECTATION(atleast(1).of(a1));
240    TEST_EXPECTATION(atleast(1).of(a1, n1));
241    TEST_EXPECTATION(atleast(1).of(n2, a1, n1));
242
243    TEST_EXPECTATION(wrong(atleast(2).of(a1, n1, n2)));
244    TEST_EXPECTATION(wrong(atleast(2).of(a1, n1)));
245    TEST_EXPECTATION(wrong(atleast(2).of(a1))); // impossible
246
247    TEST_EXPECTATION(atmost(2).of(a1));
248    TEST_EXPECTATION(atmost(2).of(a1, a2));
249    TEST_EXPECTATION(atmost(2).of(a1, a2, n1));
250    TEST_EXPECTATION(atmost(2).of(a1, n1, n2));
251    TEST_EXPECTATION(atmost(2).of(n1, n2));
252    TEST_EXPECTATION(wrong(atmost(2).of(a1, a2, a3)));
253
254    TEST_EXPECTATION(exactly(1).of(ff1, nf1, nf2));
255    TEST_EXPECTATION(wrong(exactly(1).of(nf1, nf2)));
256    TEST_EXPECTATION(wrong(exactly(1).of(nf1, nf2, nf3)));
257    TEST_EXPECTATION(wrong(exactly(1).of(ff1, ff2, nf2)));
258    TEST_EXPECTATION(wrong(exactly(1).of(ff1, ff2, ff3)));
259
260}
261
262void TEST_expectation_groups() {
263    using namespace arb_test;
264
265    expectation_group no_expectations;
266    TEST_EXPECTATION(all().ofgroup(no_expectations));
267    TEST_EXPECTATION(none().ofgroup(no_expectations));
268
269    expectation_group fulfilled_expectation  (that(1).is_equal_to(1));
270    expectation_group unfulfilled_expectation(that(1).is_equal_to(0));
271    expectation_group some_fulfilled_expectations(that(1).is_equal_to(0), that(1).is_equal_to(1));
272
273    TEST_EXPECTATION(all().ofgroup(fulfilled_expectation));
274    TEST_EXPECTATION(none().ofgroup(unfulfilled_expectation));
275
276    TEST_EXPECT(none().ofgroup(fulfilled_expectation).unfulfilled());
277    TEST_EXPECT(all().ofgroup(unfulfilled_expectation).unfulfilled());
278   
279    TEST_EXPECT(all().ofgroup(some_fulfilled_expectations).unfulfilled());
280    TEST_EXPECT(none().ofgroup(some_fulfilled_expectations).unfulfilled());
281}
282
283void TEST_replace_old_TEST_EXPECTS_by_expectations() {
284    // test various string-types are matchable (w/o casts)
285    {
286        const char *car_ccp = "Alfa";
287        char       *car_cp  = strdup("Alfa");
288        string      car_str("Alfa");
289
290        TEST_EXPECT_EQUAL(car_ccp, "Alfa");
291        TEST_EXPECT_EQUAL(car_cp, "Alfa");
292        TEST_EXPECT_EQUAL(car_str, "Alfa");
293
294        TEST_EXPECT_EQUAL("Alfa", car_ccp);
295        TEST_EXPECT_EQUAL("Alfa", car_cp);
296        TEST_EXPECT_EQUAL("Alfa", car_str);
297
298        TEST_EXPECT_EQUAL(car_cp, car_ccp);
299        TEST_EXPECT_EQUAL(car_cp, car_str);
300        TEST_EXPECT_EQUAL(car_ccp, car_cp);
301        TEST_EXPECT_EQUAL(car_ccp, car_str);
302        TEST_EXPECT_EQUAL(car_str, car_cp);
303        TEST_EXPECT_EQUAL(car_str, car_ccp);
304
305        char *null = NULL;
306        TEST_EXPECT_NULL((void*)NULL);
307        TEST_EXPECT_NULL(null);
308
309        TEST_EXPECT_CONTAINS(car_ccp, "lf");
310        TEST_EXPECT_CONTAINS(car_cp, "fa");
311        TEST_EXPECT_CONTAINS(car_str, "Al");
312
313        free(car_cp);
314    }
315
316    // test various numeric types are matchable
317
318    {
319        short unsigned su = 7;
320        short          s  = -su;
321
322        unsigned iu = su;
323        int      i  = -iu;
324
325        long unsigned lu = (long unsigned)INT_MAX+3;
326        long          l  = -lu;
327
328        float  f = s;
329        double d = i;
330
331        TEST_EXPECT_EQUAL(s, -7);
332        TEST_EXPECT_EQUAL(i, -7);
333
334        TEST_EXPECT_EQUAL(su, 7);  TEST_EXPECT_EQUAL(iu, 7);
335        TEST_EXPECT_EQUAL(su, 7U); TEST_EXPECT_EQUAL(iu, 7U);
336        TEST_EXPECT_EQUAL(su, 7L); TEST_EXPECT_EQUAL(iu, 7L);
337
338        TEST_EXPECT_EQUAL(s, -su); TEST_EXPECT_EQUAL(s, -iu);
339        TEST_EXPECT_EQUAL(i, -iu); TEST_EXPECT_EQUAL(i, -su);
340        TEST_EXPECT_EQUAL(l, -lu);
341
342        TEST_EXPECT_EQUAL(f, d);
343        TEST_EXPECT_EQUAL(d, f);
344    }
345
346    TEST_EXPECT_ZERO(7-7);
347}
348
349// --- simulate user_type (which may be defined anywhere) ---
350class user_type {
351    int x, y;
352public:
353    user_type(int X, int Y) : x(X), y(Y) {}
354
355    int get_x() const { return x; }
356    int get_y() const { return y; }
357
358    user_type flipped() const { return user_type(y,x); }
359
360    int quadrant() const {
361        if (x == 0 || y == 0) return 0; // on axis
362        if (y>0) return x<0 ? 2 : 1;
363        return x<0 ? 3 : 4;
364    }
365};
366// --- end of user_type ---
367
368// helpers needed for tests:
369inline bool operator == (const user_type& u1, const user_type& u2) { return u1.get_x() == u2.get_x() && u1.get_y() == u2.get_y(); }
370inline char *val2readable(const user_type& u) { return arb_test::StaticCode::strf("user_type(%i,%i)", u.get_x(), u.get_y()); }
371inline bool in_same_quadrant(const user_type& u1, const user_type& u2) { return u1.quadrant() == u2.quadrant(); }
372
373void TEST_user_type_with_expectations() {
374    user_type ut1(3, 4);
375    user_type ut12(4, 4);
376    user_type ut2(-4, 4);
377    user_type ut3(-4, -8);
378    user_type ut4(4, -8);
379
380    TEST_EXPECTATION(that(ut1).does_differ_from(ut12));
381    TEST_EXPECTATION(that(ut12).is_equal_to(ut12.flipped()));
382    TEST_EXPECTATION(that(ut1).does_differ_from(ut1.flipped()));
383
384    TEST_EXPECTATION(that(ut1).fulfills(in_same_quadrant, ut12));
385    TEST_EXPECTATION(none().of(that(ut1).fulfills(in_same_quadrant, ut2),
386                          that(ut2).fulfills(in_same_quadrant, ut3),
387                          that(ut3).fulfills(in_same_quadrant, ut4)));
388}
389TEST_PUBLISH(TEST_user_type_with_expectations);
390
391void TEST_similarity() {
392    double d1      = 0.7531;
393    double epsilon = 0.00001;
394    double d2      = d1-epsilon*0.6;
395    double d3      = d1+epsilon*0.6;
396
397    TEST_EXPECTATION(that(d1).fulfills(epsilon_similar(epsilon), d2));
398    TEST_EXPECTATION(that(d1).fulfills(epsilon_similar(epsilon), d3));
399    TEST_EXPECTATION(that(d2).contradicts(epsilon_similar(epsilon), d3));
400
401    TEST_EXPECT_SIMILAR(d1, d2, epsilon);
402    TEST_EXPECT_SIMILAR(d1, d3, epsilon);
403}
404
405void TEST_less_equal() {
406    int x = 7;
407    int y = 8;
408    int z = 9;
409
410    // less/more etc
411
412    TEST_EXPECTATION(that(x).is_less_than(y));
413    TEST_EXPECTATION(that(x).is_less_or_equal(y));
414    TEST_EXPECTATION(that(x).is_less_or_equal(x));
415   
416    TEST_EXPECTATION(that(y).is_more_than(x));
417    TEST_EXPECTATION(that(y).is_more_or_equal(x));
418    TEST_EXPECTATION(that(y).is_more_or_equal(y));
419
420    TEST_EXPECT_LESS_EQUAL(x, y);
421    TEST_EXPECT_LESS_EQUAL(x, x);
422    TEST_EXPECT_LESS(x, y);
423    TEST_EXPECT_IN_RANGE(y, x, z);
424}
425TEST_PUBLISH(TEST_less_equal);
426
427#endif // UNIT_TESTS
428
429// --------------------------------------------------------------------------------
430
431
Note: See TracBrowser for help on using the repository browser.