Home | History | Annotate | Download | only in net
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/basictypes.h"
      6 #include "chrome/browser/net/quoted_printable.h"
      7 #include "testing/gtest/include/gtest/gtest.h"
      8 
      9 namespace {
     10 
     11 class QuotedPrintableTest : public testing::Test {
     12 };
     13 
     14 const char* const kNormalText[] = {
     15   // Basic sentence with an =.
     16   "If you believe that truth=beauty, then surely mathematics is the most "
     17   "beautiful branch of philosophy.",
     18 
     19   // All ASCII chars.
     20   "\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF"
     21   "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
     22   "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F"
     23   "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
     24   "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F"
     25   "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F"
     26   "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F"
     27   "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F"
     28   "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
     29   "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
     30   "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
     31   "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF"
     32   "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF"
     33   "\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF"
     34   "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF"
     35   "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF",
     36 
     37   // Space right before max char per line.
     38   "This line has a space at the 75 characters mark = ********************** "
     39   "The end.",
     40 
     41   // Space on max char per line index.
     42   "This line has a space at the 76 characters mark = *********************** "
     43   "The end.",
     44 
     45   // Space at end of line.
     46   "This line ends with a space \r\nThe end.",
     47 
     48   // Space at end of input.
     49   "This input ends with a space. ",
     50 
     51   // Tab right before max char per line.
     52   "This line has a tab at the 75 characters mark = ************************\t"
     53   "The end.",
     54 
     55   // Tab on max char per line index.
     56   "This line has a tab at the 76 characters mark = *************************\t"
     57   "The end.",
     58 
     59   // Tab at end of line.
     60   "This line ends with a tab\t\r\nThe end.",
     61 
     62   // Tab at end of input.
     63   "This input ends with a tab.\t",
     64 
     65   // Various EOLs in input.
     66   "This is a test of having EOLs in the input\r\n"
     67   "Any EOL should be converted \r to \n a CRLF \r\n."
     68 };
     69 
     70 const char* const kEncodedText[] = {
     71   "If you believe that truth=3Dbeauty, then surely mathematics is the most "
     72   "bea=\r\nutiful branch of philosophy.",
     73 
     74   "=01=02=03=04=05=06=07=08=09\r\n"
     75   "=0B=0C\r\n"
     76   "=0E=0F=10=11=12=13=14=15=16=17=18=19=1A=1B=1C=1D=1E=1F !\"#$%&'()*+,-./01234"
     77     "=\r\n"
     78   "56789:;<=3D>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}"
     79     "=\r\n"
     80   "~=7F=80=81=82=83=84=85=86=87=88=89=8A=8B=8C=8D=8E=8F=90=91=92=93=94=95=96="
     81     "\r\n"
     82   "=97=98=99=9A=9B=9C=9D=9E=9F=A0=A1=A2=A3=A4=A5=A6=A7=A8=A9=AA=AB=AC=AD=AE=AF="
     83     "\r\n"
     84   "=B0=B1=B2=B3=B4=B5=B6=B7=B8=B9=BA=BB=BC=BD=BE=BF=C0=C1=C2=C3=C4=C5=C6=C7=C8="
     85     "\r\n"
     86   "=C9=CA=CB=CC=CD=CE=CF=D0=D1=D2=D3=D4=D5=D6=D7=D8=D9=DA=DB=DC=DD=DE=DF=E0=E1="
     87     "\r\n"
     88   "=E2=E3=E4=E5=E6=E7=E8=E9=EA=EB=EC=ED=EE=EF=F0=F1=F2=F3=F4=F5=F6=F7=F8=F9=FA="
     89     "\r\n"
     90   "=FB=FC=FD=FE=FF",
     91 
     92   "This line has a space at the 75 characters mark =3D ********************** ="
     93   "\r\nThe end.",
     94 
     95   "This line has a space at the 76 characters mark =3D ***********************="
     96   "\r\n The end.",
     97 
     98   "This line ends with a space=20\r\nThe end.",
     99 
    100   "This input ends with a space.=20",
    101 
    102   "This line has a tab at the 75 characters mark =3D ************************\t"
    103       "=\r\nThe end.",
    104 
    105   "This line has a tab at the 76 characters mark =3D *************************="
    106   "\r\n\tThe end.",
    107 
    108   "This line ends with a tab=09\r\nThe end.",
    109 
    110   "This input ends with a tab.=09",
    111 
    112   "This is a test of having EOLs in the input\r\n"
    113   "Any EOL should be converted=20\r\n to=20\r\n a CRLF=20\r\n."
    114 };
    115 
    116 
    117 const char* const kBadEncodedText[] = {
    118   // Invalid finish with =.
    119   "A =3D at the end of the input is bad=",
    120 
    121   // Invalid = sequence.
    122   "This line contains a valid =3D sequence and invalid ones =$$ = =\t =1 = 2 "
    123       "==",
    124 };
    125 
    126 const char* const kBadEncodedTextDecoded[] = {
    127   "A = at the end of the input is bad=",
    128 
    129   "This line contains a valid = sequence and invalid ones =$$ = =\t =1 = 2 ==",
    130 };
    131 
    132 // Compares the 2 strings and returns true if they are identical, but for EOLs
    133 // that don't have to be the same (ex: \r\n can match \n).
    134 bool CompareEOLInsensitive(const std::string& s1, const std::string& s2) {
    135   std::string::const_iterator s1_iter = s1.begin();
    136   std::string::const_iterator s2_iter = s2.begin();
    137 
    138   while (true) {
    139     if (s1_iter == s1.end() && s2_iter == s2.end())
    140       return true;
    141     if ((s1_iter == s1.end() && s2_iter != s2.end()) ||
    142         (s1_iter != s1.end() && s2_iter == s2.end())) {
    143       return false;
    144     }
    145     int s1_eol = chrome::browser::net::IsEOL(s1_iter, s1);
    146     int s2_eol = chrome::browser::net::IsEOL(s2_iter, s2);
    147     if ((!s1_eol && s2_eol) || (s1_eol && !s2_eol)) {
    148       // Unmatched EOL.
    149       return false;
    150     }
    151     if (s1_eol > 0) {
    152       s1_iter += s1_eol;
    153       s2_iter += s2_eol;
    154     } else {
    155       // Non-EOL char.
    156       if (*s1_iter != *s2_iter)
    157         return false;
    158       s1_iter++;
    159       s2_iter++;
    160     }
    161   }
    162   return true;
    163 }
    164 
    165 }  // namespace
    166 
    167 TEST(QuotedPrintableTest, Encode) {
    168   ASSERT_EQ(arraysize(kNormalText), arraysize(kEncodedText));
    169   for (size_t i = 0; i < arraysize(kNormalText); ++i) {
    170     SCOPED_TRACE(::testing::Message() << "Iteration " << i);
    171     std::string output;
    172     chrome::browser::net::QuotedPrintableEncode(kNormalText[i], &output);
    173     std::string expected(kEncodedText[i]);
    174     EXPECT_EQ(expected, output);
    175   }
    176 }
    177 
    178 TEST(QuotedPrintableTest, Decode) {
    179   ASSERT_EQ(arraysize(kNormalText), arraysize(kEncodedText));
    180   for (size_t i = 0; i < arraysize(kNormalText); ++i) {
    181     std::string output;
    182     EXPECT_TRUE(chrome::browser::net::QuotedPrintableDecode(
    183         kEncodedText[i], &output));
    184     std::string expected(kNormalText[i]);
    185     SCOPED_TRACE(::testing::Message() << "Iteration " << i <<
    186                  "\n  Actual=\n" << output << "\n  Expected=\n" <<
    187                  expected);
    188     // We cannot test for equality as EOLs won't match the normal text
    189     // (as any EOL is converted to a CRLF during encoding).
    190     EXPECT_TRUE(CompareEOLInsensitive(expected, output));
    191   }
    192 }
    193 
    194 // Tests that we return false but still do our best to decode badly encoded
    195 // inputs.
    196 TEST(QuotedPrintableTest, DecodeBadInput) {
    197   ASSERT_EQ(arraysize(kBadEncodedText), arraysize(kBadEncodedTextDecoded));
    198   for (size_t i = 0; i < arraysize(kBadEncodedText); ++i) {
    199     SCOPED_TRACE(::testing::Message() << "Iteration " << i);
    200     std::string output;
    201     EXPECT_FALSE(chrome::browser::net::QuotedPrintableDecode(
    202         kBadEncodedText[i], &output));
    203     std::string expected(kBadEncodedTextDecoded[i]);
    204     EXPECT_EQ(expected, output);
    205   }
    206 }
    207