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