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
19 using namespace std;
20
21 namespace {
22
CanonicalizePath(string* path)23 void CanonicalizePath(string* path) {
24 uint64_t unused;
25 ::CanonicalizePath(path, &unused);
26 }
27
28 } // namespace
29
TEST(CanonicalizePath, PathSamples)30 TEST(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 = "../";
97 CanonicalizePath(&path);
98 EXPECT_EQ("..", path);
99
100 path = "../foo";
101 CanonicalizePath(&path);
102 EXPECT_EQ("../foo", path);
103
104 path = "../foo/";
105 CanonicalizePath(&path);
106 EXPECT_EQ("../foo", path);
107
108 path = "../..";
109 CanonicalizePath(&path);
110 EXPECT_EQ("../..", path);
111
112 path = "../../";
113 CanonicalizePath(&path);
114 EXPECT_EQ("../..", path);
115
116 path = "./../";
117 CanonicalizePath(&path);
118 EXPECT_EQ("..", path);
119
120 path = "/..";
121 CanonicalizePath(&path);
122 EXPECT_EQ("/..", path);
123
124 path = "/../";
125 CanonicalizePath(&path);
126 EXPECT_EQ("/..", path);
127
128 path = "/../..";
129 CanonicalizePath(&path);
130 EXPECT_EQ("/../..", path);
131
132 path = "/../../";
133 CanonicalizePath(&path);
134 EXPECT_EQ("/../..", path);
135
136 path = "/";
137 CanonicalizePath(&path);
138 EXPECT_EQ("/", path);
139
140 path = "/foo/..";
141 CanonicalizePath(&path);
142 EXPECT_EQ("/", path);
143
144 path = ".";
145 CanonicalizePath(&path);
146 EXPECT_EQ(".", path);
147
148 path = "./.";
149 CanonicalizePath(&path);
150 EXPECT_EQ(".", path);
151
152 path = "foo/..";
153 CanonicalizePath(&path);
154 EXPECT_EQ(".", path);
155
156 path = "foo/.._bar";
157 CanonicalizePath(&path);
158 EXPECT_EQ("foo/.._bar", path);
159 }
160
161 #ifdef _WIN32
TEST(CanonicalizePath, PathSamplesWindows)162 TEST(CanonicalizePath, PathSamplesWindows) {
163 string path;
164
165 CanonicalizePath(&path);
166 EXPECT_EQ("", path);
167
168 path = "foo.h";
169 CanonicalizePath(&path);
170 EXPECT_EQ("foo.h", path);
171
172 path = ".\\foo.h";
173 CanonicalizePath(&path);
174 EXPECT_EQ("foo.h", path);
175
176 path = ".\\foo\\.\\bar.h";
177 CanonicalizePath(&path);
178 EXPECT_EQ("foo/bar.h", path);
179
180 path = ".\\x\\foo\\..\\bar.h";
181 CanonicalizePath(&path);
182 EXPECT_EQ("x/bar.h", path);
183
184 path = ".\\x\\foo\\..\\..\\bar.h";
185 CanonicalizePath(&path);
186 EXPECT_EQ("bar.h", path);
187
188 path = "foo\\\\bar";
189 CanonicalizePath(&path);
190 EXPECT_EQ("foo/bar", path);
191
192 path = "foo\\\\.\\\\..\\\\\\bar";
193 CanonicalizePath(&path);
194 EXPECT_EQ("bar", path);
195
196 path = ".\\x\\..\\foo\\..\\..\\bar.h";
197 CanonicalizePath(&path);
198 EXPECT_EQ("../bar.h", path);
199
200 path = "foo\\.\\.";
201 CanonicalizePath(&path);
202 EXPECT_EQ("foo", path);
203
204 path = "foo\\bar\\..";
205 CanonicalizePath(&path);
206 EXPECT_EQ("foo", path);
207
208 path = "foo\\.hidden_bar";
209 CanonicalizePath(&path);
210 EXPECT_EQ("foo/.hidden_bar", path);
211
212 path = "\\foo";
213 CanonicalizePath(&path);
214 EXPECT_EQ("/foo", path);
215
216 path = "\\\\foo";
217 CanonicalizePath(&path);
218 EXPECT_EQ("//foo", path);
219
220 path = "\\";
221 CanonicalizePath(&path);
222 EXPECT_EQ("/", path);
223 }
224
TEST(CanonicalizePath, SlashTracking)225 TEST(CanonicalizePath, SlashTracking) {
226 string path;
227 uint64_t slash_bits;
228
229 path = "foo.h";
230 CanonicalizePath(&path, &slash_bits);
231 EXPECT_EQ("foo.h", path);
232 EXPECT_EQ(0, slash_bits);
233
234 path = "a\\foo.h";
235 CanonicalizePath(&path, &slash_bits);
236 EXPECT_EQ("a/foo.h", path);
237 EXPECT_EQ(1, slash_bits);
238
239 path = "a/bcd/efh\\foo.h";
240 CanonicalizePath(&path, &slash_bits);
241 EXPECT_EQ("a/bcd/efh/foo.h", path);
242 EXPECT_EQ(4, slash_bits);
243
244 path = "a\\bcd/efh\\foo.h";
245 CanonicalizePath(&path, &slash_bits);
246 EXPECT_EQ("a/bcd/efh/foo.h", path);
247 EXPECT_EQ(5, slash_bits);
248
249 path = "a\\bcd\\efh\\foo.h";
250 CanonicalizePath(&path, &slash_bits);
251 EXPECT_EQ("a/bcd/efh/foo.h", path);
252 EXPECT_EQ(7, slash_bits);
253
254 path = "a/bcd/efh/foo.h";
255 CanonicalizePath(&path, &slash_bits);
256 EXPECT_EQ("a/bcd/efh/foo.h", path);
257 EXPECT_EQ(0, slash_bits);
258
259 path = "a\\./efh\\foo.h";
260 CanonicalizePath(&path, &slash_bits);
261 EXPECT_EQ("a/efh/foo.h", path);
262 EXPECT_EQ(3, slash_bits);
263
264 path = "a\\../efh\\foo.h";
265 CanonicalizePath(&path, &slash_bits);
266 EXPECT_EQ("efh/foo.h", path);
267 EXPECT_EQ(1, slash_bits);
268
269 path = "a\\b\\c\\d\\e\\f\\g\\foo.h";
270 CanonicalizePath(&path, &slash_bits);
271 EXPECT_EQ("a/b/c/d/e/f/g/foo.h", path);
272 EXPECT_EQ(127, slash_bits);
273
274 path = "a\\b\\c\\..\\..\\..\\g\\foo.h";
275 CanonicalizePath(&path, &slash_bits);
276 EXPECT_EQ("g/foo.h", path);
277 EXPECT_EQ(1, slash_bits);
278
279 path = "a\\b/c\\../../..\\g\\foo.h";
280 CanonicalizePath(&path, &slash_bits);
281 EXPECT_EQ("g/foo.h", path);
282 EXPECT_EQ(1, slash_bits);
283
284 path = "a\\b/c\\./../..\\g\\foo.h";
285 CanonicalizePath(&path, &slash_bits);
286 EXPECT_EQ("a/g/foo.h", path);
287 EXPECT_EQ(3, slash_bits);
288
289 path = "a\\b/c\\./../..\\g/foo.h";
290 CanonicalizePath(&path, &slash_bits);
291 EXPECT_EQ("a/g/foo.h", path);
292 EXPECT_EQ(1, slash_bits);
293
294 path = "a\\\\\\foo.h";
295 CanonicalizePath(&path, &slash_bits);
296 EXPECT_EQ("a/foo.h", path);
297 EXPECT_EQ(1, slash_bits);
298
299 path = "a/\\\\foo.h";
300 CanonicalizePath(&path, &slash_bits);
301 EXPECT_EQ("a/foo.h", path);
302 EXPECT_EQ(0, slash_bits);
303
304 path = "a\\//foo.h";
305 CanonicalizePath(&path, &slash_bits);
306 EXPECT_EQ("a/foo.h", path);
307 EXPECT_EQ(1, slash_bits);
308 }
309
TEST(CanonicalizePath, CanonicalizeNotExceedingLen)310 TEST(CanonicalizePath, CanonicalizeNotExceedingLen) {
311 // Make sure searching \/ doesn't go past supplied len.
312 char buf[] = "foo/bar\\baz.h\\"; // Last \ past end.
313 uint64_t slash_bits;
314 size_t size = 13;
315 ::CanonicalizePath(buf, &size, &slash_bits);
316 EXPECT_EQ(0, strncmp("foo/bar/baz.h", buf, size));
317 EXPECT_EQ(2, slash_bits); // Not including the trailing one.
318 }
319
TEST(CanonicalizePath, TooManyComponents)320 TEST(CanonicalizePath, TooManyComponents) {
321 string path;
322 uint64_t slash_bits;
323
324 // 64 is OK.
325 path = "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./"
326 "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./x.h";
327 CanonicalizePath(&path, &slash_bits);
328 EXPECT_EQ(slash_bits, 0x0);
329
330 // Backslashes version.
331 path =
332 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
333 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
334 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
335 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\x.h";
336
337 CanonicalizePath(&path, &slash_bits);
338 EXPECT_EQ(slash_bits, 0xffffffff);
339
340 // 65 is OK if #component is less than 60 after path canonicalization.
341 path = "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./"
342 "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./x/y.h";
343 CanonicalizePath(&path, &slash_bits);
344 EXPECT_EQ(slash_bits, 0x0);
345
346 // Backslashes version.
347 path =
348 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
349 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
350 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
351 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\x\\y.h";
352 CanonicalizePath(&path, &slash_bits);
353 EXPECT_EQ(slash_bits, 0x1ffffffff);
354
355
356 // 59 after canonicalization is OK.
357 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/"
358 "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";
359 EXPECT_EQ(58, std::count(path.begin(), path.end(), '/'));
360 CanonicalizePath(&path, &slash_bits);
361 EXPECT_EQ(slash_bits, 0x0);
362
363 // Backslashes version.
364 path =
365 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
366 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
367 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
368 "a\\a\\a\\a\\a\\a\\a\\a\\a\\x\\y.h";
369 EXPECT_EQ(58, std::count(path.begin(), path.end(), '\\'));
370 CanonicalizePath(&path, &slash_bits);
371 EXPECT_EQ(slash_bits, 0x3ffffffffffffff);
372
373 // More than 60 components is now completely ok too.
374 path =
375 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
376 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
377 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
378 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
379 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
380 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
381 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
382 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
383 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
384 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
385 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
386 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
387 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
388 "a\\a\\a\\a\\a\\a\\a\\a\\a\\x\\y.h";
389 EXPECT_EQ(218, std::count(path.begin(), path.end(), '\\'));
390 CanonicalizePath(&path, &slash_bits);
391 EXPECT_EQ(slash_bits, 0xffffffffffffffff);
392 }
393 #else // !_WIN32
TEST(CanonicalizePath, TooManyComponents)394 TEST(CanonicalizePath, TooManyComponents) {
395 string path;
396 uint64_t slash_bits;
397
398 // More than 60 components is now completely ok.
399 path =
400 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
401 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
402 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
403 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
404 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
405 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
406 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
407 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
408 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
409 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
410 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
411 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
412 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
413 "a/a/a/a/a/a/a/a/a/x/y.h";
414 EXPECT_EQ(218, std::count(path.begin(), path.end(), '/'));
415 CanonicalizePath(&path, &slash_bits);
416 EXPECT_EQ(slash_bits, 0x0);
417 }
418 #endif // !_WIN32
419
TEST(CanonicalizePath, UpDir)420 TEST(CanonicalizePath, UpDir) {
421 string path, err;
422 path = "../../foo/bar.h";
423 CanonicalizePath(&path);
424 EXPECT_EQ("../../foo/bar.h", path);
425
426 path = "test/../../foo/bar.h";
427 CanonicalizePath(&path);
428 EXPECT_EQ("../foo/bar.h", path);
429 }
430
TEST(CanonicalizePath, AbsolutePath)431 TEST(CanonicalizePath, AbsolutePath) {
432 string path = "/usr/include/stdio.h";
433 string err;
434 CanonicalizePath(&path);
435 EXPECT_EQ("/usr/include/stdio.h", path);
436 }
437
TEST(CanonicalizePath, NotNullTerminated)438 TEST(CanonicalizePath, NotNullTerminated) {
439 string path;
440 size_t len;
441 uint64_t unused;
442
443 path = "foo/. bar/.";
444 len = strlen("foo/."); // Canonicalize only the part before the space.
445 CanonicalizePath(&path[0], &len, &unused);
446 EXPECT_EQ(strlen("foo"), len);
447 EXPECT_EQ("foo/. bar/.", string(path));
448
449 // Verify that foo/..file gets canonicalized to 'file' without
450 // touching the rest of the string.
451 path = "foo/../file bar/.";
452 len = strlen("foo/../file");
453 CanonicalizePath(&path[0], &len, &unused);
454 EXPECT_EQ(strlen("file"), len);
455 EXPECT_EQ("file../file bar/.", string(path));
456 }
457
TEST(PathEscaping, TortureTest)458 TEST(PathEscaping, TortureTest) {
459 string result;
460
461 GetWin32EscapedString("foo bar\\\"'$@d!st!c'\\path'\\", &result);
462 EXPECT_EQ("\"foo bar\\\\\\\"'$@d!st!c'\\path'\\\\\"", result);
463 result.clear();
464
465 GetShellEscapedString("foo bar\"/'$@d!st!c'/path'", &result);
466 EXPECT_EQ("'foo bar\"/'\\''$@d!st!c'\\''/path'\\'''", result);
467 }
468
TEST(PathEscaping, SensiblePathsAreNotNeedlesslyEscaped)469 TEST(PathEscaping, SensiblePathsAreNotNeedlesslyEscaped) {
470 const char* path = "some/sensible/path/without/crazy/characters.c++";
471 string result;
472
473 GetWin32EscapedString(path, &result);
474 EXPECT_EQ(path, result);
475 result.clear();
476
477 GetShellEscapedString(path, &result);
478 EXPECT_EQ(path, result);
479 }
480
TEST(PathEscaping, SensibleWin32PathsAreNotNeedlesslyEscaped)481 TEST(PathEscaping, SensibleWin32PathsAreNotNeedlesslyEscaped) {
482 const char* path = "some\\sensible\\path\\without\\crazy\\characters.c++";
483 string result;
484
485 GetWin32EscapedString(path, &result);
486 EXPECT_EQ(path, result);
487 }
488
TEST(StripAnsiEscapeCodes, EscapeAtEnd)489 TEST(StripAnsiEscapeCodes, EscapeAtEnd) {
490 string stripped = StripAnsiEscapeCodes("foo\33");
491 EXPECT_EQ("foo", stripped);
492
493 stripped = StripAnsiEscapeCodes("foo\33[");
494 EXPECT_EQ("foo", stripped);
495 }
496
TEST(StripAnsiEscapeCodes, StripColors)497 TEST(StripAnsiEscapeCodes, StripColors) {
498 // An actual clang warning.
499 string input = "\33[1maffixmgr.cxx:286:15: \33[0m\33[0;1;35mwarning: "
500 "\33[0m\33[1musing the result... [-Wparentheses]\33[0m";
501 string stripped = StripAnsiEscapeCodes(input);
502 EXPECT_EQ("affixmgr.cxx:286:15: warning: using the result... [-Wparentheses]",
503 stripped);
504 }
505
TEST(ElideMiddle, NothingToElide)506 TEST(ElideMiddle, NothingToElide) {
507 string input = "Nothing to elide in this short string.";
508 EXPECT_EQ(input, ElideMiddle(input, 80));
509 EXPECT_EQ(input, ElideMiddle(input, 38));
510 EXPECT_EQ("", ElideMiddle(input, 0));
511 EXPECT_EQ(".", ElideMiddle(input, 1));
512 EXPECT_EQ("..", ElideMiddle(input, 2));
513 EXPECT_EQ("...", ElideMiddle(input, 3));
514 }
515
TEST(ElideMiddle, ElideInTheMiddle)516 TEST(ElideMiddle, ElideInTheMiddle) {
517 string input = "01234567890123456789";
518 string elided = ElideMiddle(input, 10);
519 EXPECT_EQ("012...789", elided);
520 EXPECT_EQ("01234567...23456789", ElideMiddle(input, 19));
521 }
522