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 : 10 : static void CheckSplitTorReplyLine(std::string input, std::string command, std::string args)
20 : : {
21 : 10 : auto ret = SplitTorReplyLine(input);
22 [ + - + - ]: 10 : BOOST_CHECK_EQUAL(ret.first, command);
23 [ + - + - ]: 10 : BOOST_CHECK_EQUAL(ret.second, args);
24 : 10 : }
25 : :
26 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_SplitTorReplyLine)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
27 : : {
28 : : // Data we should receive during normal usage
29 [ + - + - : 2 : CheckSplitTorReplyLine(
+ - ]
30 : : "PROTOCOLINFO PIVERSION",
31 : : "PROTOCOLINFO", "PIVERSION");
32 [ + - + - : 2 : CheckSplitTorReplyLine(
+ - ]
33 : : "AUTH METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"",
34 : : "AUTH", "METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"");
35 [ + - + - : 2 : CheckSplitTorReplyLine(
+ - ]
36 : : "AUTH METHODS=NULL",
37 : : "AUTH", "METHODS=NULL");
38 [ + - + - : 2 : CheckSplitTorReplyLine(
+ - ]
39 : : "AUTH METHODS=HASHEDPASSWORD",
40 : : "AUTH", "METHODS=HASHEDPASSWORD");
41 [ + - + - : 2 : CheckSplitTorReplyLine(
+ - ]
42 : : "VERSION Tor=\"0.2.9.8 (git-a0df013ea241b026)\"",
43 : : "VERSION", "Tor=\"0.2.9.8 (git-a0df013ea241b026)\"");
44 [ + - + - : 2 : CheckSplitTorReplyLine(
+ - ]
45 : : "AUTHCHALLENGE SERVERHASH=aaaa SERVERNONCE=bbbb",
46 : : "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 : 1 : }
58 : :
59 : 26 : static void CheckParseTorReplyMapping(std::string input, std::map<std::string,std::string> expected)
60 : : {
61 : 26 : auto ret = ParseTorReplyMapping(input);
62 [ + - + - ]: 26 : BOOST_CHECK_EQUAL(ret.size(), expected.size());
63 : 26 : auto r_it = ret.begin();
64 : 26 : auto e_it = expected.begin();
65 [ + + + - ]: 55 : while (r_it != ret.end() && e_it != expected.end()) {
66 [ + - + - ]: 29 : BOOST_CHECK_EQUAL(r_it->first, e_it->first);
67 [ + - + - ]: 29 : BOOST_CHECK_EQUAL(r_it->second, e_it->second);
68 : 29 : r_it++;
69 : 29 : e_it++;
70 : : }
71 : 26 : }
72 : :
73 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_ParseTorReplyMapping)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
74 : : {
75 : : // Data we should receive during normal usage
76 [ + - + - : 4 : CheckParseTorReplyMapping(
+ - + + -
- ]
77 : : "METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"", {
78 : : {"METHODS", "COOKIE,SAFECOOKIE"},
79 : : {"COOKIEFILE", "/home/x/.tor/control_auth_cookie"},
80 : : });
81 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
82 : : "METHODS=NULL", {
83 : : {"METHODS", "NULL"},
84 : : });
85 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
86 : : "METHODS=HASHEDPASSWORD", {
87 : : {"METHODS", "HASHEDPASSWORD"},
88 : : });
89 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
90 : : "Tor=\"0.2.9.8 (git-a0df013ea241b026)\"", {
91 : : {"Tor", "0.2.9.8 (git-a0df013ea241b026)"},
92 : : });
93 [ + - + - : 4 : CheckParseTorReplyMapping(
+ - + + -
- ]
94 : : "SERVERHASH=aaaa SERVERNONCE=bbbb", {
95 : : {"SERVERHASH", "aaaa"},
96 : : {"SERVERNONCE", "bbbb"},
97 : : });
98 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
99 : : "ServiceID=exampleonion1234", {
100 : : {"ServiceID", "exampleonion1234"},
101 : : });
102 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
103 : : "PrivateKey=RSA1024:BLOB", {
104 : : {"PrivateKey", "RSA1024:BLOB"},
105 : : });
106 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
107 : : "ClientAuth=bob:BLOB", {
108 : : {"ClientAuth", "bob:BLOB"},
109 : : });
110 : :
111 : : // Other valid inputs
112 [ + - + - : 4 : CheckParseTorReplyMapping(
+ - + + -
- ]
113 : : "Foo=Bar=Baz Spam=Eggs", {
114 : : {"Foo", "Bar=Baz"},
115 : : {"Spam", "Eggs"},
116 : : });
117 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
118 : : "Foo=\"Bar=Baz\"", {
119 : : {"Foo", "Bar=Baz"},
120 : : });
121 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
122 : : "Foo=\"Bar Baz\"", {
123 : : {"Foo", "Bar Baz"},
124 : : });
125 : :
126 : : // Escapes
127 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
128 : : "Foo=\"Bar\\ Baz\"", {
129 : : {"Foo", "Bar Baz"},
130 : : });
131 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
132 : : "Foo=\"Bar\\Baz\"", {
133 : : {"Foo", "BarBaz"},
134 : : });
135 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
136 : : "Foo=\"Bar\\@Baz\"", {
137 : : {"Foo", "Bar@Baz"},
138 : : });
139 [ + - + - : 4 : CheckParseTorReplyMapping(
+ - + + -
- ]
140 : : "Foo=\"Bar\\\"Baz\" Spam=\"\\\"Eggs\\\"\"", {
141 : : {"Foo", "Bar\"Baz"},
142 : : {"Spam", "\"Eggs\""},
143 : : });
144 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
145 : : "Foo=\"Bar\\\\Baz\"", {
146 : : {"Foo", "Bar\\Baz"},
147 : : });
148 : :
149 : : // C escapes
150 [ + - + - : 6 : CheckParseTorReplyMapping(
+ - + + -
- ]
151 : : "Foo=\"Bar\\nBaz\\t\" Spam=\"\\rEggs\" Octals=\"\\1a\\11\\17\\18\\81\\377\\378\\400\\2222\" Final=Check", {
152 : : {"Foo", "Bar\nBaz\t"},
153 : : {"Spam", "\rEggs"},
154 : : {"Octals", "\1a\11\17\1" "881\377\37" "8\40" "0\222" "2"},
155 : : {"Final", "Check"},
156 : : });
157 [ + - + - : 4 : CheckParseTorReplyMapping(
+ - + + -
- ]
158 : : "Valid=Mapping Escaped=\"Escape\\\\\"", {
159 : : {"Valid", "Mapping"},
160 : : {"Escaped", "Escape\\"},
161 : : });
162 [ + - + - ]: 2 : CheckParseTorReplyMapping(
163 : : "Valid=Mapping Bare=\"Escape\\\"", {});
164 [ + - + - : 4 : CheckParseTorReplyMapping(
+ - + + -
- ]
165 : : "OneOctal=\"OneEnd\\1\" TwoOctal=\"TwoEnd\\11\"", {
166 : : {"OneOctal", "OneEnd\1"},
167 : : {"TwoOctal", "TwoEnd\11"},
168 : : });
169 : :
170 : : // Special handling for null case
171 : : // (needed because string comparison reads the null as end-of-string)
172 [ + - ]: 1 : auto ret = ParseTorReplyMapping("Null=\"\\0\"");
173 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(ret.size(), 1U);
174 [ + - ]: 1 : auto r_it = ret.begin();
175 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(r_it->first, "Null");
176 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(r_it->second.size(), 1U);
177 [ + - + - ]: 1 : 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 [ + - + - : 3 : CheckParseTorReplyMapping(
+ - + + -
- ]
184 : : "SOME=args,here MORE optional=arguments here", {
185 : : {"SOME", "args,here"},
186 : : });
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 [ + - + - : 3 : CheckParseTorReplyMapping("MORE ARGS", {});
+ - ]
198 [ + - + - ]: 2 : CheckParseTorReplyMapping("EVEN more=ARGS", {});
199 [ + - + - ]: 2 : CheckParseTorReplyMapping("EVEN+more ARGS", {});
200 [ + - + - : 21 : }
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
- - - - -
- - - - -
- - - - ]
201 : :
202 : : BOOST_AUTO_TEST_SUITE_END()
|