Initial commit
This commit is contained in:
commit
e6d1ce57f1
3 changed files with 193 additions and 0 deletions
54
Makefile
Normal file
54
Makefile
Normal file
|
@ -0,0 +1,54 @@
|
|||
# _,.---._ .-._ .--.-. ,--.--------.
|
||||
# _,..---._ ,-.' , - `. /==/ \ .-._/==/ //==/, - , -\
|
||||
# /==/, - \ /==/_, , - \|==|, \/ /, |==\ -\\==\.-. - ,-./
|
||||
# |==| _ _\==| .=. |==|- \| | \==\- \`--`\==\- \
|
||||
# |==| .=. |==|_ : ;=: - |==| , | -| `--`-' \==\_ \
|
||||
# |==|,| | -|==| , '=' |==| - _ | |==|- |
|
||||
# |==| '=' /\==\ - ,_ /|==| /\ , | |==|, |
|
||||
# |==|-, _`/ '.='. - .' /==/, | |- | /==/ -/
|
||||
# `-.`.____.' `--`--'' `--`./ `--` `--`--`
|
||||
# _ __ ,---. .-._ .=-.-. _,.----.
|
||||
# .-`.' ,`..--.' \ /==/ \ .-._ /==/_ /.' .' - \
|
||||
# /==/, - \==\-/\ \ |==|, \/ /, /==|, |/==/ , ,-'
|
||||
# |==| _ .=. /==/-|_\ | |==|- \| ||==| ||==|- | .
|
||||
# |==| , '=',\==\, - \ |==| , | -||==|- ||==|_ `-' \
|
||||
# |==|- '..'/==/ - ,| |==| - _ ||==| ,||==| _ , |
|
||||
# |==|, | /==/- /\ - \|==| /\ , ||==|- |\==\. /
|
||||
# /==/ - | \==\ _.\=\.-'/==/, | |- |/==/. / `-.`.___.-'
|
||||
# `--`---' `--` `--`./ `--``--`-`
|
||||
#
|
||||
# @(#)Copyright (c) 2023, Nathan D. Fisher.
|
||||
#
|
||||
# This is free software. It comes with NO WARRANTY.
|
||||
# Permission to use, modify and distribute this source code
|
||||
# is granted subject to the following conditions.
|
||||
# 1/ that the above copyright notice and this notice
|
||||
# are preserved in all copies and that due credit be given
|
||||
# to the author.
|
||||
# 2/ that any changes to this code are clearly commented
|
||||
# as such so that the author does not get blamed for bugs
|
||||
# other than his own.
|
||||
#
|
||||
|
||||
CFLAGS += -I../include
|
||||
# Add your library to $(LDLIBS)
|
||||
#LDLIBS += ../lib<yourlibrary>.a
|
||||
# Any other libraries in $(LIBS) also get linked in
|
||||
LDLIBS += $(LIBS)
|
||||
|
||||
# Add the names of your tests to the array $(tests)
|
||||
#tests += <testname>
|
||||
|
||||
.PHONY: test
|
||||
test: $(tests) runner output
|
||||
./runner $(tests)
|
||||
|
||||
output:
|
||||
@ [-d $@ ] 2>/dev/null || install -d $@
|
||||
|
||||
runner: runner.c
|
||||
$(CC) -o runner runner.c
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(tests) runner output/*
|
62
README.md
Normal file
62
README.md
Normal file
|
@ -0,0 +1,62 @@
|
|||
Contents
|
||||
========
|
||||
- [Rationale](#rationale)
|
||||
- [Usage](#usage)
|
||||
- [Writing Tests](#writing_tests)
|
||||
|
||||
## Rationale
|
||||
The purpose of this package is both practical and as a demonstration for just how
|
||||
simple a test harness can be, in order to encourage both more testing in C code
|
||||
as well as the use of simple tools. As such, the **Roadrunner** test runner consists
|
||||
of a test runner written in a single file of highly portable C, totaling 43 lines,
|
||||
and a simple, POSIX compatible Makefile which works with both GNU and BSD make.
|
||||
|
||||
The original version of this project was written entirely in POSIX make, but due to
|
||||
the variations in POSIX shell behavior, especially in regards to the variety of ways
|
||||
that both the built in *echo* command and */bin/echo* screw up sending terminal escape
|
||||
sequences, something more robust and portable was desirable. There were simply too
|
||||
many corner cases to be bothered to find them all.
|
||||
|
||||
## Usage
|
||||
The best way to use this is to stuff it into a `test` subdirectory and call it via
|
||||
`make -C test`, or invoke it from your project's `Makefile` as a sub-make. If you
|
||||
are using something other than plain *make* to build your project then you probably
|
||||
don't want this, but also, why? That said, let's not get sidetracked.
|
||||
|
||||
The example Makefile also goes into the `test` subdirectory, and you will want to add
|
||||
the name of the library that you are testing on the appropriate line as well as the
|
||||
names of all of the tests that you wish to run. Add those to the `tests` array.
|
||||
```Makefile
|
||||
tests += my_test
|
||||
```
|
||||
For each member of `tests` there should be a corresponding file `<testname>.c` which
|
||||
will be compiled when you run `make` in this directory, along with the small helper
|
||||
program `runner.c`. Make will then invoke `./runner` with the list of tests as it's
|
||||
arguments. The *runner* program will keep track of successes and failures, as well
|
||||
as skipped tests, giving colored output and a nice summary at the end. If there are
|
||||
no failures the program exits with a value of **0**, otherwise the number of failures
|
||||
is returned.
|
||||
|
||||
Your library will have to be built as a static library and statically linked to each
|
||||
test program. All you have to do (after building the static library) is add it to
|
||||
the `$(LDLIBS)` array in the Makefile.
|
||||
|
||||
## Writing Tests
|
||||
### Return values
|
||||
The return values for each test shouuld follow these conventions.
|
||||
- 0 for success
|
||||
- 255 or -1 indicates this test was skipped
|
||||
- any other value indicates failure
|
||||
|
||||
### Skips
|
||||
If your test requires elevated privileges, you can simply test for uid == 0 and then
|
||||
bail with code 255 if the runner is run by a different user. Similarly, if your test
|
||||
needs the network then you can test programmatically for a working connection and bail
|
||||
with 255 if it isn't available.
|
||||
|
||||
### Don't use *assert*
|
||||
The `assert` function from `assert.h` will not cause your test to fail, because it
|
||||
simply aborts the program after printing a message to stderr. Instead, check for
|
||||
proper results and return an exit code if the test fails. You can also print error
|
||||
messages in your tests, which *runner* will capture, assume it means failure, and
|
||||
print to stderr in the terminal session.
|
77
runner.c
Normal file
77
runner.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* _,.---._ .-._ .--.-. ,--.--------.
|
||||
* _,..---._ ,-.' , - `. /==/ \ .-._/==/ //==/, - , -\
|
||||
* /==/, - \ /==/_, , - \|==|, \/ /, |==\ -\\==\.-. - ,-./
|
||||
* |==| _ _\==| .=. |==|- \| | \==\- \`--`\==\- \
|
||||
* |==| .=. |==|_ : ;=: - |==| , | -| `--`-' \==\_ \
|
||||
* |==|,| | -|==| , '=' |==| - _ | |==|- |
|
||||
* |==| '=' /\==\ - ,_ /|==| /\ , | |==|, |
|
||||
* |==|-, _`/ '.='. - .' /==/, | |- | /==/ -/
|
||||
* `-.`.____.' `--`--'' `--`./ `--` `--`--`
|
||||
* _ __ ,---. .-._ .=-.-. _,.----.
|
||||
* .-`.' ,`..--.' \ /==/ \ .-._ /==/_ /.' .' - \
|
||||
* /==/, - \==\-/\ \ |==|, \/ /, /==|, |/==/ , ,-'
|
||||
* |==| _ .=. /==/-|_\ | |==|- \| ||==| ||==|- | .
|
||||
* |==| , '=',\==\, - \ |==| , | -||==|- ||==|_ `-' \
|
||||
* |==|- '..'/==/ - ,| |==| - _ ||==| ,||==| _ , |
|
||||
* |==|, | /==/- /\ - \|==| /\ , ||==|- |\==\. /
|
||||
* /==/ - | \==\ _.\=\.-'/==/, | |- |/==/. / `-.`.___.-'
|
||||
* `--`---' `--` `--`./ `--``--`-`
|
||||
*
|
||||
* @(#)Copyright (c) 2024, Nathan D. Fisher.
|
||||
*
|
||||
* This is free software. It comes with NO WARRANTY.
|
||||
* Permission to use, modify and distribute this source code
|
||||
* is granted subject to the following conditions.
|
||||
* 1/ that the above copyright notice and this notice
|
||||
* are preserved in all copies and that due credit be given
|
||||
* to the author.
|
||||
* 2/ that any changes to this code are clearly commented
|
||||
* as such so that the author does not get blamed for bugs
|
||||
* other than his own.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i, pass = 0, fail = 0, skip = 0, total, ret, read = 0;
|
||||
FILE *pipe;
|
||||
char cmd[100], output[500];
|
||||
|
||||
total = argc-1;
|
||||
printf("\n\t=== \033[0;33mRunning %i tests\033[0m ===\n\n", total);
|
||||
for (i = 1; i < argc; i++) {
|
||||
snprintf(cmd, 100, "./%s", argv[i]);
|
||||
printf("[%03i/%03i] %-25s", i, total, argv[i]);
|
||||
pipe = popen(cmd, "w");
|
||||
read = fread(&output, 1, 500, pipe);
|
||||
ret = pclose(pipe);
|
||||
if (read) {
|
||||
fail++;
|
||||
printf("\033[0;31mFailed\033[0m\n");
|
||||
fprintf(stderr, "%s\n", &output);
|
||||
continue;
|
||||
}
|
||||
switch (WEXITSTATUS(ret)) {
|
||||
case 0:
|
||||
pass++;
|
||||
printf("\033[0;32mSuccess\033[0m\n");
|
||||
break;
|
||||
case 255:
|
||||
skip++;
|
||||
printf("Skipped\n");
|
||||
break;
|
||||
default:
|
||||
fail++;
|
||||
printf("\033[0;31mFailed\033[0m\n");
|
||||
}
|
||||
}
|
||||
if (fail) {
|
||||
printf("\nResults: \033[0;31mFAILED\033[0m %i succeeded; %i failed; %i skipped\n\n",
|
||||
pass, fail, skip);
|
||||
} else {
|
||||
printf("\nResults: \033[0;32mOk\033[0m %i succeeded; %i failed; %i skipped\n\n",
|
||||
pass, fail, skip);
|
||||
}
|
||||
return fail;
|
||||
}
|
Loading…
Add table
Reference in a new issue