Show
Ignore:
Timestamp:
09/09/10 22:40:57 (21 months ago)
Author:
westram
Message:
  • unit-test improvements (merged [6757] [6758] [6759] [6760] [6761] [6762] [6764] [6791] [6795] [6798] [6799] [6800] [6801] [6802] [6809] [6810])
    • moved file compare to test_unit.h
    • fake report for skipped tests
    • added templates for char compare
    • perform minihexdump
    • flush output
    • added
      • TEST_ASSERT_FILES_EQUAL__BROKEN
      • TEST_ASSERT_ZERO_OR_SHOW_ERRNO
    • create a fake.patch if there are no changes
    • all code affecting assertions in UNIT_TESTS-mode went to test_global.h
      • overwrites arb_assert()
    • undefine UNIT_TESTS for GDE submakefiles (foreign code there)
    • arb_test::FlushedOutput::errorf raises assertion itself
    • test against I/O errors
    • moved test code
    • refactored message printing
    • unit-tester switches to run directory itself
      • eliminates path hack for valgrind
    • control leak-check by variable
    • added global test-environment (does nothing yet)
Location:
trunk/UNIT_TESTER
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/UNIT_TESTER

    • Property svn:ignore
      •  

        old new  
        55*.gcno 
        66logs 
         7test_environment 
  • trunk/UNIT_TESTER/test_unit.h

    r6750 r6816  
    1919#include <cstdarg> 
    2020#endif 
     21#ifndef ERRNO_H 
     22#include <errno.h> 
     23#endif 
    2124 
    2225#define ENABLE_CRASH_TESTS // comment out this line to get rid of provoked SEGVs (e.g. while debugging test-code) 
     
    3336 
    3437namespace arb_test { 
    35     class FlushedOutput { 
    36         inline void flushall() { fflush(stdout); fflush(stderr); } 
     38 
     39    class StaticCode { 
     40        static void vcompiler_msg(const char *filename, int lineno, const char *message_type, const char *format, va_list parg) { 
     41            fprintf(stderr, "%s:%i: ", filename, lineno); 
     42            if (message_type) fprintf(stderr, "%s: ", message_type); 
     43            vfprintf(stderr, format, parg); 
     44        } 
     45 
     46#define WITHVALISTFROM(format,CODE)             do { va_list parg; va_start(parg, format); CODE; va_end(parg); } while(0) 
     47#define VPRINTFORMAT(format)                    WITHVALISTFROM(format, vfprintf(stderr, format, parg)) 
     48#define VCOMPILERMSG(file,line,msgtype,format)  WITHVALISTFROM(format, vcompiler_msg(file, line, msgtype, format, parg)) 
     49         
    3750    public: 
    38         FlushedOutput() { flushall(); } 
    39         ~FlushedOutput() { flushall(); } 
    40          
    41 #define VPRINTFORMAT(format) do { va_list parg; va_start(parg, format); vfprintf(stderr, format, parg); va_end(parg); } while(0) 
    42      
     51 
    4352        static void printf(const char *format, ...) __attribute__((format(printf, 1, 2))) { 
    44             FlushedOutput yes; 
    45             VPRINTFORMAT(format); 
    46         } 
    47         static void messagef(const char *filename, int lineno, const char *format, ...) __attribute__((format(printf, 3, 4))) { 
    48             FlushedOutput yes; 
    49             fprintf(stderr, "%s:%i: ", filename, lineno); 
     53            FlushedOutputNoLF yes; 
    5054            VPRINTFORMAT(format); 
    5155        } 
     
    5458            if (global.show_warnings) { 
    5559                FlushedOutput yes; 
    56                 fprintf(stderr, "%s:%i: Warning: ", filename, lineno); 
    57                 VPRINTFORMAT(format); 
     60                VCOMPILERMSG(filename, lineno, "Warning", format); 
    5861                global.warnings++; 
    5962            } 
     
    6164        static void errorf(const char *filename, int lineno, const char *format, ...) __attribute__((format(printf, 3, 4))) { 
    6265            FlushedOutput yes; 
    63             fprintf(stderr, "%s:%i: Error: ", filename, lineno); 
    64             VPRINTFORMAT(format); 
     66            VCOMPILERMSG(filename, lineno, "Error", format); 
     67            TRIGGER_ASSERTION(); // fake an assertion failure 
     68        } 
     69        static void ioerrorf(const char *filename, int lineno, const char *format, ...) __attribute__((format(printf, 3, 4))) { 
     70            FlushedOutput yes; 
     71            VCOMPILERMSG(filename, lineno, "Error", format); 
     72            fprintf(stderr, " (errno=%i='%s')", errno, strerror(errno)); 
     73            TRIGGER_ASSERTION(); // fake an assertion failure 
    6574        } 
    6675#undef VPRINTFORMAT 
     76#undef VCOMPILERMSG 
     77#undef WITHVALISTFROM 
    6778    }; 
    6879 
     
    7586    inline void print(size_t z)              { fprintf(stderr, "%zu", z); } 
    7687    inline void print_hex(size_t z)          { fprintf(stderr, "0x%zx", z); } 
     88     
     89    inline void print(unsigned char c)       { fprintf(stderr, "'%c'", c); } 
     90    inline void print_hex(unsigned char c)   { print_hex(size_t(c)); } 
     91 
     92    inline void print(char c)                { print((unsigned char)c); } 
     93    inline void print_hex(char c)            { print_hex((unsigned char)c); } 
     94 
     95    // dont dup size_t: 
    7796#ifdef ARB_64 
    7897    inline void print(unsigned u)            { fprintf(stderr, "%u", u); } 
     
    82101    inline void print_hex(long unsigned u)   { fprintf(stderr, "0x%lux", u); } 
    83102#endif 
    84      
     103 
    85104    template <typename T1, typename T2> void print_pair(T1 t1, T2 t2) { 
    86105        print(t1); 
     
    94113    } 
    95114    template <typename T1, typename T2> void print_failed_equal(T1 t1, T2 t2) { 
    96         FlushedOutput yes; 
     115        FlushedOutputNoLF yes; 
    97116        fputs("is_equal(", stderr); 
    98117        print_pair(t1, t2); 
     
    108127#define NAMEOFTYPE(type) template <> inline const char * nameoftype<>(type) { return #type; } 
    109128    NAMEOFTYPE(bool); 
     129    NAMEOFTYPE(char); 
     130    NAMEOFTYPE(unsigned char); 
    110131    NAMEOFTYPE(int); 
    111132    NAMEOFTYPE(unsigned int); 
     
    135156        bool equal = strnullequal(s1, s2); 
    136157        if (!equal) { 
    137             FlushedOutput::printf("str_equal('%s',\n" 
    138                                   "          '%s') returns false\n", s1, s2); 
     158            StaticCode::printf("str_equal('%s',\n" 
     159                               "          '%s') returns false\n", s1, s2); 
    139160        } 
    140161        return equal; 
     
    158179        bool different = !strnullequal(s1, s2); 
    159180        if (!different) { 
    160             FlushedOutput::printf("str_different('%s', ..) returns false\n", s1); 
     181            StaticCode::printf("str_different('%s', ..) returns false\n", s1); 
    161182        } 
    162183        return different; 
     
    169190        bool in_epsilon_range = diff < epsilon; 
    170191        if (!in_epsilon_range) { 
    171             FlushedOutput::printf("is_similar(%f,%f,%f) returns false\n", d1, d2, epsilon); 
     192            StaticCode::printf("is_similar(%f,%f,%f) returns false\n", d1, d2, epsilon); 
    172193        } 
    173194        return in_epsilon_range; 
     
    178199    } 
    179200 
     201 
     202 
     203    inline bool files_are_equal(const char *file1, const char *file2) { 
     204        const char        *error = NULL; 
     205        FILE              *fp1   = fopen(file1, "rb"); 
     206        FlushedOutputNoLF  yes; 
     207 
     208        if (!fp1) { 
     209            StaticCode::printf("can't open '%s'", file1); 
     210            error = "i/o error"; 
     211        } 
     212        else { 
     213            FILE *fp2 = fopen(file2, "rb"); 
     214            if (!fp2) { 
     215                StaticCode::printf("can't open '%s'", file2); 
     216                error = "i/o error"; 
     217            } 
     218            else { 
     219                const int      BLOCKSIZE    = 4096; 
     220                unsigned char *buf1         = (unsigned char*)malloc(BLOCKSIZE); 
     221                unsigned char *buf2         = (unsigned char*)malloc(BLOCKSIZE); 
     222                int            equal_bytes  = 0; 
     223                bool           repositioned = false; 
     224 
     225                while (!error) { 
     226                    int read1  = fread(buf1, 1, BLOCKSIZE, fp1); 
     227                    int read2  = fread(buf2, 1, BLOCKSIZE, fp2); 
     228                    int common = read1<read2 ? read1 : read2; 
     229 
     230                    if (!common) { 
     231                        if (read1 != read2) error = "filesize differs"; 
     232                        break; 
     233                    } 
     234 
     235                    if (memcmp(buf1, buf2, common) == 0) { 
     236                        equal_bytes += common; 
     237                    } 
     238                    else { 
     239                        int x = 0; 
     240                        while (buf1[x] == buf2[x]) { 
     241                            x++; 
     242                            equal_bytes++; 
     243                        } 
     244                        error = "content differs"; 
     245 
     246                        // x is the position inside the current block 
     247                        const int DUMP       = 7; 
     248                        int       y1         = x >= DUMP ? x-DUMP : 0; 
     249                        int       y2         = (x+DUMP)>common ? common : (x+DUMP); 
     250                        int       blockstart = equal_bytes-x; 
     251 
     252                        for (int y = y1; y <= y2; y++) { 
     253                            fprintf(stderr, "[0x%04x]", blockstart+y); 
     254                            print_pair(buf1[y], buf2[y]); 
     255                            fputc(' ', stderr); 
     256                            print_hex_pair(buf1[y], buf2[y]); 
     257                            if (x == y) fputs("                     <- diff", stderr); 
     258                            fputc('\n', stderr); 
     259                        } 
     260                        if (y2 == common) { 
     261                            fputs("[end of block - truncated]\n", stderr); 
     262                        } 
     263                    } 
     264                } 
     265 
     266                if (error) StaticCode::printf("files_are_equal: equal_bytes=%i\n", equal_bytes); 
     267                test_assert(error || equal_bytes); // comparing empty files is nonsense 
     268 
     269                free(buf2); 
     270                free(buf1); 
     271                fclose(fp2); 
     272            } 
     273            fclose(fp1); 
     274        } 
     275 
     276        if (error) StaticCode::printf("files_are_equal(%s, %s) fails: %s\n", file1, file2, error); 
     277        return !error; 
     278    } 
     279     
    180280}; 
    181281 
    182282// -------------------------------------------------------------------------------- 
    183283 
    184 #define TEST_MSG(format,strarg)           arb_test::FlushedOutput::messagef(__FILE__, __LINE__, format, (strarg)) 
    185 #define TEST_MSG2(format,strarg1,strarg2) arb_test::FlushedOutput::messagef(__FILE__, __LINE__, format, (strarg1), (strarg2)) 
    186  
    187 #define TEST_WARNING(format,strarg)           arb_test::FlushedOutput::warningf(__FILE__, __LINE__, format, (strarg)) 
    188 #define TEST_WARNING2(format,strarg1,strarg2) arb_test::FlushedOutput::warningf(__FILE__, __LINE__, format, (strarg1), (strarg2)) 
    189  
    190 #define TEST_ERROR(format,strarg)           do { arb_test::FlushedOutput::errorf(__FILE__, __LINE__, format, (strarg)); TEST_ASSERT(0); } while(0) 
    191 #define TEST_ERROR2(format,strarg1,strarg2) do { arb_test::FlushedOutput::errorf(__FILE__, __LINE__, format, (strarg1), (strarg2)); TEST_ASSERT(0); } while(0) 
     284#define TEST_WARNING(format,strarg)           arb_test::StaticCode::warningf(__FILE__, __LINE__, format, (strarg)) 
     285#define TEST_WARNING2(format,strarg1,strarg2) arb_test::StaticCode::warningf(__FILE__, __LINE__, format, (strarg1), (strarg2)) 
     286 
     287#define TEST_ERROR(format,strarg)           arb_test::StaticCode::errorf(__FILE__, __LINE__, format, (strarg)) 
     288#define TEST_ERROR2(format,strarg1,strarg2) arb_test::StaticCode::errorf(__FILE__, __LINE__, format, (strarg1), (strarg2)) 
     289#define TEST_IOERROR(format,strarg)         arb_test::StaticCode::ioerrorf(__FILE__, __LINE__, format, (strarg)) 
    192290 
    193291// -------------------------------------------------------------------------------- 
     
    206304#define TEST_ASSERT_ZERO(cond)         TEST_ASSERT((cond)         == 0) 
    207305#define TEST_ASSERT_ZERO__BROKEN(cond) TEST_ASSERT__BROKEN((cond) == 0) 
     306 
     307#define TEST_ASSERT_ZERO_OR_SHOW_ERRNO(iocond)                  \ 
     308    do {                                                        \ 
     309        if ((iocond))                                           \ 
     310            TEST_IOERROR("I/O-failure in '%s'", #iocond);       \ 
     311    } while(0) 
    208312 
    209313// -------------------------------------------------------------------------------- 
     
    350454#define TEST_ASSERT_SIMILAR__BROKEN(t1,t2,epsilon) TEST_ASSERT__BROKEN(arb_test::is_similar(t1, t2, epsilon)) 
    351455 
     456#define TEST_ASSERT_FILES_EQUAL(f1,f2)         TEST_ASSERT(arb_test::files_are_equal(f1,f2)) 
     457#define TEST_ASSERT_FILES_EQUAL__BROKEN(f1,f2) TEST_ASSERT__BROKEN(arb_test::files_are_equal(f1,f2)) 
     458 
    352459#else 
    353460#error test_unit.h included twice