From 1945410ceb383d5a43fb82bcbcf0a611b99b0bbc Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Tue, 26 Nov 2019 17:16:33 +0300 Subject: [PATCH] safely parse files from json/yaml --- retesteth/TestHelper.cpp | 40 +++++++++++++++++++++++++++++++- retesteth/TestHelper.h | 5 ++++ retesteth/TestSuite.cpp | 20 ++++------------ retesteth/configs/ClientConfig.h | 5 ++-- retesteth/configs/Options.cpp | 8 +++---- 5 files changed, 53 insertions(+), 25 deletions(-) diff --git a/retesteth/TestHelper.cpp b/retesteth/TestHelper.cpp index f4c58217c..135958237 100644 --- a/retesteth/TestHelper.cpp +++ b/retesteth/TestHelper.cpp @@ -10,9 +10,11 @@ #include #include +#include #include #include -#include +#include +#include using namespace std; namespace fs = boost::filesystem; @@ -37,6 +39,42 @@ Json::Value readJson(fs::path const& _file) } #endif +/// Safely read the json file into DataObject +DataObject readJsonData(fs::path const& _file, string const& _stopper, bool _autosort) +{ + try + { + string s = dev::contentsString(_file); + ETH_ERROR_REQUIRE_MESSAGE(s.length() > 0, + "Contents of " + _file.string() + " is empty. Trying to parse empty file."); + return dataobject::ConvertJsoncppStringToData(s, _stopper, _autosort); + } + catch (std::exception const& _ex) + { + ETH_ERROR_MESSAGE( + string("\nError when parsing file (") + _file.c_str() + ") " + _ex.what()); + return DataObject(); + } +} + +/// Safely read the yaml file into DataObject +DataObject readYamlData(fs::path const& _file) +{ + try + { + string s = dev::contentsString(_file); + ETH_ERROR_REQUIRE_MESSAGE(s.length() > 0, + "Contents of " + _file.string() + " is empty. Trying to parse empty file."); + return dataobject::ConvertYamlToData(YAML::Load(s)); + } + catch (std::exception const& _ex) + { + ETH_ERROR_MESSAGE( + string("\nError when parsing file (") + _file.c_str() + ") " + _ex.what()); + return DataObject(); + } +} + vector getFiles( fs::path const& _dirPath, set const _extentionMask, string const& _particularFile) { diff --git a/retesteth/TestHelper.h b/retesteth/TestHelper.h index ef572fce3..751a25136 100644 --- a/retesteth/TestHelper.h +++ b/retesteth/TestHelper.h @@ -20,6 +20,11 @@ namespace test { Json::Value readJson(fs::path const& _path); #endif +/// Safely read the json file into DataObject +DataObject readJsonData( + fs::path const& _file, string const& _stopper = string(), bool _autosort = false); +DataObject readYamlData(fs::path const& _file); + /// Get files from directory std::vector getFiles(boost::filesystem::path const& _dirPath, std::set _extentionMask, std::string const& _particularFile = {}); diff --git a/retesteth/TestSuite.cpp b/retesteth/TestSuite.cpp index 39a7d1084..4f824546a 100644 --- a/retesteth/TestSuite.cpp +++ b/retesteth/TestSuite.cpp @@ -18,8 +18,6 @@ * Base functions for all test suites */ -#include -#include #include #include #include @@ -51,16 +49,10 @@ struct TestFileData TestFileData readTestFile(fs::path const& _testFileName) { TestFileData testData; - - // Check that file is not empty - string const s = dev::contentsString(_testFileName); - ETH_ERROR_REQUIRE_MESSAGE( - s.length() > 0, "Contents of " + _testFileName.string() + " is empty."); - if (_testFileName.extension() == ".json") - testData.data = dataobject::ConvertJsoncppStringToData(s, string(), true); + testData.data = test::readJsonData(_testFileName, string(), true); else if (_testFileName.extension() == ".yml") - testData.data = dataobject::ConvertYamlToData(YAML::Load(s)); + testData.data = test::readYamlData(_testFileName); else ETH_ERROR_MESSAGE( "Unknown test format!" + test::TestOutputHelper::get().testFile().string()); @@ -142,8 +134,7 @@ void addClientInfo( void checkFillerHash(fs::path const& _compiledTest, fs::path const& _sourceTest) { - dataobject::DataObject v = - dataobject::ConvertJsoncppStringToData(dev::contentsString(_compiledTest), "_info"); + dataobject::DataObject v = test::readJsonData(_compiledTest, "_info"); TestFileData fillerData = readTestFile(_sourceTest); for (auto const& i: v.getSubObjects()) { @@ -525,10 +516,7 @@ void TestSuite::executeTest(string const& _testFolder, fs::path const& _testFile void TestSuite::executeFile(boost::filesystem::path const& _file) const { TestSuiteOptions opt; - std::string s = dev::contentsString(_file); - ETH_ERROR_REQUIRE_MESSAGE( - s.length() > 0, "Contents of " + _file.string() + " is empty. Have you filled the test?"); - doTests(dataobject::ConvertJsoncppStringToData(s), opt); + doTests(test::readJsonData(_file), opt); } } diff --git a/retesteth/configs/ClientConfig.h b/retesteth/configs/ClientConfig.h index b8319da45..f1e25f766 100644 --- a/retesteth/configs/ClientConfig.h +++ b/retesteth/configs/ClientConfig.h @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include #include #include @@ -111,8 +111,7 @@ class ClientConfig : public object std::vector const& getAdditionalNetworks() const { return m_additional_networks; } void addGenesisTemplate(string const& _network, fs::path const& _pathToJson) { - string s = dev::contentsString(_pathToJson); - m_genesisTemplate[_network] = dataobject::ConvertJsoncppStringToData(s); + m_genesisTemplate[_network] = test::readJsonData(_pathToJson); } DataObject const& getGenesisTemplate(string const& _network) const { diff --git a/retesteth/configs/Options.cpp b/retesteth/configs/Options.cpp index c60ce2bcc..75463771f 100644 --- a/retesteth/configs/Options.cpp +++ b/retesteth/configs/Options.cpp @@ -18,7 +18,6 @@ void deployFirstRunConfigs() if (!fs::exists(homeDir / "version")) return; string version = dev::contentsString(homeDir / "version"); - version = version.substr(0, version.length() - 1); // new line char if (version != string(ETH_PROJECT_VERSION)) ETH_WARNING("Retesteth configs version is different (running: '" + string(ETH_PROJECT_VERSION) + "' vs config '" + version + @@ -113,8 +112,8 @@ std::vector const& Options::DynamicOptions::getClientConfigs() fs::path configFilePath = configPath / "config"; ETH_FAIL_REQUIRE_MESSAGE(fs::exists(configFilePath), string("Client config not found: ") + configFilePath.c_str()); - string s = dev::contentsString(configFilePath); - ClientConfig cfg(dataobject::ConvertJsoncppStringToData(s), ClientConfigID(), + + ClientConfig cfg(test::readJsonData(configFilePath), ClientConfigID(), configPath / string(clientName + ".sh")); // Load genesis templates @@ -129,8 +128,7 @@ std::vector const& Options::DynamicOptions::getClientConfigs() fs::path correctMiningRewardPath = genesisTemplatePath / "correctMiningReward.json"; ETH_FAIL_REQUIRE_MESSAGE(fs::exists(correctMiningRewardPath), "correctMiningReward.json client config not found!"); - s = dev::contentsString(correctMiningRewardPath); - cfg.setMiningRewardInfo(dataobject::ConvertJsoncppStringToData(s)); + cfg.setMiningRewardInfo(test::readJsonData(correctMiningRewardPath)); cfg.setCorrectMiningRewardFilePath(correctMiningRewardPath); auto registerGenesisTemplate = [&cfg, &genesisTemplatePath, &clientName](