3
#include <torrent/object.h>
4
#include <torrent/object_stream.h>
5
#include "torrent/object_static_map.h"
6
#include "protocol/extensions.h"
8
#import "object_test_utils.h"
9
#import "object_static_map_test.h"
11
CPPUNIT_TEST_SUITE_REGISTRATION(ObjectStaticMapTest);
13
// Possible bencode keys in a DHT message.
41
typedef torrent::static_map_type<keys, key_LAST> test_map_type;
42
typedef torrent::static_map_type<keys_2, key_2_LAST> test_map_2_type;
44
// List of all possible keys we need/support in a DHT message.
45
// Unsupported keys we receive are dropped (ignored) while decoding.
46
// See torrent/object_static_map.h for how this works.
48
const test_map_type::key_list_type test_map_type::keys = {
49
{ key_d_a, "d_a::b" },
50
{ key_d_d_a, "d_a::c::a" },
51
{ key_d_b, "d_a::d" },
65
const test_map_2_type::key_list_type test_map_2_type::keys = {
66
{ key_2_d_x_y, "d_x::f" },
67
{ key_2_d_x_z, "d_x::g" },
68
{ key_2_l_x_1, "l_x[]" },
69
{ key_2_l_x_2, "l_x[]" },
75
ObjectStaticMapTest::test_basics() {
76
test_map_type test_map;
78
test_map[key_v_a] = int64_t(1);
79
test_map[key_v_b] = int64_t(2);
81
test_map[key_s_a] = std::string("a");
82
test_map[key_s_b] = std::string("b");
84
CPPUNIT_ASSERT(test_map[key_v_a].as_value() == 1);
85
CPPUNIT_ASSERT(test_map[key_v_b].as_value() == 2);
86
CPPUNIT_ASSERT(test_map[key_s_a].as_string() == "a");
87
CPPUNIT_ASSERT(test_map[key_s_b].as_string() == "b");
91
ObjectStaticMapTest::test_write() {
92
test_map_type test_map;
94
test_map[key_v_a] = int64_t(1);
95
test_map[key_v_b] = int64_t(2);
97
test_map[key_s_a] = std::string("a");
98
// test_map[key_s_b] = std::string("b");
100
test_map[key_d_a] = std::string("xx");
101
test_map[key_d_d_a] = std::string("a");
102
test_map[key_d_b] = std::string("yy");
104
test_map[key_e_0] = std::string("f");
105
test_map[key_e_1] = torrent::object_create_raw_bencode_c_str("1:g");
106
test_map[key_e_2] = std::string("h");
110
torrent::object_buffer_t result = torrent::static_map_write_bencode_c(torrent::object_write_to_buffer,
112
std::make_pair(buffer, buffer + sizeof(buffer)),
115
// std::cout << "static map write: '" << std::string(buffer, std::distance(buffer, result.first)) << "'" << std::endl;
117
CPPUNIT_ASSERT(validate_bencode(buffer, result.first));
120
static const char* test_read_bencode = "d3:d_xd1:fi3e1:gli4ei5eee3:l_xli1ei2ei3ee3:s_a1:a3:v_ai2ee";
121
static const char* test_read_skip_bencode = "d3:d_xd1:fi3e1:gli4ei5eee1:fi1e3:l_xli1ei2ei3ee3:s_a1:a3:v_ai2ee";
123
template <typename map_type>
124
bool static_map_read_bencode(map_type& map, const char* str) {
126
return torrent::static_map_read_bencode(str, str + strlen(str), map) == str + strlen(str);
127
} catch (torrent::bencode_error&) { return false; }
130
template <typename map_type>
131
bool static_map_read_bencode_exception(map_type& map, const char* str) {
133
torrent::static_map_read_bencode(str, str + strlen(str), map);
135
} catch (torrent::bencode_error&) { return true; }
139
ObjectStaticMapTest::test_read() {
140
test_map_2_type test_map;
142
CPPUNIT_ASSERT(static_map_read_bencode(test_map, test_read_bencode));
143
CPPUNIT_ASSERT(test_map[key_2_d_x_y].as_value() == 3);
144
CPPUNIT_ASSERT(test_map[key_2_d_x_z].as_list().size() == 2);
145
CPPUNIT_ASSERT(test_map[key_2_l_x_1].as_value() == 1);
146
CPPUNIT_ASSERT(test_map[key_2_l_x_2].as_value() == 2);
147
CPPUNIT_ASSERT(test_map[key_2_s_a].as_string() == "a");
148
CPPUNIT_ASSERT(test_map[key_2_v_a].as_value() == 2);
150
test_map_2_type test_skip_map;
152
CPPUNIT_ASSERT(static_map_read_bencode(test_skip_map, test_read_skip_bencode));
156
const torrent::ExtHandshakeMessage::key_list_type torrent::ExtHandshakeMessage::keys = {
158
{ key_m_utPex, "m::ut_pex" },
160
{ key_reqq, "reqq" },
165
ObjectStaticMapTest::test_read_extensions() {
166
torrent::ExtHandshakeMessage test_ext;
168
CPPUNIT_ASSERT(static_map_read_bencode(test_ext, "d1:ai1ee"));
170
CPPUNIT_ASSERT(static_map_read_bencode(test_ext, "d1:mi1ee"));
171
CPPUNIT_ASSERT(static_map_read_bencode(test_ext, "d1:mdee"));
172
CPPUNIT_ASSERT(static_map_read_bencode(test_ext, "d6:ut_pexi0ee"));
173
CPPUNIT_ASSERT(static_map_read_bencode(test_ext, "d1:md6:ut_pexi0eee"));
176
template <typename map_type>
177
bool static_map_write_bencode(map_type map, const char* original) {
180
char* last = torrent::static_map_write_bencode_c(&torrent::object_write_to_buffer,
182
torrent::object_buffer_t(buffer, buffer + 1024),
184
return std::strncmp(buffer, original, std::distance(buffer, last)) == 0;
186
} catch (torrent::bencode_error& e) {
192
// Proper unit tests:
195
enum keys_empty { key_empty_LAST };
196
enum keys_single { key_single_a, key_single_LAST };
197
enum keys_raw { key_raw_a, key_raw_LAST };
198
enum keys_raw_types { key_raw_types_empty, key_raw_types_list, key_raw_types_map, key_raw_types_str, key_raw_types_LAST};
199
enum keys_multiple { key_multiple_a, key_multiple_b, key_multiple_c, key_multiple_LAST };
200
enum keys_dict { key_dict_a_b, key_dict_LAST };
202
typedef torrent::static_map_type<keys_empty, key_empty_LAST> test_empty_type;
203
typedef torrent::static_map_type<keys_single, key_single_LAST> test_single_type;
204
typedef torrent::static_map_type<keys_raw, key_raw_LAST> test_raw_type;
205
typedef torrent::static_map_type<keys_raw_types, key_raw_types_LAST> test_raw_types_type;
206
typedef torrent::static_map_type<keys_multiple, key_multiple_LAST> test_multiple_type;
207
typedef torrent::static_map_type<keys_dict, key_dict_LAST> test_dict_type;
209
template <> const test_empty_type::key_list_type
210
test_empty_type::keys = { };
211
template <> const test_single_type::key_list_type
212
test_single_type::keys = { { key_single_a, "b" } };
213
template <> const test_raw_type::key_list_type
214
test_raw_type::keys = { { key_raw_a, "b*" } };
215
template <> const test_raw_types_type::key_list_type
216
test_raw_types_type::keys = { { key_raw_types_empty, "e*"},
217
{ key_raw_types_list, "l*L"},
218
{ key_raw_types_map, "m*M"},
219
{ key_raw_types_str, "s*S"} };
220
template <> const test_multiple_type::key_list_type
221
test_multiple_type::keys = { { key_multiple_a, "a" }, { key_multiple_b, "b*" }, { key_multiple_c, "c" } };
222
template <> const test_dict_type::key_list_type
223
test_dict_type::keys = { { key_dict_a_b, "a::b" } };
226
ObjectStaticMapTest::test_read_empty() {
227
test_empty_type map_normal;
228
test_empty_type map_skip;
229
test_empty_type map_incomplete;
231
CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "de"));
232
CPPUNIT_ASSERT(static_map_read_bencode(map_skip, "d1:ai1ee"));
234
CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, ""));
235
CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "d"));
239
ObjectStaticMapTest::test_read_single() {
240
test_single_type map_normal;
241
test_single_type map_skip;
242
test_single_type map_incomplete;
244
CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:bi1ee"));
245
CPPUNIT_ASSERT(map_normal[key_single_a].as_value() == 1);
247
CPPUNIT_ASSERT(static_map_read_bencode(map_skip, "d1:ai0e1:bi1e1:ci2ee"));
248
CPPUNIT_ASSERT(map_skip[key_single_a].as_value() == 1);
250
CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "d"));
251
CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "d1:b"));
252
CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "d1:bi1"));
253
CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "d1:bi1e"));
257
ObjectStaticMapTest::test_read_single_raw() {
258
test_raw_type map_raw;
260
CPPUNIT_ASSERT(static_map_read_bencode(map_raw, "d1:bi1ee"));
261
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode(), "i1e"));
263
CPPUNIT_ASSERT(static_map_read_bencode(map_raw, "d1:b2:abe"));
264
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode(), "2:ab"));
265
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode().as_raw_string(), "ab"));
267
CPPUNIT_ASSERT(static_map_read_bencode(map_raw, "d1:bli1ei2eee"));
268
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode(), "li1ei2ee"));
269
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode().as_raw_list(), "i1ei2e"));
271
CPPUNIT_ASSERT(static_map_read_bencode(map_raw, "d1:bd1:ai1e1:bi2eee"));
272
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode(), "d1:ai1e1:bi2ee"));
273
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode().as_raw_map(), "1:ai1e1:bi2e"));
277
ObjectStaticMapTest::test_read_raw_types() {
278
test_raw_types_type map_raw;
280
CPPUNIT_ASSERT(static_map_read_bencode(map_raw, "d" "1:ei1e" "1:lli1ei2ee" "1:md1:ai1e1:bi2ee" "1:s2:ab" "e"));
281
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_types_empty].as_raw_bencode(), "i1e"));
282
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_types_str].as_raw_string(), "ab"));
283
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_types_list].as_raw_list(), "i1ei2e"));
284
CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_types_map].as_raw_map(), "1:ai1e1:bi2e"));
288
ObjectStaticMapTest::test_read_multiple() {
289
test_multiple_type map_normal;
291
CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ai1ee"));
292
CPPUNIT_ASSERT(map_normal[key_multiple_a].as_value() == 1);
293
CPPUNIT_ASSERT(map_normal[key_multiple_b].is_empty());
294
CPPUNIT_ASSERT(map_normal[key_multiple_c].is_empty());
296
map_normal = test_multiple_type();
297
CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ci3ee"));
298
CPPUNIT_ASSERT(map_normal[key_multiple_a].is_empty());
299
CPPUNIT_ASSERT(map_normal[key_multiple_b].is_empty());
300
CPPUNIT_ASSERT(map_normal[key_multiple_c].as_value() == 3);
302
map_normal = test_multiple_type();
303
CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ai1e1:ci3ee"));
304
CPPUNIT_ASSERT(map_normal[key_multiple_a].as_value() == 1);
305
CPPUNIT_ASSERT(map_normal[key_multiple_b].is_empty());
306
CPPUNIT_ASSERT(map_normal[key_multiple_c].as_value() == 3);
308
map_normal = test_multiple_type();
309
CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ai1e1:bi2e1:ci3ee"));
310
CPPUNIT_ASSERT(map_normal[key_multiple_a].as_value() == 1);
311
// CPPUNIT_ASSERT(map_normal[key_multiple_b].as_raw_bencode().as_raw_value().size() == 1);
312
// CPPUNIT_ASSERT(map_normal[key_multiple_b].as_raw_bencode().as_raw_value().data()[0] == '2');
313
CPPUNIT_ASSERT(map_normal[key_multiple_c].as_value() == 3);
317
ObjectStaticMapTest::test_read_dict() {
318
test_dict_type map_normal;
320
CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ai1ee"));
321
CPPUNIT_ASSERT(map_normal[key_dict_a_b].is_empty());
323
CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:adee"));
324
CPPUNIT_ASSERT(map_normal[key_dict_a_b].is_empty());
326
CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ad1:bi1eee"));
327
CPPUNIT_ASSERT(map_normal[key_dict_a_b].as_value() == 1);
331
ObjectStaticMapTest::test_write_empty() {
332
test_empty_type map_normal;
334
CPPUNIT_ASSERT(static_map_write_bencode(map_normal, "de"));
338
ObjectStaticMapTest::test_write_single() {
339
test_single_type map_value;
341
CPPUNIT_ASSERT(static_map_write_bencode(map_value, "de"));
343
map_value[key_single_a] = (int64_t)1;
344
CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bi1ee"));
346
map_value[key_single_a] = "test";
347
CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:b4:teste"));
349
map_value[key_single_a] = torrent::Object::create_list();
350
map_value[key_single_a].as_list().push_back("test");
351
CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bl4:testee"));
353
map_value[key_single_a] = torrent::raw_bencode("i1e", 3);
354
CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bi1ee"));
356
// map_value[key_single_a] = torrent::raw_value("1", 1);
357
// CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bi1ee"));
359
map_value[key_single_a] = torrent::raw_string("test", 4);
360
CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:b4:teste"));
362
map_value[key_single_a] = torrent::raw_list("1:a2:bb", strlen("1:a2:bb"));
363
CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bl1:a2:bbee"));
365
map_value[key_single_a] = torrent::raw_map("1:a2:bb", strlen("1:a2:bb"));
366
CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bd1:a2:bbee"));
370
ObjectStaticMapTest::test_write_multiple() {
371
// test_multiple_type map_value;
373
// CPPUNIT_ASSERT(static_map_write_bencode(map_value, "de"));