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