Files
dragonx/src/test/torcontrol_tests.cpp
Duke Leto be16f80abc Hush Full Node is now GPLv3
Any projects which want to use Hush code from now on will need to be licensed as
GPLv3 or we will send the lawyers: https://www.softwarefreedom.org/

Notably, Komodo (KMD) is licensed as GPLv2 and is no longer compatible to receive
code changes, without causing legal issues. MIT projects, such as Zcash, also cannot pull
in changes from the Hush Full Node without permission from The Hush Developers,
which may in some circumstances grant an MIT license on a case-by-case basis.
2020-10-21 07:28:10 -04:00

200 lines
7.0 KiB
C++

// Copyright (c) 2017 The Zcash developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
//
#include "test/test_bitcoin.h"
#include "torcontrol.cpp"
#include <boost/test/unit_test.hpp>
BOOST_FIXTURE_TEST_SUITE(torcontrol_tests, BasicTestingSetup)
void CheckSplitTorReplyLine(std::string input, std::string command, std::string args)
{
BOOST_TEST_MESSAGE(std::string("CheckSplitTorReplyLine(") + input + ")");
auto ret = SplitTorReplyLine(input);
BOOST_CHECK_EQUAL(ret.first, command);
BOOST_CHECK_EQUAL(ret.second, args);
}
BOOST_AUTO_TEST_CASE(util_SplitTorReplyLine)
{
// Data we should receive during normal usage
CheckSplitTorReplyLine(
"PROTOCOLINFO PIVERSION",
"PROTOCOLINFO", "PIVERSION");
CheckSplitTorReplyLine(
"AUTH METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"",
"AUTH", "METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"");
CheckSplitTorReplyLine(
"AUTH METHODS=NULL",
"AUTH", "METHODS=NULL");
CheckSplitTorReplyLine(
"AUTH METHODS=HASHEDPASSWORD",
"AUTH", "METHODS=HASHEDPASSWORD");
CheckSplitTorReplyLine(
"VERSION Tor=\"0.2.9.8 (git-a0df013ea241b026)\"",
"VERSION", "Tor=\"0.2.9.8 (git-a0df013ea241b026)\"");
CheckSplitTorReplyLine(
"AUTHCHALLENGE SERVERHASH=aaaa SERVERNONCE=bbbb",
"AUTHCHALLENGE", "SERVERHASH=aaaa SERVERNONCE=bbbb");
// Other valid inputs
CheckSplitTorReplyLine("COMMAND", "COMMAND", "");
CheckSplitTorReplyLine("COMMAND SOME ARGS", "COMMAND", "SOME ARGS");
// These inputs are valid because PROTOCOLINFO accepts an OtherLine that is
// just an OptArguments, which enables multiple spaces to be present
// between the command and arguments.
CheckSplitTorReplyLine("COMMAND ARGS", "COMMAND", " ARGS");
CheckSplitTorReplyLine("COMMAND EVEN+more ARGS", "COMMAND", " EVEN+more ARGS");
}
void CheckParseTorReplyMapping(std::string input, std::map<std::string,std::string> expected)
{
BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(") + input + ")");
auto ret = ParseTorReplyMapping(input);
BOOST_CHECK_EQUAL(ret.size(), expected.size());
auto r_it = ret.begin();
auto e_it = expected.begin();
while (r_it != ret.end() && e_it != expected.end()) {
BOOST_CHECK_EQUAL(r_it->first, e_it->first);
BOOST_CHECK_EQUAL(r_it->second, e_it->second);
r_it++;
e_it++;
}
}
BOOST_AUTO_TEST_CASE(util_ParseTorReplyMapping)
{
// Data we should receive during normal usage
CheckParseTorReplyMapping(
"METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"", {
{"METHODS", "COOKIE,SAFECOOKIE"},
{"COOKIEFILE", "/home/x/.tor/control_auth_cookie"},
});
CheckParseTorReplyMapping(
"METHODS=NULL", {
{"METHODS", "NULL"},
});
CheckParseTorReplyMapping(
"METHODS=HASHEDPASSWORD", {
{"METHODS", "HASHEDPASSWORD"},
});
CheckParseTorReplyMapping(
"Tor=\"0.2.9.8 (git-a0df013ea241b026)\"", {
{"Tor", "0.2.9.8 (git-a0df013ea241b026)"},
});
CheckParseTorReplyMapping(
"SERVERHASH=aaaa SERVERNONCE=bbbb", {
{"SERVERHASH", "aaaa"},
{"SERVERNONCE", "bbbb"},
});
CheckParseTorReplyMapping(
"ServiceID=exampleonion1234", {
{"ServiceID", "exampleonion1234"},
});
CheckParseTorReplyMapping(
"PrivateKey=RSA1024:BLOB", {
{"PrivateKey", "RSA1024:BLOB"},
});
CheckParseTorReplyMapping(
"ClientAuth=bob:BLOB", {
{"ClientAuth", "bob:BLOB"},
});
// Other valid inputs
CheckParseTorReplyMapping(
"Foo=Bar=Baz Spam=Eggs", {
{"Foo", "Bar=Baz"},
{"Spam", "Eggs"},
});
CheckParseTorReplyMapping(
"Foo=\"Bar=Baz\"", {
{"Foo", "Bar=Baz"},
});
CheckParseTorReplyMapping(
"Foo=\"Bar Baz\"", {
{"Foo", "Bar Baz"},
});
// Escapes
CheckParseTorReplyMapping(
"Foo=\"Bar\\ Baz\"", {
{"Foo", "Bar Baz"},
});
CheckParseTorReplyMapping(
"Foo=\"Bar\\Baz\"", {
{"Foo", "BarBaz"},
});
CheckParseTorReplyMapping(
"Foo=\"Bar\\@Baz\"", {
{"Foo", "Bar@Baz"},
});
CheckParseTorReplyMapping(
"Foo=\"Bar\\\"Baz\" Spam=\"\\\"Eggs\\\"\"", {
{"Foo", "Bar\"Baz"},
{"Spam", "\"Eggs\""},
});
CheckParseTorReplyMapping(
"Foo=\"Bar\\\\Baz\"", {
{"Foo", "Bar\\Baz"},
});
// C escapes
CheckParseTorReplyMapping(
"Foo=\"Bar\\nBaz\\t\" Spam=\"\\rEggs\" Octals=\"\\1a\\11\\17\\18\\81\\377\\378\\400\\2222\" Final=Check", {
{"Foo", "Bar\nBaz\t"},
{"Spam", "\rEggs"},
{"Octals", "\1a\11\17\1" "881\377\37" "8\40" "0\222" "2"},
{"Final", "Check"},
});
CheckParseTorReplyMapping(
"Valid=Mapping Escaped=\"Escape\\\\\"", {
{"Valid", "Mapping"},
{"Escaped", "Escape\\"},
});
CheckParseTorReplyMapping(
"Valid=Mapping Bare=\"Escape\\\"", {});
CheckParseTorReplyMapping(
"OneOctal=\"OneEnd\\1\" TwoOctal=\"TwoEnd\\11\"", {
{"OneOctal", "OneEnd\1"},
{"TwoOctal", "TwoEnd\11"},
});
// Special handling for null case
// (needed because string comparison reads the null as end-of-string)
BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(Null=\"\\0\")"));
auto ret = ParseTorReplyMapping("Null=\"\\0\"");
BOOST_CHECK_EQUAL(ret.size(), 1);
auto r_it = ret.begin();
BOOST_CHECK_EQUAL(r_it->first, "Null");
BOOST_CHECK_EQUAL(r_it->second.size(), 1);
BOOST_CHECK_EQUAL(r_it->second[0], '\0');
// A more complex valid grammar. PROTOCOLINFO accepts a VersionLine that
// takes a key=value pair followed by an OptArguments, making this valid.
// Because an OptArguments contains no semantic data, there is no point in
// parsing it.
CheckParseTorReplyMapping(
"SOME=args,here MORE optional=arguments here", {
{"SOME", "args,here"},
});
// Inputs that are effectively invalid under the target grammar.
// PROTOCOLINFO accepts an OtherLine that is just an OptArguments, which
// would make these inputs valid. However,
// - This parser is never used in that situation, because the
// SplitTorReplyLine parser enables OtherLine to be skipped.
// - Even if these were valid, an OptArguments contains no semantic data,
// so there is no point in parsing it.
CheckParseTorReplyMapping("ARGS", {});
CheckParseTorReplyMapping("MORE ARGS", {});
CheckParseTorReplyMapping("MORE ARGS", {});
CheckParseTorReplyMapping("EVEN more=ARGS", {});
CheckParseTorReplyMapping("EVEN+more ARGS", {});
}
BOOST_AUTO_TEST_SUITE_END()