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