forked from Bitcoin-ABC/bitcoin-abc
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
torcontrol: Add unit tests for Tor reply parsers
- Loading branch information
Showing
2 changed files
with
169 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// Copyright (c) 2017 The Zcash developers | ||
// Distributed under the MIT software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
// | ||
#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 (which are left escaped by the parser) | ||
CheckParseTorReplyMapping( | ||
"Foo=\"Bar\\ Baz\"", { | ||
{"Foo", "Bar\\ Baz"}, | ||
}); | ||
CheckParseTorReplyMapping( | ||
"Foo=\"Bar\\Baz\"", { | ||
{"Foo", "Bar\\Baz"}, | ||
}); | ||
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"}, | ||
}); | ||
|
||
// 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() |