aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--SConstruct12
-rw-r--r--include/tests.h50
-rw-r--r--tests/fdso.c82
-rwxr-xr-xtests/make_catalog.py95
-rw-r--r--tests/runner.c77
6 files changed, 320 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index c8d60f4..74b4f43 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,11 @@
2*.o 2*.o
3*.a 3*.a
4 4
5# generated files
6tests/__test_catalog.inc
7
5# executables 8# executables
9runtests
6rt_launch 10rt_launch
7wait_test 11wait_test
8np_test 12np_test
diff --git a/SConstruct b/SConstruct
index 1f2a35b..b216216 100644
--- a/SConstruct
+++ b/SConstruct
@@ -130,3 +130,15 @@ rt.Program('rt_launch', ['bin/rt_launch.c', 'bin/common.c'])
130rt.Program('rtspin', ['bin/rtspin.c', 'bin/common.c']) 130rt.Program('rtspin', ['bin/rtspin.c', 'bin/common.c'])
131rt.Program('release_ts', 'bin/release_ts.c') 131rt.Program('release_ts', 'bin/release_ts.c')
132rtm.Program('measure_syscall', 'bin/null_call.c') 132rtm.Program('measure_syscall', 'bin/null_call.c')
133
134
135# #####################################################################
136# Test suite.
137
138mkc = Builder(action = 'tests/make_catalog.py $SOURCE > $TARGET')
139test = mtrt.Clone()
140test.Append(BUILDERS = {'TestCatalog' : mkc})
141test.Append(CPPPATH = ['tests/'])
142
143catalog = test.TestCatalog('tests/__test_catalog.inc', Glob('tests/*.c'))
144test.Program('runtests', Glob('tests/*.c'))
diff --git a/include/tests.h b/include/tests.h
new file mode 100644
index 0000000..3adba18
--- /dev/null
+++ b/include/tests.h
@@ -0,0 +1,50 @@
1#ifndef TESTS_H
2#define TESTS_H
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <errno.h>
7
8#define fail(fmt, args...) \
9 do { \
10 fprintf(stderr, "\n!! TEST FAILURE " fmt "\n at %s:%d (%s)\n", \
11 ## args, __FILE__, __LINE__, __FUNCTION__); \
12 fflush(stderr); \
13 exit(200); \
14 } while (0)
15
16#define ASSERT(predicate) \
17 do { \
18 if (!(predicate)) \
19 fail("%s", #predicate); \
20 } while (0)
21
22#define SYSCALL(call) \
23 do { \
24 if ((call) < 0) \
25 fail("%s, %m", #call); \
26 } while (0)
27
28#define SYSCALL_FAILS(expected, call) \
29 do { \
30 if ((call) == 0 || errno != (expected)) \
31 fail("%s, %m (expected: %s)", #call, #expected); \
32 } while (0)
33
34
35typedef void (*testfun_t)(void);
36
37struct testcase {
38 testfun_t function;
39 const char* description;
40};
41
42struct testsuite {
43 const char* plugin;
44 int* testcases;
45 int num_cases;
46};
47
48#define TESTCASE(function, plugins, description) void test_ ## function (void)
49
50#endif
diff --git a/tests/fdso.c b/tests/fdso.c
new file mode 100644
index 0000000..fb8a5bd
--- /dev/null
+++ b/tests/fdso.c
@@ -0,0 +1,82 @@
1#include <fcntl.h>
2#include <unistd.h>
3
4#include <stdio.h>
5
6
7#include "tests.h"
8
9#include "litmus.h"
10
11
12TESTCASE(fmlp_not_active, C_EDF | PFAIR | LINUX,
13 "don't open FMLP semaphores if FMLP is not supported")
14{
15 int fd;
16
17 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT) );
18
19 ASSERT(fd != -1);
20
21 SYSCALL_FAILS(EBUSY, open_fmlp_sem(fd, 0) );
22
23 SYSCALL( close(fd) );
24
25 SYSCALL( remove(".fmlp_locks") );
26}
27
28
29TESTCASE(invalid_od, ALL,
30 "reject invalid object descriptors")
31{
32 SYSCALL_FAILS( EINVAL, fmlp_down(3) );
33
34 SYSCALL_FAILS( EINVAL, fmlp_up(3) );
35
36 SYSCALL_FAILS( EINVAL, od_close(3) );
37
38
39 SYSCALL_FAILS( EINVAL, fmlp_down(-1) );
40
41 SYSCALL_FAILS( EINVAL, fmlp_up(-1) );
42
43 SYSCALL_FAILS( EINVAL, od_close(-1) );
44}
45
46TESTCASE(not_inherit_od, GSN_EDF | PSN_EDF,
47 "don't inherit FDSO handles across fork")
48{
49 int fd, od, pid, status;
50
51 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT) );
52
53 SYSCALL( od = open_fmlp_sem(fd, 0) );
54
55 SYSCALL( fmlp_down(od) );
56
57 SYSCALL( fmlp_up(od) );
58
59 pid = fork();
60
61 ASSERT( pid != -1 );
62
63 if (pid == 0) {
64 /* child */
65 SYSCALL_FAILS(EINVAL, fmlp_down(od) );
66 SYSCALL_FAILS(EINVAL, fmlp_up(od) );
67 exit(0);
68 } else {
69 SYSCALL( fmlp_down(od) );
70 SYSCALL( fmlp_up(od) );
71 SYSCALL( waitpid(pid, &status, 0) );
72 ASSERT(WEXITSTATUS(status) == 0);
73 }
74
75 SYSCALL( od_close(od) );
76
77 SYSCALL( close(fd) );
78
79 SYSCALL( remove(".fmlp_locks") );
80}
81
82
diff --git a/tests/make_catalog.py b/tests/make_catalog.py
new file mode 100755
index 0000000..75b6aca
--- /dev/null
+++ b/tests/make_catalog.py
@@ -0,0 +1,95 @@
1#!/usr/bin/env python
2
3import re
4import sys
5
6class TestCase(object):
7 def __init__(self, function, plugins, desc):
8 self.function = function
9 self.plugins = plugins
10 self.desc = desc
11
12 def __str__(self):
13 return 'TESTCASE(%s, %s, "%s")' % \
14 (self.function, " | ".join(self.plugins), self.desc)
15
16
17class Finder(object):
18 def __init__(self):
19 self.found = []
20 self.regex = re.compile(
21 "TESTCASE\\("
22 "\\s*([a-zA-z_0-9]+)\\s*," # function name
23 "\\s*([- |a-zA-z_0-9]+)\\s*," # plugins
24 "\\s*\"([^\"]*)\"\\s*" # description
25 "\\)"
26 , re.MULTILINE)
27
28 def search_file(self, fname):
29 f = open(fname, "r")
30 src = ''.join(f)
31 f.close()
32 matches = self.regex.findall(src)
33 del src
34
35 for m in matches:
36 name = m[0]
37 plugins = m[1].split('|')
38 desc = m[2]
39 plugins = [p.strip() for p in plugins]
40 self.found.append(TestCase(name, plugins, desc))
41
42
43def search_files(args=sys.argv[1:]):
44 f = Finder()
45 for fname in args:
46 try:
47 f.search_file(fname)
48 except IOError, msg:
49 sys.stderr.write("%s: %s\n" % (fname, msg))
50 sys.exit(1)
51 return f.found
52
53
54def create_tc_tables(out=sys.stdout):
55 def _(o):
56 out.write("%s\n" % str(o))
57
58 tests = search_files()
59
60 plugins = set()
61 for tc in tests:
62 for p in tc.plugins:
63 plugins.add(p)
64
65 plugins.discard('ALL')
66
67 _('#include "tests.h"')
68
69 for tc in tests:
70 _('void test_%s(void);' % tc.function)
71
72 _('struct testcase test_catalog[] = {')
73 for tc in tests:
74 _('\t{test_%s, "%s"},' % (tc.function, tc.desc))
75 _('};')
76
77 for p in plugins:
78 count = 0
79 _('int %s_TESTS[] = {' % p)
80 for (i, tc) in enumerate(tests):
81 if p in tc.plugins or 'ALL' in tc.plugins:
82 _('\t%d,' % i)
83 count += 1
84 _('};')
85 _('#define NUM_%s_TESTS %d' % (p, count))
86
87 _('struct testsuite testsuite[] = {')
88 for p in plugins:
89 _('\t{"%s", %s_TESTS, NUM_%s_TESTS},' % (p.replace('_', '-'), p, p))
90 _('};')
91 _('#define NUM_PLUGINS %s' % len(plugins))
92
93if __name__ == '__main__':
94 create_tc_tables()
95
diff --git a/tests/runner.c b/tests/runner.c
new file mode 100644
index 0000000..f2e42b2
--- /dev/null
+++ b/tests/runner.c
@@ -0,0 +1,77 @@
1#include <fcntl.h>
2#include <unistd.h>
3
4#include <sys/wait.h>
5
6#include <string.h>
7#include <stdio.h>
8
9
10/* auto generated by SConstruct */
11#include "__test_catalog.inc"
12
13#include "litmus.h"
14
15int run_test(struct testcase *tc) {
16 int status;
17 pid_t pid;
18
19 printf("** Testing: %s... ", tc->description);
20 fflush(stdout);
21 SYSCALL( pid = fork() );
22 if (pid == 0) {
23 /* child: init liblitmus and carry out test */
24 SYSCALL( init_litmus() );
25 tc->function();
26 exit(0);
27 } else {
28 /* parent: wait for completion of test */
29 SYSCALL( waitpid(pid, &status, 0) );
30 if (WEXITSTATUS(status) == 0)
31 printf("ok.\n");
32 }
33 return WEXITSTATUS(status) == 0;
34}
35
36int run_tests(int* testidx, int num_tests, const char* plugin)
37{
38 int idx, i;
39 int ok = 0;
40
41 printf("** Running tests for %s.\n", plugin);
42 for (i = 0; i < num_tests; i++) {
43 idx = testidx[i];
44 ok += run_test(test_catalog + idx);
45 }
46 return ok;
47}
48
49#define streq(s1, s2) (!strcmp(s1, s2))
50
51int main(int argc, char** argv)
52{
53 int ok, i;
54
55 printf("** LITMUS^RT test suite.\n");
56
57 if (argc == 2) {
58 for (i = 0; i < NUM_PLUGINS; i++)
59 if (streq(testsuite[i].plugin, argv[1])) {
60 ok = run_tests(testsuite[i].testcases,
61 testsuite[i].num_cases,
62 testsuite[i].plugin);
63 printf("** Result: %d ok, %d failed.\n",
64 ok, testsuite[i].num_cases - ok);
65 return ok == testsuite[i].num_cases ? 0 : 3;
66 }
67 fprintf(stderr, "** Unknown plugin: '%s'\n", argv[1]);
68 return 1;
69 } else {
70 fprintf(stderr, "Usage: %s <plugin name>\n", argv[0]);
71 fprintf(stderr, "Supported plugins: ");
72 for (i = 0; i < NUM_PLUGINS; i++)
73 fprintf(stderr, "%s ", testsuite[i].plugin);
74 fprintf(stderr, "\n");
75 return 2;
76 }
77}