Make descriptor test deterministic

Changed MaybeUseHInsteadOfApostrophy to UseHInsteadOfApostrophe.
This function now always replaces apostrophes with 'h'.
The original Check function was renamed to DoCheck and it's
called with an additional parameter which tells it to either
leave the prv and pub arguments as is or replace the apostrophes
with 'h'. The test runs with apostrophes replaced in prv only,
pub only, prv and pub and without replacement at all. Replacement
of apostrophes in a descriptor and then running DoCheck is conditional
on whether apostrophes are found in that descriptor.

Additionally, instead of dropping the checksum recalculate it
after replacing apostrophes with 'h' in the function UseHInsteadOfApostrophe
using the GetDescriptorChecksum function. That way, this also
introduces an indirect unit test to GetDescriptoChecksum.
This commit is contained in:
David Reikher 2019-08-07 14:50:48 +03:00
parent 48e5bfe224
commit b9ee63c71b

View file

@ -42,33 +42,47 @@ bool EqualDescriptor(std::string a, std::string b)
return a == b; return a == b;
} }
std::string MaybeUseHInsteadOfApostrophy(std::string ret) std::string UseHInsteadOfApostrophe(const std::string& desc)
{ {
if (InsecureRandBool()) { std::string ret = desc;
while (true) { while (true) {
auto it = ret.find("'"); auto it = ret.find('\'');
if (it != std::string::npos) { if (it == std::string::npos) break;
ret[it] = 'h'; ret[it] = 'h';
if (ret.size() > 9 && ret[ret.size() - 9] == '#') ret = ret.substr(0, ret.size() - 9); // Changing apostrophe to h breaks the checksum }
} else {
break; // GetDescriptorChecksum returns "" if the checksum exists but is bad.
} // Switching apostrophes with 'h' breaks the checksum if it exists - recalculate it and replace the broken one.
} if (GetDescriptorChecksum(ret) == "") {
ret = ret.substr(0, desc.size() - 9);
ret += std::string("#") + GetDescriptorChecksum(ret);
} }
return ret; return ret;
} }
const std::set<std::vector<uint32_t>> ONLY_EMPTY{{}}; const std::set<std::vector<uint32_t>> ONLY_EMPTY{{}};
void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY) void DoCheck(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY,
bool replace_apostrophe_with_h_in_prv=false, bool replace_apostrophe_with_h_in_pub=false)
{ {
FlatSigningProvider keys_priv, keys_pub; FlatSigningProvider keys_priv, keys_pub;
std::set<std::vector<uint32_t>> left_paths = paths; std::set<std::vector<uint32_t>> left_paths = paths;
std::string error; std::string error;
std::unique_ptr<Descriptor> parse_priv;
std::unique_ptr<Descriptor> parse_pub;
// Check that parsing succeeds. // Check that parsing succeeds.
auto parse_priv = Parse(MaybeUseHInsteadOfApostrophy(prv), keys_priv, error); if (replace_apostrophe_with_h_in_prv) {
auto parse_pub = Parse(MaybeUseHInsteadOfApostrophy(pub), keys_pub, error); parse_priv = Parse(UseHInsteadOfApostrophe(prv), keys_priv, error);
} else {
parse_priv = Parse(prv, keys_priv, error);
}
if (replace_apostrophe_with_h_in_pub) {
parse_pub = Parse(UseHInsteadOfApostrophe(pub), keys_pub, error);
} else {
parse_pub = Parse(pub, keys_pub, error);
}
BOOST_CHECK(parse_priv); BOOST_CHECK(parse_priv);
BOOST_CHECK(parse_pub); BOOST_CHECK(parse_pub);
@ -167,6 +181,32 @@ void Check(const std::string& prv, const std::string& pub, int flags, const std:
BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv); BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv);
} }
void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY)
{
bool found_apostrophes_in_prv = false;
bool found_apostrophes_in_pub = false;
// Do not replace apostrophes with 'h' in prv and pub
DoCheck(prv, pub, flags, scripts, paths);
// Replace apostrophes with 'h' in prv but not in pub, if apostrophes are found in prv
if (prv.find('\'') != std::string::npos) {
found_apostrophes_in_prv = true;
DoCheck(prv, pub, flags, scripts, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */false);
}
// Replace apostrophes with 'h' in pub but not in prv, if apostrophes are found in pub
if (pub.find('\'') != std::string::npos) {
found_apostrophes_in_pub = true;
DoCheck(prv, pub, flags, scripts, paths, /* replace_apostrophe_with_h_in_prv = */false, /*replace_apostrophe_with_h_in_pub = */true);
}
// Replace apostrophes with 'h' both in prv and in pub, if apostrophes are found in both
if (found_apostrophes_in_prv && found_apostrophes_in_pub) {
DoCheck(prv, pub, flags, scripts, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */true);
}
}
} }
BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup) BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup)