LCOV - code coverage report
Current view: top level - tests - DecoderTests.cpp (source / functions) Hit Total Coverage
Test: cpp-bencoding code coverage Lines: 255 258 98.8 %
Date: 2018-04-21 15:28:44 Functions: 152 153 99.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /**
       2             : * @file      DecoderTests.cpp
       3             : * @copyright (c) 2014 by Petr Zemek (s3rvac@gmail.com) and contributors
       4             : * @license   BSD, see the @c LICENSE file for more details
       5             : * @brief     Tests for the Decoder class.
       6             : */
       7             : 
       8             : #include <memory>
       9             : #include <sstream>
      10             : 
      11             : #include <gtest/gtest.h>
      12             : 
      13             : #include "BDictionary.h"
      14             : #include "BInteger.h"
      15             : #include "BList.h"
      16             : #include "BString.h"
      17             : #include "Decoder.h"
      18             : #include "TestUtils.h"
      19             : 
      20             : namespace bencoding {
      21             : namespace tests {
      22             : 
      23             : using namespace testing;
      24             : 
      25          36 : class DecoderTests: public Test {
      26             : protected:
      27          36 :     DecoderTests(): decoder(Decoder::create()) {}
      28             : 
      29             :     template <typename T>
      30             :     void assertDecodedAs(std::shared_ptr<BItem> bItem);
      31             : 
      32             : protected:
      33             :     std::unique_ptr<Decoder> decoder;
      34             : };
      35             : 
      36             : template <typename T>
      37          30 : void DecoderTests::assertDecodedAs(
      38             :         std::shared_ptr<BItem> bItem) {
      39             : 
      40          60 :     ASSERT_NE(bItem, nullptr)
      41           0 :         << "expected a correctly decoded item";
      42          60 :     EXPECT_NE(bItem->as<T>(), nullptr)
      43           0 :         << "expected " << typeid(T).name() << ", "
      44           0 :         << "got " << typeid(*bItem).name();
      45             : }
      46             : 
      47             : //
      48             : // Dictionary decoding.
      49             : //
      50             : 
      51           5 : TEST_F(DecoderTests,
      52             : EmptyDictionaryIsDecodedCorrectly) {
      53           2 :     std::string data("de");
      54           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
      55             : 
      56           2 :     ADD_SCOPED_TRACE;
      57           1 :     assertDecodedAs<BDictionary>(bItem);
      58           2 :     auto bDictionary = bItem->as<BDictionary>();
      59           1 :     EXPECT_TRUE(bDictionary->empty());
      60           1 : }
      61             : 
      62           5 : TEST_F(DecoderTests,
      63             : DictionaryWithSingleItemIsDecodedCorrectly) {
      64           2 :     std::string data("d4:testi1ee");
      65           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
      66             : 
      67           2 :     ADD_SCOPED_TRACE;
      68           1 :     assertDecodedAs<BDictionary>(bItem);
      69           2 :     auto bDictionary = bItem->as<BDictionary>();
      70           1 :     EXPECT_EQ(1, bDictionary->size());
      71             : 
      72           1 :     auto i = bDictionary->begin();
      73           1 :     assertDecodedAs<BString>(i->first);
      74           2 :     auto key = i->first->as<BString>();
      75           1 :     EXPECT_EQ("test", key->value());
      76             : 
      77           1 :     assertDecodedAs<BInteger>(i->second);
      78           2 :     auto value = i->second->as<BInteger>();
      79           1 :     EXPECT_EQ(1, value->value());
      80           1 : }
      81             : 
      82           5 : TEST_F(DecoderTests,
      83             : DictionaryWithTwoItemsIsDecodedCorrectly) {
      84           2 :     std::string data("d5:test1i1e5:test2i2ee");
      85           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
      86             : 
      87           2 :     ADD_SCOPED_TRACE;
      88           1 :     assertDecodedAs<BDictionary>(bItem);
      89           2 :     auto bDictionary = bItem->as<BDictionary>();
      90           1 :     EXPECT_EQ(2, bDictionary->size());
      91             : 
      92           1 :     auto i = bDictionary->begin();
      93           1 :     assertDecodedAs<BString>(i->first);
      94           2 :     auto key1 = i->first->as<BString>();
      95           1 :     EXPECT_EQ("test1", key1->value());
      96             : 
      97           1 :     assertDecodedAs<BInteger>(i->second);
      98           2 :     auto value1 = i->second->as<BInteger>();
      99           1 :     EXPECT_EQ(1, value1->value());
     100             : 
     101           1 :     ++i;
     102           1 :     assertDecodedAs<BString>(i->first);
     103           2 :     auto key2 = i->first->as<BString>();
     104           1 :     EXPECT_EQ("test2", key2->value());
     105             : 
     106           1 :     assertDecodedAs<BInteger>(i->second);
     107           2 :     auto value2 = i->second->as<BInteger>();
     108           1 :     EXPECT_EQ(2, value2->value());
     109           1 : }
     110             : 
     111           5 : TEST_F(DecoderTests,
     112             : DictionaryWithKeysThatAreNotSortedIsDecodedCorrectly) {
     113             :     // Even though the specification says that a dictionary has all its keys
     114             :     // lexicographically sorted, we support the decoding of dictionaries whose
     115             :     // keys are not sorted. The resulting dictionary, however, will always have
     116             :     // its keys sorted to conform to the specification.
     117           2 :     std::string data("d1:bi2e1:ai1ee");
     118           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
     119             : 
     120           2 :     ADD_SCOPED_TRACE;
     121           1 :     assertDecodedAs<BDictionary>(bItem);
     122           2 :     auto bDictionary = bItem->as<BDictionary>();
     123           1 :     EXPECT_EQ(2, bDictionary->size());
     124             : 
     125           1 :     auto i = bDictionary->begin();
     126           1 :     assertDecodedAs<BString>(i->first);
     127           2 :     auto key1 = i->first->as<BString>();
     128           1 :     EXPECT_EQ("a", key1->value());
     129             : 
     130           1 :     assertDecodedAs<BInteger>(i->second);
     131           2 :     auto value1 = i->second->as<BInteger>();
     132           1 :     EXPECT_EQ(1, value1->value());
     133             : 
     134           1 :     ++i;
     135           1 :     assertDecodedAs<BString>(i->first);
     136           2 :     auto key2 = i->first->as<BString>();
     137           1 :     EXPECT_EQ("b", key2->value());
     138             : 
     139           1 :     assertDecodedAs<BInteger>(i->second);
     140           2 :     auto value2 = i->second->as<BInteger>();
     141           1 :     EXPECT_EQ(2, value2->value());
     142           1 : }
     143             : 
     144           5 : TEST_F(DecoderTests,
     145             : DecodeThrowsDecodingErrorWhenDecodingDictionaryWithoutEndingE) {
     146           2 :     EXPECT_THROW(decoder->decode("d"), DecodingError);
     147           1 : }
     148             : 
     149           5 : TEST_F(DecoderTests,
     150             : DecodeThrowsDecodingErrorWhenDecodingDictionaryWithKeyNotBeingString) {
     151           2 :     EXPECT_THROW(decoder->decode("di1ei2ee"), DecodingError);
     152           1 : }
     153             : 
     154             : //
     155             : // Integer decoding.
     156             : //
     157             : 
     158           5 : TEST_F(DecoderTests,
     159             : IntegerZeroIsCorrectlyDecoded) {
     160           2 :     std::string data("i0e");
     161           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
     162             : 
     163           2 :     ADD_SCOPED_TRACE;
     164           1 :     assertDecodedAs<BInteger>(bItem);
     165           2 :     auto bInteger = bItem->as<BInteger>();
     166           1 :     EXPECT_EQ(0, bInteger->value());
     167           1 : }
     168             : 
     169           5 : TEST_F(DecoderTests,
     170             : PositiveIntegerIsCorrectlyDecoded) {
     171           2 :     std::shared_ptr<BItem> bItem(decoder->decode("i13e"));
     172             : 
     173           2 :     ADD_SCOPED_TRACE;
     174           1 :     assertDecodedAs<BInteger>(bItem);
     175           2 :     auto bInteger = bItem->as<BInteger>();
     176           1 :     EXPECT_EQ(13, bInteger->value());
     177           1 : }
     178             : 
     179           5 : TEST_F(DecoderTests,
     180             : ExplicitlyPositiveIntegerIsCorrectlyDecoded) {
     181           2 :     std::shared_ptr<BItem> bItem(decoder->decode("i+13e"));
     182             : 
     183           2 :     ADD_SCOPED_TRACE;
     184           1 :     assertDecodedAs<BInteger>(bItem);
     185           2 :     auto bInteger = bItem->as<BInteger>();
     186           1 :     EXPECT_EQ(+13, bInteger->value());
     187           1 : }
     188             : 
     189           5 : TEST_F(DecoderTests,
     190             : NegativeIntegerIsCorrectlyDecoded) {
     191           2 :     std::shared_ptr<BItem> bItem(decoder->decode("i-13e"));
     192             : 
     193           2 :     ADD_SCOPED_TRACE;
     194           1 :     assertDecodedAs<BInteger>(bItem);
     195           2 :     auto bInteger = bItem->as<BInteger>();
     196           1 :     EXPECT_EQ(-13, bInteger->value());
     197           1 : }
     198             : 
     199           5 : TEST_F(DecoderTests,
     200             : DecodeThrowsDecodingErrorWhenDecodingIntegerWithoutEndingE) {
     201           2 :     EXPECT_THROW(decoder->decode("i13"), DecodingError);
     202           1 : }
     203             : 
     204           5 : TEST_F(DecoderTests,
     205             : DecodeThrowsDecodingErrorWhenDecodingIntegerWithoutValue) {
     206           2 :     EXPECT_THROW(decoder->decode("ie"), DecodingError);
     207           1 : }
     208             : 
     209           5 : TEST_F(DecoderTests,
     210             : DecodeThrowsDecodingErrorWhenDecodingIntegerWithBeginningWhitespace) {
     211           2 :     EXPECT_THROW(decoder->decode("i 1e"), DecodingError);
     212           1 : }
     213             : 
     214           5 : TEST_F(DecoderTests,
     215             : DecodeThrowsDecodingErrorWhenDecodingIntegerWithTrailingWhitespace) {
     216           2 :     EXPECT_THROW(decoder->decode("i1 e"), DecodingError);
     217           1 : }
     218             : 
     219           5 : TEST_F(DecoderTests,
     220             : DecodeThrowsDecodingErrorWhenDecodingIntegerIsPaddedWithZeros) {
     221             :     // From https://wiki.theory.org/BitTorrentSpecification#Bencoding:
     222             :     //
     223             :     // "Only the significant digits should be used, one cannot pad the Integer
     224             :     //  with zeroes. such as i04e."
     225             :     //
     226           2 :     EXPECT_THROW(decoder->decode("i001e"), DecodingError);
     227           1 : }
     228             : 
     229           5 : TEST_F(DecoderTests,
     230             : DecodeThrowsDecodingErrorWhenDecodingIntegerOfInvalidValue) {
     231           2 :     EXPECT_THROW(decoder->decode("i e"), DecodingError);
     232           2 :     EXPECT_THROW(decoder->decode("i+e"), DecodingError);
     233           2 :     EXPECT_THROW(decoder->decode("i-e"), DecodingError);
     234           2 :     EXPECT_THROW(decoder->decode("i1-e"), DecodingError);
     235           2 :     EXPECT_THROW(decoder->decode("i1+e"), DecodingError);
     236           2 :     EXPECT_THROW(decoder->decode("i$e"), DecodingError);
     237           2 :     EXPECT_THROW(decoder->decode("i1.1e"), DecodingError);
     238           1 : }
     239             : 
     240             : //
     241             : // List decoding.
     242             : //
     243             : 
     244           5 : TEST_F(DecoderTests,
     245             : EmptyListIsCorrectlyDecoded) {
     246           2 :     std::string data("le");
     247           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
     248             : 
     249           2 :     ADD_SCOPED_TRACE;
     250           1 :     assertDecodedAs<BList>(bItem);
     251           2 :     auto bList = bItem->as<BList>();
     252           1 :     EXPECT_TRUE(bList->empty());
     253           1 : }
     254             : 
     255           5 : TEST_F(DecoderTests,
     256             : ListWithSingleIntegerIsDecodedCorrectly) {
     257           2 :     std::string data("li1ee");
     258           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
     259             : 
     260           2 :     ADD_SCOPED_TRACE;
     261           1 :     assertDecodedAs<BList>(bItem);
     262           2 :     auto bList = bItem->as<BList>();
     263           1 :     ASSERT_EQ(1, bList->size());
     264           2 :     auto firstItem = bList->front();
     265           1 :     assertDecodedAs<BInteger>(firstItem);
     266           2 :     auto firstItemAsInteger = firstItem->as<BInteger>();
     267           1 :     EXPECT_EQ(1, firstItemAsInteger->value());
     268             : }
     269             : 
     270           5 : TEST_F(DecoderTests,
     271             : ListWithTwoStringsIsDecodedCorrectly) {
     272           2 :     std::string data("l4:test5:helloe");
     273           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
     274             : 
     275           2 :     ADD_SCOPED_TRACE;
     276           1 :     assertDecodedAs<BList>(bItem);
     277           2 :     auto bList = bItem->as<BList>();
     278           1 :     ASSERT_EQ(2, bList->size());
     279             :     // "test"
     280           2 :     auto firstItem = bList->front();
     281           1 :     assertDecodedAs<BString>(firstItem);
     282           2 :     auto firstItemAsString = firstItem->as<BString>();
     283           1 :     EXPECT_EQ("test", firstItemAsString->value());
     284             :     // "hello"
     285           2 :     auto secondItem = bList->back();
     286           1 :     assertDecodedAs<BString>(secondItem);
     287           2 :     auto secondItemAsString = secondItem->as<BString>();
     288           1 :     EXPECT_EQ("hello", secondItemAsString->value());
     289             : }
     290             : 
     291           5 : TEST_F(DecoderTests,
     292             : DecodeThrowsDecodingErrorWhenCharEIsMissingFromEndOfList) {
     293           2 :     EXPECT_THROW(decoder->decode("li1e"), DecodingError);
     294           2 :     EXPECT_THROW(decoder->decode("l4:test"), DecodingError);
     295           1 : }
     296             : 
     297           5 : TEST_F(DecoderTests,
     298             : DecodeThrowsDecodingErrorWhenListItemIsInvalidIsMissingFromEndOfList) {
     299           2 :     EXPECT_THROW(decoder->decode("l$e"), DecodingError);
     300           1 : }
     301             : 
     302             : //
     303             : // String decoding.
     304             : //
     305             : 
     306           5 : TEST_F(DecoderTests,
     307             : EmptyStringIsCorrrectlyDecoded) {
     308           2 :     std::string data("0:");
     309           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
     310             : 
     311           2 :     ADD_SCOPED_TRACE;
     312           1 :     assertDecodedAs<BString>(bItem);
     313           2 :     auto bString = bItem->as<BString>();
     314           1 :     EXPECT_EQ("", bString->value());
     315           1 : }
     316             : 
     317           5 : TEST_F(DecoderTests,
     318             : NonemptyStringWithSingleCharacterIsCorrrectlyDecoded) {
     319           2 :     std::string data("1:a");
     320           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
     321             : 
     322           2 :     ADD_SCOPED_TRACE;
     323           1 :     assertDecodedAs<BString>(bItem);
     324           2 :     auto bString = bItem->as<BString>();
     325           1 :     EXPECT_EQ("a", bString->value());
     326           1 : }
     327             : 
     328           5 : TEST_F(DecoderTests,
     329             : NonemptyStringWithTenCharacterIsCorrrectlyDecoded) {
     330           2 :     std::string data("10:abcdefghij");
     331           2 :     std::shared_ptr<BItem> bItem(decoder->decode(data));
     332             : 
     333           2 :     ADD_SCOPED_TRACE;
     334           1 :     assertDecodedAs<BString>(bItem);
     335           2 :     auto bString = bItem->as<BString>();
     336           1 :     EXPECT_EQ("abcdefghij", bString->value());
     337           1 : }
     338             : 
     339           5 : TEST_F(DecoderTests,
     340             : DecodeThrowsDecodingErrorWhenColonIsMissingInString) {
     341           2 :     EXPECT_THROW(decoder->decode("1a"), DecodingError);
     342           1 : }
     343             : 
     344           5 : TEST_F(DecoderTests,
     345             : DecodeThrowsDecodingErrorWhenStringHasNotEnoughCharacters) {
     346           2 :     EXPECT_THROW(decoder->decode("3:aa"), DecodingError);
     347           1 : }
     348             : 
     349             : //
     350             : // Other.
     351             : //
     352             : 
     353           5 : TEST_F(DecoderTests,
     354             : DecodeThrowsDecodingErrorWhenInputIsEmpty) {
     355           2 :     EXPECT_THROW(decoder->decode(""), DecodingError);
     356           1 : }
     357             : 
     358           5 : TEST_F(DecoderTests,
     359             : DecodeThrowsDecodingErrorWhenInputIsAtEOF) {
     360           2 :     std::istringstream input;
     361           1 :     putIntoEOFState(input);
     362             : 
     363           2 :     EXPECT_THROW(decoder->decode(input), DecodingError);
     364           1 : }
     365             : 
     366           5 : TEST_F(DecoderTests,
     367             : DecodeThrowsDecodingErrorWhenInputIsInError) {
     368           2 :     std::istringstream input;
     369           1 :     putIntoErrorState(input);
     370             : 
     371           2 :     EXPECT_THROW(decoder->decode(input), DecodingError);
     372           1 : }
     373             : 
     374           5 : TEST_F(DecoderTests,
     375             : DecodeThrowsDecodingErrorWhenInputBeginsWithInvalidSymbol) {
     376           2 :     EXPECT_THROW(decoder->decode("$"), DecodingError);
     377           1 : }
     378             : 
     379           5 : TEST_F(DecoderTests,
     380             : DecodeThrowsDecodingErrorWhenInputBeginsWithUnexpectedSymbol) {
     381           2 :     EXPECT_THROW(decoder->decode("e"), DecodingError);
     382           1 : }
     383             : 
     384           5 : TEST_F(DecoderTests,
     385             : DecodeForStringThrowsDecodingErrorWhenInputIsNotCompletelyRead) {
     386             :     // Only the first i1e should be decoded, thus leaving i2e unread (such an
     387             :     // input is invalid as the integers are not inside of a list).
     388           2 :     EXPECT_THROW(decoder->decode("i1ei2e"), DecodingError);
     389           1 : }
     390             : 
     391           5 : TEST_F(DecoderTests,
     392             : DecodeFromStreamWorksAsDecodeFromString) {
     393           2 :     std::istringstream input("i0e");
     394           2 :     std::shared_ptr<BItem> bItem(decoder->decode(input));
     395             : 
     396           2 :     ADD_SCOPED_TRACE;
     397           1 :     assertDecodedAs<BInteger>(bItem);
     398           2 :     auto bInteger = bItem->as<BInteger>();
     399           1 :     EXPECT_EQ(0, bInteger->value());
     400           1 : }
     401             : 
     402           5 : TEST_F(DecoderTests,
     403             : DecodeForStreamDoesNotReadCharactersPassFirstDecodedItem) {
     404             :     // The second i2e is supposed to be left in the stream.
     405           2 :     std::istringstream input("i1ei2e");
     406           2 :     std::shared_ptr<BItem> bItem(decoder->decode(input));
     407             : 
     408           1 :     ASSERT_EQ('i', input.get());
     409           1 :     ASSERT_EQ('2', input.get());
     410           1 :     ASSERT_EQ('e', input.get());
     411             : }
     412             : 
     413           5 : TEST_F(DecoderTests,
     414             : DecodeFunctionForStringWorksAsCreatingDecoderAndCallingDecode) {
     415           2 :     std::string input("i0e");
     416           2 :     std::shared_ptr<BItem> bItem(decode(input));
     417             : 
     418           2 :     ADD_SCOPED_TRACE;
     419           1 :     assertDecodedAs<BInteger>(bItem);
     420           2 :     auto bInteger = bItem->as<BInteger>();
     421           1 :     EXPECT_EQ(0, bInteger->value());
     422           1 : }
     423             : 
     424           5 : TEST_F(DecoderTests,
     425             : DecodeFunctionForStreamWorksAsCreatingDecoderAndCallingDecode) {
     426           2 :     std::istringstream input("i0e");
     427           2 :     std::shared_ptr<BItem> bItem(decode(input));
     428             : 
     429           2 :     ADD_SCOPED_TRACE;
     430           1 :     assertDecodedAs<BInteger>(bItem);
     431           2 :     auto bInteger = bItem->as<BInteger>();
     432           1 :     EXPECT_EQ(0, bInteger->value());
     433           1 : }
     434             : 
     435             : } // namespace tests
     436           3 : } // namespace bencoding

Generated by: LCOV version 1.13