1 // Copyright 2012 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 "includes_normalize.h"
16
17 #include <algorithm>
18
19 #include <direct.h>
20
21 #include "string_piece_util.h"
22 #include "test.h"
23 #include "util.h"
24
25 using namespace std;
26
27 namespace {
28
GetCurDir()29 string GetCurDir() {
30 char buf[_MAX_PATH];
31 _getcwd(buf, sizeof(buf));
32 vector<StringPiece> parts = SplitStringPiece(buf, '\\');
33 return parts[parts.size() - 1].AsString();
34 }
35
NormalizeAndCheckNoError(const string & input)36 string NormalizeAndCheckNoError(const string& input) {
37 string result, err;
38 IncludesNormalize normalizer(".");
39 EXPECT_TRUE(normalizer.Normalize(input, &result, &err));
40 EXPECT_EQ("", err);
41 return result;
42 }
43
NormalizeRelativeAndCheckNoError(const string & input,const string & relative_to)44 string NormalizeRelativeAndCheckNoError(const string& input,
45 const string& relative_to) {
46 string result, err;
47 IncludesNormalize normalizer(relative_to);
48 EXPECT_TRUE(normalizer.Normalize(input, &result, &err));
49 EXPECT_EQ("", err);
50 return result;
51 }
52
53 } // namespace
54
TEST(IncludesNormalize,Simple)55 TEST(IncludesNormalize, Simple) {
56 EXPECT_EQ("b", NormalizeAndCheckNoError("a\\..\\b"));
57 EXPECT_EQ("b", NormalizeAndCheckNoError("a\\../b"));
58 EXPECT_EQ("a/b", NormalizeAndCheckNoError("a\\.\\b"));
59 EXPECT_EQ("a/b", NormalizeAndCheckNoError("a\\./b"));
60 }
61
TEST(IncludesNormalize,WithRelative)62 TEST(IncludesNormalize, WithRelative) {
63 string err;
64 string currentdir = GetCurDir();
65 EXPECT_EQ("c", NormalizeRelativeAndCheckNoError("a/b/c", "a/b"));
66 EXPECT_EQ("a",
67 NormalizeAndCheckNoError(IncludesNormalize::AbsPath("a", &err)));
68 EXPECT_EQ("", err);
69 EXPECT_EQ(string("../") + currentdir + string("/a"),
70 NormalizeRelativeAndCheckNoError("a", "../b"));
71 EXPECT_EQ(string("../") + currentdir + string("/a/b"),
72 NormalizeRelativeAndCheckNoError("a/b", "../c"));
73 EXPECT_EQ("../../a", NormalizeRelativeAndCheckNoError("a", "b/c"));
74 EXPECT_EQ(".", NormalizeRelativeAndCheckNoError("a", "a"));
75 }
76
TEST(IncludesNormalize,Case)77 TEST(IncludesNormalize, Case) {
78 EXPECT_EQ("b", NormalizeAndCheckNoError("Abc\\..\\b"));
79 EXPECT_EQ("BdEf", NormalizeAndCheckNoError("Abc\\..\\BdEf"));
80 EXPECT_EQ("A/b", NormalizeAndCheckNoError("A\\.\\b"));
81 EXPECT_EQ("a/b", NormalizeAndCheckNoError("a\\./b"));
82 EXPECT_EQ("A/B", NormalizeAndCheckNoError("A\\.\\B"));
83 EXPECT_EQ("A/B", NormalizeAndCheckNoError("A\\./B"));
84 }
85
TEST(IncludesNormalize,DifferentDrive)86 TEST(IncludesNormalize, DifferentDrive) {
87 EXPECT_EQ("stuff.h",
88 NormalizeRelativeAndCheckNoError("p:\\vs08\\stuff.h", "p:\\vs08"));
89 EXPECT_EQ("stuff.h",
90 NormalizeRelativeAndCheckNoError("P:\\Vs08\\stuff.h", "p:\\vs08"));
91 EXPECT_EQ("p:/vs08/stuff.h",
92 NormalizeRelativeAndCheckNoError("p:\\vs08\\stuff.h", "c:\\vs08"));
93 EXPECT_EQ("P:/vs08/stufF.h", NormalizeRelativeAndCheckNoError(
94 "P:\\vs08\\stufF.h", "D:\\stuff/things"));
95 EXPECT_EQ("P:/vs08/stuff.h", NormalizeRelativeAndCheckNoError(
96 "P:/vs08\\stuff.h", "D:\\stuff/things"));
97 EXPECT_EQ("P:/wee/stuff.h",
98 NormalizeRelativeAndCheckNoError("P:/vs08\\../wee\\stuff.h",
99 "D:\\stuff/things"));
100 }
101
TEST(IncludesNormalize,LongInvalidPath)102 TEST(IncludesNormalize, LongInvalidPath) {
103 const char kLongInputString[] =
104 "C:\\Program Files (x86)\\Microsoft Visual Studio "
105 "12.0\\VC\\INCLUDEwarning #31001: The dll for reading and writing the "
106 "pdb (for example, mspdb110.dll) could not be found on your path. This "
107 "is usually a configuration error. Compilation will continue using /Z7 "
108 "instead of /Zi, but expect a similar error when you link your program.";
109 // Too long, won't be canonicalized. Ensure doesn't crash.
110 string result, err;
111 IncludesNormalize normalizer(".");
112 EXPECT_FALSE(
113 normalizer.Normalize(kLongInputString, &result, &err));
114 EXPECT_EQ("path too long", err);
115
116
117 // Construct max size path having cwd prefix.
118 // kExactlyMaxPath = "$cwd\\a\\aaaa...aaaa\0";
119 char kExactlyMaxPath[_MAX_PATH + 1];
120 ASSERT_NE(_getcwd(kExactlyMaxPath, sizeof kExactlyMaxPath), NULL);
121
122 int cwd_len = strlen(kExactlyMaxPath);
123 ASSERT_LE(cwd_len + 3 + 1, _MAX_PATH)
124 kExactlyMaxPath[cwd_len] = '\\';
125 kExactlyMaxPath[cwd_len + 1] = 'a';
126 kExactlyMaxPath[cwd_len + 2] = '\\';
127
128 kExactlyMaxPath[cwd_len + 3] = 'a';
129
130 for (int i = cwd_len + 4; i < _MAX_PATH; ++i) {
131 if (i > cwd_len + 4 && i < _MAX_PATH - 1 && i % 10 == 0)
132 kExactlyMaxPath[i] = '\\';
133 else
134 kExactlyMaxPath[i] = 'a';
135 }
136
137 kExactlyMaxPath[_MAX_PATH] = '\0';
138 EXPECT_EQ(strlen(kExactlyMaxPath), _MAX_PATH);
139
140 string forward_slashes(kExactlyMaxPath);
141 replace(forward_slashes.begin(), forward_slashes.end(), '\\', '/');
142 // Make sure a path that's exactly _MAX_PATH long is canonicalized.
143 EXPECT_EQ(forward_slashes.substr(cwd_len + 1),
144 NormalizeAndCheckNoError(kExactlyMaxPath));
145 }
146
TEST(IncludesNormalize,ShortRelativeButTooLongAbsolutePath)147 TEST(IncludesNormalize, ShortRelativeButTooLongAbsolutePath) {
148 string result, err;
149 IncludesNormalize normalizer(".");
150 // A short path should work
151 EXPECT_TRUE(normalizer.Normalize("a", &result, &err));
152 EXPECT_EQ("", err);
153
154 // Construct max size path having cwd prefix.
155 // kExactlyMaxPath = "aaaa\\aaaa...aaaa\0";
156 char kExactlyMaxPath[_MAX_PATH + 1];
157 for (int i = 0; i < _MAX_PATH; ++i) {
158 if (i < _MAX_PATH - 1 && i % 10 == 4)
159 kExactlyMaxPath[i] = '\\';
160 else
161 kExactlyMaxPath[i] = 'a';
162 }
163 kExactlyMaxPath[_MAX_PATH] = '\0';
164 EXPECT_EQ(strlen(kExactlyMaxPath), _MAX_PATH);
165
166 // Make sure a path that's exactly _MAX_PATH long fails with a proper error.
167 EXPECT_FALSE(normalizer.Normalize(kExactlyMaxPath, &result, &err));
168 EXPECT_TRUE(err.find("GetFullPathName") != string::npos);
169 }
170