Ninja
util_test.cc
Go to the documentation of this file.
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
19using namespace std;
20
21namespace {
22
23void CanonicalizePath(string* path) {
24 uint64_t unused;
25 ::CanonicalizePath(path, &unused);
26}
27
28} // namespace
29
30TEST(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
162TEST(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
225TEST(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
310TEST(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
320TEST(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, uint64_t(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, uint64_t(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
394TEST(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
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
431TEST(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
438TEST(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
458TEST(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
469TEST(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
481TEST(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
490 string stripped = StripAnsiEscapeCodes("foo\33");
491 EXPECT_EQ("foo", stripped);
492
493 stripped = StripAnsiEscapeCodes("foo\33[");
494 EXPECT_EQ("foo", stripped);
495}
496
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}
Definition hash_map.h:26
void GetWin32EscapedString(const string &input, string *result)
Definition util.cc:380
void GetShellEscapedString(const string &input, string *result)
Definition util.cc:353
void CanonicalizePath(string *path, uint64_t *slash_bits)
Definition util.cc:124
string StripAnsiEscapeCodes(const string &in)
Definition util.cc:571
TEST(CanonicalizePath, PathSamples)
Definition util_test.cc:30
unsigned long long uint64_t
Definition win32port.h:29