Skip to content

Commit

Permalink
Config test uses unique directories for each test:
Browse files Browse the repository at this point in the history
* This fixes an uncommon, but annoying, spurious failure running this
  test, particularly in release builds. This appears to be an issue with
  Windows of the FS where quickly creating and deleting the same
  directory repeatedly will eventually fail.
* RIPD-1390
  • Loading branch information
ximinez committed Feb 1, 2017
1 parent c218417 commit 76eaab6
Showing 1 changed file with 75 additions and 52 deletions.
127 changes: 75 additions & 52 deletions src/test/core/Config_test.cpp
Expand Up @@ -144,12 +144,16 @@ class ConfigGuard
};

public:
ConfigGuard (beast::unit_test::suite& test, std::string subDir)
ConfigGuard (beast::unit_test::suite& test, path subDir,
bool useCounter = true)
: subDir_ (std::move (subDir))
, test_ (test)
{
using namespace boost::filesystem;
{
static auto subDirCounter = 0;
if (useCounter)
subDir_ += to_string(++subDirCounter);
if (!exists (subDir_))
{
create_directory (subDir_);
Expand All @@ -166,6 +170,7 @@ class ConfigGuard
}
}
}

~ConfigGuard ()
{
try
Expand All @@ -184,12 +189,17 @@ class ConfigGuard
test_.log << "Error in ~ConfigGuard: " << e.what () << std::endl;
};
}

path const& subdir() const
{
return subDir_;
}
};

