1695b41eeSopenharmony_ci// Copyright 2012 Google Inc. All Rights Reserved. 2695b41eeSopenharmony_ci// 3695b41eeSopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4695b41eeSopenharmony_ci// you may not use this file except in compliance with the License. 5695b41eeSopenharmony_ci// You may obtain a copy of the License at 6695b41eeSopenharmony_ci// 7695b41eeSopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8695b41eeSopenharmony_ci// 9695b41eeSopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10695b41eeSopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11695b41eeSopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12695b41eeSopenharmony_ci// See the License for the specific language governing permissions and 13695b41eeSopenharmony_ci// limitations under the License. 14695b41eeSopenharmony_ci 15695b41eeSopenharmony_ci#include "includes_normalize.h" 16695b41eeSopenharmony_ci 17695b41eeSopenharmony_ci#include <algorithm> 18695b41eeSopenharmony_ci 19695b41eeSopenharmony_ci#include <direct.h> 20695b41eeSopenharmony_ci 21695b41eeSopenharmony_ci#include "string_piece_util.h" 22695b41eeSopenharmony_ci#include "test.h" 23695b41eeSopenharmony_ci#include "util.h" 24695b41eeSopenharmony_ci 25695b41eeSopenharmony_ciusing namespace std; 26695b41eeSopenharmony_ci 27695b41eeSopenharmony_cinamespace { 28695b41eeSopenharmony_ci 29695b41eeSopenharmony_cistring GetCurDir() { 30695b41eeSopenharmony_ci char buf[_MAX_PATH]; 31695b41eeSopenharmony_ci _getcwd(buf, sizeof(buf)); 32695b41eeSopenharmony_ci vector<StringPiece> parts = SplitStringPiece(buf, '\\'); 33695b41eeSopenharmony_ci return parts[parts.size() - 1].AsString(); 34695b41eeSopenharmony_ci} 35695b41eeSopenharmony_ci 36695b41eeSopenharmony_cistring NormalizeAndCheckNoError(const string& input) { 37695b41eeSopenharmony_ci string result, err; 38695b41eeSopenharmony_ci IncludesNormalize normalizer("."); 39695b41eeSopenharmony_ci EXPECT_TRUE(normalizer.Normalize(input, &result, &err)); 40695b41eeSopenharmony_ci EXPECT_EQ("", err); 41695b41eeSopenharmony_ci return result; 42695b41eeSopenharmony_ci} 43695b41eeSopenharmony_ci 44695b41eeSopenharmony_cistring NormalizeRelativeAndCheckNoError(const string& input, 45695b41eeSopenharmony_ci const string& relative_to) { 46695b41eeSopenharmony_ci string result, err; 47695b41eeSopenharmony_ci IncludesNormalize normalizer(relative_to); 48695b41eeSopenharmony_ci EXPECT_TRUE(normalizer.Normalize(input, &result, &err)); 49695b41eeSopenharmony_ci EXPECT_EQ("", err); 50695b41eeSopenharmony_ci return result; 51695b41eeSopenharmony_ci} 52695b41eeSopenharmony_ci 53695b41eeSopenharmony_ci} // namespace 54695b41eeSopenharmony_ci 55695b41eeSopenharmony_ciTEST(IncludesNormalize, Simple) { 56695b41eeSopenharmony_ci EXPECT_EQ("b", NormalizeAndCheckNoError("a\\..\\b")); 57695b41eeSopenharmony_ci EXPECT_EQ("b", NormalizeAndCheckNoError("a\\../b")); 58695b41eeSopenharmony_ci EXPECT_EQ("a/b", NormalizeAndCheckNoError("a\\.\\b")); 59695b41eeSopenharmony_ci EXPECT_EQ("a/b", NormalizeAndCheckNoError("a\\./b")); 60695b41eeSopenharmony_ci} 61695b41eeSopenharmony_ci 62695b41eeSopenharmony_ciTEST(IncludesNormalize, WithRelative) { 63695b41eeSopenharmony_ci string err; 64695b41eeSopenharmony_ci string currentdir = GetCurDir(); 65695b41eeSopenharmony_ci EXPECT_EQ("c", NormalizeRelativeAndCheckNoError("a/b/c", "a/b")); 66695b41eeSopenharmony_ci EXPECT_EQ("a", 67695b41eeSopenharmony_ci NormalizeAndCheckNoError(IncludesNormalize::AbsPath("a", &err))); 68695b41eeSopenharmony_ci EXPECT_EQ("", err); 69695b41eeSopenharmony_ci EXPECT_EQ(string("../") + currentdir + string("/a"), 70695b41eeSopenharmony_ci NormalizeRelativeAndCheckNoError("a", "../b")); 71695b41eeSopenharmony_ci EXPECT_EQ(string("../") + currentdir + string("/a/b"), 72695b41eeSopenharmony_ci NormalizeRelativeAndCheckNoError("a/b", "../c")); 73695b41eeSopenharmony_ci EXPECT_EQ("../../a", NormalizeRelativeAndCheckNoError("a", "b/c")); 74695b41eeSopenharmony_ci EXPECT_EQ(".", NormalizeRelativeAndCheckNoError("a", "a")); 75695b41eeSopenharmony_ci} 76695b41eeSopenharmony_ci 77695b41eeSopenharmony_ciTEST(IncludesNormalize, Case) { 78695b41eeSopenharmony_ci EXPECT_EQ("b", NormalizeAndCheckNoError("Abc\\..\\b")); 79695b41eeSopenharmony_ci EXPECT_EQ("BdEf", NormalizeAndCheckNoError("Abc\\..\\BdEf")); 80695b41eeSopenharmony_ci EXPECT_EQ("A/b", NormalizeAndCheckNoError("A\\.\\b")); 81695b41eeSopenharmony_ci EXPECT_EQ("a/b", NormalizeAndCheckNoError("a\\./b")); 82695b41eeSopenharmony_ci EXPECT_EQ("A/B", NormalizeAndCheckNoError("A\\.\\B")); 83695b41eeSopenharmony_ci EXPECT_EQ("A/B", NormalizeAndCheckNoError("A\\./B")); 84695b41eeSopenharmony_ci} 85695b41eeSopenharmony_ci 86695b41eeSopenharmony_ciTEST(IncludesNormalize, DifferentDrive) { 87695b41eeSopenharmony_ci EXPECT_EQ("stuff.h", 88695b41eeSopenharmony_ci NormalizeRelativeAndCheckNoError("p:\\vs08\\stuff.h", "p:\\vs08")); 89695b41eeSopenharmony_ci EXPECT_EQ("stuff.h", 90695b41eeSopenharmony_ci NormalizeRelativeAndCheckNoError("P:\\Vs08\\stuff.h", "p:\\vs08")); 91695b41eeSopenharmony_ci EXPECT_EQ("p:/vs08/stuff.h", 92695b41eeSopenharmony_ci NormalizeRelativeAndCheckNoError("p:\\vs08\\stuff.h", "c:\\vs08")); 93695b41eeSopenharmony_ci EXPECT_EQ("P:/vs08/stufF.h", NormalizeRelativeAndCheckNoError( 94695b41eeSopenharmony_ci "P:\\vs08\\stufF.h", "D:\\stuff/things")); 95695b41eeSopenharmony_ci EXPECT_EQ("P:/vs08/stuff.h", NormalizeRelativeAndCheckNoError( 96695b41eeSopenharmony_ci "P:/vs08\\stuff.h", "D:\\stuff/things")); 97695b41eeSopenharmony_ci EXPECT_EQ("P:/wee/stuff.h", 98695b41eeSopenharmony_ci NormalizeRelativeAndCheckNoError("P:/vs08\\../wee\\stuff.h", 99695b41eeSopenharmony_ci "D:\\stuff/things")); 100695b41eeSopenharmony_ci} 101695b41eeSopenharmony_ci 102695b41eeSopenharmony_ciTEST(IncludesNormalize, LongInvalidPath) { 103695b41eeSopenharmony_ci const char kLongInputString[] = 104695b41eeSopenharmony_ci "C:\\Program Files (x86)\\Microsoft Visual Studio " 105695b41eeSopenharmony_ci "12.0\\VC\\INCLUDEwarning #31001: The dll for reading and writing the " 106695b41eeSopenharmony_ci "pdb (for example, mspdb110.dll) could not be found on your path. This " 107695b41eeSopenharmony_ci "is usually a configuration error. Compilation will continue using /Z7 " 108695b41eeSopenharmony_ci "instead of /Zi, but expect a similar error when you link your program."; 109695b41eeSopenharmony_ci // Too long, won't be canonicalized. Ensure doesn't crash. 110695b41eeSopenharmony_ci string result, err; 111695b41eeSopenharmony_ci IncludesNormalize normalizer("."); 112695b41eeSopenharmony_ci EXPECT_FALSE( 113695b41eeSopenharmony_ci normalizer.Normalize(kLongInputString, &result, &err)); 114695b41eeSopenharmony_ci EXPECT_EQ("path too long", err); 115695b41eeSopenharmony_ci 116695b41eeSopenharmony_ci 117695b41eeSopenharmony_ci // Construct max size path having cwd prefix. 118695b41eeSopenharmony_ci // kExactlyMaxPath = "$cwd\\a\\aaaa...aaaa\0"; 119695b41eeSopenharmony_ci char kExactlyMaxPath[_MAX_PATH + 1]; 120695b41eeSopenharmony_ci ASSERT_STRNE(_getcwd(kExactlyMaxPath, sizeof kExactlyMaxPath), NULL); 121695b41eeSopenharmony_ci 122695b41eeSopenharmony_ci int cwd_len = strlen(kExactlyMaxPath); 123695b41eeSopenharmony_ci ASSERT_LE(cwd_len + 3 + 1, _MAX_PATH); 124695b41eeSopenharmony_ci kExactlyMaxPath[cwd_len] = '\\'; 125695b41eeSopenharmony_ci kExactlyMaxPath[cwd_len + 1] = 'a'; 126695b41eeSopenharmony_ci kExactlyMaxPath[cwd_len + 2] = '\\'; 127695b41eeSopenharmony_ci 128695b41eeSopenharmony_ci kExactlyMaxPath[cwd_len + 3] = 'a'; 129695b41eeSopenharmony_ci 130695b41eeSopenharmony_ci for (int i = cwd_len + 4; i < _MAX_PATH; ++i) { 131695b41eeSopenharmony_ci if (i > cwd_len + 4 && i < _MAX_PATH - 1 && i % 10 == 0) 132695b41eeSopenharmony_ci kExactlyMaxPath[i] = '\\'; 133695b41eeSopenharmony_ci else 134695b41eeSopenharmony_ci kExactlyMaxPath[i] = 'a'; 135695b41eeSopenharmony_ci } 136695b41eeSopenharmony_ci 137695b41eeSopenharmony_ci kExactlyMaxPath[_MAX_PATH] = '\0'; 138695b41eeSopenharmony_ci EXPECT_EQ(strlen(kExactlyMaxPath), _MAX_PATH); 139695b41eeSopenharmony_ci 140695b41eeSopenharmony_ci string forward_slashes(kExactlyMaxPath); 141695b41eeSopenharmony_ci replace(forward_slashes.begin(), forward_slashes.end(), '\\', '/'); 142695b41eeSopenharmony_ci // Make sure a path that's exactly _MAX_PATH long is canonicalized. 143695b41eeSopenharmony_ci EXPECT_EQ(forward_slashes.substr(cwd_len + 1), 144695b41eeSopenharmony_ci NormalizeAndCheckNoError(kExactlyMaxPath)); 145695b41eeSopenharmony_ci} 146695b41eeSopenharmony_ci 147695b41eeSopenharmony_ciTEST(IncludesNormalize, ShortRelativeButTooLongAbsolutePath) { 148695b41eeSopenharmony_ci string result, err; 149695b41eeSopenharmony_ci IncludesNormalize normalizer("."); 150695b41eeSopenharmony_ci // A short path should work 151695b41eeSopenharmony_ci EXPECT_TRUE(normalizer.Normalize("a", &result, &err)); 152695b41eeSopenharmony_ci EXPECT_EQ("", err); 153695b41eeSopenharmony_ci 154695b41eeSopenharmony_ci // Construct max size path having cwd prefix. 155695b41eeSopenharmony_ci // kExactlyMaxPath = "aaaa\\aaaa...aaaa\0"; 156695b41eeSopenharmony_ci char kExactlyMaxPath[_MAX_PATH + 1]; 157695b41eeSopenharmony_ci for (int i = 0; i < _MAX_PATH; ++i) { 158695b41eeSopenharmony_ci if (i < _MAX_PATH - 1 && i % 10 == 4) 159695b41eeSopenharmony_ci kExactlyMaxPath[i] = '\\'; 160695b41eeSopenharmony_ci else 161695b41eeSopenharmony_ci kExactlyMaxPath[i] = 'a'; 162695b41eeSopenharmony_ci } 163695b41eeSopenharmony_ci kExactlyMaxPath[_MAX_PATH] = '\0'; 164695b41eeSopenharmony_ci EXPECT_EQ(strlen(kExactlyMaxPath), _MAX_PATH); 165695b41eeSopenharmony_ci 166695b41eeSopenharmony_ci // Make sure a path that's exactly _MAX_PATH long fails with a proper error. 167695b41eeSopenharmony_ci EXPECT_FALSE(normalizer.Normalize(kExactlyMaxPath, &result, &err)); 168695b41eeSopenharmony_ci EXPECT_TRUE(err.find("GetFullPathName") != string::npos); 169695b41eeSopenharmony_ci} 170