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