From 50ae21d1bfaf016a6e8f467dcde6bca65a753af7 Mon Sep 17 00:00:00 2001 From: a3d4 Date: Sun, 20 Feb 2022 02:36:11 +0100 Subject: [PATCH] Fix running tests from any drive --- libsolidity/interface/FileReader.cpp | 31 +++++++++++++++++------ libsolidity/interface/FileReader.h | 11 ++++++++ test/libsolidity/interface/FileReader.cpp | 5 ++-- test/solc/CommandLineInterface.cpp | 8 +++--- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index e581c4a56..8300feb57 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -276,14 +276,8 @@ boost::filesystem::path FileReader::normalizeCLIPathForVFS( // If the path is on the same drive as the working dir, for portability we prefer not to // include the root name. Do this only for non-UNC paths - my experiments show that on Windows // when the working dir is an UNC path, / does not not actually refer to the root of the UNC path. - boost::filesystem::path normalizedRootPath = normalizedPath.root_path(); - if (!isUNCPath(normalizedPath)) - { - boost::filesystem::path workingDirRootPath = canonicalWorkDir.root_path(); - // Ignore drive letter case on Windows (C:\ <=> c:\). - if (boost::filesystem::equivalent(normalizedRootPath, workingDirRootPath)) - normalizedRootPath = "/"; - } + + boost::filesystem::path normalizedRootPath = normalizeCLIRootPathForVFS(normalizedPath, canonicalWorkDir); // lexically_normal() will not squash paths like "/../../" into "/". We have to do it manually. boost::filesystem::path dotDotPrefix = absoluteDotDotPrefix(normalizedPath); @@ -308,6 +302,27 @@ boost::filesystem::path FileReader::normalizeCLIPathForVFS( return normalizedPathNoDotDot; } +boost::filesystem::path FileReader::normalizeCLIRootPathForVFS( + boost::filesystem::path const& _path, + boost::filesystem::path const& _workDir +) +{ + solAssert(_workDir.is_absolute(), ""); + + boost::filesystem::path absolutePath = boost::filesystem::absolute(_path, _workDir); + boost::filesystem::path rootPath = absolutePath.root_path(); + boost::filesystem::path baseRootPath = _workDir.root_path(); + + if (isUNCPath(absolutePath)) + return rootPath; + + // Ignore drive letter case on Windows (C:\ <=> c:\). + if (boost::filesystem::equivalent(rootPath, baseRootPath)) + return "/"; + + return rootPath; +} + bool FileReader::isPathPrefix(boost::filesystem::path const& _prefix, boost::filesystem::path const& _path) { solAssert(!_prefix.empty() && !_path.empty(), ""); diff --git a/libsolidity/interface/FileReader.h b/libsolidity/interface/FileReader.h index 3892e9826..f05ce894d 100644 --- a/libsolidity/interface/FileReader.h +++ b/libsolidity/interface/FileReader.h @@ -115,6 +115,17 @@ public: SymlinkResolution _symlinkResolution = SymlinkResolution::Disabled ); + /// Normalizes a root path by excluding, in some cases, its root name. + /// The function is used for better portability, and intended to omit root name + /// if the path can be used without it. + /// @param _path Path to normalize the root path. + /// @param _workDir Current working directory path, must be absolute. + /// @returns a normalized root path. + static boost::filesystem::path normalizeCLIRootPathForVFS( + boost::filesystem::path const& _path, + boost::filesystem::path const& _workDir = boost::filesystem::current_path() + ); + /// @returns true if all the path components of @a _prefix are present at the beginning of @a _path. /// Both paths must be absolute (or have slash as root) and normalized (no . or .. segments, no /// multiple consecutive slashes). diff --git a/test/libsolidity/interface/FileReader.cpp b/test/libsolidity/interface/FileReader.cpp index 39355e536..ea85685fd 100644 --- a/test/libsolidity/interface/FileReader.cpp +++ b/test/libsolidity/interface/FileReader.cpp @@ -313,8 +313,9 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_should_not_resolve_symlinks_unless_r if (!createSymlinkIfSupportedByFilesystem(tempDir.path() / "abc", tempDir.path() / "sym", true)) return; - boost::filesystem::path expectedPrefixWithSymlinks = "/" / tempDir.path().relative_path(); - boost::filesystem::path expectedPrefixWithoutSymlinks = "/" / boost::filesystem::weakly_canonical(tempDir).relative_path(); + boost::filesystem::path expectedRootPath = FileReader::normalizeCLIRootPathForVFS(tempDir); + boost::filesystem::path expectedPrefixWithSymlinks = expectedRootPath / tempDir.path().relative_path(); + boost::filesystem::path expectedPrefixWithoutSymlinks = expectedRootPath / boost::filesystem::weakly_canonical(tempDir).relative_path(); BOOST_CHECK_EQUAL( FileReader::normalizeCLIPathForVFS(tempDir.path() / "sym/contract.sol", SymlinkResolution::Disabled), diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 73c999f3f..169437f3c 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -178,8 +178,9 @@ BOOST_AUTO_TEST_CASE(cli_input) createFilesWithParentDirs({tempDir1.path() / "input1.sol"}); createFilesWithParentDirs({tempDir2.path() / "input2.sol"}); - boost::filesystem::path expectedDir1 = "/" / tempDir1.path().relative_path(); - boost::filesystem::path expectedDir2 = "/" / tempDir2.path().relative_path(); + boost::filesystem::path expectedRootPath = FileReader::normalizeCLIRootPathForVFS(tempDir1); + boost::filesystem::path expectedDir1 = expectedRootPath / tempDir1.path().relative_path(); + boost::filesystem::path expectedDir2 = expectedRootPath / tempDir2.path().relative_path(); soltestAssert(expectedDir1.is_absolute() || expectedDir1.root_path() == "/", ""); soltestAssert(expectedDir2.is_absolute() || expectedDir2.root_path() == "/", ""); @@ -223,7 +224,8 @@ BOOST_AUTO_TEST_CASE(cli_ignore_missing_some_files_exist) TemporaryDirectory tempDir2(TEST_CASE_NAME); createFilesWithParentDirs({tempDir1.path() / "input1.sol"}); - boost::filesystem::path expectedDir1 = "/" / tempDir1.path().relative_path(); + boost::filesystem::path expectedRootPath = FileReader::normalizeCLIRootPathForVFS(tempDir1); + boost::filesystem::path expectedDir1 = expectedRootPath / tempDir1.path().relative_path(); soltestAssert(expectedDir1.is_absolute() || expectedDir1.root_path() == "/", ""); // NOTE: Allowed paths should not be added for skipped files.