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