Branch data Line data Source code
# 1 : : // Copyright (c) 2017 The Zcash developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : : //
# 5 : :
# 6 : : #include <boost/test/unit_test.hpp>
# 7 : :
# 8 : : #include <map>
# 9 : : #include <string>
# 10 : : #include <utility>
# 11 : :
# 12 : :
# 13 : : std::pair<std::string, std::string> SplitTorReplyLine(const std::string& s);
# 14 : : std::map<std::string, std::string> ParseTorReplyMapping(const std::string& s);
# 15 : :
# 16 : :
# 17 : : BOOST_AUTO_TEST_SUITE(torcontrol_tests)
# 18 : :
# 19 : : static void CheckSplitTorReplyLine(std::string input, std::string command, std::string args)
# 20 : 20 : {
# 21 : 20 : auto ret = SplitTorReplyLine(input);
# 22 : 20 : BOOST_CHECK_EQUAL(ret.first, command);
# 23 : 20 : BOOST_CHECK_EQUAL(ret.second, args);
# 24 : 20 : }
# 25 : :
# 26 : : BOOST_AUTO_TEST_CASE(util_SplitTorReplyLine)
# 27 : 2 : {
# 28 : : // Data we should receive during normal usage
# 29 : 2 : CheckSplitTorReplyLine(
# 30 : 2 : "PROTOCOLINFO PIVERSION",
# 31 : 2 : "PROTOCOLINFO", "PIVERSION");
# 32 : 2 : CheckSplitTorReplyLine(
# 33 : 2 : "AUTH METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"",
# 34 : 2 : "AUTH", "METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"");
# 35 : 2 : CheckSplitTorReplyLine(
# 36 : 2 : "AUTH METHODS=NULL",
# 37 : 2 : "AUTH", "METHODS=NULL");
# 38 : 2 : CheckSplitTorReplyLine(
# 39 : 2 : "AUTH METHODS=HASHEDPASSWORD",
# 40 : 2 : "AUTH", "METHODS=HASHEDPASSWORD");
# 41 : 2 : CheckSplitTorReplyLine(
# 42 : 2 : "VERSION Tor=\"0.2.9.8 (git-a0df013ea241b026)\"",
# 43 : 2 : "VERSION", "Tor=\"0.2.9.8 (git-a0df013ea241b026)\"");
# 44 : 2 : CheckSplitTorReplyLine(
# 45 : 2 : "AUTHCHALLENGE SERVERHASH=aaaa SERVERNONCE=bbbb",
# 46 : 2 : "AUTHCHALLENGE", "SERVERHASH=aaaa SERVERNONCE=bbbb");
# 47 : :
# 48 : : // Other valid inputs
# 49 : 2 : CheckSplitTorReplyLine("COMMAND", "COMMAND", "");
# 50 : 2 : CheckSplitTorReplyLine("COMMAND SOME ARGS", "COMMAND", "SOME ARGS");
# 51 : :
# 52 : : // These inputs are valid because PROTOCOLINFO accepts an OtherLine that is
# 53 : : // just an OptArguments, which enables multiple spaces to be present
# 54 : : // between the command and arguments.
# 55 : 2 : CheckSplitTorReplyLine("COMMAND ARGS", "COMMAND", " ARGS");
# 56 : 2 : CheckSplitTorReplyLine("COMMAND EVEN+more ARGS", "COMMAND", " EVEN+more ARGS");
# 57 : 2 : }
# 58 : :
# 59 : : static void CheckParseTorReplyMapping(std::string input, std::map<std::string,std::string> expected)
# 60 : 52 : {
# 61 : 52 : auto ret = ParseTorReplyMapping(input);
# 62 : 52 : BOOST_CHECK_EQUAL(ret.size(), expected.size());
# 63 : 52 : auto r_it = ret.begin();
# 64 : 52 : auto e_it = expected.begin();
# 65 [ + + ][ + + ]: 110 : while (r_it != ret.end() && e_it != expected.end()) {
# [ + - ]
# 66 : 58 : BOOST_CHECK_EQUAL(r_it->first, e_it->first);
# 67 : 58 : BOOST_CHECK_EQUAL(r_it->second, e_it->second);
# 68 : 58 : r_it++;
# 69 : 58 : e_it++;
# 70 : 58 : }
# 71 : 52 : }
# 72 : :
# 73 : : BOOST_AUTO_TEST_CASE(util_ParseTorReplyMapping)
# 74 : 2 : {
# 75 : : // Data we should receive during normal usage
# 76 : 2 : CheckParseTorReplyMapping(
# 77 : 2 : "METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"", {
# 78 : 2 : {"METHODS", "COOKIE,SAFECOOKIE"},
# 79 : 2 : {"COOKIEFILE", "/home/x/.tor/control_auth_cookie"},
# 80 : 2 : });
# 81 : 2 : CheckParseTorReplyMapping(
# 82 : 2 : "METHODS=NULL", {
# 83 : 2 : {"METHODS", "NULL"},
# 84 : 2 : });
# 85 : 2 : CheckParseTorReplyMapping(
# 86 : 2 : "METHODS=HASHEDPASSWORD", {
# 87 : 2 : {"METHODS", "HASHEDPASSWORD"},
# 88 : 2 : });
# 89 : 2 : CheckParseTorReplyMapping(
# 90 : 2 : "Tor=\"0.2.9.8 (git-a0df013ea241b026)\"", {
# 91 : 2 : {"Tor", "0.2.9.8 (git-a0df013ea241b026)"},
# 92 : 2 : });
# 93 : 2 : CheckParseTorReplyMapping(
# 94 : 2 : "SERVERHASH=aaaa SERVERNONCE=bbbb", {
# 95 : 2 : {"SERVERHASH", "aaaa"},
# 96 : 2 : {"SERVERNONCE", "bbbb"},
# 97 : 2 : });
# 98 : 2 : CheckParseTorReplyMapping(
# 99 : 2 : "ServiceID=exampleonion1234", {
# 100 : 2 : {"ServiceID", "exampleonion1234"},
# 101 : 2 : });
# 102 : 2 : CheckParseTorReplyMapping(
# 103 : 2 : "PrivateKey=RSA1024:BLOB", {
# 104 : 2 : {"PrivateKey", "RSA1024:BLOB"},
# 105 : 2 : });
# 106 : 2 : CheckParseTorReplyMapping(
# 107 : 2 : "ClientAuth=bob:BLOB", {
# 108 : 2 : {"ClientAuth", "bob:BLOB"},
# 109 : 2 : });
# 110 : :
# 111 : : // Other valid inputs
# 112 : 2 : CheckParseTorReplyMapping(
# 113 : 2 : "Foo=Bar=Baz Spam=Eggs", {
# 114 : 2 : {"Foo", "Bar=Baz"},
# 115 : 2 : {"Spam", "Eggs"},
# 116 : 2 : });
# 117 : 2 : CheckParseTorReplyMapping(
# 118 : 2 : "Foo=\"Bar=Baz\"", {
# 119 : 2 : {"Foo", "Bar=Baz"},
# 120 : 2 : });
# 121 : 2 : CheckParseTorReplyMapping(
# 122 : 2 : "Foo=\"Bar Baz\"", {
# 123 : 2 : {"Foo", "Bar Baz"},
# 124 : 2 : });
# 125 : :
# 126 : : // Escapes
# 127 : 2 : CheckParseTorReplyMapping(
# 128 : 2 : "Foo=\"Bar\\ Baz\"", {
# 129 : 2 : {"Foo", "Bar Baz"},
# 130 : 2 : });
# 131 : 2 : CheckParseTorReplyMapping(
# 132 : 2 : "Foo=\"Bar\\Baz\"", {
# 133 : 2 : {"Foo", "BarBaz"},
# 134 : 2 : });
# 135 : 2 : CheckParseTorReplyMapping(
# 136 : 2 : "Foo=\"Bar\\@Baz\"", {
# 137 : 2 : {"Foo", "Bar@Baz"},
# 138 : 2 : });
# 139 : 2 : CheckParseTorReplyMapping(
# 140 : 2 : "Foo=\"Bar\\\"Baz\" Spam=\"\\\"Eggs\\\"\"", {
# 141 : 2 : {"Foo", "Bar\"Baz"},
# 142 : 2 : {"Spam", "\"Eggs\""},
# 143 : 2 : });
# 144 : 2 : CheckParseTorReplyMapping(
# 145 : 2 : "Foo=\"Bar\\\\Baz\"", {
# 146 : 2 : {"Foo", "Bar\\Baz"},
# 147 : 2 : });
# 148 : :
# 149 : : // C escapes
# 150 : 2 : CheckParseTorReplyMapping(
# 151 : 2 : "Foo=\"Bar\\nBaz\\t\" Spam=\"\\rEggs\" Octals=\"\\1a\\11\\17\\18\\81\\377\\378\\400\\2222\" Final=Check", {
# 152 : 2 : {"Foo", "Bar\nBaz\t"},
# 153 : 2 : {"Spam", "\rEggs"},
# 154 : 2 : {"Octals", "\1a\11\17\1" "881\377\37" "8\40" "0\222" "2"},
# 155 : 2 : {"Final", "Check"},
# 156 : 2 : });
# 157 : 2 : CheckParseTorReplyMapping(
# 158 : 2 : "Valid=Mapping Escaped=\"Escape\\\\\"", {
# 159 : 2 : {"Valid", "Mapping"},
# 160 : 2 : {"Escaped", "Escape\\"},
# 161 : 2 : });
# 162 : 2 : CheckParseTorReplyMapping(
# 163 : 2 : "Valid=Mapping Bare=\"Escape\\\"", {});
# 164 : 2 : CheckParseTorReplyMapping(
# 165 : 2 : "OneOctal=\"OneEnd\\1\" TwoOctal=\"TwoEnd\\11\"", {
# 166 : 2 : {"OneOctal", "OneEnd\1"},
# 167 : 2 : {"TwoOctal", "TwoEnd\11"},
# 168 : 2 : });
# 169 : :
# 170 : : // Special handling for null case
# 171 : : // (needed because string comparison reads the null as end-of-string)
# 172 : 2 : auto ret = ParseTorReplyMapping("Null=\"\\0\"");
# 173 : 2 : BOOST_CHECK_EQUAL(ret.size(), 1U);
# 174 : 2 : auto r_it = ret.begin();
# 175 : 2 : BOOST_CHECK_EQUAL(r_it->first, "Null");
# 176 : 2 : BOOST_CHECK_EQUAL(r_it->second.size(), 1U);
# 177 : 2 : BOOST_CHECK_EQUAL(r_it->second[0], '\0');
# 178 : :
# 179 : : // A more complex valid grammar. PROTOCOLINFO accepts a VersionLine that
# 180 : : // takes a key=value pair followed by an OptArguments, making this valid.
# 181 : : // Because an OptArguments contains no semantic data, there is no point in
# 182 : : // parsing it.
# 183 : 2 : CheckParseTorReplyMapping(
# 184 : 2 : "SOME=args,here MORE optional=arguments here", {
# 185 : 2 : {"SOME", "args,here"},
# 186 : 2 : });
# 187 : :
# 188 : : // Inputs that are effectively invalid under the target grammar.
# 189 : : // PROTOCOLINFO accepts an OtherLine that is just an OptArguments, which
# 190 : : // would make these inputs valid. However,
# 191 : : // - This parser is never used in that situation, because the
# 192 : : // SplitTorReplyLine parser enables OtherLine to be skipped.
# 193 : : // - Even if these were valid, an OptArguments contains no semantic data,
# 194 : : // so there is no point in parsing it.
# 195 : 2 : CheckParseTorReplyMapping("ARGS", {});
# 196 : 2 : CheckParseTorReplyMapping("MORE ARGS", {});
# 197 : 2 : CheckParseTorReplyMapping("MORE ARGS", {});
# 198 : 2 : CheckParseTorReplyMapping("EVEN more=ARGS", {});
# 199 : 2 : CheckParseTorReplyMapping("EVEN+more ARGS", {});
# 200 : 2 : }
# 201 : :
# 202 : : BOOST_AUTO_TEST_SUITE_END()
|