]> git.ipfire.org Git - pakfire.git/blob - tests/testsuite.c
compress: Be less verbose when walking through the file system
[pakfire.git] / tests / testsuite.c
1 /*#############################################################################
2 # #
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2017 Pakfire development team #
5 # #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
18 # #
19 #############################################################################*/
20
21 #include <errno.h>
22 #include <linux/limits.h>
23 #include <stdlib.h>
24
25 #include "testsuite.h"
26
27 #include <pakfire/logging.h>
28 #include <pakfire/mount.h>
29 #include <pakfire/pakfire.h>
30 #include <pakfire/util.h>
31
32 #define TMP_TEMPLATE "/tmp/pakfire-test.XXXXXX"
33
34 struct testsuite ts;
35
36 static int test_run(int i, struct test* t) {
37 struct pakfire_ctx* ctx = NULL;
38 struct pakfire* p = NULL;
39 FILE* c = NULL;
40
41 char root[PATH_MAX] = TEST_ROOTFS "/pakfire-test-XXXXXX";
42 int r;
43
44 // Create test root directory
45 char* tmp = pakfire_mkdtemp(root);
46 if (!tmp) {
47 LOG("Could not create temporary directory %s: %m\n", root);
48 exit(1);
49 }
50
51 LOG("running %s (%s)\n", t->name, root);
52
53 // Create a new context
54 r = pakfire_ctx_create(&t->ctx, TEST_CONFIG_FILE);
55 if (r) {
56 LOG("Could not create context: %m\n");
57 goto ERROR;
58 }
59
60 // Set the log level to DEBUG
61 pakfire_ctx_set_log_level(t->ctx, LOG_DEBUG);
62
63 // Log everything to the console
64 pakfire_ctx_set_log_callback(t->ctx, pakfire_log_stderr, NULL);
65
66 // Open the configuration file
67 c = fopen(TEST_SRC_PATH "/pakfire.conf", "r");
68 if (!c) {
69 LOG("Could not open configuration file: %m\n");
70 r = 1;
71 goto ERROR;
72 }
73
74 // Create a pakfire instance (if requested)
75 if (t->flags & TEST_WANTS_PAKFIRE) {
76 r = pakfire_create(&t->pakfire, t->ctx, root, NULL, c, 0);
77 if (r) {
78 LOG("ERROR: Could not initialize pakfire: %m\n");
79 goto ERROR;
80 }
81
82 // Check if the instance was created properly
83 if (r == 0 && !t->pakfire) {
84 LOG("ERROR: Pakfire was not initialized, but no error was raised: %m\n");
85 goto ERROR;
86 }
87
88 // Copy command into environment
89 r = pakfire_bind(t->pakfire, TEST_STUB_COMMAND, "/command", 0);
90 if (r) {
91 LOG("ERROR: Could not copy command: %m\n");
92 goto ERROR;
93 }
94 }
95
96 // Create a HTTP client (if requested)
97 if (t->flags & TEST_WANTS_HTTPCLIENT) {
98 r = pakfire_httpclient_create(&t->httpclient, t->ctx);
99 if (r) {
100 LOG("ERROR: Could not initialize the HTTP client: %s\n", strerror(-r));
101 goto ERROR;
102 }
103 }
104
105 // Run test
106 r = t->func(t);
107 if (r)
108 LOG("Test failed with error code: %d\n", r);
109
110 ERROR:
111 // Release HTTP client
112 if (t->httpclient)
113 pakfire_httpclient_unref(t->httpclient);
114
115 // Release pakfire
116 if (t->pakfire) {
117 p = pakfire_unref(t->pakfire);
118
119 // Check if Pakfire was actually released
120 if (p) {
121 LOG("Error: Pakfire instance was not released in test %d\n", i);
122 r = 1;
123 }
124
125 // Reset pointer (just in case)
126 t->pakfire = NULL;
127 }
128
129 // Release context
130 if (t->ctx) {
131 ctx = pakfire_ctx_unref(t->ctx);
132
133 // Check if the context was actually released
134 if (ctx) {
135 LOG("Error: Context was not released in test %s\n", t->name);
136 r = 1;
137 }
138
139 // Reset pointer (just in case)
140 t->ctx = NULL;
141 }
142
143 // Close the configuration file
144 if (c)
145 fclose(c);
146
147 // Cleanup root
148 pakfire_rmtree(root, 0);
149
150 return r;
151 }
152
153 int __testsuite_add_test(const char* name, int (*func)(const struct test* t), int flags) {
154 // Check if any space is left
155 if (ts.num >= MAX_TESTS) {
156 LOG("ERROR: We are out of space for tests\n");
157 exit(EXIT_FAILURE);
158 }
159
160 struct test* test = &ts.tests[ts.num++];
161
162 // Set parameters
163 test->name = name;
164 test->func = func;
165 test->flags = flags;
166
167 return 0;
168 }
169
170 static int check_whether_to_run(const struct test* t, const int argc, const char* argv[]) {
171 // Run all tests when nothing has been selected
172 if (argc < 2)
173 return 1;
174
175 // Check if this test has been listed
176 for (unsigned int i = 1; i < argc; i++) {
177 if (strcmp(t->name, argv[i]) == 0)
178 return 1;
179 }
180
181 return 0;
182 }
183
184 int testsuite_run(int argc, const char* argv[]) {
185 for (unsigned int i = 0; i < ts.num; i++) {
186 struct test* test = &ts.tests[i];
187
188 // Skip any tests that should not be run
189 if (!check_whether_to_run(test, argc, argv))
190 continue;
191
192 // Run the test
193 int r = test_run(i, test);
194 if (r)
195 exit(r);
196 }
197
198 return EXIT_SUCCESS;
199 }
200
201 FILE* test_mktemp(char** path) {
202 char* p = NULL;
203
204 // Reset path
205 if (path)
206 *path = NULL;
207
208 int r = asprintf(&p, "%s", TMP_TEMPLATE);
209 if (r < 0)
210 return NULL;
211
212 int fd = mkstemp(p);
213 if (fd < 0)
214 return NULL;
215
216 // If we want a named temporary file, we set path
217 if (path) {
218 *path = p;
219
220 // Otherwise we unlink the path and free p
221 } else {
222 unlink(p);
223 free(p);
224 }
225
226 return fdopen(fd, "w+");
227 }
228
229 char* test_mkdtemp() {
230 char path[] = TMP_TEMPLATE;
231
232 char* p = mkdtemp(path);
233 if (!p)
234 return NULL;
235
236 return strdup(path);
237 }