├── .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 |
--------------------------------------------------------------------------------