From 1b54e64d34f87dca00a9d93bf110207a1098a2a5 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 9 Dec 2008 14:43:11 +0000 Subject: 2008-12-09 Tatsuhiro Tsujikawa Added bencode helper functions and BDE class. They will replace MetaFileUtil and Dictionary/List/Data classes. * src/Makefile.am * src/bencode.cc * src/bencode.h * test/BencodeTest.cc * test/Makefile.am --- test/BencodeTest.cc | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/Makefile.am | 3 +- test/Makefile.in | 12 ++- 3 files changed, 281 insertions(+), 6 deletions(-) create mode 100644 test/BencodeTest.cc (limited to 'test') diff --git a/test/BencodeTest.cc b/test/BencodeTest.cc new file mode 100644 index 00000000..8db1b1f5 --- /dev/null +++ b/test/BencodeTest.cc @@ -0,0 +1,272 @@ +#include "bencode.h" + +#include +#include + +#include + +namespace aria2 { + +class BencodeTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(BencodeTest); + CPPUNIT_TEST(testString); + CPPUNIT_TEST(testInteger); + CPPUNIT_TEST(testDict); + CPPUNIT_TEST(testDictIter); + CPPUNIT_TEST(testList); + CPPUNIT_TEST(testListIter); + CPPUNIT_TEST(testDecode); + CPPUNIT_TEST(testEncode); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void testString(); + void testInteger(); + void testDict(); + void testDictIter(); + void testList(); + void testListIter(); + void testDecode(); + void testEncode(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( BencodeTest ); + +void BencodeTest::testString() +{ + bencode::BDE s(std::string("aria2")); + CPPUNIT_ASSERT_EQUAL(std::string("aria2"), s.s()); + + unsigned char dataWithNull[] = { 0xf0, '\0', 0x0f }; + bencode::BDE sWithNull(dataWithNull, sizeof(dataWithNull)); + CPPUNIT_ASSERT(memcmp(dataWithNull, sWithNull.s().c_str(), + sizeof(dataWithNull)) == 0); + + bencode::BDE zero(""); + CPPUNIT_ASSERT_EQUAL(std::string(""), zero.s()); +} + +void BencodeTest::testInteger() +{ + bencode::BDE integer(INT64_MAX); + CPPUNIT_ASSERT_EQUAL(INT64_MAX, integer.i()); +} + +void BencodeTest::testDict() +{ + bencode::BDE dict = bencode::BDE::dict(); + CPPUNIT_ASSERT(dict.empty()); + + dict["ki"] = 7; + dict["ks"] = std::string("abc"); + + CPPUNIT_ASSERT_EQUAL(static_cast(2), dict.size()); + CPPUNIT_ASSERT(dict.containsKey("ki")); + CPPUNIT_ASSERT_EQUAL(static_cast(7), dict["ki"].i()); + CPPUNIT_ASSERT(dict.containsKey("ks")); + CPPUNIT_ASSERT_EQUAL(std::string("abc"), dict["ks"].s()); + + CPPUNIT_ASSERT(dict["kn"].isNone()); // This adds kn key with default value. + CPPUNIT_ASSERT_EQUAL(static_cast(3), dict.size()); + CPPUNIT_ASSERT(dict.containsKey("kn")); + + const bencode::BDE& ref = dict; + ref["kn2"]; // This doesn't add kn2 key. + CPPUNIT_ASSERT_EQUAL(static_cast(3), ref.size()); + CPPUNIT_ASSERT(!ref.containsKey("kn2")); +} + +void BencodeTest::testDictIter() +{ + bencode::BDE dict = bencode::BDE::dict(); + dict["alpha2"] = std::string("alpha2"); + dict["charlie"] = std::string("charlie"); + dict["bravo"] = std::string("bravo"); + dict["alpha"] = std::string("alpha"); + + bencode::BDE::Dict::iterator i = dict.dictBegin(); + CPPUNIT_ASSERT_EQUAL(std::string("alpha"), (*i++).first); + CPPUNIT_ASSERT_EQUAL(std::string("alpha2"), (*i++).first); + CPPUNIT_ASSERT_EQUAL(std::string("bravo"), (*i++).first); + CPPUNIT_ASSERT_EQUAL(std::string("charlie"), (*i++).first); + CPPUNIT_ASSERT(dict.dictEnd() == i); + + const bencode::BDE& ref = dict; + bencode::BDE::Dict::const_iterator ci = ref.dictBegin(); + CPPUNIT_ASSERT_EQUAL(std::string("alpha"), (*ci++).first); + std::advance(ci, 3); + CPPUNIT_ASSERT(ref.dictEnd() == ci); +} + +void BencodeTest::testList() +{ + bencode::BDE list = bencode::BDE::list(); + CPPUNIT_ASSERT(list.empty()); + list << 7; + list << std::string("aria2"); + + CPPUNIT_ASSERT_EQUAL(static_cast(2), list.size()); + CPPUNIT_ASSERT_EQUAL(static_cast(7), list[0].i()); + CPPUNIT_ASSERT_EQUAL(std::string("aria2"), list[1].s()); + + const bencode::BDE& ref = list; + CPPUNIT_ASSERT_EQUAL(static_cast(7), ref[0].i()); + CPPUNIT_ASSERT_EQUAL(std::string("aria2"), ref[1].s()); +} + +void BencodeTest::testListIter() +{ + bencode::BDE list = bencode::BDE::list(); + list << std::string("alpha2"); + list << std::string("charlie"); + list << std::string("bravo"); + list << std::string("alpha"); + + bencode::BDE::List::iterator i = list.listBegin(); + CPPUNIT_ASSERT_EQUAL(std::string("alpha2"), (*i++).s()); + CPPUNIT_ASSERT_EQUAL(std::string("charlie"), (*i++).s()); + CPPUNIT_ASSERT_EQUAL(std::string("bravo"), (*i++).s()); + CPPUNIT_ASSERT_EQUAL(std::string("alpha"), (*i++).s()); + CPPUNIT_ASSERT(list.listEnd() == i); + + const bencode::BDE& ref = list; + bencode::BDE::List::const_iterator ci = ref.listBegin(); + CPPUNIT_ASSERT_EQUAL(std::string("alpha2"), (*ci++).s()); + std::advance(ci, 3); + CPPUNIT_ASSERT(ref.listEnd() == ci); +} + +void BencodeTest::testDecode() +{ + { + // string, integer and list in dict + bencode::BDE dict = + bencode::decode("d4:name5:aria24:sizei12345678900e5:filesl3:bin3:docee"); + CPPUNIT_ASSERT(dict.isDict()); + CPPUNIT_ASSERT_EQUAL(std::string("aria2"), dict["name"].s()); + CPPUNIT_ASSERT_EQUAL(static_cast(12345678900LL), + dict["size"].i()); + bencode::BDE list = dict["files"]; + CPPUNIT_ASSERT(list.isList()); + CPPUNIT_ASSERT_EQUAL(static_cast(2), list.size()); + CPPUNIT_ASSERT_EQUAL(std::string("bin"), list[0].s()); + CPPUNIT_ASSERT_EQUAL(std::string("doc"), list[1].s()); + } + { + // dict in list + bencode::BDE list = bencode::decode("ld1:ki123eee"); + CPPUNIT_ASSERT(list.isList()); + CPPUNIT_ASSERT_EQUAL(static_cast(1), list.size()); + bencode::BDE dict = list[0]; + CPPUNIT_ASSERT(dict.isDict()); + CPPUNIT_ASSERT_EQUAL(static_cast(123), + dict["k"].i()); + } + { + // empty key is allowed + bencode::BDE s = bencode::decode("d0:1:ve"); + } + { + // empty string + bencode::BDE s = bencode::decode("0:"); + CPPUNIT_ASSERT_EQUAL(std::string(""), s.s()); + } + { + // empty dict + bencode::BDE d = bencode::decode("de"); + CPPUNIT_ASSERT(d.empty()); + } + { + // empty list + bencode::BDE l = bencode::decode("le"); + CPPUNIT_ASSERT(l.empty()); + } + { + // integer, without ending 'e' + try { + bencode::decode("i3"); + CPPUNIT_FAIL("exception must be thrown."); + } catch(RecoverableException& e) { + CPPUNIT_ASSERT_EQUAL(std::string("Delimiter 'e' not found."), + std::string(e.what())); + } + } + { + // dict, without ending 'e' + try { + bencode::decode("d"); + CPPUNIT_FAIL("exception must be thrown."); + } catch(RecoverableException& e) { + CPPUNIT_ASSERT_EQUAL(std::string("Unexpected EOF in dict context." + " 'e' expected."), + std::string(e.what())); + } + } + { + // list, without ending 'e' + try { + bencode::decode("l"); + CPPUNIT_FAIL("exception must be thrown."); + } catch(RecoverableException& e) { + CPPUNIT_ASSERT_EQUAL(std::string("Unexpected EOF in list context." + " 'e' expected."), + std::string(e.what())); + } + } + { + // string, less than the specified length. + try { + bencode::decode("3:ab"); + CPPUNIT_FAIL("exception must be thrown."); + } catch(RecoverableException& e) { + CPPUNIT_ASSERT_EQUAL(std::string("Expected 3 bytes of data," + " but only 2 read."), + std::string(e.what())); + } + } + { + // string, but length is invalid + try { + bencode::decode("x:abc"); + CPPUNIT_FAIL("exception must be thrown."); + } catch(RecoverableException& e) { + CPPUNIT_ASSERT_EQUAL(std::string("Integer expected but none found."), + std::string(e.what())); + } + } + { + // empty encoded data + CPPUNIT_ASSERT(bencode::decode("").isNone()); + } + { + // ignore trailing garbage at the end of the input. + bencode::BDE s = bencode::decode("5:aria2trail"); + CPPUNIT_ASSERT_EQUAL(std::string("aria2"), s.s()); + } +} + +void BencodeTest::testEncode() +{ + { + bencode::BDE dict = bencode::BDE::dict(); + dict["name"] = std::string("aria2"); + dict["loc"] = 80000; + dict["files"] = bencode::BDE::list(); + dict["files"] << std::string("aria2c"); + dict["attrs"] = bencode::BDE::dict(); + dict["attrs"]["license"] = std::string("GPL"); + + CPPUNIT_ASSERT_EQUAL(std::string("d" + "5:attrsd7:license3:GPLe" + "5:filesl6:aria2ce" + "3:loci80000e" + "4:name5:aria2" + "e"), + bencode::encode(dict)); + } +} + +} // namespace aria2 diff --git a/test/Makefile.am b/test/Makefile.am index ece04638..35baefb7 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -63,7 +63,8 @@ aria2c_SOURCES = AllTest.cc\ FtpConnectionTest.cc\ OptionParserTest.cc\ SimpleDNSCacheTest.cc\ - DownloadHelperTest.cc + DownloadHelperTest.cc\ + BencodeTest.cc if HAVE_LIBZ aria2c_SOURCES += GZipDecoderTest.cc diff --git a/test/Makefile.in b/test/Makefile.in index 63806457..a4ad2f90 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -197,7 +197,7 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \ DirectDiskAdaptorTest.cc CookieTest.cc CookieStorageTest.cc \ TimeTest.cc CopyDiskAdaptorTest.cc FtpConnectionTest.cc \ OptionParserTest.cc SimpleDNSCacheTest.cc \ - DownloadHelperTest.cc GZipDecoderTest.cc \ + DownloadHelperTest.cc BencodeTest.cc GZipDecoderTest.cc \ Sqlite3MozCookieParserTest.cc MessageDigestHelperTest.cc \ IteratableChunkChecksumValidatorTest.cc \ IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \ @@ -371,8 +371,8 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \ TimeTest.$(OBJEXT) CopyDiskAdaptorTest.$(OBJEXT) \ FtpConnectionTest.$(OBJEXT) OptionParserTest.$(OBJEXT) \ SimpleDNSCacheTest.$(OBJEXT) DownloadHelperTest.$(OBJEXT) \ - $(am__objects_1) $(am__objects_2) $(am__objects_3) \ - $(am__objects_4) $(am__objects_5) + BencodeTest.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) $(am__objects_4) $(am__objects_5) aria2c_OBJECTS = $(am_aria2c_OBJECTS) am__DEPENDENCIES_1 = aria2c_DEPENDENCIES = ../src/libaria2c.a ../src/download_helper.o \ @@ -595,8 +595,9 @@ aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \ DirectDiskAdaptorTest.cc CookieTest.cc CookieStorageTest.cc \ TimeTest.cc CopyDiskAdaptorTest.cc FtpConnectionTest.cc \ OptionParserTest.cc SimpleDNSCacheTest.cc \ - DownloadHelperTest.cc $(am__append_1) $(am__append_2) \ - $(am__append_3) $(am__append_4) $(am__append_5) + DownloadHelperTest.cc BencodeTest.cc $(am__append_1) \ + $(am__append_2) $(am__append_3) $(am__append_4) \ + $(am__append_5) #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 #aria2c_LDFLAGS = ${CPPUNIT_LIBS} @@ -692,6 +693,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthConfigFactoryTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BNodeTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64Test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BencodeTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BencodeVisitorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldManTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtAllowedFastMessageTest.Po@am__quote@ -- cgit