mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Extract TemporaryDirectory test helper from yulPhaser's tests into a more general location
This commit is contained in:
		
							parent
							
								
									98e2b4e5ed
								
							
						
					
					
						commit
						5619702d31
					
				| @ -11,6 +11,9 @@ set(sources | ||||
|     InteractiveTests.h | ||||
|     Metadata.cpp | ||||
|     Metadata.h | ||||
|     TemporaryDirectory.cpp | ||||
|     TemporaryDirectory.h | ||||
|     TemporaryDirectoryTest.cpp | ||||
|     TestCase.cpp | ||||
|     TestCase.h | ||||
|     TestCaseReader.cpp | ||||
|  | ||||
							
								
								
									
										65
									
								
								test/TemporaryDirectory.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								test/TemporaryDirectory.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| /*
 | ||||
| 	This file is part of solidity. | ||||
| 
 | ||||
| 	solidity is free software: you can redistribute it and/or modify | ||||
| 	it under the terms of the GNU General Public License as published by | ||||
| 	the Free Software Foundation, either version 3 of the License, or | ||||
| 	(at your option) any later version. | ||||
| 
 | ||||
| 	solidity is distributed in the hope that it will be useful, | ||||
| 	but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| 	GNU General Public License for more details. | ||||
| 
 | ||||
| 	You should have received a copy of the GNU General Public License | ||||
| 	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| // SPDX-License-Identifier: GPL-3.0
 | ||||
| 
 | ||||
| #include <test/TemporaryDirectory.h> | ||||
| 
 | ||||
| #include <boost/filesystem.hpp> | ||||
| 
 | ||||
| #include <cassert> | ||||
| #include <regex> | ||||
| #include <iostream> | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace solidity; | ||||
| using namespace solidity::test; | ||||
| 
 | ||||
| namespace fs = boost::filesystem; | ||||
| 
 | ||||
| TemporaryDirectory::TemporaryDirectory(std::string const& _prefix): | ||||
| 	m_path((fs::temp_directory_path() / fs::unique_path(_prefix + "%%%%-%%%%-%%%%-%%%%")).string()) | ||||
| { | ||||
| 	// Prefix should just be a file name and not contain anything that would make us step out of /tmp.
 | ||||
| 	assert(fs::path(_prefix) == fs::path(_prefix).stem()); | ||||
| 
 | ||||
| 	fs::create_directory(m_path); | ||||
| } | ||||
| 
 | ||||
| TemporaryDirectory::~TemporaryDirectory() | ||||
| { | ||||
| 	// A few paranoid sanity checks just to be extra sure we're not deleting someone's homework.
 | ||||
| 	assert(m_path.find(fs::temp_directory_path().string()) == 0); | ||||
| 	assert(fs::path(m_path) != fs::temp_directory_path()); | ||||
| 	assert(fs::path(m_path) != fs::path(m_path).root_path()); | ||||
| 	assert(!fs::path(m_path).empty()); | ||||
| 
 | ||||
| 	boost::system::error_code errorCode; | ||||
| 	uintmax_t numRemoved = fs::remove_all(m_path, errorCode); | ||||
| 	if (errorCode.value() != boost::system::errc::success) | ||||
| 	{ | ||||
| 		cerr << "Failed to completely remove temporary directory '" << m_path << "'. "; | ||||
| 		cerr << "Only " << numRemoved << " files were actually removed." << endl; | ||||
| 		cerr << "Reason: " << errorCode.message() << endl; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| string TemporaryDirectory::memberPath(string const& _relativePath) const | ||||
| { | ||||
| 	assert(fs::path(_relativePath).is_relative()); | ||||
| 
 | ||||
| 	return (fs::path(m_path) / _relativePath).string(); | ||||
| } | ||||
							
								
								
									
										52
									
								
								test/TemporaryDirectory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								test/TemporaryDirectory.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| /*
 | ||||
| 	This file is part of solidity. | ||||
| 
 | ||||
| 	solidity is free software: you can redistribute it and/or modify | ||||
| 	it under the terms of the GNU General Public License as published by | ||||
| 	the Free Software Foundation, either version 3 of the License, or | ||||
| 	(at your option) any later version. | ||||
| 
 | ||||
| 	solidity is distributed in the hope that it will be useful, | ||||
| 	but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| 	GNU General Public License for more details. | ||||
| 
 | ||||
| 	You should have received a copy of the GNU General Public License | ||||
| 	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| // SPDX-License-Identifier: GPL-3.0
 | ||||
| /**
 | ||||
|  * Utility for creating temporary directories for use in tests. | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| namespace solidity::test | ||||
| { | ||||
| 
 | ||||
| /**
 | ||||
|  * An object that creates a unique temporary directory and automatically deletes it and its | ||||
|  * content upon being destroyed. | ||||
|  * | ||||
|  * The directory is guaranteed to be newly created and empty. Directory names are generated | ||||
|  * randomly. If a directory with the same name already exists (very unlikely but possible) the | ||||
|  * object won't reuse it and will fail with an exception instead. | ||||
|  */ | ||||
| class TemporaryDirectory | ||||
| { | ||||
| public: | ||||
| 	TemporaryDirectory(std::string const& _prefix = "solidity-test-"); | ||||
| 	~TemporaryDirectory(); | ||||
| 
 | ||||
| 	std::string const& path() const { return m_path; } | ||||
| 
 | ||||
| 	/// Converts a path relative to the directory held by the object into an absolute one.
 | ||||
| 	std::string memberPath(std::string const& _relativePath) const; | ||||
| 
 | ||||
| private: | ||||
| 	std::string m_path; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										95
									
								
								test/TemporaryDirectoryTest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								test/TemporaryDirectoryTest.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,95 @@ | ||||
| /*
 | ||||
| 	This file is part of solidity. | ||||
| 
 | ||||
| 	solidity is free software: you can redistribute it and/or modify | ||||
| 	it under the terms of the GNU General Public License as published by | ||||
| 	the Free Software Foundation, either version 3 of the License, or | ||||
| 	(at your option) any later version. | ||||
| 
 | ||||
| 	solidity is distributed in the hope that it will be useful, | ||||
| 	but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| 	GNU General Public License for more details. | ||||
| 
 | ||||
| 	You should have received a copy of the GNU General Public License | ||||
| 	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| // SPDX-License-Identifier: GPL-3.0
 | ||||
| 
 | ||||
| #include <test/TemporaryDirectory.h> | ||||
| 
 | ||||
| #include <boost/filesystem.hpp> | ||||
| #include <boost/test/unit_test.hpp> | ||||
| 
 | ||||
| #include <fstream> | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace boost::test_tools; | ||||
| 
 | ||||
| namespace fs = boost::filesystem; | ||||
| 
 | ||||
| namespace solidity::test | ||||
| { | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE(TemporaryDirectoryTest) | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(TemporaryDirectory_should_create_and_delete_a_unique_and_empty_directory) | ||||
| { | ||||
| 	fs::path dirPath; | ||||
| 	{ | ||||
| 		TemporaryDirectory tempDir("temporary-directory-test-"); | ||||
| 		dirPath = tempDir.path(); | ||||
| 
 | ||||
| 		BOOST_TEST(dirPath.stem().string().find("temporary-directory-test-") == 0); | ||||
| 		BOOST_TEST(fs::equivalent(dirPath.parent_path(), fs::temp_directory_path())); | ||||
| 		BOOST_TEST(fs::is_directory(dirPath)); | ||||
| 		BOOST_TEST(fs::is_empty(dirPath)); | ||||
| 	} | ||||
| 	BOOST_TEST(!fs::exists(dirPath)); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(TemporaryDirectory_should_delete_its_directory_even_if_not_empty) | ||||
| { | ||||
| 	fs::path dirPath; | ||||
| 	{ | ||||
| 		TemporaryDirectory tempDir("temporary-directory-test-"); | ||||
| 		dirPath = tempDir.path(); | ||||
| 
 | ||||
| 		BOOST_TEST(fs::is_directory(dirPath)); | ||||
| 
 | ||||
| 		{ | ||||
| 			ofstream tmpFile((dirPath / "test-file.txt").string()); | ||||
| 			tmpFile << "Delete me!" << endl; | ||||
| 		} | ||||
| 		assert(fs::is_regular_file(dirPath / "test-file.txt")); | ||||
| 	} | ||||
| 	BOOST_TEST(!fs::exists(dirPath / "test-file.txt")); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(TemporaryDirectory_memberPath_should_construct_paths_relative_to_the_temporary_directory) | ||||
| { | ||||
| 	TemporaryDirectory tempDir("temporary-directory-test-"); | ||||
| 
 | ||||
| 	BOOST_TEST(fs::equivalent(tempDir.memberPath(""), tempDir.path())); | ||||
| 	BOOST_TEST(fs::equivalent(tempDir.memberPath("."), tempDir.path() / fs::path("."))); | ||||
| 	BOOST_TEST(fs::equivalent(tempDir.memberPath(".."), tempDir.path() / fs::path(".."))); | ||||
| 
 | ||||
| 	// NOTE: fs::equivalent() only works with paths that actually exist
 | ||||
| 	{ | ||||
| 		ofstream file; | ||||
| 		file.open(tempDir.memberPath("file.txt"), ios::out); | ||||
| 	} | ||||
| 	BOOST_TEST(fs::equivalent(tempDir.memberPath("file.txt"), tempDir.path() / fs::path("file.txt"))); | ||||
| 
 | ||||
| 	{ | ||||
| 		fs::create_directories(tempDir.memberPath("a/b/")); | ||||
| 
 | ||||
| 		ofstream file; | ||||
| 		file.open(tempDir.memberPath("a/b/file.txt"), ios::out); | ||||
| 	} | ||||
| 	BOOST_TEST(fs::equivalent(tempDir.memberPath("a/b/file.txt"), tempDir.path() / fs::path("a") / fs::path("b") / fs::path("file.txt"))); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
| 
 | ||||
| } | ||||
| @ -16,6 +16,7 @@ | ||||
| */ | ||||
| // SPDX-License-Identifier: GPL-3.0
 | ||||
| 
 | ||||
| #include <test/TemporaryDirectory.h> | ||||
| #include <test/yulPhaser/TestHelpers.h> | ||||
| 
 | ||||
| #include <tools/yulPhaser/AlgorithmRunner.h> | ||||
| @ -37,6 +38,7 @@ using namespace std; | ||||
| using namespace boost::unit_test::framework; | ||||
| using namespace boost::test_tools; | ||||
| using namespace solidity::langutil; | ||||
| using namespace solidity::test; | ||||
| using namespace solidity::util; | ||||
| using namespace solidity::yul; | ||||
| 
 | ||||
|  | ||||
| @ -16,6 +16,7 @@ | ||||
| */ | ||||
| // SPDX-License-Identifier: GPL-3.0
 | ||||
| 
 | ||||
| #include <test/TemporaryDirectory.h> | ||||
| #include <test/yulPhaser/TestHelpers.h> | ||||
| 
 | ||||
| #include <tools/yulPhaser/Common.h> | ||||
| @ -31,6 +32,7 @@ | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace boost::test_tools; | ||||
| using namespace solidity::test; | ||||
| using namespace solidity::util; | ||||
| 
 | ||||
| namespace solidity::phaser::test | ||||
|  | ||||
| @ -16,6 +16,7 @@ | ||||
| */ | ||||
| // SPDX-License-Identifier: GPL-3.0
 | ||||
| 
 | ||||
| #include <test/TemporaryDirectory.h> | ||||
| #include <test/yulPhaser/TestHelpers.h> | ||||
| 
 | ||||
| #include <tools/yulPhaser/Exceptions.h> | ||||
| @ -31,6 +32,7 @@ | ||||
| #include <algorithm> | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace solidity::test; | ||||
| using namespace solidity::util; | ||||
| using namespace solidity::langutil; | ||||
| using namespace solidity::yul; | ||||
|  | ||||
| @ -20,10 +20,7 @@ | ||||
| 
 | ||||
| #include <libyul/optimiser/Suite.h> | ||||
| 
 | ||||
| #include <boost/filesystem.hpp> | ||||
| 
 | ||||
| #include <regex> | ||||
| #include <iostream> | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace solidity; | ||||
| @ -31,8 +28,6 @@ using namespace solidity::yul; | ||||
| using namespace solidity::phaser; | ||||
| using namespace solidity::phaser::test; | ||||
| 
 | ||||
| namespace fs = boost::filesystem; | ||||
| 
 | ||||
| function<Mutation> phaser::test::wholeChromosomeReplacement(Chromosome _newChromosome) | ||||
| { | ||||
| 	return [_newChromosome = move(_newChromosome)](Chromosome const&) { return _newChromosome; }; | ||||
| @ -82,40 +77,6 @@ size_t phaser::test::countDifferences(Chromosome const& _chromosome1, Chromosome | ||||
| 	)); | ||||
| } | ||||
| 
 | ||||
| TemporaryDirectory::TemporaryDirectory(std::string const& _prefix): | ||||
| 	m_path((fs::temp_directory_path() / fs::unique_path(_prefix + "%%%%-%%%%-%%%%-%%%%")).string()) | ||||
| { | ||||
| 	// Prefix should just be a file name and not contain anything that would make us step out of /tmp.
 | ||||
| 	assert(fs::path(_prefix) == fs::path(_prefix).stem()); | ||||
| 
 | ||||
| 	fs::create_directory(m_path); | ||||
| } | ||||
| 
 | ||||
| TemporaryDirectory::~TemporaryDirectory() | ||||
| { | ||||
| 	// A few paranoid sanity checks just to be extra sure we're not deleting someone's homework.
 | ||||
| 	assert(m_path.find(fs::temp_directory_path().string()) == 0); | ||||
| 	assert(fs::path(m_path) != fs::temp_directory_path()); | ||||
| 	assert(fs::path(m_path) != fs::path(m_path).root_path()); | ||||
| 	assert(!fs::path(m_path).empty()); | ||||
| 
 | ||||
| 	boost::system::error_code errorCode; | ||||
| 	uintmax_t numRemoved = fs::remove_all(m_path, errorCode); | ||||
| 	if (errorCode.value() != boost::system::errc::success) | ||||
| 	{ | ||||
| 		cerr << "Failed to completely remove temporary directory '" << m_path << "'. "; | ||||
| 		cerr << "Only " << numRemoved << " files were actually removed." << endl; | ||||
| 		cerr << "Reason: " << errorCode.message() << endl; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| string TemporaryDirectory::memberPath(string const& _relativePath) const | ||||
| { | ||||
| 	assert(fs::path(_relativePath).is_relative()); | ||||
| 
 | ||||
| 	return (fs::path(m_path) / _relativePath).string(); | ||||
| } | ||||
| 
 | ||||
| string phaser::test::stripWhitespace(string const& input) | ||||
| { | ||||
| 	regex whitespaceRegex("\\s+"); | ||||
|  | ||||
| @ -107,31 +107,6 @@ size_t countDifferences(Chromosome const& _chromosome1, Chromosome const& _chrom | ||||
| /// integers.
 | ||||
| std::map<std::string, size_t> enumerateOptmisationSteps(); | ||||
| 
 | ||||
| // FILESYSTEM UTILITIES
 | ||||
| 
 | ||||
| /**
 | ||||
|  * An object that creates a unique temporary directory and automatically deletes it and its | ||||
|  * content upon being destroyed. | ||||
|  * | ||||
|  * The directory is guaranteed to be newly created and empty. Directory names are generated | ||||
|  * randomly. If a directory with the same name already exists (very unlikely but possible) the | ||||
|  * object won't reuse it and will fail with an exception instead. | ||||
|  */ | ||||
| class TemporaryDirectory | ||||
| { | ||||
| public: | ||||
| 	TemporaryDirectory(std::string const& _prefix = "yul-phaser-test-"); | ||||
| 	~TemporaryDirectory(); | ||||
| 
 | ||||
| 	std::string const& path() const { return m_path; } | ||||
| 
 | ||||
| 	/// Converts a path relative to the directory held by the object into an absolute one.
 | ||||
| 	std::string memberPath(std::string const& _relativePath) const; | ||||
| 
 | ||||
| private: | ||||
| 	std::string m_path; | ||||
| }; | ||||
| 
 | ||||
| // STRING UTILITIES
 | ||||
| 
 | ||||
| /// Returns the input string with all the whitespace characters (spaces, line endings, etc.) removed.
 | ||||
|  | ||||
| @ -20,18 +20,14 @@ | ||||
| 
 | ||||
| #include <libyul/optimiser/Suite.h> | ||||
| 
 | ||||
| #include <boost/filesystem.hpp> | ||||
| #include <boost/test/unit_test.hpp> | ||||
| 
 | ||||
| #include <fstream> | ||||
| #include <set> | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace solidity::yul; | ||||
| using namespace boost::test_tools; | ||||
| 
 | ||||
| namespace fs = boost::filesystem; | ||||
| 
 | ||||
| namespace solidity::phaser::test | ||||
| { | ||||
| 
 | ||||
| @ -119,63 +115,6 @@ BOOST_AUTO_TEST_CASE(enumerateOptimisationSteps_should_assing_indices_to_all_ava | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(TemporaryDirectory_should_create_and_delete_a_unique_and_empty_directory) | ||||
| { | ||||
| 	fs::path dirPath; | ||||
| 	{ | ||||
| 		TemporaryDirectory tempDir("temporary-directory-test-"); | ||||
| 		dirPath = tempDir.path(); | ||||
| 
 | ||||
| 		BOOST_TEST(dirPath.stem().string().find("temporary-directory-test-") == 0); | ||||
| 		BOOST_TEST(fs::equivalent(dirPath.parent_path(), fs::temp_directory_path())); | ||||
| 		BOOST_TEST(fs::is_directory(dirPath)); | ||||
| 		BOOST_TEST(fs::is_empty(dirPath)); | ||||
| 	} | ||||
| 	BOOST_TEST(!fs::exists(dirPath)); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(TemporaryDirectory_should_delete_its_directory_even_if_not_empty) | ||||
| { | ||||
| 	fs::path dirPath; | ||||
| 	{ | ||||
| 		TemporaryDirectory tempDir("temporary-directory-test-"); | ||||
| 		dirPath = tempDir.path(); | ||||
| 
 | ||||
| 		BOOST_TEST(fs::is_directory(dirPath)); | ||||
| 
 | ||||
| 		{ | ||||
| 			ofstream tmpFile((dirPath / "test-file.txt").string()); | ||||
| 			tmpFile << "Delete me!" << endl; | ||||
| 		} | ||||
| 		assert(fs::is_regular_file(dirPath / "test-file.txt")); | ||||
| 	} | ||||
| 	BOOST_TEST(!fs::exists(dirPath / "test-file.txt")); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(TemporaryDirectory_memberPath_should_construct_paths_relative_to_the_temporary_directory) | ||||
| { | ||||
| 	TemporaryDirectory tempDir("temporary-directory-test-"); | ||||
| 
 | ||||
| 	BOOST_TEST(fs::equivalent(tempDir.memberPath(""), tempDir.path())); | ||||
| 	BOOST_TEST(fs::equivalent(tempDir.memberPath("."), tempDir.path() / fs::path("."))); | ||||
| 	BOOST_TEST(fs::equivalent(tempDir.memberPath(".."), tempDir.path() / fs::path(".."))); | ||||
| 
 | ||||
| 	// NOTE: fs::equivalent() only works with paths that actually exist
 | ||||
| 	{ | ||||
| 		ofstream file; | ||||
| 		file.open(tempDir.memberPath("file.txt"), ios::out); | ||||
| 	} | ||||
| 	BOOST_TEST(fs::equivalent(tempDir.memberPath("file.txt"), tempDir.path() / fs::path("file.txt"))); | ||||
| 
 | ||||
| 	{ | ||||
| 		fs::create_directories(tempDir.memberPath("a/b/")); | ||||
| 
 | ||||
| 		ofstream file; | ||||
| 		file.open(tempDir.memberPath("a/b/file.txt"), ios::out); | ||||
| 	} | ||||
| 	BOOST_TEST(fs::equivalent(tempDir.memberPath("a/b/file.txt"), tempDir.path() / fs::path("a") / fs::path("b") / fs::path("file.txt"))); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(stripWhitespace_should_remove_all_whitespace_characters_from_a_string) | ||||
| { | ||||
| 	BOOST_TEST(stripWhitespace("") == ""); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user