Home | History | Annotate | Download | only in quic
      1 // Copyright (c) 2012 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 "net/quic/quic_fec_group.h"
      6 
      7 #include <algorithm>
      8 #include <vector>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/logging.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "testing/gmock/include/gmock/gmock.h"
     14 
     15 using ::testing::_;
     16 using base::StringPiece;
     17 
     18 namespace net {
     19 
     20 namespace {
     21 
     22 const char* kData[] = {
     23   "abc12345678",
     24   "987defg",
     25   "ghi12345",
     26   "987jlkmno",
     27   "mno4567890",
     28   "789pqrstuvw",
     29 };
     30 
     31 const bool kEntropyFlag[] = {
     32   false,
     33   true,
     34   true,
     35   false,
     36   true,
     37   true,
     38 };
     39 
     40 }  // namespace
     41 
     42 class QuicFecGroupTest : public ::testing::Test {
     43  protected:
     44   void RunTest(size_t num_packets, size_t lost_packet, bool out_of_order) {
     45     size_t max_len = strlen(kData[0]);
     46     scoped_ptr<char[]> redundancy(new char[max_len]);
     47     for (size_t packet = 0; packet < num_packets; ++packet) {
     48       for (size_t i = 0; i < max_len; i++) {
     49         if (packet == 0) {
     50           // Initialize to the first packet.
     51           redundancy[i] = kData[0][i];
     52           continue;
     53         }
     54         // XOR in the remaining packets.
     55         uint8 byte = i > strlen(kData[packet]) ? 0x00 : kData[packet][i];
     56         redundancy[i] = redundancy[i] ^ byte;
     57       }
     58     }
     59 
     60     QuicFecGroup group;
     61 
     62     // If we're out of order, send the FEC packet in the position of the
     63     // lost packet. Otherwise send all (non-missing) packets, then FEC.
     64     if (out_of_order) {
     65       // Update the FEC state for each non-lost packet.
     66       for (size_t packet = 0; packet < num_packets; packet++) {
     67         if (packet == lost_packet) {
     68           ASSERT_FALSE(group.IsFinished());
     69           QuicFecData fec;
     70           fec.fec_group = 0;
     71           fec.redundancy = StringPiece(redundancy.get(), strlen(kData[0]));
     72           ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, num_packets,
     73                                       fec));
     74         } else {
     75           QuicPacketHeader header;
     76           header.packet_sequence_number = packet;
     77           header.entropy_flag = kEntropyFlag[packet];
     78           ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header,
     79                                    kData[packet]));
     80         }
     81         ASSERT_TRUE(group.CanRevive() == (packet == num_packets - 1));
     82       }
     83     } else {
     84       // Update the FEC state for each non-lost packet.
     85       for (size_t packet = 0; packet < num_packets; packet++) {
     86         if (packet == lost_packet) {
     87           continue;
     88         }
     89 
     90         QuicPacketHeader header;
     91         header.packet_sequence_number = packet;
     92         header.entropy_flag = kEntropyFlag[packet];
     93         ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header,
     94                                  kData[packet]));
     95         ASSERT_FALSE(group.CanRevive());
     96       }
     97 
     98       ASSERT_FALSE(group.IsFinished());
     99       // Attempt to revive the missing packet.
    100       QuicFecData fec;
    101       fec.fec_group = 0;
    102       fec.redundancy = StringPiece(redundancy.get(), strlen(kData[0]));
    103 
    104       ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, num_packets,
    105                                   fec));
    106     }
    107     QuicPacketHeader header;
    108     char recovered[kMaxPacketSize];
    109     ASSERT_TRUE(group.CanRevive());
    110     size_t len = group.Revive(&header, recovered, arraysize(recovered));
    111     ASSERT_NE(0u, len)
    112         << "Failed to revive packet " << lost_packet << " out of "
    113         << num_packets;
    114     EXPECT_EQ(lost_packet, header.packet_sequence_number)
    115         << "Failed to revive packet " << lost_packet << " out of "
    116         << num_packets;
    117     // Revived packets have an unknown entropy.
    118     EXPECT_FALSE(header.entropy_flag);
    119     ASSERT_GE(len, strlen(kData[lost_packet])) << "Incorrect length";
    120     for (size_t i = 0; i < strlen(kData[lost_packet]); i++) {
    121       EXPECT_EQ(kData[lost_packet][i], recovered[i]);
    122     }
    123     ASSERT_TRUE(group.IsFinished());
    124   }
    125 };
    126 
    127 TEST_F(QuicFecGroupTest, UpdateAndRevive) {
    128   RunTest(2, 0, false);
    129   RunTest(2, 1, false);
    130 
    131   RunTest(3, 0, false);
    132   RunTest(3, 1, false);
    133   RunTest(3, 2, false);
    134 }
    135 
    136 TEST_F(QuicFecGroupTest, UpdateAndReviveOutOfOrder) {
    137   RunTest(2, 0, true);
    138   RunTest(2, 1, true);
    139 
    140   RunTest(3, 0, true);
    141   RunTest(3, 1, true);
    142   RunTest(3, 2, true);
    143 }
    144 
    145 TEST_F(QuicFecGroupTest, UpdateFecIfReceivedPacketIsNotCovered) {
    146   char data1[] = "abc123";
    147   char redundancy[arraysize(data1)];
    148   for (size_t i = 0; i < arraysize(data1); i++) {
    149     redundancy[i] = data1[i];
    150   }
    151 
    152   QuicFecGroup group;
    153 
    154   QuicPacketHeader header;
    155   header.packet_sequence_number = 3;
    156   group.Update(ENCRYPTION_FORWARD_SECURE, header, data1);
    157 
    158   QuicFecData fec;
    159   fec.fec_group = 1;
    160   fec.redundancy = redundancy;
    161 
    162   header.packet_sequence_number = 2;
    163   ASSERT_FALSE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, 2, fec));
    164 }
    165 
    166 TEST_F(QuicFecGroupTest, ProtectsPacketsBefore) {
    167   QuicPacketHeader header;
    168   header.packet_sequence_number = 3;
    169 
    170   QuicFecGroup group;
    171   ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0]));
    172 
    173   EXPECT_FALSE(group.ProtectsPacketsBefore(1));
    174   EXPECT_FALSE(group.ProtectsPacketsBefore(2));
    175   EXPECT_FALSE(group.ProtectsPacketsBefore(3));
    176   EXPECT_TRUE(group.ProtectsPacketsBefore(4));
    177   EXPECT_TRUE(group.ProtectsPacketsBefore(5));
    178   EXPECT_TRUE(group.ProtectsPacketsBefore(50));
    179 }
    180 
    181 TEST_F(QuicFecGroupTest, ProtectsPacketsBeforeWithSeveralPackets) {
    182   QuicPacketHeader header;
    183   header.packet_sequence_number = 3;
    184 
    185   QuicFecGroup group;
    186   ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0]));
    187 
    188   header.packet_sequence_number = 7;
    189   ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0]));
    190 
    191   header.packet_sequence_number = 5;
    192   ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0]));
    193 
    194   EXPECT_FALSE(group.ProtectsPacketsBefore(1));
    195   EXPECT_FALSE(group.ProtectsPacketsBefore(2));
    196   EXPECT_FALSE(group.ProtectsPacketsBefore(3));
    197   EXPECT_TRUE(group.ProtectsPacketsBefore(4));
    198   EXPECT_TRUE(group.ProtectsPacketsBefore(5));
    199   EXPECT_TRUE(group.ProtectsPacketsBefore(6));
    200   EXPECT_TRUE(group.ProtectsPacketsBefore(7));
    201   EXPECT_TRUE(group.ProtectsPacketsBefore(8));
    202   EXPECT_TRUE(group.ProtectsPacketsBefore(9));
    203   EXPECT_TRUE(group.ProtectsPacketsBefore(50));
    204 }
    205 
    206 TEST_F(QuicFecGroupTest, ProtectsPacketsBeforeWithFecData) {
    207   QuicFecData fec;
    208   fec.fec_group = 2;
    209   fec.redundancy = kData[0];
    210 
    211   QuicFecGroup group;
    212   ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, 3, fec));
    213 
    214   EXPECT_FALSE(group.ProtectsPacketsBefore(1));
    215   EXPECT_FALSE(group.ProtectsPacketsBefore(2));
    216   EXPECT_TRUE(group.ProtectsPacketsBefore(3));
    217   EXPECT_TRUE(group.ProtectsPacketsBefore(4));
    218   EXPECT_TRUE(group.ProtectsPacketsBefore(5));
    219   EXPECT_TRUE(group.ProtectsPacketsBefore(50));
    220 }
    221 
    222 TEST_F(QuicFecGroupTest, EffectiveEncryptionLevel) {
    223   QuicFecGroup group;
    224   EXPECT_EQ(NUM_ENCRYPTION_LEVELS, group.effective_encryption_level());
    225 
    226   QuicPacketHeader header;
    227   header.packet_sequence_number = 5;
    228   ASSERT_TRUE(group.Update(ENCRYPTION_INITIAL, header, kData[0]));
    229   EXPECT_EQ(ENCRYPTION_INITIAL, group.effective_encryption_level());
    230 
    231   QuicFecData fec;
    232   fec.fec_group = 0;
    233   fec.redundancy = kData[0];
    234   ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, 7, fec));
    235   EXPECT_EQ(ENCRYPTION_INITIAL, group.effective_encryption_level());
    236 
    237   header.packet_sequence_number = 3;
    238   ASSERT_TRUE(group.Update(ENCRYPTION_NONE, header, kData[0]));
    239   EXPECT_EQ(ENCRYPTION_NONE, group.effective_encryption_level());
    240 }
    241 
    242 }  // namespace net
    243