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 
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 = "../";
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
162 TEST(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 
225 TEST(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 
310 TEST(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 
320 TEST(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
394 TEST(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 
431 TEST(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 
438 TEST(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 
458 TEST(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 
469 TEST(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 
481 TEST(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 
489 TEST(StripAnsiEscapeCodes, EscapeAtEnd) {
490  string stripped = StripAnsiEscapeCodes("foo\33");
491  EXPECT_EQ("foo", stripped);
492 
493  stripped = StripAnsiEscapeCodes("foo\33[");
494  EXPECT_EQ("foo", stripped);
495 }
496 
497 TEST(StripAnsiEscapeCodes, StripColors) {
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