DHTRoutingTableSerializerTest.cc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. #include "DHTRoutingTableSerializer.h"
  2. #include <cstring>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <cppunit/extensions/HelperMacros.h>
  6. #include "Exception.h"
  7. #include "util.h"
  8. #include "DHTNode.h"
  9. #include "array_fun.h"
  10. #include "DHTConstants.h"
  11. #include "bittorrent_helper.h"
  12. #include "a2netcompat.h"
  13. namespace aria2 {
  14. class DHTRoutingTableSerializerTest:public CppUnit::TestFixture {
  15. CPPUNIT_TEST_SUITE(DHTRoutingTableSerializerTest);
  16. CPPUNIT_TEST(testSerialize);
  17. CPPUNIT_TEST(testSerialize6);
  18. CPPUNIT_TEST_SUITE_END();
  19. private:
  20. char zero[256];
  21. char buf[20];
  22. void checkToLocalnode
  23. (std::istream& ss, const SharedHandle<DHTNode>& localNode);
  24. void checkNumNodes(std::istream& ss, size_t expected);
  25. public:
  26. void setUp()
  27. {
  28. memset(zero, 0, sizeof(zero));
  29. }
  30. void tearDown() {}
  31. void testSerialize();
  32. void testSerialize6();
  33. };
  34. CPPUNIT_TEST_SUITE_REGISTRATION(DHTRoutingTableSerializerTest);
  35. void DHTRoutingTableSerializerTest::checkToLocalnode
  36. (std::istream& ss, const SharedHandle<DHTNode>& localNode)
  37. {
  38. // header
  39. ss.read(buf, 8);
  40. // magic
  41. CPPUNIT_ASSERT((char)0xa1 == buf[0]);
  42. CPPUNIT_ASSERT((char)0xa2 == buf[1]);
  43. // format ID
  44. CPPUNIT_ASSERT((char)0x02 == buf[2]);
  45. // reserved
  46. CPPUNIT_ASSERT((char)0x00 == buf[3]);
  47. CPPUNIT_ASSERT((char)0x00 == buf[4]);
  48. CPPUNIT_ASSERT((char)0x00 == buf[5]);
  49. // version
  50. CPPUNIT_ASSERT((char)0x00 == buf[6]);
  51. CPPUNIT_ASSERT((char)0x03 == buf[7]);
  52. // time
  53. ss.read(buf, 8);
  54. time_t time;
  55. uint64_t timebuf;
  56. memcpy(&timebuf, buf, sizeof(timebuf));
  57. time = ntoh64(timebuf);
  58. std::cerr << time << std::endl;
  59. // localnode
  60. // 8bytes reserved
  61. ss.read(buf, 8);
  62. CPPUNIT_ASSERT(memcmp(zero, buf, 8) == 0);
  63. // localnode ID
  64. ss.read(buf, DHT_ID_LENGTH);
  65. CPPUNIT_ASSERT(memcmp(localNode->getID(), buf, DHT_ID_LENGTH) == 0);
  66. // 4bytes reserved
  67. ss.read(buf, 4);
  68. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  69. }
  70. void DHTRoutingTableSerializerTest::checkNumNodes
  71. (std::istream& ss, size_t expected)
  72. {
  73. // number of nodes saved
  74. ss.read(buf, 4);
  75. uint32_t numNodes;
  76. memcpy(&numNodes, buf, sizeof(numNodes));
  77. numNodes = ntohl(numNodes);
  78. CPPUNIT_ASSERT_EQUAL((uint32_t)expected, numNodes);
  79. }
  80. void DHTRoutingTableSerializerTest::testSerialize()
  81. {
  82. SharedHandle<DHTNode> localNode(new DHTNode());
  83. SharedHandle<DHTNode> nodesSrc[3];
  84. for(size_t i = 0; i < A2_ARRAY_LEN(nodesSrc); ++i) {
  85. nodesSrc[i].reset(new DHTNode());
  86. nodesSrc[i]->setIPAddress("192.168.0."+util::uitos(i+1));
  87. nodesSrc[i]->setPort(6881+i);
  88. }
  89. nodesSrc[1]->setIPAddress("non-numerical-name");
  90. std::vector<SharedHandle<DHTNode> > nodes(vbegin(nodesSrc), vend(nodesSrc));
  91. DHTRoutingTableSerializer s(AF_INET);
  92. s.setLocalNode(localNode);
  93. s.setNodes(nodes);
  94. std::string filename = A2_TEST_OUT_DIR"/aria2_DHTRoutingTableSerializerTest_testSerialize";
  95. s.serialize(filename);
  96. std::ifstream ss(filename.c_str(), std::ios::binary);
  97. checkToLocalnode(ss, localNode);
  98. size_t numNodes = 3;
  99. checkNumNodes(ss, numNodes);
  100. // 4bytes reserved
  101. ss.read(buf, 4);
  102. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  103. // node[0]
  104. // 1byte compatc peer format length
  105. {
  106. uint8_t len;
  107. ss >> len;
  108. CPPUNIT_ASSERT_EQUAL((uint8_t)6, len);
  109. }
  110. // 7bytes reserved
  111. ss.read(buf, 7);
  112. CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
  113. // 6bytes compact peer info
  114. ss.read(buf, 6);
  115. {
  116. std::pair<std::string, uint16_t> peer =
  117. bittorrent::unpackcompact(reinterpret_cast<const unsigned char*>(buf),
  118. AF_INET);
  119. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer.first);
  120. CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peer.second);
  121. }
  122. // 2bytes reserved
  123. ss.read(buf, 2);
  124. CPPUNIT_ASSERT(memcmp(zero, buf, 2) == 0);
  125. // 16bytes reserved
  126. ss.read(buf, 16);
  127. CPPUNIT_ASSERT(memcmp(zero, buf, 16) == 0);
  128. // localnode ID
  129. ss.read(buf, DHT_ID_LENGTH);
  130. CPPUNIT_ASSERT(memcmp(nodes[0]->getID(), buf, DHT_ID_LENGTH) == 0);
  131. // 4bytes reserved
  132. ss.read(buf, 4);
  133. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  134. // node[1]
  135. // 1byte compatc peer format length
  136. {
  137. uint8_t len;
  138. ss >> len;
  139. CPPUNIT_ASSERT_EQUAL((uint8_t)6, len);
  140. }
  141. // 7bytes reserved
  142. ss.read(buf, 7);
  143. CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
  144. // 6bytes compact peer info
  145. ss.read(buf, 6);
  146. // zero filled because node[1]'s hostname is not numerical form
  147. // deserializer should skip this entry
  148. CPPUNIT_ASSERT(memcmp(zero, buf, 6) == 0);
  149. // 2bytes reserved
  150. ss.read(buf, 2);
  151. CPPUNIT_ASSERT(memcmp(zero, buf, 2) == 0);
  152. // 16bytes reserved
  153. ss.read(buf, 16);
  154. CPPUNIT_ASSERT(memcmp(zero, buf, 16) == 0);
  155. // localnode ID
  156. ss.read(buf, DHT_ID_LENGTH);
  157. CPPUNIT_ASSERT(memcmp(nodes[1]->getID(), buf, DHT_ID_LENGTH) == 0);
  158. // 4bytes reserved
  159. ss.read(buf, 4);
  160. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  161. // node[2]
  162. // 1byte compatc peer format length
  163. {
  164. uint8_t len;
  165. ss >> len;
  166. CPPUNIT_ASSERT_EQUAL((uint8_t)6, len);
  167. }
  168. // 7bytes reserved
  169. ss.read(buf, 7);
  170. CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
  171. // 6bytes compact peer info
  172. ss.read(buf, 6);
  173. {
  174. std::pair<std::string, uint16_t> peer =
  175. bittorrent::unpackcompact(reinterpret_cast<const unsigned char*>(buf),
  176. AF_INET);
  177. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.3"), peer.first);
  178. CPPUNIT_ASSERT_EQUAL((uint16_t)6883, peer.second);
  179. }
  180. // 2bytes reserved
  181. ss.read(buf, 2);
  182. CPPUNIT_ASSERT(memcmp(zero, buf, 2) == 0);
  183. // 16bytes reserved
  184. ss.read(buf, 16);
  185. CPPUNIT_ASSERT(memcmp(zero, buf, 16) == 0);
  186. // localnode ID
  187. ss.read(buf, DHT_ID_LENGTH);
  188. CPPUNIT_ASSERT(memcmp(nodes[2]->getID(), buf, DHT_ID_LENGTH) == 0);
  189. // 4bytes reserved
  190. ss.read(buf, 4);
  191. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  192. // check to see stream ends
  193. ss.read(buf, 1);
  194. CPPUNIT_ASSERT_EQUAL((std::streamsize)0, ss.gcount());
  195. CPPUNIT_ASSERT(ss.eof());
  196. }
  197. void DHTRoutingTableSerializerTest::testSerialize6()
  198. {
  199. SharedHandle<DHTNode> localNode(new DHTNode());
  200. SharedHandle<DHTNode> nodesSrc[2];
  201. for(size_t i = 0; i < A2_ARRAY_LEN(nodesSrc); ++i) {
  202. nodesSrc[i].reset(new DHTNode());
  203. nodesSrc[i]->setIPAddress("2001::100"+util::uitos(i+1));
  204. nodesSrc[i]->setPort(6881+i);
  205. }
  206. nodesSrc[1]->setIPAddress("non-numerical-name");
  207. std::vector<SharedHandle<DHTNode> > nodes(vbegin(nodesSrc), vend(nodesSrc));
  208. DHTRoutingTableSerializer s(AF_INET6);
  209. s.setLocalNode(localNode);
  210. s.setNodes(nodes);
  211. std::string filename = A2_TEST_OUT_DIR"/aria2_DHTRoutingTableSerializerTest_testSerialize6";
  212. s.serialize(filename);
  213. std::ifstream ss(filename.c_str(), std::ios::binary);
  214. checkToLocalnode(ss, localNode);
  215. size_t numNodes = 2;
  216. checkNumNodes(ss, numNodes);
  217. // 4bytes reserved
  218. ss.read(buf, 4);
  219. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  220. // node[0]
  221. // 1byte compatc peer format length
  222. {
  223. uint8_t len;
  224. ss >> len;
  225. CPPUNIT_ASSERT_EQUAL((uint8_t)18, len);
  226. }
  227. // 7bytes reserved
  228. ss.read(buf, 7);
  229. CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
  230. // 18 bytes compact peer info
  231. ss.read(buf, 18);
  232. {
  233. std::pair<std::string, uint16_t> peer =
  234. bittorrent::unpackcompact(reinterpret_cast<const unsigned char*>(buf),
  235. AF_INET6);
  236. CPPUNIT_ASSERT_EQUAL(std::string("2001::1001"), peer.first);
  237. CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peer.second);
  238. }
  239. // 6bytes reserved
  240. ss.read(buf, 6);
  241. CPPUNIT_ASSERT(memcmp(zero, buf, 6) == 0);
  242. // localnode ID
  243. ss.read(buf, DHT_ID_LENGTH);
  244. CPPUNIT_ASSERT(memcmp(nodes[0]->getID(), buf, DHT_ID_LENGTH) == 0);
  245. // 4bytes reserved
  246. ss.read(buf, 4);
  247. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  248. // node[1]
  249. // 1byte compatc peer format length
  250. {
  251. uint8_t len;
  252. ss >> len;
  253. CPPUNIT_ASSERT_EQUAL((uint8_t)18, len);
  254. }
  255. // 7bytes reserved
  256. ss.read(buf, 7);
  257. CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
  258. // 18bytes compact peer info
  259. ss.read(buf, 18);
  260. // zero filled because node[1]'s hostname is not numerical form
  261. // deserializer should skip this entry
  262. CPPUNIT_ASSERT(memcmp(zero, buf, 18) == 0);
  263. // 6bytes reserved
  264. ss.read(buf, 6);
  265. CPPUNIT_ASSERT(memcmp(zero, buf, 6) == 0);
  266. // localnode ID
  267. ss.read(buf, DHT_ID_LENGTH);
  268. CPPUNIT_ASSERT(memcmp(nodes[1]->getID(), buf, DHT_ID_LENGTH) == 0);
  269. // 4bytes reserved
  270. ss.read(buf, 4);
  271. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  272. // check to see stream ends
  273. ss.read(buf, 1);
  274. CPPUNIT_ASSERT_EQUAL((std::streamsize)0, ss.gcount());
  275. CPPUNIT_ASSERT(ss.eof());
  276. }
  277. } // namespace aria2