libkmod: fix return error when opening index
[platform/upstream/kmod.git] / testsuite / testsuite.h
1 /*
2  * Copyright (C) 2012-2013  ProFUSION embedded systems
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #pragma once
19
20 #include <stdbool.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #include <shared/macro.h>
25
26 struct test;
27 typedef int (*testfunc)(const struct test *t);
28
29 enum test_config {
30         /*
31          * Where's the roots dir for this test. It will LD_PRELOAD path.so in
32          * order to trap calls to functions using paths.
33          */
34         TC_ROOTFS = 0,
35
36         /*
37          * What's the desired string to be returned by `uname -r`. It will
38          * trap calls to uname(3P) by LD_PRELOAD'ing uname.so and then filling
39          * in the information in u.release.
40          */
41         TC_UNAME_R,
42
43         /*
44          * Fake calls to init_module(2), returning return-code and setting
45          * errno to err-code. Set this variable with the following format:
46          *
47          *        modname:return-code:err-code
48          *
49          * When this variable is used, all calls to init_module() are trapped
50          * and by default the return code is 0. In other words, they fake
51          * "success" for all modules, except the ones in the list above, for
52          * which the return codes are used.
53          */
54         TC_INIT_MODULE_RETCODES,
55
56         /*
57          * Fake calls to delete_module(2), returning return-code and setting
58          * errno to err-code. Set this variable with the following format:
59          *
60          *        modname:return-code:err-code
61          *
62          * When this variable is used, all calls to init_module() are trapped
63          * and by default the return code is 0. In other words, they fake
64          * "success" for all modules, except the ones in the list above, for
65          * which the return codes are used.
66          */
67         TC_DELETE_MODULE_RETCODES,
68
69         _TC_LAST,
70 };
71
72 #define S_TC_ROOTFS "TESTSUITE_ROOTFS"
73 #define S_TC_UNAME_R "TESTSUITE_UNAME_R"
74 #define S_TC_INIT_MODULE_RETCODES "TESTSUITE_INIT_MODULE_RETCODES"
75 #define S_TC_DELETE_MODULE_RETCODES "TESTSUITE_DELETE_MODULE_RETCODES"
76
77 struct keyval {
78         const char *key;
79         const char *val;
80 };
81
82 struct test {
83         const char *name;
84         const char *description;
85         struct {
86                 /* File with correct stdout */
87                 const char *out;
88                 /* File with correct stderr */
89                 const char *err;
90
91                 /*
92                  * whether to treat the correct files as regex to the real
93                  * output
94                  */
95                 bool regex;
96
97                 /*
98                  * Vector with pair of files
99                  * key = correct file
100                  * val = file to check
101                  */
102                 const struct keyval *files;
103         } output;
104         /* comma-separated list of loaded modules at the end of the test */
105         const char *modules_loaded;
106         testfunc func;
107         const char *config[_TC_LAST];
108         const char *path;
109         const struct keyval *env_vars;
110         bool need_spawn;
111         bool expected_fail;
112         bool print_outputs;
113 } __attribute__((aligned(8)));
114
115
116 int test_init(const struct test *start, const struct test *stop,
117               int argc, char *const argv[]);
118 const struct test *test_find(const struct test *start, const struct test *stop,
119                              const char *name);
120 int test_spawn_prog(const char *prog, const char *const args[]);
121 int test_run(const struct test *t);
122
123 #define TS_EXPORT __attribute__ ((visibility("default")))
124
125 #define _LOG(prefix, fmt, ...) printf("TESTSUITE: " prefix fmt, ## __VA_ARGS__)
126 #define LOG(fmt, ...) _LOG("", fmt, ## __VA_ARGS__)
127 #define WARN(fmt, ...) _LOG("WARN: ", fmt, ## __VA_ARGS__)
128 #define ERR(fmt, ...) _LOG("ERR: ", fmt, ## __VA_ARGS__)
129
130 #define assert_return(expr, r)                                          \
131         do {                                                            \
132                 if ((!(expr))) {                                        \
133                         ERR("Failed assertion: " #expr " %s:%d %s\n",   \
134                             __FILE__, __LINE__, __PRETTY_FUNCTION__);   \
135                         return (r);                                     \
136                 }                                                       \
137         } while (false)
138
139
140 /* Test definitions */
141 #define DEFINE_TEST(_name, ...) \
142         static const struct test s##_name##UNIQ \
143         __attribute__((used, section("kmod_tests"), aligned(8))) = { \
144                 .name = #_name, \
145                 .func = _name, \
146                 ## __VA_ARGS__ \
147         };
148
149 #define TESTSUITE_MAIN() \
150         extern struct test __start_kmod_tests[] __attribute__((weak, visibility("hidden")));    \
151         extern struct test __stop_kmod_tests[] __attribute__((weak, visibility("hidden")));     \
152         int main(int argc, char *argv[])                                                        \
153         {                                                                                       \
154                 const struct test *t;                                                           \
155                 int arg;                                                                        \
156                                                                                                 \
157                 arg = test_init(__start_kmod_tests, __stop_kmod_tests, argc, argv);             \
158                 if (arg == 0)                                                                   \
159                         return 0;                                                               \
160                 if (arg < 0)                                                                    \
161                         return EXIT_FAILURE;                                                    \
162                                                                                                 \
163                 if (arg < argc) {                                                               \
164                         t = test_find(__start_kmod_tests, __stop_kmod_tests, argv[arg]);        \
165                         if (t == NULL) {                                                        \
166                                 fprintf(stderr, "could not find test %s\n", argv[arg]);         \
167                                 exit(EXIT_FAILURE);                                             \
168                         }                                                                       \
169                                                                                                 \
170                         return test_run(t);                                                     \
171                 }                                                                               \
172                                                                                                 \
173                 for (t = __start_kmod_tests; t < __stop_kmod_tests; t++) {                      \
174                         if (test_run(t) != 0)                                                   \
175                                 exit(EXIT_FAILURE);                                             \
176                 }                                                                               \
177                                                                                                 \
178                 exit(EXIT_SUCCESS);                                                             \
179         }                                                                                       \
180
181 #ifdef noreturn
182 # define __noreturn noreturn
183 #elif __STDC_VERSION__ >= 201112L
184 # define __noreturn _Noreturn
185 #else
186 # define __noreturn __attribute__((noreturn))
187 #endif