├── .gitignore ├── .travis.yml ├── COPYING ├── INSTALL ├── Makefile ├── Makefile.win ├── README.md ├── t ├── cmp_mem.c ├── cmp_mem.expected ├── cmpok.c ├── cmpok.expected ├── diag.c ├── diag.expected ├── diesok.c ├── diesok.expected ├── is.c ├── is.expected ├── like.c ├── like.expected ├── simple.c ├── simple.expected ├── skip.c ├── skip.expected ├── synopsis.c ├── synopsis.expected ├── test.c ├── todo.c └── todo.expected ├── tap.c └── tap.h /.gitignore: -------------------------------------------------------------------------------- 1 | /t/* 2 | !/t/*.* 3 | /t/*.exe 4 | /t/*.got 5 | *.a 6 | *.lo 7 | *.o 8 | *.so 9 | *.pc 10 | usr/ 11 | *.sw? 12 | /.deps 13 | /.dirstamp 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | compiler: 4 | - gcc 5 | - clang 6 | 7 | before_install: sudo apt-get install -y libtest-differences-perl 8 | 9 | install: make CC=$CC install 10 | 11 | script: make CC=$CC test 12 | 13 | after_script: make uninstall 14 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | To install libtap on a Unix-like system: 2 | 3 | $ make 4 | $ make check 5 | $ make install 6 | 7 | To compile with gcc -ansi, run: 8 | 9 | $ ANSI=1 make 10 | 11 | To install to a different directory than /usr/local, supply the 12 | PREFIX variable to make: 13 | 14 | $ PREFIX=/usr make install 15 | 16 | On Windows, the library can be created by first setting up the 17 | correct development environment variables. Usually this is done by 18 | running vcvars32.bat included in the Visual Studio distribution. 19 | You should also install gnu make which can be found at 20 | http://gnuwin32.sourceforge.net/packages/make.htm. Once this is 21 | done, you should be able to run the following: 22 | 23 | > make -f Makefile.win 24 | 25 | If you want to use it directly in another project, you can copy tap.c 26 | and tap.h there and it shouldn't have a problem compiling. 27 | 28 | $ ls 29 | tap.c tap.h test.c 30 | $ cat test.c 31 | #include "tap.h" 32 | int main () { 33 | plan(1); 34 | ok(50 + 5, "foo %s", "bar"); 35 | done_testing(); 36 | } 37 | $ gcc test.c tap.c 38 | $ a.out 39 | 1..1 40 | ok 1 - foo bar 41 | 42 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC ?= gcc 2 | CFLAGS += -Wall -I. -fPIC 3 | PREFIX ?= $(DESTDIR)/usr/local 4 | TESTS = $(patsubst %.c, %, $(wildcard t/*.c)) 5 | 6 | ifdef ANSI 7 | # -D_BSD_SOURCE for MAP_ANONYMOUS 8 | CFLAGS += -ansi -D_BSD_SOURCE 9 | LDLIBS += -lbsd-compat 10 | endif 11 | 12 | %: 13 | $(CC) $(LDFLAGS) $(TARGET_ARCH) $(filter %.o %.a %.so, $^) $(LDLIBS) -o $@ 14 | 15 | %.o: 16 | $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $(filter %.c, $^) $(LDLIBS) -o $@ 17 | 18 | %.a: 19 | $(AR) rcs $@ $(filter %.o, $^) 20 | 21 | %.so: 22 | $(CC) -shared $(LDFLAGS) $(TARGET_ARCH) $(filter %.o, $^) $(LDLIBS) -o $@ 23 | 24 | all: libtap.a libtap.so tap.pc tests 25 | 26 | tap.pc: 27 | @echo generating tap.pc 28 | @echo 'prefix='$(PREFIX) > tap.pc 29 | @echo 'exec_prefix=$${prefix}' >> tap.pc 30 | @echo 'libdir=$${prefix}/lib' >> tap.pc 31 | @echo 'includedir=$${prefix}/include' >> tap.pc 32 | @echo '' >> tap.pc 33 | @echo 'Name: libtap' >> tap.pc 34 | @echo 'Description: Write tests in C' >> tap.pc 35 | @echo 'Version: 0.1.0' >> tap.pc 36 | @echo 'URL: https://github.com/zorgnax/libtap' >> tap.pc 37 | @echo 'Libs: -L$${libdir} -ltap' >> tap.pc 38 | @echo 'Cflags: -I$${includedir}' >> tap.pc 39 | 40 | libtap.a: tap.o 41 | 42 | libtap.so: tap.o 43 | 44 | tap.o: tap.c tap.h 45 | 46 | tests: $(TESTS) 47 | 48 | $(TESTS): %: %.o libtap.a 49 | 50 | $(patsubst %, %.o, $(TESTS)): %.o: %.c tap.h 51 | $(CC) $(CFLAGS) -O0 $(CPPFLAGS) $(TARGET_ARCH) -c $(filter %.c, $^) $(LDLIBS) -o $@ 52 | 53 | clean: 54 | rm -rf *.o t/*.o tap.pc libtap.a libtap.so $(TESTS) 55 | 56 | install: libtap.a tap.h libtap.so tap.pc 57 | mkdir -p $(PREFIX)/lib $(PREFIX)/include $(PREFIX)/lib/pkgconfig 58 | install -c libtap.a $(PREFIX)/lib 59 | install -c libtap.so $(PREFIX)/lib 60 | install -c tap.pc $(PREFIX)/lib/pkgconfig 61 | install -c tap.h $(PREFIX)/include 62 | 63 | uninstall: 64 | rm $(PREFIX)/lib/libtap.a $(PREFIX)/lib/libtap.so $(PREFIX)/include/tap.h 65 | 66 | dist: 67 | rm libtap.zip 68 | zip -r libtap * 69 | 70 | check test: all 71 | ./t/test 72 | 73 | .PHONY: all clean install uninstall dist check test tests 74 | -------------------------------------------------------------------------------- /Makefile.win: -------------------------------------------------------------------------------- 1 | CFLAGS = /Zi /Wall /wd4255 /wd4996 /wd4127 /wd4820 /wd4100 /wd4619 \ 2 | /wd4514 /wd4668 /I. 3 | CC = cl /nologo 4 | TESTS = $(patsubst %.c, %.exe, $(wildcard t/*.c)) 5 | 6 | %.exe: 7 | $(CC) $(LDFLAGS) $(filter %.obj %.lib %.dll, $^) $(LDLIBS) /Fe $@ 8 | 9 | %.o: 10 | $(CC) $(CFLAGS) $(CPPFLAGS) /c $(filter %.c, $^) $(LDLIBS) /Fo $@ 11 | 12 | %.lib: 13 | lib /nologo /out:$@ $(filter %.obj, $^) 14 | 15 | %.dll: 16 | lib /nologo /out:$@ $(filter %.obj, $^) 17 | 18 | all: tap.lib tests 19 | 20 | tap.lib: tap.obj 21 | 22 | tap.obj: tap.c tap.h 23 | 24 | tests: $(TESTS) 25 | 26 | $(TESTS): %.exe: %.obj tap.lib 27 | 28 | $(patsubst %.exe, %.obj, $(TESTS)): %.obj: %.c tap.h 29 | 30 | clean: 31 | rm -rf *.obj t/*.obj tap.lib $(TESTS) 32 | 33 | check test: all 34 | prove 35 | 36 | .PHONY: all clean check test tests 37 | 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NAME 2 | ==== 3 | 4 | libtap - Write tests in C 5 | 6 | SYNOPSIS 7 | ======== 8 | 9 | #include 10 | 11 | int main () { 12 | plan(5); 13 | int bronze = 1, silver = 2, gold = 3; 14 | ok(bronze < silver, "bronze is less than silver"); 15 | ok(bronze > silver, "not quite"); 16 | is("gold", "gold", "gold is gold"); 17 | cmp_ok(silver, "<", gold, "%d <= %d", silver, gold); 18 | like("platinum", ".*inum", "platinum matches .*inum"); 19 | done_testing(); 20 | } 21 | 22 | results in: 23 | 24 | 1..5 25 | ok 1 - bronze is less than silver 26 | not ok 2 - not quite 27 | # Failed test 'not quite' 28 | # at t/synopsis.c line 7. 29 | ok 3 - gold is gold 30 | ok 4 - 2 <= 3 31 | ok 5 - platinum matches .*inum 32 | # Looks like you failed 1 test of 5 run. 33 | 34 | DESCRIPTION 35 | =========== 36 | 37 | tap is an easy to read and easy to write way of creating tests for 38 | your software. This library creates functions that can be used to 39 | generate it for your C programs. It is implemented using macros 40 | that include file and line info automatically, and makes it so that 41 | the format message of each test is optional. It is mostly based on 42 | the Test::More Perl module. 43 | 44 | INSTALL 45 | ======= 46 | 47 | On **Unix** systems: 48 | 49 | $ make 50 | $ make install 51 | 52 | For more detailed installation instructions (eg, for **Windows**), see `INSTALL`. 53 | 54 | FUNCTIONS 55 | ========= 56 | 57 | - plan(tests) 58 | - plan(NO_PLAN) 59 | - plan(SKIP_ALL); 60 | - plan(SKIP_ALL, fmt, ...) 61 | 62 | Use this to start a series of tests. When you know how many tests there 63 | will be, you can put a number as a number of tests you expect to run. If 64 | you do not know how many tests there will be, you can use plan(NO_PLAN) 65 | or not call this function. When you pass it a number of tests to run, a 66 | message similar to the following will appear in the output: 67 | 68 | 1..5 69 | 70 | If you pass it SKIP_ALL, the whole test will be skipped. 71 | 72 | - ok(test) 73 | - ok(test, fmt, ...) 74 | 75 | Specify a test. the test can be any statement returning a true or false 76 | value. You may optionally pass a format string describing the test. 77 | 78 | ok(r = reader_new("Of Mice and Men"), "create a new reader"); 79 | ok(reader_go_to_page(r, 55), "can turn the page"); 80 | ok(r->page == 55, "page turned to the right one"); 81 | 82 | Should print out: 83 | 84 | ok 1 - create a new reader 85 | ok 2 - can turn the page 86 | ok 3 - page turned to the right one 87 | 88 | On failure, a diagnostic message will be printed out. 89 | 90 | not ok 3 - page turned to the right one 91 | # Failed test 'page turned to the right one' 92 | # at reader.c line 13. 93 | 94 | - is(got, expected) 95 | - is(got, expected, fmt, ...) 96 | - isnt(got, unexpected) 97 | - isnt(got, unexpected, fmt, ...) 98 | 99 | Tests that the string you got is what you expected. with isnt, it is the 100 | reverse. 101 | 102 | is("this", "that", "this is that"); 103 | 104 | prints: 105 | 106 | not ok 1 - this is that 107 | # Failed test 'this is that' 108 | # at is.c line 6. 109 | # got: 'this' 110 | # expected: 'that' 111 | 112 | - cmp_ok(a, op, b) 113 | - cmp_ok(a, op, b, fmt, ...) 114 | 115 | Compares two ints with any binary operator that doesn't require an lvalue. 116 | This is nice to use since it provides a better error message than an 117 | equivalent ok. 118 | 119 | cmp_ok(420, ">", 666); 120 | 121 | prints: 122 | 123 | not ok 1 124 | # Failed test at cmpok.c line 5. 125 | # 420 126 | # > 127 | # 666 128 | 129 | - cmp_mem(got, expected, n) 130 | - cmp_mem(got, expected, n, fmt, ...) 131 | 132 | Tests that the first n bytes of the memory you got is what you expected. 133 | NULL pointers for got and expected are handled (if either is NULL, 134 | the test fails), but you need to ensure n is not too large. 135 | 136 | char *a = "foo"; 137 | char *b = "bar"; 138 | cmp_mem(a, b, 3) 139 | 140 | prints 141 | 142 | not ok 1 143 | # Failed test at t/cmp_mem.c line 9. 144 | # Difference starts at offset 0 145 | # got: 0x66 146 | # expected: 0x62 147 | 148 | - like(got, expected) 149 | - like(got, expected, fmt, ...) 150 | - unlike(got, unexpected) 151 | - unlike(got, unexpected, fmt, ...) 152 | 153 | Tests that the string you got matches the expected extended POSIX regex. 154 | unlike is the reverse. These macros are the equivalent of a skip on 155 | Windows. 156 | 157 | like("stranger", "^s.(r).*\\1$", "matches the regex"); 158 | 159 | prints: 160 | 161 | ok 1 - matches the regex 162 | 163 | - pass() 164 | - pass(fmt, ...) 165 | - fail() 166 | - fail(fmt, ...) 167 | 168 | Speciy that a test succeeded or failed. Use these when the statement is 169 | longer than you can fit into the argument given to an ok() test. 170 | 171 | - dies_ok(code) 172 | - dies_ok(code, fmt, ...) 173 | - lives_ok(code) 174 | - lives_ok(code, fmt, ...) 175 | 176 | Tests whether the given code causes your program to exit. The code gets 177 | passed to a macro that will test it in a forked process. If the code 178 | succeeds it will be executed in the parent process. You can test things 179 | like passing a function a null pointer and make sure it doesnt 180 | dereference it and crash. 181 | 182 | dies_ok({abort();}, "abort does close your program"); 183 | dies_ok({int x = 0/0;}, "divide by zero crash"); 184 | lives_ok({pow(3.0, 5.0);}, "nothing wrong with taking 3**5"); 185 | 186 | On Windows, these macros are the equivalent of a skip. 187 | 188 | - done_testing() 189 | 190 | Summarizes the tests that occurred and exits the main function. If 191 | there was no plan, it will print out the number of tests as. 192 | 193 | 1..5 194 | 195 | It will also print a diagnostic message about how many 196 | failures there were. 197 | 198 | # Looks like you failed 2 tests of 3 run. 199 | 200 | If all planned tests were successful, it will return 0. If any 201 | test fails, it will return 1. If they all passed, but there 202 | were missing tests, it will return 2. 203 | 204 | - diag(fmt, ...) 205 | 206 | print out a message to the tap output on stdout. Each line is 207 | preceeded by a "# " so that you know its a diagnostic message. 208 | 209 | diag("This is\na diag\nto describe\nsomething."); 210 | 211 | prints: 212 | 213 | # This is 214 | # a diag 215 | # to describe 216 | # something 217 | 218 | ok() and this function return an int so you can use it like: 219 | 220 | ok(0) || diag("doh!"); 221 | 222 | - skip(test, n) 223 | - skip(test, n, fmt, ...) 224 | - end_skip 225 | 226 | Skip a series of n tests if test is true. You may give a reason why you are 227 | skipping them or not. The (possibly) skipped tests must occur between the 228 | skip and end_skip macros. 229 | 230 | skip(TRUE, 2); 231 | ok(1); 232 | ok(0); 233 | end_skip; 234 | 235 | prints: 236 | 237 | ok 1 # skip 238 | ok 2 # skip 239 | 240 | - todo() 241 | - todo(fmt, ...) 242 | - end_todo 243 | 244 | Specifies a series of tests that you expect to fail because they are not 245 | yet implemented. 246 | 247 | todo() 248 | ok(0); 249 | end_todo; 250 | 251 | prints: 252 | 253 | not ok 1 # TODO 254 | # Failed (TODO) test at todo.c line 7 255 | 256 | - BAIL_OUT() 257 | - BAIL_OUT(fmt, ...) 258 | 259 | Immediately stops all testing. 260 | 261 | BAIL_OUT("Can't go no further"); 262 | 263 | prints 264 | 265 | Bail out! Can't go no further 266 | 267 | and exits with 255. 268 | 269 | -------------------------------------------------------------------------------- /t/cmp_mem.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | 3 | int main () { 4 | unsigned char all_0[] = {0, 0, 0, 0}; 5 | unsigned char all_255[] = {255, 255, 255, 255}; 6 | unsigned char half[] = {0, 0, 255, 255}; 7 | unsigned char half_2[] = {0, 0, 255, 255}; 8 | 9 | plan(8); 10 | cmp_mem(half, half_2, 4, "Same array different address"); 11 | cmp_mem(all_0, all_0, 4, "Array must be equal to itself"); 12 | cmp_mem(all_0, all_255, 4, "Arrays with different contents"); 13 | cmp_mem(all_0, half, 4, "Arrays differ, but start the same"); 14 | cmp_mem(all_0, all_255, 0, "Comparing 0 bytes of different arrays"); 15 | cmp_mem(NULL, all_0, 4, "got == NULL"); 16 | cmp_mem(all_0, NULL, 4, "expected == NULL"); 17 | cmp_mem(NULL, NULL, 4, "got == expected == NULL"); 18 | done_testing(); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /t/cmp_mem.expected: -------------------------------------------------------------------------------- 1 | 1..8 2 | ok 1 - Same array different address 3 | ok 2 - Array must be equal to itself 4 | not ok 3 - Arrays with different contents 5 | # Failed test 'Arrays with different contents' 6 | # at t/cmp_mem.c line 12. 7 | # Difference starts at offset 0 8 | # got: 0x00 9 | # expected: 0xff 10 | not ok 4 - Arrays differ, but start the same 11 | # Failed test 'Arrays differ, but start the same' 12 | # at t/cmp_mem.c line 13. 13 | # Difference starts at offset 2 14 | # got: 0x00 15 | # expected: 0xff 16 | ok 5 - Comparing 0 bytes of different arrays 17 | not ok 6 - got == NULL 18 | # Failed test 'got == NULL' 19 | # at t/cmp_mem.c line 15. 20 | # got: NULL 21 | # expected: not NULL 22 | not ok 7 - expected == NULL 23 | # Failed test 'expected == NULL' 24 | # at t/cmp_mem.c line 16. 25 | # got: not NULL 26 | # expected: NULL 27 | ok 8 - got == expected == NULL 28 | # Looks like you failed 4 tests of 8 run. 29 | -------------------------------------------------------------------------------- /t/cmpok.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | 3 | int main () { 4 | plan(9); 5 | cmp_ok(420, ">", 666); 6 | cmp_ok(23, "==", 55, "the number 23 is definitely 55"); 7 | cmp_ok(23, "==", 55); 8 | cmp_ok(23, "!=", 55); 9 | cmp_ok(23, "frob", 55); 10 | cmp_ok(23, "<=", 55); 11 | cmp_ok(55, "+", -55); 12 | cmp_ok(23, "%", 5); 13 | cmp_ok(55, "%", 5); 14 | done_testing(); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /t/cmpok.expected: -------------------------------------------------------------------------------- 1 | 1..9 2 | not ok 1 3 | # Failed test at t/cmpok.c line 5. 4 | # 420 5 | # > 6 | # 666 7 | not ok 2 - the number 23 is definitely 55 8 | # Failed test 'the number 23 is definitely 55' 9 | # at t/cmpok.c line 6. 10 | # 23 11 | # == 12 | # 55 13 | not ok 3 14 | # Failed test at t/cmpok.c line 7. 15 | # 23 16 | # == 17 | # 55 18 | ok 4 19 | # unrecognized operator 'frob' 20 | not ok 5 21 | # Failed test at t/cmpok.c line 9. 22 | # 23 23 | # frob 24 | # 55 25 | ok 6 26 | not ok 7 27 | # Failed test at t/cmpok.c line 11. 28 | # 55 29 | # + 30 | # -55 31 | ok 8 32 | not ok 9 33 | # Failed test at t/cmpok.c line 13. 34 | # 55 35 | # % 36 | # 5 37 | # Looks like you failed 6 tests of 9 run. 38 | -------------------------------------------------------------------------------- /t/diag.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | 3 | int main () { 4 | diag("diag no new line"); 5 | diag("diag new line\n"); 6 | diag(""); 7 | diag(NULL); 8 | return 1; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /t/diag.expected: -------------------------------------------------------------------------------- 1 | # diag no new line 2 | # diag new line 3 | -------------------------------------------------------------------------------- /t/diesok.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | 3 | int main () { 4 | plan(5); 5 | ok(1, "sanity"); 6 | dies_ok({int x = 0; x = 1/x;}, "can't divide by zero"); 7 | lives_ok({int x = 3; x = x/7;}, "this is a perfectly fine statement"); 8 | dies_ok({abort();}, "abort kills the program"); 9 | dies_ok( 10 | {printf("stdout\n"); fprintf(stderr, "stderr\n"); abort();}, 11 | "supress output"); 12 | done_testing(); 13 | } 14 | 15 | -------------------------------------------------------------------------------- /t/diesok.expected: -------------------------------------------------------------------------------- 1 | 1..5 2 | ok 1 - sanity 3 | ok 2 - can't divide by zero 4 | ok 3 - this is a perfectly fine statement 5 | ok 4 - abort kills the program 6 | ok 5 - supress output 7 | -------------------------------------------------------------------------------- /t/is.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | 3 | int main () { 4 | plan(18); 5 | is("this", "that", "this is that"); /* bang */ 6 | is("this", "this", "this is this"); 7 | is("this", "that"); /* bang */ 8 | is("this", "this"); 9 | is(NULL, NULL, "null is null"); 10 | is(NULL, "this", "null is this"); /* bang */ 11 | is("this", NULL, "this is null"); /* bang */ 12 | is("foo\nfoo\nfoo", "bar\nbar\nbar"); /* bang */ 13 | is("foo\nfoo\nfoo", "foo\nfoo\nfoo"); 14 | isnt("this", "that", "this isnt that"); 15 | isnt("this", "this", "this isnt this"); /* bang */ 16 | isnt("this", "that"); 17 | isnt("this", "this"); /* bang */ 18 | isnt(NULL, NULL, "null isnt null"); /* bang */ 19 | isnt(NULL, "this", "null isnt this"); 20 | isnt("this", NULL, "this isnt null"); 21 | isnt("foo\nfoo\nfoo", "bar\nbar\nbar"); 22 | isnt("foo\nfoo\nfoo", "foo\nfoo\nfoo"); /* bang */ 23 | done_testing(); 24 | } 25 | -------------------------------------------------------------------------------- /t/is.expected: -------------------------------------------------------------------------------- 1 | 1..18 2 | not ok 1 - this is that 3 | # Failed test 'this is that' 4 | # at t/is.c line 5. 5 | # got: 'this' 6 | # expected: 'that' 7 | ok 2 - this is this 8 | not ok 3 9 | # Failed test at t/is.c line 7. 10 | # got: 'this' 11 | # expected: 'that' 12 | ok 4 13 | ok 5 - null is null 14 | not ok 6 - null is this 15 | # Failed test 'null is this' 16 | # at t/is.c line 10. 17 | # got: '(null)' 18 | # expected: 'this' 19 | not ok 7 - this is null 20 | # Failed test 'this is null' 21 | # at t/is.c line 11. 22 | # got: 'this' 23 | # expected: '(null)' 24 | not ok 8 25 | # Failed test at t/is.c line 12. 26 | # got: 'foo 27 | # foo 28 | # foo' 29 | # expected: 'bar 30 | # bar 31 | # bar' 32 | ok 9 33 | ok 10 - this isnt that 34 | not ok 11 - this isnt this 35 | # Failed test 'this isnt this' 36 | # at t/is.c line 15. 37 | # got: 'this' 38 | # expected: anything else 39 | ok 12 40 | not ok 13 41 | # Failed test at t/is.c line 17. 42 | # got: 'this' 43 | # expected: anything else 44 | not ok 14 - null isnt null 45 | # Failed test 'null isnt null' 46 | # at t/is.c line 18. 47 | # got: '(null)' 48 | # expected: anything else 49 | ok 15 - null isnt this 50 | ok 16 - this isnt null 51 | ok 17 52 | not ok 18 53 | # Failed test at t/is.c line 22. 54 | # got: 'foo 55 | # foo 56 | # foo' 57 | # expected: anything else 58 | # Looks like you failed 9 tests of 18 run. 59 | -------------------------------------------------------------------------------- /t/like.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | 3 | int main () { 4 | plan(3); 5 | like("strange", "range", "strange ~~ /range/"); 6 | unlike("strange", "anger", "strange !~~ /anger/"); 7 | like("stranger", "^s.(r).*$", "matches the regex"); 8 | done_testing(); 9 | } 10 | 11 | -------------------------------------------------------------------------------- /t/like.expected: -------------------------------------------------------------------------------- 1 | 1..3 2 | ok 1 - strange ~~ /range/ 3 | ok 2 - strange !~~ /anger/ 4 | ok 3 - matches the regex 5 | -------------------------------------------------------------------------------- /t/simple.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | 3 | int main () { 4 | plan(24); 5 | ok(1); 6 | ok(1); 7 | ok(1); 8 | ok(0); 9 | ok(1, "foo"); 10 | ok(1, "bar"); 11 | ok(1, "baz"); 12 | ok(1, "quux"); 13 | ok(1, "thud"); 14 | ok(1, "wombat"); 15 | ok(1, "blurgle"); 16 | ok(1, "frob"); 17 | ok(0, "frobnicate"); 18 | ok(1, "eek"); 19 | ok(1, "ook"); 20 | ok(1, "frodo"); 21 | ok(1, "bilbo"); 22 | ok(1, "wubble"); 23 | ok(1, "flarp"); 24 | ok(1, "fnord"); 25 | pass(); 26 | fail(); 27 | pass("good"); 28 | fail("bad"); 29 | done_testing(); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /t/simple.expected: -------------------------------------------------------------------------------- 1 | 1..24 2 | ok 1 3 | ok 2 4 | ok 3 5 | not ok 4 6 | # Failed test at t/simple.c line 8. 7 | ok 5 - foo 8 | ok 6 - bar 9 | ok 7 - baz 10 | ok 8 - quux 11 | ok 9 - thud 12 | ok 10 - wombat 13 | ok 11 - blurgle 14 | ok 12 - frob 15 | not ok 13 - frobnicate 16 | # Failed test 'frobnicate' 17 | # at t/simple.c line 17. 18 | ok 14 - eek 19 | ok 15 - ook 20 | ok 16 - frodo 21 | ok 17 - bilbo 22 | ok 18 - wubble 23 | ok 19 - flarp 24 | ok 20 - fnord 25 | ok 21 26 | not ok 22 27 | # Failed test at t/simple.c line 26. 28 | ok 23 - good 29 | not ok 24 - bad 30 | # Failed test 'bad' 31 | # at t/simple.c line 28. 32 | # Looks like you failed 4 tests of 24 run. 33 | -------------------------------------------------------------------------------- /t/skip.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | 3 | int main () { 4 | plan(8); 5 | skip(0, 3, "%s cannot fork", "windows"); 6 | ok(1, "quux"); 7 | ok(1, "thud"); 8 | ok(1, "wombat"); 9 | end_skip; 10 | skip(1, 1, "need to be on windows"); 11 | ok(0, "blurgle"); 12 | end_skip; 13 | skip(0, 3); 14 | ok(1, "quux"); 15 | ok(1, "thud"); 16 | ok(1, "wombat"); 17 | end_skip; 18 | skip(1, 1); 19 | ok(0, "blurgle"); 20 | end_skip; 21 | done_testing(); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /t/skip.expected: -------------------------------------------------------------------------------- 1 | 1..8 2 | ok 1 - quux 3 | ok 2 - thud 4 | ok 3 - wombat 5 | ok 4 # skip need to be on windows 6 | ok 5 - quux 7 | ok 6 - thud 8 | ok 7 - wombat 9 | ok 8 # skip 10 | -------------------------------------------------------------------------------- /t/synopsis.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | 3 | int main () { 4 | plan(5); 5 | int bronze = 1, silver = 2, gold = 3; 6 | ok(bronze < silver, "bronze is less than silver"); 7 | ok(bronze > silver, "not quite"); 8 | is("gold", "gold", "gold is gold"); 9 | cmp_ok(silver, "<", gold, "%d <= %d", silver, gold); 10 | like("platinum", ".*inum", "platinum matches .*inum"); 11 | done_testing(); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /t/synopsis.expected: -------------------------------------------------------------------------------- 1 | 1..5 2 | ok 1 - bronze is less than silver 3 | not ok 2 - not quite 4 | # Failed test 'not quite' 5 | # at t/synopsis.c line 7. 6 | ok 3 - gold is gold 7 | ok 4 - 2 <= 3 8 | ok 5 - platinum matches .*inum 9 | # Looks like you failed 1 test of 5 run. 10 | -------------------------------------------------------------------------------- /t/test.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main () { 8 | DIR *dp = opendir("t"); 9 | if (!dp) { 10 | perror("opendir"); 11 | exit(1); 12 | } 13 | struct dirent *ep; 14 | while ((ep = readdir(dp))) { 15 | char *name = ep->d_name; 16 | if (strchr(name, '.') || !strcmp(name, "test")) 17 | continue; 18 | char command[1024]; 19 | snprintf(command, 1024, "./t/%s >t/%s.got 2>&1", name, name); 20 | system(command); 21 | snprintf(command, 1024, "diff -up t/%s.expected t/%s.got", name, name); 22 | int retval = system(command); 23 | ok(!(retval >> 8), name); 24 | } 25 | closedir(dp); 26 | done_testing(); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /t/todo.c: -------------------------------------------------------------------------------- 1 | #include "tap.h" 2 | 3 | int main () { 4 | plan(6); 5 | todo(); 6 | ok(0, "foo"); 7 | ok(1, "bar"); 8 | ok(1, "baz"); 9 | end_todo; 10 | todo("im not ready"); 11 | ok(0, "quux"); 12 | ok(1, "thud"); 13 | ok(1, "wombat"); 14 | end_todo; 15 | done_testing(); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /t/todo.expected: -------------------------------------------------------------------------------- 1 | 1..6 2 | not ok 1 - foo # TODO 3 | # Failed (TODO) test 'foo' 4 | # at t/todo.c line 6. 5 | ok 2 - bar # TODO 6 | ok 3 - baz # TODO 7 | not ok 4 - quux # TODO im not ready 8 | # Failed (TODO) test 'quux' 9 | # at t/todo.c line 11. 10 | ok 5 - thud # TODO im not ready 11 | ok 6 - wombat # TODO im not ready 12 | -------------------------------------------------------------------------------- /tap.c: -------------------------------------------------------------------------------- 1 | /* 2 | libtap - Write tests in C 3 | Copyright 2012 Jake Gelbman 4 | This file is licensed under the LGPL 5 | */ 6 | 7 | #define _DEFAULT_SOURCE 1 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "tap.h" 14 | 15 | #ifndef _WIN32 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #ifndef MAP_ANONYMOUS 22 | #ifdef MAP_ANON 23 | #define MAP_ANONYMOUS MAP_ANON 24 | #else 25 | #error "System does not support mapping anonymous pages" 26 | #endif 27 | #endif 28 | #endif 29 | 30 | static int expected_tests = NO_PLAN; 31 | static int failed_tests; 32 | static int current_test; 33 | static char *todo_mesg; 34 | 35 | static char * 36 | vstrdupf (const char *fmt, va_list args) { 37 | char *str; 38 | int size; 39 | va_list args2; 40 | va_copy(args2, args); 41 | if (!fmt) 42 | fmt = ""; 43 | size = vsnprintf(NULL, 0, fmt, args2) + 2; 44 | str = malloc(size); 45 | if (!str) { 46 | perror("malloc error"); 47 | exit(1); 48 | } 49 | vsprintf(str, fmt, args); 50 | va_end(args2); 51 | return str; 52 | } 53 | 54 | void 55 | tap_plan (int tests, const char *fmt, ...) { 56 | expected_tests = tests; 57 | if (tests == SKIP_ALL) { 58 | char *why; 59 | va_list args; 60 | va_start(args, fmt); 61 | why = vstrdupf(fmt, args); 62 | va_end(args); 63 | printf("1..0 "); 64 | diag("SKIP %s\n", why); 65 | exit(0); 66 | } 67 | if (tests != NO_PLAN) { 68 | printf("1..%d\n", tests); 69 | } 70 | } 71 | 72 | int 73 | vok_at_loc (const char *file, int line, int test, const char *fmt, 74 | va_list args) 75 | { 76 | char *name = vstrdupf(fmt, args); 77 | if (!test) { 78 | printf("not "); 79 | } 80 | printf("ok %d", ++current_test); 81 | if (*name) 82 | printf(" - %s", name); 83 | if (todo_mesg) { 84 | printf(" # TODO"); 85 | if (*todo_mesg) 86 | printf(" %s", todo_mesg); 87 | } 88 | printf("\n"); 89 | if (!test) { 90 | printf("# Failed "); 91 | if (todo_mesg) 92 | printf("(TODO) "); 93 | printf("test "); 94 | if (*name) 95 | printf("'%s'\n# ", name); 96 | printf("at %s line %d.\n", file, line); 97 | if (!todo_mesg) 98 | failed_tests++; 99 | } 100 | free(name); 101 | return test; 102 | } 103 | 104 | int 105 | ok_at_loc (const char *file, int line, int test, const char *fmt, ...) { 106 | va_list args; 107 | va_start(args, fmt); 108 | vok_at_loc(file, line, test, fmt, args); 109 | va_end(args); 110 | return test; 111 | } 112 | 113 | static int 114 | mystrcmp (const char *a, const char *b) { 115 | return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b); 116 | } 117 | 118 | #define eq(a, b) (!mystrcmp(a, b)) 119 | #define ne(a, b) (mystrcmp(a, b)) 120 | 121 | int 122 | is_at_loc (const char *file, int line, const char *got, const char *expected, 123 | const char *fmt, ...) 124 | { 125 | int test = eq(got, expected); 126 | va_list args; 127 | va_start(args, fmt); 128 | vok_at_loc(file, line, test, fmt, args); 129 | va_end(args); 130 | if (!test) { 131 | diag(" got: '%s'", got); 132 | diag(" expected: '%s'", expected); 133 | } 134 | return test; 135 | } 136 | 137 | int 138 | isnt_at_loc (const char *file, int line, const char *got, const char *expected, 139 | const char *fmt, ...) 140 | { 141 | int test = ne(got, expected); 142 | va_list args; 143 | va_start(args, fmt); 144 | vok_at_loc(file, line, test, fmt, args); 145 | va_end(args); 146 | if (!test) { 147 | diag(" got: '%s'", got); 148 | diag(" expected: anything else"); 149 | } 150 | return test; 151 | } 152 | 153 | int 154 | cmp_ok_at_loc (const char *file, int line, int a, const char *op, int b, 155 | const char *fmt, ...) 156 | { 157 | int test = eq(op, "||") ? a || b 158 | : eq(op, "&&") ? a && b 159 | : eq(op, "|") ? a | b 160 | : eq(op, "^") ? a ^ b 161 | : eq(op, "&") ? a & b 162 | : eq(op, "==") ? a == b 163 | : eq(op, "!=") ? a != b 164 | : eq(op, "<") ? a < b 165 | : eq(op, ">") ? a > b 166 | : eq(op, "<=") ? a <= b 167 | : eq(op, ">=") ? a >= b 168 | : eq(op, "<<") ? a << b 169 | : eq(op, ">>") ? a >> b 170 | : eq(op, "+") ? a + b 171 | : eq(op, "-") ? a - b 172 | : eq(op, "*") ? a * b 173 | : eq(op, "/") ? a / b 174 | : eq(op, "%") ? a % b 175 | : diag("unrecognized operator '%s'", op); 176 | va_list args; 177 | va_start(args, fmt); 178 | vok_at_loc(file, line, test, fmt, args); 179 | va_end(args); 180 | if (!test) { 181 | diag(" %d", a); 182 | diag(" %s", op); 183 | diag(" %d", b); 184 | } 185 | return test; 186 | } 187 | 188 | static int 189 | find_mem_diff (const char *a, const char *b, size_t n, size_t *offset) { 190 | size_t i; 191 | if (a == b) 192 | return 0; 193 | if (!a || !b) 194 | return 2; 195 | for (i = 0; i < n; i++) { 196 | if (a[i] != b[i]) { 197 | *offset = i; 198 | return 1; 199 | } 200 | } 201 | return 0; 202 | } 203 | 204 | int 205 | cmp_mem_at_loc (const char *file, int line, const void *got, 206 | const void *expected, size_t n, const char *fmt, ...) 207 | { 208 | size_t offset; 209 | int diff = find_mem_diff(got, expected, n, &offset); 210 | va_list args; 211 | va_start(args, fmt); 212 | vok_at_loc(file, line, !diff, fmt, args); 213 | va_end(args); 214 | if (diff == 1) { 215 | diag(" Difference starts at offset %d", offset); 216 | diag(" got: 0x%02x", ((const unsigned char *)got)[offset]); 217 | diag(" expected: 0x%02x", ((const unsigned char *)expected)[offset]); 218 | } 219 | else if (diff == 2) { 220 | diag(" got: %s", got ? "not NULL" : "NULL"); 221 | diag(" expected: %s", expected ? "not NULL" : "NULL"); 222 | } 223 | return !diff; 224 | } 225 | 226 | int 227 | diag (const char *fmt, ...) { 228 | va_list args; 229 | char *mesg, *line; 230 | int i; 231 | va_start(args, fmt); 232 | if (!fmt) { 233 | va_end(args); 234 | return 0; 235 | } 236 | mesg = vstrdupf(fmt, args); 237 | line = mesg; 238 | for (i = 0; *line; i++) { 239 | char c = mesg[i]; 240 | if (!c || c == '\n') { 241 | mesg[i] = '\0'; 242 | printf("# %s\n", line); 243 | if (!c) 244 | break; 245 | mesg[i] = c; 246 | line = mesg + i + 1; 247 | } 248 | } 249 | free(mesg); 250 | va_end(args); 251 | return 0; 252 | } 253 | 254 | int 255 | exit_status () { 256 | int retval = 0; 257 | if (expected_tests == NO_PLAN) { 258 | printf("1..%d\n", current_test); 259 | } 260 | else if (current_test != expected_tests) { 261 | diag("Looks like you planned %d test%s but ran %d.", 262 | expected_tests, expected_tests > 1 ? "s" : "", current_test); 263 | retval = 2; 264 | } 265 | if (failed_tests) { 266 | diag("Looks like you failed %d test%s of %d run.", 267 | failed_tests, failed_tests > 1 ? "s" : "", current_test); 268 | retval = 1; 269 | } 270 | return retval; 271 | } 272 | 273 | int 274 | bail_out (int ignore, const char *fmt, ...) { 275 | va_list args; 276 | (void) ignore; 277 | va_start(args, fmt); 278 | printf("Bail out! "); 279 | vprintf(fmt, args); 280 | printf("\n"); 281 | va_end(args); 282 | exit(255); 283 | return 0; 284 | } 285 | 286 | void 287 | tap_skip (int n, const char *fmt, ...) { 288 | char *why; 289 | va_list args; 290 | va_start(args, fmt); 291 | why = vstrdupf(fmt, args); 292 | va_end(args); 293 | while (n --> 0) { 294 | printf("ok %d ", ++current_test); 295 | diag("skip %s\n", why); 296 | } 297 | free(why); 298 | } 299 | 300 | void 301 | tap_todo (int ignore, const char *fmt, ...) { 302 | va_list args; 303 | (void) ignore; 304 | va_start(args, fmt); 305 | todo_mesg = vstrdupf(fmt, args); 306 | va_end(args); 307 | } 308 | 309 | void 310 | tap_end_todo () { 311 | free(todo_mesg); 312 | todo_mesg = NULL; 313 | } 314 | 315 | #ifndef _WIN32 316 | /* Create a shared memory int to keep track of whether a piece of code executed 317 | dies. to be used in the dies_ok and lives_ok macros. */ 318 | int 319 | tap_test_died (int status) { 320 | static int *test_died = NULL; 321 | int prev; 322 | if (!test_died) { 323 | test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE, 324 | MAP_SHARED | MAP_ANONYMOUS, -1, 0); 325 | *test_died = 0; 326 | } 327 | prev = *test_died; 328 | *test_died = status; 329 | return prev; 330 | } 331 | 332 | int 333 | like_at_loc (int for_match, const char *file, int line, const char *got, 334 | const char *expected, const char *fmt, ...) 335 | { 336 | int test; 337 | regex_t re; 338 | va_list args; 339 | int err = regcomp(&re, expected, REG_EXTENDED); 340 | if (err) { 341 | char errbuf[256]; 342 | regerror(err, &re, errbuf, sizeof errbuf); 343 | fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n", 344 | expected, errbuf, file, line); 345 | exit(255); 346 | } 347 | err = regexec(&re, got, 0, NULL, 0); 348 | regfree(&re); 349 | test = for_match ? !err : err; 350 | va_start(args, fmt); 351 | vok_at_loc(file, line, test, fmt, args); 352 | va_end(args); 353 | if (!test) { 354 | if (for_match) { 355 | diag(" '%s'", got); 356 | diag(" doesn't match: '%s'", expected); 357 | } 358 | else { 359 | diag(" '%s'", got); 360 | diag(" matches: '%s'", expected); 361 | } 362 | } 363 | return test; 364 | } 365 | #endif 366 | -------------------------------------------------------------------------------- /tap.h: -------------------------------------------------------------------------------- 1 | /* 2 | libtap - Write tests in C 3 | Copyright 2012 Jake Gelbman 4 | This file is licensed under the LGPL 5 | */ 6 | 7 | #ifndef __TAP_H__ 8 | #define __TAP_H__ 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #ifndef va_copy 15 | #ifdef __va_copy 16 | #define va_copy __va_copy 17 | #else 18 | #define va_copy(d, s) ((d) = (s)) 19 | #endif 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | int vok_at_loc (const char *file, int line, int test, const char *fmt, 27 | va_list args); 28 | int ok_at_loc (const char *file, int line, int test, const char *fmt, 29 | ...); 30 | int is_at_loc (const char *file, int line, const char *got, 31 | const char *expected, const char *fmt, ...); 32 | int isnt_at_loc (const char *file, int line, const char *got, 33 | const char *expected, const char *fmt, ...); 34 | int cmp_ok_at_loc (const char *file, int line, int a, const char *op, 35 | int b, const char *fmt, ...); 36 | int cmp_mem_at_loc (const char *file, int line, const void *got, 37 | const void *expected, size_t n, const char *fmt, ...); 38 | int bail_out (int ignore, const char *fmt, ...); 39 | void tap_plan (int tests, const char *fmt, ...); 40 | int diag (const char *fmt, ...); 41 | int exit_status (void); 42 | void tap_skip (int n, const char *fmt, ...); 43 | void tap_todo (int ignore, const char *fmt, ...); 44 | void tap_end_todo (void); 45 | 46 | #define NO_PLAN -1 47 | #define SKIP_ALL -2 48 | #define ok(...) ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 49 | #define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 50 | #define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 51 | #define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 52 | #define cmp_mem(...) cmp_mem_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 53 | #define plan(...) tap_plan(__VA_ARGS__, NULL) 54 | #define done_testing() return exit_status() 55 | #define BAIL_OUT(...) bail_out(0, "" __VA_ARGS__, NULL) 56 | #define pass(...) ok(1, "" __VA_ARGS__) 57 | #define fail(...) ok(0, "" __VA_ARGS__) 58 | 59 | #define skip(test, ...) do {if (test) {tap_skip(__VA_ARGS__, NULL); break;} 60 | #define end_skip } while (0) 61 | 62 | #define todo(...) tap_todo(0, "" __VA_ARGS__, NULL) 63 | #define end_todo tap_end_todo() 64 | 65 | #define dies_ok(...) dies_ok_common(1, __VA_ARGS__) 66 | #define lives_ok(...) dies_ok_common(0, __VA_ARGS__) 67 | 68 | #ifdef _WIN32 69 | #define like(...) tap_skip(1, "like is not implemented on Windows") 70 | #define unlike(...) tap_skip(1, "unlike is not implemented on Windows") 71 | #define dies_ok_common(...) \ 72 | tap_skip(1, "Death detection is not supported on Windows") 73 | #else 74 | #define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL) 75 | #define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL) 76 | int like_at_loc (int for_match, const char *file, int line, 77 | const char *got, const char *expected, 78 | const char *fmt, ...); 79 | #include 80 | #include 81 | #include 82 | int tap_test_died (int status); 83 | #define dies_ok_common(for_death, code, ...) \ 84 | do { \ 85 | int cpid; \ 86 | int it_died; \ 87 | tap_test_died(1); \ 88 | cpid = fork(); \ 89 | switch (cpid) { \ 90 | case -1: \ 91 | perror("fork error"); \ 92 | exit(1); \ 93 | case 0: \ 94 | close(1); \ 95 | close(2); \ 96 | code \ 97 | tap_test_died(0); \ 98 | exit(0); \ 99 | } \ 100 | if (waitpid(cpid, NULL, 0) < 0) { \ 101 | perror("waitpid error"); \ 102 | exit(1); \ 103 | } \ 104 | it_died = tap_test_died(0); \ 105 | if (!it_died) \ 106 | {code} \ 107 | ok(for_death ? it_died : !it_died, "" __VA_ARGS__); \ 108 | } while (0) 109 | #endif 110 | 111 | #ifdef __cplusplus 112 | } 113 | #endif 114 | 115 | #endif 116 | --------------------------------------------------------------------------------