1/* Authors: Mark Goldman <mgoldman@tresys.com>
2 *
3 * Copyright (C) 2007 Tresys Technology, LLC
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20/*  The purpose of this file is to provide unit tests of the functions in:
21 *
22 *  libsemanage/src/utilities.c
23 *
24 */
25
26#include <CUnit/Basic.h>
27#include <CUnit/Console.h>
28#include <CUnit/TestDB.h>
29
30#include <utilities.h>
31#include <stdio.h>
32#include <getopt.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36
37void test_semanage_is_prefix(void);
38void test_semanage_split_on_space(void);
39void test_semanage_split(void);
40void test_semanage_list(void);
41void test_semanage_str_count(void);
42void test_semanage_rtrim(void);
43void test_semanage_str_replace(void);
44void test_semanage_findval(void);
45void test_slurp_file_filter(void);
46
47char fname[] = {
48	'T', 'E', 'S', 'T', '_', 'T', 'E', 'M', 'P', '_', 'X', 'X', 'X', 'X',
49	'X', 'X', '\0'
50};
51int fd;
52FILE *fptr;
53
54int semanage_utilities_test_init(void)
55{
56	fd = mkstemp(fname);
57
58	if (fd < 0) {
59		perror("test_semanage_findval: ");
60		CU_FAIL_FATAL
61		    ("Error opening temporary file, test cannot start.");
62	}
63
64	fptr = fdopen(fd, "w+");
65	if (!fptr) {
66		perror("test_semanage_findval file: ");
67		CU_FAIL_FATAL("Error opening file stream, test cannot start.");
68	}
69
70	fprintf(fptr, "one\ntwo\nthree\nsigma=foo\n#boo\n#bar\n");
71
72	rewind(fptr);
73	return 0;
74}
75
76int semanage_utilities_test_cleanup(void)
77{
78	unlink(fname);
79	return 0;
80}
81
82int semanage_utilities_add_tests(CU_pSuite suite)
83{
84	if (NULL == CU_add_test(suite, "semanage_is_prefix",
85				test_semanage_is_prefix)) {
86		goto err;
87	}
88	if (NULL == CU_add_test(suite, "semanage_split_on_space",
89				test_semanage_split_on_space)) {
90		goto err;
91	}
92	if (NULL == CU_add_test(suite, "semanage_split", test_semanage_split)) {
93		goto err;
94	}
95	if (NULL == CU_add_test(suite, "semanage_list", test_semanage_list)) {
96		goto err;
97	}
98	if (NULL == CU_add_test(suite, "semanage_str_count",
99				test_semanage_str_count)) {
100		goto err;
101	}
102	if (NULL == CU_add_test(suite, "semanage_rtrim", test_semanage_rtrim)) {
103		goto err;
104	}
105	if (NULL == CU_add_test(suite, "semanage_str_replace",
106				test_semanage_str_replace)) {
107		goto err;
108	}
109	if (NULL == CU_add_test(suite, "semanage_findval",
110				test_semanage_findval)) {
111		goto err;
112	}
113	if (NULL == CU_add_test(suite, "slurp_file_filter",
114				test_slurp_file_filter)) {
115		goto err;
116	}
117	return 0;
118      err:
119	CU_cleanup_registry();
120	return CU_get_error();
121}
122
123void test_semanage_is_prefix(void)
124{
125	const char *str = "some string";
126	const char *pre = "some";
127	const char *not_pre = "not this";
128
129	CU_ASSERT_TRUE(semanage_is_prefix(str, pre));
130	CU_ASSERT_TRUE(semanage_is_prefix(str, ""));
131	CU_ASSERT_TRUE(semanage_is_prefix(str, NULL));
132	CU_ASSERT_FALSE(semanage_is_prefix(str, not_pre));
133}
134
135void test_semanage_split_on_space(void)
136{
137	char *str = strdup("   foo   bar    baz");
138	char *temp;
139
140	if (!str) {
141		CU_FAIL
142		    ("semanage_split_on_space: unable to perform test, no memory");
143	}
144	temp = semanage_split_on_space(str);
145	CU_ASSERT_STRING_EQUAL(temp, "bar    baz");
146	free(str);
147	str = temp;
148
149	temp = semanage_split_on_space(str);
150	CU_ASSERT_STRING_EQUAL(temp, "baz");
151	free(str);
152	str = temp;
153
154	temp = semanage_split_on_space(str);
155	CU_ASSERT_STRING_EQUAL(temp, "");
156	free(str);
157	free(temp);
158}
159
160void test_semanage_split(void)
161{
162	char *str = strdup("foo1 foo2   foo:bar:");
163	char *temp;
164
165	if (!str) {
166		CU_FAIL
167		    ("semanage_split_on_space: unable to perform test, no memory");
168		return;
169	}
170	temp = semanage_split(str, NULL);
171	CU_ASSERT_STRING_EQUAL(temp, "foo2   foo:bar:");
172	free(str);
173	str = temp;
174
175	temp = semanage_split(str, "");
176	CU_ASSERT_STRING_EQUAL(temp, "foo:bar:");
177	free(str);
178	str = temp;
179
180	temp = semanage_split(str, ":");
181	CU_ASSERT_STRING_EQUAL(temp, "bar:");
182	free(str);
183	str = temp;
184
185	temp = semanage_split(str, ":");
186	CU_ASSERT_STRING_EQUAL(temp, "");
187	free(str);
188	free(temp);
189}
190
191void test_semanage_list(void)
192{
193	semanage_list_t *list = NULL;
194	semanage_list_t *ptr = NULL;
195	char *temp = NULL;
196	int retval = 0;
197
198	CU_ASSERT_FALSE(semanage_list_push(&list, "foo"));
199	CU_ASSERT_PTR_NOT_NULL(list);
200	CU_ASSERT_FALSE(semanage_list_push(&list, "bar"));
201	CU_ASSERT_FALSE(semanage_list_push(&list, "gonk"));
202	CU_ASSERT_FALSE(semanage_list_push(&list, "zebra"));
203
204	for (ptr = list; ptr; ptr = ptr->next)
205		retval++;
206	CU_ASSERT_EQUAL(retval, 4);
207
208	temp = semanage_list_pop(&list);
209	CU_ASSERT_STRING_EQUAL(temp, "zebra");
210	CU_ASSERT_FALSE(semanage_list_push(&list, temp));
211	free(temp);
212	temp = NULL;
213
214	retval = 0;
215	for (ptr = list; ptr; ptr = ptr->next)
216		retval++;
217	CU_ASSERT_EQUAL(retval, 4);
218
219	retval = semanage_list_sort(&list);
220	if (retval) {
221		CU_FAIL
222		    ("semanage_list_sort: error unrelated to sort (memory?)");
223		goto past_sort;
224	}
225	CU_ASSERT_STRING_EQUAL(list->data, "bar");
226	CU_ASSERT_STRING_EQUAL(list->next->data, "foo");
227	CU_ASSERT_STRING_EQUAL(list->next->next->data, "gonk");
228	CU_ASSERT_STRING_EQUAL(list->next->next->next->data, "zebra");
229
230      past_sort:
231	ptr = semanage_list_find(list, "zebra");
232	CU_ASSERT_PTR_NOT_NULL(ptr);
233	ptr = semanage_list_find(list, "bogus");
234	CU_ASSERT_PTR_NULL(ptr);
235
236	semanage_list_destroy(&list);
237	CU_ASSERT_PTR_NULL(list);
238}
239
240void test_semanage_str_count(void)
241{
242	const char *test_string = "abaababbaaaba";
243
244	CU_ASSERT_EQUAL(semanage_str_count(test_string, 'z'), 0);
245	CU_ASSERT_EQUAL(semanage_str_count(test_string, 'a'), 8);
246	CU_ASSERT_EQUAL(semanage_str_count(test_string, 'b'), 5);
247}
248
249void test_semanage_rtrim(void)
250{
251	char *str = strdup("/blah/foo/bar/baz/");
252
253	CU_ASSERT_PTR_NOT_NULL_FATAL(str);
254
255	semanage_rtrim(str, 'Q');
256	CU_ASSERT_STRING_EQUAL(str, "/blah/foo/bar/baz/");
257	semanage_rtrim(str, 'a');
258	CU_ASSERT_STRING_EQUAL(str, "/blah/foo/bar/b");
259	semanage_rtrim(str, '/');
260	CU_ASSERT_STRING_EQUAL(str, "/blah/foo/bar");
261
262	free(str);
263}
264
265void test_semanage_str_replace(void)
266{
267	const char *test_str = "Hello, I am %{USERNAME} and my id is %{USERID}";
268	char *str1, *str2;
269
270	str1 = semanage_str_replace("%{USERNAME}", "root", test_str, 0);
271	CU_ASSERT_STRING_EQUAL(str1, "Hello, I am root and my id is %{USERID}");
272
273	str2 = semanage_str_replace("%{USERID}", "0", str1, 1);
274	CU_ASSERT_STRING_EQUAL(str2, "Hello, I am root and my id is 0");
275	free(str1);
276	free(str2);
277
278	str1 = semanage_str_replace(":(", ";)", "Test :( :) ! :(:(:))(:(", 0);
279	CU_ASSERT_STRING_EQUAL(str1, "Test ;) :) ! ;);):))(;)");
280	free(str1);
281
282	str1 = semanage_str_replace(":(", ";)", "Test :( :) ! :(:(:))(:(", 3);
283	CU_ASSERT_STRING_EQUAL(str1, "Test ;) :) ! ;);):))(:(");
284	free(str1);
285
286	str1 = semanage_str_replace("", "empty search string", "test", 0);
287	CU_ASSERT_EQUAL(str1, NULL);
288
289	str1 = semanage_str_replace("a", "", "abracadabra", 0);
290	CU_ASSERT_STRING_EQUAL(str1, "brcdbr");
291	free(str1);
292}
293
294void test_semanage_findval(void)
295{
296	char *tok;
297	if (!fptr) {
298		CU_FAIL_FATAL("Temporary file was not created, aborting test.");
299	}
300	tok = semanage_findval(fname, "one", NULL);
301	CU_ASSERT_STRING_EQUAL(tok, "");
302	free(tok);
303	rewind(fptr);
304	tok = semanage_findval(fname, "one", "");
305	CU_ASSERT_STRING_EQUAL(tok, "");
306	free(tok);
307	rewind(fptr);
308	tok = semanage_findval(fname, "sigma", "=");
309	CU_ASSERT_STRING_EQUAL(tok, "foo");
310	free(tok);
311}
312
313int PREDICATE(const char *str)
314{
315	return semanage_is_prefix(str, "#");
316}
317
318void test_slurp_file_filter(void)
319{
320	semanage_list_t *data, *tmp;
321	int cnt = 0;
322
323	if (!fptr) {
324		CU_FAIL_FATAL("Temporary file was not created, aborting test.");
325	}
326	rewind(fptr);
327	data = semanage_slurp_file_filter(fptr, PREDICATE);
328	CU_ASSERT_PTR_NOT_NULL_FATAL(data);
329	for (tmp = data; tmp; tmp = tmp->next)
330		cnt++;
331	CU_ASSERT_EQUAL(cnt, 2);
332
333	semanage_list_destroy(&data);
334}
335