1 /*
2  * libdpkg - Debian packaging suite library routines
3  * t-path.c - test path handling code
4  *
5  * Copyright © 2009-2012 Guillem Jover <guillem@debian.org>
6  *
7  * This is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include <config.h>
22 #include <compat.h>
23 
24 #include <ctype.h>
25 #include <stdbool.h>
26 #include <stdlib.h>
27 
28 #include <dpkg/test.h>
29 #include <dpkg/path.h>
30 
31 /* Use the test_trim_eq_ref macro to avoid leaking the string and to get
32  * meaningful line numbers from assert. */
33 #define test_trim_eq_ref(p, ref) \
34 do { \
35 	char *t = test_alloc(strdup((p))); \
36 	path_trim_slash_slashdot(t); \
37 	test_str(t, ==, (ref)); \
38 	free(t); \
39 } while (0)
40 
41 static void
test_path_trim(void)42 test_path_trim(void)
43 {
44 	test_trim_eq_ref("/a", "/a");
45 	test_trim_eq_ref("./././.", ".");
46 	test_trim_eq_ref("./././", ".");
47 	test_trim_eq_ref("./.", ".");
48 	test_trim_eq_ref("./", ".");
49 	test_trim_eq_ref("/./././.", "/");
50 	test_trim_eq_ref("/./", "/");
51 	test_trim_eq_ref("/.", "/");
52 	test_trim_eq_ref("/", "/");
53 	test_trim_eq_ref("", "");
54 	test_trim_eq_ref("/./../.", "/./..");
55 	test_trim_eq_ref("/foo/bar/./", "/foo/bar");
56 	test_trim_eq_ref("./foo/bar/./", "./foo/bar");
57 	test_trim_eq_ref("/./foo/bar/./", "/./foo/bar");
58 }
59 
60 static void
test_path_skip(void)61 test_path_skip(void)
62 {
63 	test_str(path_skip_slash_dotslash("./././."), ==, ".");
64 	test_str(path_skip_slash_dotslash("./././"), ==, "");
65 	test_str(path_skip_slash_dotslash("./."), ==, ".");
66 	test_str(path_skip_slash_dotslash("./"), ==, "");
67 	test_str(path_skip_slash_dotslash("/./././."), ==, ".");
68 	test_str(path_skip_slash_dotslash("/./"), ==, "");
69 	test_str(path_skip_slash_dotslash("/."), ==, ".");
70 	test_str(path_skip_slash_dotslash("/"), ==, "");
71 	test_str(path_skip_slash_dotslash("/./../."), ==, "../.");
72 	test_str(path_skip_slash_dotslash("/foo/bar/./"), ==, "foo/bar/./");
73 	test_str(path_skip_slash_dotslash("./foo/bar/./"), ==, "foo/bar/./");
74 	test_str(path_skip_slash_dotslash("/./foo/bar/./"), ==, "foo/bar/./");
75 }
76 
77 static void
test_path_basename(void)78 test_path_basename(void)
79 {
80 	test_str(path_basename("./."), ==, ".");
81 	test_str(path_basename("./"), ==, "");
82 	test_str(path_basename("/."), ==, ".");
83 	test_str(path_basename("/"), ==, "");
84 	test_str(path_basename("/foo"), ==, "foo");
85 	test_str(path_basename("/foo/bar"), ==, "bar");
86 	test_str(path_basename("/foo/bar/"), ==, "");
87 }
88 
89 static void
test_path_temp(void)90 test_path_temp(void)
91 {
92 	char *template;
93 
94 	template = path_make_temp_template("test");
95 
96 	test_pass(strstr(template, "test") != NULL);
97 	test_pass(strstr(template, "XXXXXX") != NULL);
98 
99 	free(template);
100 }
101 
102 static bool
string_is_ascii(const char * str)103 string_is_ascii(const char *str)
104 {
105 	while (*str) {
106 		if (!isascii(*str))
107 			return false;
108 
109 		str++;
110 	}
111 
112 	return true;
113 }
114 
115 static void
test_path_quote(void)116 test_path_quote(void)
117 {
118 	const char src_7_bit[] = "string with 7-bit chars only";
119 	const char src_7_bit_trim[] = "string with 7-bit chars";
120 	const char src_8_bit[] = "text w/ 8-bit chars: \\ \370 \300 \342 end";
121 	const char src_8_bit_end[] = "text \370";
122 	const char src_bs_end[] = "text \\";
123 	char *dst;
124 	size_t len;
125 
126 	/* Test 0 length. */
127 	dst = NULL;
128 	path_quote_filename(dst, src_7_bit, 0);
129 
130 	/* Test no quoting. */
131 	len = strlen(src_7_bit) + 1;
132 	dst = test_alloc(malloc(len));
133 
134 	path_quote_filename(dst, src_7_bit, len);
135 	test_str(dst, ==, src_7_bit);
136 	free(dst);
137 
138 	/* Test no quoting with limit. */
139 	len = strlen(src_7_bit_trim) + 1;
140 	dst = test_alloc(malloc(len));
141 
142 	path_quote_filename(dst, src_7_bit, len);
143 	test_str(dst, ==, src_7_bit_trim);
144 	free(dst);
145 
146 	/* Test normal quoting. */
147 	len = strlen(src_8_bit) * 2 + 1;
148 	dst = test_alloc(malloc(len));
149 
150 	path_quote_filename(dst, src_8_bit, len);
151 	test_pass(strstr(dst, "end") != NULL);
152 	test_pass(string_is_ascii(dst));
153 	free(dst);
154 
155 	/* Test normal quoting with limit. */
156 	len = strlen(src_8_bit_end) + 1 + 2;
157 	dst = test_alloc(malloc(len));
158 
159 	path_quote_filename(dst, src_8_bit_end, len);
160 	test_str(dst, ==, "text ");
161 	free(dst);
162 
163 	/* Test backslash quoting with limit. */
164 	len = strlen(src_bs_end) + 1;
165 	dst = test_alloc(malloc(len));
166 
167 	path_quote_filename(dst, src_bs_end, len);
168 	test_str(dst, ==, "text ");
169 	free(dst);
170 }
171 
TEST_ENTRY(test)172 TEST_ENTRY(test)
173 {
174 	test_plan(41);
175 
176 	test_path_trim();
177 	test_path_skip();
178 	test_path_basename();
179 	test_path_temp();
180 	test_path_quote();
181 }
182