/**
Write a rippled config file and remove when done.
*/
class RippledCfgGuard : ConfigGuard
class RippledCfgGuard : public ConfigGuard
{
private:
path configFile_;
Expand All @@ -201,9 +211,11 @@ class RippledCfgGuard : ConfigGuard

public:
RippledCfgGuard (beast::unit_test::suite& test,
std::string subDir, std::string const& dbPath,
std::string const& validatorsFile)
: ConfigGuard (test, std::move (subDir)), dataDir_ (dbPath)
path subDir, path const& dbPath,
path const& validatorsFile,
bool useCounter = true)
: ConfigGuard (test, std::move (subDir), useCounter)
, dataDir_ (dbPath)
{
if (dbPath.empty ())
dataDir_ = subDir_ / path (Config::databaseDirName);
Expand All @@ -213,7 +225,7 @@ class RippledCfgGuard : ConfigGuard
if (!exists (configFile_))
{
std::ofstream o (configFile_.string ());
o << configContents (dbPath, validatorsFile);
o << configContents (dbPath.string (), validatorsFile.string ());
}
else
{
Expand All @@ -223,25 +235,30 @@ class RippledCfgGuard : ConfigGuard
}

rmDataDir_ = !exists (dataDir_);
config_.setup (configFile_.string (), /*bQuiet*/ false,
config_.setup (configFile_.string (), /*bQuiet*/ true,
/* bSilent */ false, /* bStandalone */ false);
}
Config& config ()

Config const& config () const
{
return config_;
}

std::string configFile() const
{
return configFile_.string();
}

bool dataDirExists () const
{
return boost::filesystem::is_directory (dataDir_);
}

bool configFileExists () const
{
return boost::filesystem::exists (configFile_);
}

~RippledCfgGuard ()
{
try
Expand All @@ -251,7 +268,7 @@ class RippledCfgGuard : ConfigGuard
test_.log << "Expected " << configFile_.string ()
<< " to be an existing file." << std::endl;
else
remove (configFile_.string ());
remove (configFile_);

if (rmDataDir_)
rmDir (dataDir_);
Expand Down Expand Up @@ -296,16 +313,16 @@ nHUPDdcdb2Y5DZAJne4c2iabFuAP3F34xZUgYQT2NH7qfkdapgnz
/**
Write a validators.txt file and remove when done.
*/
class ValidatorsTxtGuard : ConfigGuard
class ValidatorsTxtGuard : public ConfigGuard
{
private:
path validatorsFile_;

public:
ValidatorsTxtGuard (beast::unit_test::suite& test,
std::string subDir, std::string const& validatorsFileName,
boost::optional<int> const& quorum)
: ConfigGuard (test, std::move (subDir))
path subDir, path const& validatorsFileName,
boost::optional<int> const& quorum, bool useCounter = true)
: ConfigGuard (test, std::move (subDir), useCounter)
{
using namespace boost::filesystem;
validatorsFile_ = current_path () / subDir_ / path (
Expand All @@ -324,14 +341,17 @@ class ValidatorsTxtGuard : ConfigGuard
validatorsFile_.string ());
}
}

bool validatorsFileExists () const
{
return boost::filesystem::exists (validatorsFile_);
}

std::string validatorsFile () const
{
return validatorsFile_.string ();
}

~ValidatorsTxtGuard ()
{
try
Expand All @@ -341,7 +361,7 @@ class ValidatorsTxtGuard : ConfigGuard
test_.log << "Expected " << validatorsFile_.string ()
<< " to be an existing file." << std::endl;
else
remove (validatorsFile_.string ());
remove (validatorsFile_);
}
catch (std::exception& e)
{
Expand Down Expand Up @@ -422,30 +442,32 @@ port_wss_admin
{
// read from file absolute path
auto const cwd = current_path ();
detail::ConfigGuard const g0(*this, "test_db");
path const dataDirRel ("test_data_dir");
path const dataDirAbs (cwd / path ("test_db") / dataDirRel);
detail::RippledCfgGuard g (*this, "test_db", dataDirAbs.string (), "");
auto& c (g.config ());
path const dataDirAbs(cwd / g0.subdir () / dataDirRel);
detail::RippledCfgGuard const g (*this, g0.subdir(),
dataDirAbs, "", false);
auto const& c (g.config ());
BEAST_EXPECT(g.dataDirExists ());
BEAST_EXPECT(g.configFileExists ());
BEAST_EXPECT(c.legacy ("database_path") == dataDirAbs.string ());
}
{
// read from file relative path
std::string const dbPath ("my_db");
detail::RippledCfgGuard g (*this, "test_db", dbPath, "");
auto& c (g.config ());
detail::RippledCfgGuard const g (*this, "test_db", dbPath, "");
auto const& c (g.config ());
std::string const nativeDbPath = absolute (path (dbPath)).string ();
BEAST_EXPECT(g.dataDirExists ());
BEAST_EXPECT(g.configFileExists ());
BEAST_EXPECT(c.legacy ("database_path") == nativeDbPath);
}
{
// read from file no path
detail::RippledCfgGuard g (*this, "test_db", "", "");
auto& c (g.config ());
detail::RippledCfgGuard const g (*this, "test_db", "", "");
auto const& c (g.config ());
std::string const nativeDbPath =
absolute (path ("test_db") /
absolute (g.subdir () /
path (Config::databaseDirName))
.string ();
BEAST_EXPECT(g.dataDirExists ());
Expand All @@ -461,14 +483,14 @@ port_wss_admin
using namespace boost::filesystem;
{
// load should throw for missing specified validators file
Config c;
boost::format cc ("[validators_file]\n%1%\n");
std::string error;
std::string const missingPath = "/no/way/this/path/exists";
auto const expectedError =
"The file specified in [validators_file] does not exist: " +
missingPath;
try {
Config c;
c.loadFromString (boost::str (cc % missingPath));
} catch (std::runtime_error& e) {
error = e.what();
Expand All @@ -478,16 +500,16 @@ port_wss_admin
{
// load should throw for invalid [validators_file]
int const quorum = 3;
detail::ValidatorsTxtGuard vtg (
detail::ValidatorsTxtGuard const vtg (
*this, "test_cfg", "validators.cfg", quorum);
Config c;
path const invalidFile = current_path () / "test_cfg";
path const invalidFile = current_path () / vtg.subdir ();
boost::format cc ("[validators_file]\n%1%\n");
std::string error;
auto const expectedError =
"Invalid file specified in [validators_file]: " +
invalidFile.string ();
try {
Config c;
c.loadFromString (boost::str (cc % invalidFile.string ()));
} catch (std::runtime_error& e) {
error = e.what();
Expand Down Expand Up @@ -519,7 +541,7 @@ nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
{
// load from specified [validators_file] absolute path
int const quorum = 3;
detail::ValidatorsTxtGuard vtg (
detail::ValidatorsTxtGuard const vtg (
*this, "test_cfg", "validators.cfg", quorum);
BEAST_EXPECT(vtg.validatorsFileExists ());
Config c;
Expand All @@ -535,13 +557,13 @@ nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
// in config directory
int const quorum = 3;
std::string const valFileName = "validators.txt";
detail::ValidatorsTxtGuard vtg (
detail::ValidatorsTxtGuard const vtg (
*this, "test_cfg", valFileName, quorum);
detail::RippledCfgGuard rcg (
*this, "test_cfg", "", valFileName);
detail::RippledCfgGuard const rcg (
*this, vtg.subdir (), "", valFileName, false);
BEAST_EXPECT(vtg.validatorsFileExists ());
BEAST_EXPECT(rcg.configFileExists ());
auto& c (rcg.config ());
auto const& c (rcg.config ());
BEAST_EXPECT(c.legacy ("validators_file") == valFileName);
BEAST_EXPECT(c.section (SECTION_VALIDATORS).values ().size () == 5);
BEAST_EXPECT(c.section (SECTION_VALIDATOR_KEYS).values ().size () == 3);
Expand All @@ -551,14 +573,14 @@ nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
// load from specified [validators_file] relative path
// to config directory
int const quorum = 3;
std::string const valFilePath = "../test_cfg/validators.txt";
detail::ValidatorsTxtGuard vtg (
detail::ValidatorsTxtGuard const vtg (
*this, "test_cfg", "validators.txt", quorum);
detail::RippledCfgGuard rcg (
*this, "test_cfg", "", valFilePath);
auto const valFilePath = ".." / vtg.subdir() / "validators.txt";
detail::RippledCfgGuard const rcg (
*this, vtg.subdir (), "", valFilePath, false);
BEAST_EXPECT(vtg.validatorsFileExists ());
BEAST_EXPECT(rcg.configFileExists ());
auto& c (rcg.config ());
auto const& c (rcg.config ());
BEAST_EXPECT(c.legacy ("validators_file") == valFilePath);
BEAST_EXPECT(c.section (SECTION_VALIDATORS).values ().size () == 5);
BEAST_EXPECT(c.section (SECTION_VALIDATOR_KEYS).values ().size () == 3);
Expand All @@ -567,12 +589,13 @@ nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
{
// load from validators file in default location
int const quorum = 3;
detail::ValidatorsTxtGuard vtg (
detail::ValidatorsTxtGuard const vtg (
*this, "test_cfg", "validators.txt", quorum);
detail::RippledCfgGuard rcg (*this, "test_cfg", "", "");
detail::RippledCfgGuard const rcg (*this, vtg.subdir (),
"", "", false);
BEAST_EXPECT(vtg.validatorsFileExists ());
BEAST_EXPECT(rcg.configFileExists ());
auto& c (rcg.config ());
auto const& c (rcg.config ());
BEAST_EXPECT(c.legacy ("validators_file").empty ());
BEAST_EXPECT(c.section (SECTION_VALIDATORS).values ().size () == 5);
BEAST_EXPECT(c.section (SECTION_VALIDATOR_KEYS).values ().size () == 3);
Expand All @@ -582,16 +605,16 @@ nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
// load from specified [validators_file] instead
// of default location
int const quorum = 3;
detail::ValidatorsTxtGuard vtg (
detail::ValidatorsTxtGuard const vtg (
*this, "test_cfg", "validators.cfg", quorum);
BEAST_EXPECT(vtg.validatorsFileExists ());
detail::ValidatorsTxtGuard vtgDefault (
*this, "test_cfg", "validators.txt", 4);
detail::ValidatorsTxtGuard const vtgDefault (
*this, vtg.subdir (), "validators.txt", 4, false);
BEAST_EXPECT(vtgDefault.validatorsFileExists ());
detail::RippledCfgGuard rcg (
*this, "test_cfg", "", vtg.validatorsFile ());
detail::RippledCfgGuard const rcg (
*this, vtg.subdir (), "", vtg.validatorsFile (), false);
BEAST_EXPECT(rcg.configFileExists ());
auto& c (rcg.config ());
auto const& c (rcg.config ());
BEAST_EXPECT(c.legacy ("validators_file") == vtg.validatorsFile ());
BEAST_EXPECT(c.section (SECTION_VALIDATORS).values ().size () == 5);
BEAST_EXPECT(c.section (SECTION_VALIDATOR_KEYS).values ().size () == 3);
Expand All @@ -607,7 +630,7 @@ nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
4
)rippleConfig");
int const quorum = 3;
detail::ValidatorsTxtGuard vtg (
detail::ValidatorsTxtGuard const vtg (
*this, "test_cfg", "validators.cfg", quorum);
BEAST_EXPECT(vtg.validatorsFileExists ());
Config c;
Expand Down Expand Up @@ -636,7 +659,7 @@ nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB
)rippleConfig");
int const quorum = 3;
detail::ValidatorsTxtGuard vtg (
detail::ValidatorsTxtGuard const vtg (
*this, "test_cfg", "validators.cfg", quorum);
BEAST_EXPECT(vtg.validatorsFileExists ());
Config c;
Expand All @@ -649,10 +672,9 @@ nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB
{
// load should throw if [validators] and [validator_keys] are
// missing from rippled cfg and validators file
Config c;
boost::format cc ("[validators_file]\n%1%\n");
std::string error;
detail::ValidatorsTxtGuard vtg (
detail::ValidatorsTxtGuard const vtg (
*this, "test_cfg", "validators.cfg", boost::none);
BEAST_EXPECT(vtg.validatorsFileExists ());
auto const expectedError =
Expand All @@ -662,6 +684,7 @@ nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB
std::ofstream o (vtg.validatorsFile ());
o << "[validation_quorum]\n3\n";
try {
Config c;
c.loadFromString (boost::str (cc % vtg.validatorsFile ()));
} catch (std::runtime_error& e) {
error = e.what();
Expand All @@ -671,16 +694,16 @@ nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB
{
// load should throw if [validation_quorum] is
// missing from rippled cfg and validators file
Config c;
boost::format cc ("[validators_file]\n%1%\n");
std::string error;
detail::ValidatorsTxtGuard vtg (
detail::ValidatorsTxtGuard const vtg (
*this, "test_cfg", "validators.cfg", boost::none);
BEAST_EXPECT(vtg.validatorsFileExists ());
auto const expectedError =
"The file specified in [validators_file] does not contain a "
"[validation_quorum] section: " + vtg.validatorsFile ();
try {
Config c;
c.loadFromString (boost::str (cc % vtg.validatorsFile ()));
} catch (std::runtime_error& e) {
error = e.what();
Expand All @@ -691,7 +714,7 @@ nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB

void testSetup(bool explicitPath)
{
detail::RippledCfgGuard cfg(*this, "testSetup",
detail::RippledCfgGuard const cfg(*this, "testSetup",
explicitPath ? "test_db" : "", "");
/* ConfigGuard has a Config object that gets loaded on construction,
but Config::setup is not reentrant, so we need a fresh config
Expand Down

0 comments on commit 76eaab6

Please sign in to comment.