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 bool CanonicalizePath(string* path, string* err) {
24  uint64_t unused;
25  return ::CanonicalizePath(path, &unused, err);
26 }
27 
28 } // namespace
29 
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
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 }
bool CanonicalizePath(string *path, uint64_t *slash_bits, string *err)
Definition: util.cc:95
void GetWin32EscapedString(const string &input, string *result)
Definition: util.cc:283
#define EXPECT_TRUE(a)
Definition: test.h:76
#define EXPECT_FALSE(a)
Definition: test.h:78
void GetShellEscapedString(const string &input, string *result)
Definition: util.cc:256
TEST(CanonicalizePath, PathSamples)
Definition: util_test.cc:30
#define EXPECT_EQ(a, b)
Definition: test.h:64
string StripAnsiEscapeCodes(const string &in)
Definition: util.cc:461
unsigned long long uint64_t
Definition: win32port.h:29
string ElideMiddle(const string &str, size_t width)
Definition: util.cc:600