1// Copyright 2011 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "util.h"
16
17#include "test.h"
18
19using namespace std;
20
21namespace {
22
23void CanonicalizePath(string* path) {
24 uint64_t unused;
25 ::CanonicalizePath(path, &unused);
26}
27
28} // namespace
29
30TEST(CanonicalizePath, PathSamples) {
31 string path;
32
33 CanonicalizePath(&path);
34 EXPECT_EQ("", path);
35
36 path = "foo.h";
37 CanonicalizePath(&path);
38 EXPECT_EQ("foo.h", path);
39
40 path = "./foo.h";
41 CanonicalizePath(&path);
42 EXPECT_EQ("foo.h", path);
43
44 path = "./foo/./bar.h";
45 CanonicalizePath(&path);
46 EXPECT_EQ("foo/bar.h", path);
47
48 path = "./x/foo/../bar.h";
49 CanonicalizePath(&path);
50 EXPECT_EQ("x/bar.h", path);
51
52 path = "./x/foo/../../bar.h";
53 CanonicalizePath(&path);
54 EXPECT_EQ("bar.h", path);
55
56 path = "foo//bar";
57 CanonicalizePath(&path);
58 EXPECT_EQ("foo/bar", path);
59
60 path = "foo//.//..///bar";
61 CanonicalizePath(&path);
62 EXPECT_EQ("bar", path);
63
64 path = "./x/../foo/../../bar.h";
65 CanonicalizePath(&path);
66 EXPECT_EQ("../bar.h", path);
67
68 path = "foo/./.";
69 CanonicalizePath(&path);
70 EXPECT_EQ("foo", path);
71
72 path = "foo/bar/..";
73 CanonicalizePath(&path);
74 EXPECT_EQ("foo", path);
75
76 path = "foo/.hidden_bar";
77 CanonicalizePath(&path);
78 EXPECT_EQ("foo/.hidden_bar", path);
79
80 path = "/foo";
81 CanonicalizePath(&path);
82 EXPECT_EQ("/foo", path);
83
84 path = "//foo";
85 CanonicalizePath(&path);
86#ifdef _WIN32
87 EXPECT_EQ("//foo", path);
88#else
89 EXPECT_EQ("/foo", path);
90#endif
91
92 path = "/";
93 CanonicalizePath(&path);
94 EXPECT_EQ("", path);
95
96 path = "/foo/..";
97 CanonicalizePath(&path);
98 EXPECT_EQ("", path);
99
100 path = ".";
101 CanonicalizePath(&path);
102 EXPECT_EQ(".", path);
103
104 path = "./.";
105 CanonicalizePath(&path);
106 EXPECT_EQ(".", path);
107
108 path = "foo/..";
109 CanonicalizePath(&path);
110 EXPECT_EQ(".", path);
111}
112
113#ifdef _WIN32
114TEST(CanonicalizePath, PathSamplesWindows) {
115 string path;
116
117 CanonicalizePath(&path);
118 EXPECT_EQ("", path);
119
120 path = "foo.h";
121 CanonicalizePath(&path);
122 EXPECT_EQ("foo.h", path);
123
124 path = ".\\foo.h";
125 CanonicalizePath(&path);
126 EXPECT_EQ("foo.h", path);
127
128 path = ".\\foo\\.\\bar.h";
129 CanonicalizePath(&path);
130 EXPECT_EQ("foo/bar.h", path);
131
132 path = ".\\x\\foo\\..\\bar.h";
133 CanonicalizePath(&path);
134 EXPECT_EQ("x/bar.h", path);
135
136 path = ".\\x\\foo\\..\\..\\bar.h";
137 CanonicalizePath(&path);
138 EXPECT_EQ("bar.h", path);
139
140 path = "foo\\\\bar";
141 CanonicalizePath(&path);
142 EXPECT_EQ("foo/bar", path);
143
144 path = "foo\\\\.\\\\..\\\\\\bar";
145 CanonicalizePath(&path);
146 EXPECT_EQ("bar", path);
147
148 path = ".\\x\\..\\foo\\..\\..\\bar.h";
149 CanonicalizePath(&path);
150 EXPECT_EQ("../bar.h", path);
151
152 path = "foo\\.\\.";
153 CanonicalizePath(&path);
154 EXPECT_EQ("foo", path);
155
156 path = "foo\\bar\\..";
157 CanonicalizePath(&path);
158 EXPECT_EQ("foo", path);
159
160 path = "foo\\.hidden_bar";
161 CanonicalizePath(&path);
162 EXPECT_EQ("foo/.hidden_bar", path);
163
164 path = "\\foo";
165 CanonicalizePath(&path);
166 EXPECT_EQ("/foo", path);
167
168 path = "\\\\foo";
169 CanonicalizePath(&path);
170 EXPECT_EQ("//foo", path);
171
172 path = "\\";
173 CanonicalizePath(&path);
174 EXPECT_EQ("", path);
175}
176
177TEST(CanonicalizePath, SlashTracking) {
178 string path;
179 uint64_t slash_bits;
180
181 path = "foo.h";
182 CanonicalizePath(&path, &slash_bits);
183 EXPECT_EQ("foo.h", path);
184 EXPECT_EQ(0, slash_bits);
185
186 path = "a\\foo.h";
187 CanonicalizePath(&path, &slash_bits);
188 EXPECT_EQ("a/foo.h", path);
189 EXPECT_EQ(1, slash_bits);
190
191 path = "a/bcd/efh\\foo.h";
192 CanonicalizePath(&path, &slash_bits);
193 EXPECT_EQ("a/bcd/efh/foo.h", path);
194 EXPECT_EQ(4, slash_bits);
195
196 path = "a\\bcd/efh\\foo.h";
197 CanonicalizePath(&path, &slash_bits);
198 EXPECT_EQ("a/bcd/efh/foo.h", path);
199 EXPECT_EQ(5, slash_bits);
200
201 path = "a\\bcd\\efh\\foo.h";
202 CanonicalizePath(&path, &slash_bits);
203 EXPECT_EQ("a/bcd/efh/foo.h", path);
204 EXPECT_EQ(7, slash_bits);
205
206 path = "a/bcd/efh/foo.h";
207 CanonicalizePath(&path, &slash_bits);
208 EXPECT_EQ("a/bcd/efh/foo.h", path);
209 EXPECT_EQ(0, slash_bits);
210
211 path = "a\\./efh\\foo.h";
212 CanonicalizePath(&path, &slash_bits);
213 EXPECT_EQ("a/efh/foo.h", path);
214 EXPECT_EQ(3, slash_bits);
215
216 path = "a\\../efh\\foo.h";
217 CanonicalizePath(&path, &slash_bits);
218 EXPECT_EQ("efh/foo.h", path);
219 EXPECT_EQ(1, slash_bits);
220
221 path = "a\\b\\c\\d\\e\\f\\g\\foo.h";
222 CanonicalizePath(&path, &slash_bits);
223 EXPECT_EQ("a/b/c/d/e/f/g/foo.h", path);
224 EXPECT_EQ(127, slash_bits);
225
226 path = "a\\b\\c\\..\\..\\..\\g\\foo.h";
227 CanonicalizePath(&path, &slash_bits);
228 EXPECT_EQ("g/foo.h", path);
229 EXPECT_EQ(1, slash_bits);
230
231 path = "a\\b/c\\../../..\\g\\foo.h";
232 CanonicalizePath(&path, &slash_bits);
233 EXPECT_EQ("g/foo.h", path);
234 EXPECT_EQ(1, slash_bits);
235
236 path = "a\\b/c\\./../..\\g\\foo.h";
237 CanonicalizePath(&path, &slash_bits);
238 EXPECT_EQ("a/g/foo.h", path);
239 EXPECT_EQ(3, slash_bits);
240
241 path = "a\\b/c\\./../..\\g/foo.h";
242 CanonicalizePath(&path, &slash_bits);
243 EXPECT_EQ("a/g/foo.h", path);
244 EXPECT_EQ(1, slash_bits);
245
246 path = "a\\\\\\foo.h";
247 CanonicalizePath(&path, &slash_bits);
248 EXPECT_EQ("a/foo.h", path);
249 EXPECT_EQ(1, slash_bits);
250
251 path = "a/\\\\foo.h";
252 CanonicalizePath(&path, &slash_bits);
253 EXPECT_EQ("a/foo.h", path);
254 EXPECT_EQ(0, slash_bits);
255
256 path = "a\\//foo.h";
257 CanonicalizePath(&path, &slash_bits);
258 EXPECT_EQ("a/foo.h", path);
259 EXPECT_EQ(1, slash_bits);
260}
261
262TEST(CanonicalizePath, CanonicalizeNotExceedingLen) {
263 // Make sure searching \/ doesn't go past supplied len.
264 char buf[] = "foo/bar\\baz.h\\"; // Last \ past end.
265 uint64_t slash_bits;
266 size_t size = 13;
267 ::CanonicalizePath(buf, &size, &slash_bits);
268 EXPECT_EQ(0, strncmp("foo/bar/baz.h", buf, size));
269 EXPECT_EQ(2, slash_bits); // Not including the trailing one.
270}
271
272TEST(CanonicalizePath, TooManyComponents) {
273 string path;
274 uint64_t slash_bits;
275
276 // 64 is OK.
277 path = "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./"
278 "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./x.h";
279 CanonicalizePath(&path, &slash_bits);
280 EXPECT_EQ(slash_bits, 0x0);
281
282 // Backslashes version.
283 path =
284 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
285 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
286 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
287 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\x.h";
288
289 CanonicalizePath(&path, &slash_bits);
290 EXPECT_EQ(slash_bits, 0xffffffff);
291
292 // 65 is OK if #component is less than 60 after path canonicalization.
293 path = "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./"
294 "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./x/y.h";
295 CanonicalizePath(&path, &slash_bits);
296 EXPECT_EQ(slash_bits, 0x0);
297
298 // Backslashes version.
299 path =
300 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
301 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
302 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
303 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\x\\y.h";
304 CanonicalizePath(&path, &slash_bits);
305 EXPECT_EQ(slash_bits, 0x1ffffffff);
306
307
308 // 59 after canonicalization is OK.
309 path = "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
310 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/x/y.h";
311 EXPECT_EQ(58, std::count(path.begin(), path.end(), '/'));
312 CanonicalizePath(&path, &slash_bits);
313 EXPECT_EQ(slash_bits, 0x0);
314
315 // Backslashes version.
316 path =
317 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
318 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
319 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
320 "a\\a\\a\\a\\a\\a\\a\\a\\a\\x\\y.h";
321 EXPECT_EQ(58, std::count(path.begin(), path.end(), '\\'));
322 CanonicalizePath(&path, &slash_bits);
323 EXPECT_EQ(slash_bits, 0x3ffffffffffffff);
324}
325#endif
326
327TEST(CanonicalizePath, UpDir) {
328 string path, err;
329 path = "../../foo/bar.h";
330 CanonicalizePath(&path);
331 EXPECT_EQ("../../foo/bar.h", path);
332
333 path = "test/../../foo/bar.h";
334 CanonicalizePath(&path);
335 EXPECT_EQ("../foo/bar.h", path);
336}
337
338TEST(CanonicalizePath, AbsolutePath) {
339 string path = "/usr/include/stdio.h";
340 string err;
341 CanonicalizePath(&path);
342 EXPECT_EQ("/usr/include/stdio.h", path);
343}
344
345TEST(CanonicalizePath, NotNullTerminated) {
346 string path;
347 size_t len;
348 uint64_t unused;
349
350 path = "foo/. bar/.";
351 len = strlen("foo/."); // Canonicalize only the part before the space.
352 CanonicalizePath(&path[0], &len, &unused);
353 EXPECT_EQ(strlen("foo"), len);
354 EXPECT_EQ("foo/. bar/.", string(path));
355
356 path = "foo/../file bar/.";
357 len = strlen("foo/../file");
358 CanonicalizePath(&path[0], &len, &unused);
359 EXPECT_EQ(strlen("file"), len);
360 EXPECT_EQ("file ./file bar/.", string(path));
361}
362
363TEST(PathEscaping, TortureTest) {
364 string result;
365
366 GetWin32EscapedString("foo bar\\\"'$@d!st!c'\\path'\\", &result);
367 EXPECT_EQ("\"foo bar\\\\\\\"'$@d!st!c'\\path'\\\\\"", result);
368 result.clear();
369
370 GetShellEscapedString("foo bar\"/'$@d!st!c'/path'", &result);
371 EXPECT_EQ("'foo bar\"/'\\''$@d!st!c'\\''/path'\\'''", result);
372}
373
374TEST(PathEscaping, SensiblePathsAreNotNeedlesslyEscaped) {
375 const char* path = "some/sensible/path/without/crazy/characters.c++";
376 string result;
377
378 GetWin32EscapedString(path, &result);
379 EXPECT_EQ(path, result);
380 result.clear();
381
382 GetShellEscapedString(path, &result);
383 EXPECT_EQ(path, result);
384}
385
386TEST(PathEscaping, SensibleWin32PathsAreNotNeedlesslyEscaped) {
387 const char* path = "some\\sensible\\path\\without\\crazy\\characters.c++";
388 string result;
389
390 GetWin32EscapedString(path, &result);
391 EXPECT_EQ(path, result);
392}
393
394TEST(StripAnsiEscapeCodes, EscapeAtEnd) {
395 string stripped = StripAnsiEscapeCodes("foo\33");
396 EXPECT_EQ("foo", stripped);
397
398 stripped = StripAnsiEscapeCodes("foo\33[");
399 EXPECT_EQ("foo", stripped);
400}
401
402TEST(StripAnsiEscapeCodes, StripColors) {
403 // An actual clang warning.
404 string input = "\33[1maffixmgr.cxx:286:15: \33[0m\33[0;1;35mwarning: "
405 "\33[0m\33[1musing the result... [-Wparentheses]\33[0m";
406 string stripped = StripAnsiEscapeCodes(input);
407 EXPECT_EQ("affixmgr.cxx:286:15: warning: using the result... [-Wparentheses]",
408 stripped);
409}
410
411TEST(ElideMiddle, NothingToElide) {
412 string input = "Nothing to elide in this short string.";
413 EXPECT_EQ(input, ElideMiddle(input, 80));
414 EXPECT_EQ(input, ElideMiddle(input, 38));
415 EXPECT_EQ("", ElideMiddle(input, 0));
416 EXPECT_EQ(".", ElideMiddle(input, 1));
417 EXPECT_EQ("..", ElideMiddle(input, 2));
418 EXPECT_EQ("...", ElideMiddle(input, 3));
419}
420
421TEST(ElideMiddle, ElideInTheMiddle) {
422 string input = "01234567890123456789";
423 string elided = ElideMiddle(input, 10);
424 EXPECT_EQ("012...789", elided);
425 EXPECT_EQ("01234567...23456789", ElideMiddle(input, 19));
426}
427