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 namespace {
20 
21 bool CanonicalizePath(string* path, string* err) {
22  uint64_t unused;
23  return ::CanonicalizePath(path, &unused, err);
24 }
25 
26 } // namespace
27 
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
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 }
424 
425 TEST(ElideMiddle, ElideInTheMiddle) {
426  string input = "01234567890123456789";
427  string elided = ElideMiddle(input, 10);
428  EXPECT_EQ("012...789", elided);
429  EXPECT_EQ("01234567...23456789", ElideMiddle(input, 19));
430 }
bool CanonicalizePath(string *path, uint64_t *slash_bits, string *err)
Canonicalize a path like "foo/../bar.h" into just "bar.h".
Definition: util.cc:93
void GetWin32EscapedString(const string &input, string *result)
Definition: util.cc:281
#define EXPECT_TRUE(a)
Definition: test.h:76
#define EXPECT_FALSE(a)
Definition: test.h:78
void GetShellEscapedString(const string &input, string *result)
Appends |input| to |*result|, escaping according to the whims of either Bash, or Win32's CommandLineT...
Definition: util.cc:254
TEST(CanonicalizePath, PathSamples)
Definition: util_test.cc:28
#define EXPECT_EQ(a, b)
Definition: test.h:64
string StripAnsiEscapeCodes(const string &in)
Removes all Ansi escape codes (http://www.termsys.demon.co.uk/vtansi.htm).
Definition: util.cc:459
unsigned long long uint64_t
Definition: win32port.h:29
string ElideMiddle(const string &str, size_t width)
Elide the given string str with '...' in the middle if the length exceeds width.
Definition: util.cc:587