Branch data Line data Source code
1 : : #include "sute.h"
2 : : #include "mocks.h"
3 : : #include <errno.h>
4 : : #include <unistd.h>
5 : :
6 : 6 : static Return assert_stderr_matches(
7 : : const char *template_file)
8 : : {
9 : : /* Status returned by this function through provide()
10 : : Default value assumes successful completion */
11 : 6 : Return status = SUCCESS;
12 : 6 : create(char,pattern);
13 : 6 : create(char,stderr_snapshot);
14 : :
15 [ - + ]: 6 : if(template_file == NULL)
16 : : {
17 : 0 : status = FAILURE;
18 : : }
19 : :
20 [ + - ]: 6 : if(SUCCESS == status)
21 : : {
22 : 6 : status = get_file_content(template_file,pattern);
23 : : }
24 : :
25 [ + - ]: 6 : if(SUCCESS == status)
26 : : {
27 : 6 : status = copy(stderr_snapshot,STDERR);
28 : : }
29 : :
30 [ + - ]: 6 : if(SUCCESS == status)
31 : : {
32 : 6 : status = match_pattern(stderr_snapshot,pattern,template_file);
33 : : }
34 : :
35 [ + - ]: 6 : if(SUCCESS == status)
36 : : {
37 [ - + - + ]: 6 : call(del(STDERR));
38 : : }
39 : :
40 [ - + - + ]: 6 : call(del(stderr_snapshot));
41 [ - + - + ]: 6 : call(del(pattern));
42 : :
43 [ - + - - : 6 : deliver(status);
- + + - ]
44 : : }
45 : :
46 : : /**
47 : : * @brief Save the current TMPDIR value and clear the output pointer when unset
48 : : *
49 : : * @param[out] saved_tmpdir_out Heap-allocated TMPDIR copy or NULL when unset
50 : : * @return Return status code
51 : : */
52 : 3 : static Return save_tmpdir_value(char **saved_tmpdir_out)
53 : : {
54 : : /* Status returned by this function through provide()
55 : : Default value assumes successful completion */
56 : 3 : Return status = SUCCESS;
57 : 3 : const char *original_tmpdir = NULL;
58 : :
59 [ - + ]: 3 : if(saved_tmpdir_out == NULL)
60 : : {
61 : 0 : status = FAILURE;
62 : : }
63 : :
64 [ + - ]: 3 : if(SUCCESS == status)
65 : : {
66 : 3 : *saved_tmpdir_out = NULL;
67 : 3 : original_tmpdir = getenv("TMPDIR");
68 : :
69 [ + - ]: 3 : if(original_tmpdir != NULL)
70 : : {
71 : 3 : *saved_tmpdir_out = strdup(original_tmpdir);
72 : :
73 [ - + ]: 3 : if(*saved_tmpdir_out == NULL)
74 : : {
75 : 0 : status = FAILURE;
76 : : }
77 : : }
78 : : }
79 : :
80 [ - + - - : 3 : deliver(status);
- + + - ]
81 : : }
82 : :
83 : : /**
84 : : * @brief Restore TMPDIR to a previously saved value or unset it when NULL
85 : : *
86 : : * @param[in] saved_tmpdir Saved TMPDIR value or NULL when TMPDIR was unset
87 : : * @return Return status code
88 : : */
89 : 3 : static Return restore_tmpdir_value(const char *saved_tmpdir)
90 : : {
91 : 3 : int restore_tmpdir_status = 0;
92 : :
93 [ + - ]: 3 : if(saved_tmpdir != NULL)
94 : : {
95 : 3 : restore_tmpdir_status = setenv("TMPDIR",saved_tmpdir,1);
96 : : } else {
97 : 0 : restore_tmpdir_status = unsetenv("TMPDIR");
98 : : }
99 : :
100 [ + - ]: 3 : return(restore_tmpdir_status == 0 ? SUCCESS : FAILURE);
101 : : }
102 : :
103 : : /**
104 : : *
105 : : * @brief delete_path() should report a NULL input path
106 : : *
107 : : */
108 : 1 : static Return test0037_1(void)
109 : : {
110 : 1 : INITTEST;
111 : :
112 [ - + - + ]: 1 : call(del(STDERR));
113 : :
114 : 1 : ASSERT(FAILURE == delete_path(NULL));
115 : 1 : ASSERT(SUCCESS == assert_stderr_matches("templates/0037_001.txt"));
116 : :
117 : 1 : RETURN_STATUS;
118 : : }
119 : :
120 : : /**
121 : : *
122 : : * @brief delete_path() should report lstat() failure for a missing path
123 : : *
124 : : */
125 : 1 : static Return test0037_2(void)
126 : : {
127 : 1 : INITTEST;
128 : :
129 [ - + - + ]: 1 : call(del(STDERR));
130 : :
131 : 1 : ASSERT(FAILURE == delete_path("delete_path_missing.txt"));
132 : 1 : ASSERT(SUCCESS == assert_stderr_matches("templates/0037_002.txt"));
133 : :
134 : 1 : RETURN_STATUS;
135 : : }
136 : :
137 : : /**
138 : : *
139 : : * @brief construct_path() should report NULL input arguments
140 : : *
141 : : */
142 : 1 : static Return test0037_3(void)
143 : : {
144 : 1 : INITTEST;
145 : :
146 : 1 : create(char,path);
147 : :
148 [ - + - + ]: 1 : call(del(STDERR));
149 : :
150 : 1 : ASSERT(FAILURE == construct_path(NULL,path));
151 : 1 : ASSERT(SUCCESS == assert_stderr_matches("templates/0037_003.txt"));
152 : :
153 [ - + - + ]: 1 : call(del(path));
154 : :
155 : 1 : RETURN_STATUS;
156 : : }
157 : :
158 : : /**
159 : : *
160 : : * @brief construct_path() should report a missing TMPDIR
161 : : *
162 : : */
163 : 1 : static Return test0037_4(void)
164 : : {
165 : 1 : INITTEST;
166 : :
167 : 1 : create(char,path);
168 : 1 : char *saved_tmpdir = NULL;
169 : 1 : Return saved_tmpdir_status = FAILURE;
170 : 1 : Return restore_tmpdir_status = SUCCESS;
171 : 1 : bool tmpdir_saved = false;
172 : :
173 : 1 : saved_tmpdir_status = save_tmpdir_value(&saved_tmpdir);
174 : 1 : ASSERT(SUCCESS == saved_tmpdir_status);
175 : :
176 [ + - ]: 1 : if(SUCCESS == saved_tmpdir_status)
177 : : {
178 : 1 : tmpdir_saved = true;
179 : : }
180 : :
181 [ + - ]: 1 : if(SUCCESS == status)
182 : : {
183 : 1 : ASSERT(unsetenv("TMPDIR") == 0);
184 : : }
185 : :
186 [ - + - + ]: 1 : call(del(STDERR));
187 : :
188 [ + - ]: 1 : if(SUCCESS == status)
189 : : {
190 : 1 : ASSERT(FAILURE == construct_path("tmpdir_missing.txt",path));
191 : 1 : ASSERT(SUCCESS == assert_stderr_matches("templates/0037_004.txt"));
192 : : }
193 : :
194 [ + - ]: 1 : if(tmpdir_saved == true)
195 : : {
196 : 1 : restore_tmpdir_status = restore_tmpdir_value(saved_tmpdir);
197 : : }
198 : :
199 [ + - ]: 1 : if(SUCCESS == status)
200 : : {
201 : 1 : ASSERT(SUCCESS == restore_tmpdir_status);
202 : : }
203 : :
204 : 1 : free(saved_tmpdir);
205 [ - + - + ]: 1 : call(del(path));
206 : :
207 : 1 : RETURN_STATUS;
208 : : }
209 : :
210 : : /**
211 : : *
212 : : * @brief delete_path() should report remove() failure for a regular file
213 : : *
214 : : */
215 : 1 : static Return test0037_5(void)
216 : : {
217 : 1 : INITTEST;
218 : :
219 : 1 : size_t remove_calls = 0;
220 : 1 : const char *file_path = "0037_read_only_dir/file.txt";
221 : :
222 : : #ifdef EVIL_EMPIRE_OS
223 : : deliver(DONOTHING);
224 : : #endif
225 : :
226 : 1 : ASSERT(SUCCESS == create_directory("0037_read_only_dir"));
227 : 1 : ASSERT(SUCCESS == truncate_file_to_zero_size(file_path));
228 : :
229 [ - + - + ]: 1 : call(del(STDERR));
230 : 1 : mocks_remove_reset();
231 : 1 : mocks_remove_set_target_suffix(file_path);
232 : 1 : mocks_remove_set_errno(EACCES);
233 : 1 : mocks_remove_enable(true);
234 : :
235 : 1 : ASSERT(FAILURE == delete_path(file_path));
236 : 1 : ASSERT(SUCCESS == assert_stderr_matches("templates/0037_005.txt"));
237 : 1 : remove_calls = mocks_remove_call_count();
238 : 1 : mocks_remove_reset();
239 : 1 : ASSERT(remove_calls == 1U);
240 : :
241 : 1 : ASSERT(SUCCESS == delete_path("0037_read_only_dir"));
242 : :
243 : 1 : RETURN_STATUS;
244 : : }
245 : :
246 : : /**
247 : : *
248 : : * @brief delete_path() should report callback remove() failure during nftw()
249 : : *
250 : : */
251 : 1 : static Return test0037_6(void)
252 : : {
253 : 1 : INITTEST;
254 : :
255 : 1 : size_t remove_calls = 0;
256 : 1 : const char *file_path = "0037_locked_tree/a/b/file.txt";
257 : :
258 : : #ifdef EVIL_EMPIRE_OS
259 : : deliver(DONOTHING);
260 : : #endif
261 : :
262 : 1 : ASSERT(SUCCESS == create_directory("0037_locked_tree/a/b"));
263 : 1 : ASSERT(SUCCESS == truncate_file_to_zero_size(file_path));
264 : :
265 [ - + - + ]: 1 : call(del(STDERR));
266 : 1 : mocks_remove_reset();
267 : 1 : mocks_remove_set_target_suffix(file_path);
268 : 1 : mocks_remove_set_errno(EACCES);
269 : 1 : mocks_remove_enable(true);
270 : :
271 : 1 : ASSERT(FAILURE == delete_path("0037_locked_tree"));
272 : 1 : ASSERT(SUCCESS == assert_stderr_matches("templates/0037_006.txt"));
273 : 1 : remove_calls = mocks_remove_call_count();
274 : 1 : mocks_remove_reset();
275 : 1 : ASSERT(remove_calls == 1U);
276 : :
277 : 1 : ASSERT(SUCCESS == delete_path("0037_locked_tree"));
278 : :
279 : 1 : RETURN_STATUS;
280 : : }
281 : :
282 : : /**
283 : : *
284 : : * @brief create_directory() should accept a symlinked directory component in TMPDIR
285 : : *
286 : : */
287 : 1 : static Return test0037_7(void)
288 : : {
289 : 1 : INITTEST;
290 : :
291 : 1 : char *saved_tmpdir = NULL;
292 : 1 : bool file_exists = false;
293 : 1 : create(char,symlinked_tmpdir);
294 : 1 : create(char,link_path);
295 : 1 : create(char,expected_directory_path);
296 : 1 : Return restore_status = SUCCESS;
297 : 1 : Return cleanup_status = SUCCESS;
298 : :
299 : 1 : ASSERT(SUCCESS == save_tmpdir_value(&saved_tmpdir));
300 : 1 : ASSERT(SUCCESS == create_directory("0037_symlink_parent"));
301 : 1 : ASSERT(SUCCESS == create_directory("0037_symlink_parent/real_tmp_root"));
302 : 1 : ASSERT(SUCCESS == construct_path("0037_symlink_parent/link_tmp_root",link_path));
303 : 1 : ASSERT(0 == symlink("real_tmp_root",getcstring(link_path)));
304 : 1 : ASSERT(SUCCESS == construct_path("0037_symlink_parent/link_tmp_root",symlinked_tmpdir));
305 : 1 : ASSERT(SUCCESS == set_environment_variable("TMPDIR",getcstring(symlinked_tmpdir)));
306 : 1 : ASSERT(SUCCESS == create_directory("a/b"));
307 : :
308 : 1 : restore_status = restore_tmpdir_value(saved_tmpdir);
309 : :
310 [ + - ]: 1 : if(SUCCESS == restore_status)
311 : : {
312 [ + - ]: 1 : if(SUCCESS == construct_path("0037_symlink_parent/real_tmp_root/a/b",expected_directory_path)
313 [ + - ]: 1 : && SUCCESS == check_file_exists(&file_exists,getcstring(expected_directory_path)))
314 : : {
315 [ - + ]: 1 : if(file_exists != true)
316 : : {
317 [ # # ]: 0 : if(SUCCESS == status)
318 : : {
319 : 0 : status = FAILURE;
320 : : }
321 : : }
322 [ # # ]: 0 : } else if(SUCCESS == status){
323 : 0 : status = FAILURE;
324 : : }
325 : :
326 : 1 : cleanup_status = delete_path("0037_symlink_parent");
327 : : }
328 : :
329 [ + - ]: 1 : if(SUCCESS == status)
330 : : {
331 : 1 : ASSERT(SUCCESS == restore_status);
332 : 1 : ASSERT(SUCCESS == cleanup_status);
333 : : }
334 : :
335 : 1 : free(saved_tmpdir);
336 [ - + - + ]: 1 : call(del(expected_directory_path));
337 [ - + - + ]: 1 : call(del(link_path));
338 [ - + - + ]: 1 : call(del(symlinked_tmpdir));
339 : :
340 : 1 : RETURN_STATUS;
341 : : }
342 : :
343 : : /**
344 : : *
345 : : * @brief create_directory() should reject a TMPDIR component that resolves to a file
346 : : *
347 : : */
348 : 1 : static Return test0037_8(void)
349 : : {
350 : 1 : INITTEST;
351 : :
352 : 1 : char *saved_tmpdir = NULL;
353 : 1 : create(char,symlinked_tmpdir);
354 : 1 : create(char,link_path);
355 : 1 : Return restore_status = SUCCESS;
356 : 1 : Return cleanup_status = SUCCESS;
357 : :
358 : 1 : ASSERT(SUCCESS == save_tmpdir_value(&saved_tmpdir));
359 : 1 : ASSERT(SUCCESS == create_directory("0037_symlink_bad_parent"));
360 : 1 : ASSERT(SUCCESS == truncate_file_to_zero_size("0037_symlink_bad_parent/file_target"));
361 : 1 : ASSERT(SUCCESS == construct_path("0037_symlink_bad_parent/link_file_root",link_path));
362 : 1 : ASSERT(0 == symlink("file_target",getcstring(link_path)));
363 : 1 : ASSERT(SUCCESS == construct_path("0037_symlink_bad_parent/link_file_root",symlinked_tmpdir));
364 : 1 : ASSERT(SUCCESS == set_environment_variable("TMPDIR",getcstring(symlinked_tmpdir)));
365 : 1 : ASSERT(FAILURE == create_directory("a/b"));
366 : :
367 : 1 : restore_status = restore_tmpdir_value(saved_tmpdir);
368 : :
369 [ + - ]: 1 : if(SUCCESS == restore_status)
370 : : {
371 : 1 : cleanup_status = delete_path("0037_symlink_bad_parent");
372 : : }
373 : :
374 [ + - ]: 1 : if(SUCCESS == status)
375 : : {
376 : 1 : ASSERT(SUCCESS == restore_status);
377 : 1 : ASSERT(SUCCESS == cleanup_status);
378 : : }
379 : :
380 : 1 : free(saved_tmpdir);
381 [ - + - + ]: 1 : call(del(link_path));
382 [ - + - + ]: 1 : call(del(symlinked_tmpdir));
383 : :
384 : 1 : RETURN_STATUS;
385 : : }
386 : :
387 : 1 : Return test0037(void)
388 : : {
389 : 1 : INITTEST;
390 : :
391 : 1 : TEST(test0037_1,"delete_path() reports NULL input path…");
392 : 1 : TEST(test0037_2,"delete_path() reports missing path lstat() failure…");
393 : 1 : TEST(test0037_3,"construct_path() reports NULL input arguments…");
394 : 1 : TEST(test0037_4,"construct_path() reports missing TMPDIR…");
395 : 1 : TEST(test0037_5,"delete_path() reports remove() failure for a regular file…");
396 : 1 : TEST(test0037_6,"delete_path() reports nftw() callback remove() failure…");
397 : 1 : TEST(test0037_7,"create_directory() accepts a symlinked directory in TMPDIR…");
398 : 1 : TEST(test0037_8,"create_directory() rejects a symlinked file in TMPDIR…");
399 : :
400 : 1 : RETURN_STATUS;
401 : : }
|