15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_fec_group.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* kData[] = {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "abc12345678",
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "987defg",
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "ghi12345",
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "987jlkmno",
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "mno4567890",
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "789pqrstuvw",
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const bool kEntropyFlag[] = {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  false,
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  true,
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  true,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  false,
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  true,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  true,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class QuicFecGroupTest : public ::testing::Test {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunTest(size_t num_packets, size_t lost_packet, bool out_of_order) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t max_len = strlen(kData[0]);
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_ptr<char[]> redundancy(new char[max_len]);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t packet = 0; packet < num_packets; ++packet) {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (size_t i = 0; i < max_len; i++) {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (packet == 0) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Initialize to the first packet.
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          redundancy[i] = kData[0][i];
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          continue;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // XOR in the remaining packets.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint8 byte = i > strlen(kData[packet]) ? 0x00 : kData[packet][i];
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        redundancy[i] = redundancy[i] ^ byte;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuicFecGroup group;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we're out of order, send the FEC packet in the position of the
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // lost packet. Otherwise send all (non-missing) packets, then FEC.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (out_of_order) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Update the FEC state for each non-lost packet.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t packet = 0; packet < num_packets; packet++) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (packet == lost_packet) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ASSERT_FALSE(group.IsFinished());
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          QuicFecData fec;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          fec.fec_group = 0;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          fec.redundancy = StringPiece(redundancy.get(), strlen(kData[0]));
72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, num_packets,
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                      fec));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          QuicPacketHeader header;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          header.packet_sequence_number = packet;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          header.entropy_flag = kEntropyFlag[packet];
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header,
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                   kData[packet]));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASSERT_TRUE(group.CanRevive() == (packet == num_packets - 1));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Update the FEC state for each non-lost packet.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t packet = 0; packet < num_packets; packet++) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (packet == lost_packet) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        QuicPacketHeader header;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        header.packet_sequence_number = packet;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        header.entropy_flag = kEntropyFlag[packet];
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header,
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                 kData[packet]));
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASSERT_FALSE(group.CanRevive());
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_FALSE(group.IsFinished());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Attempt to revive the missing packet.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      QuicFecData fec;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fec.fec_group = 0;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fec.redundancy = StringPiece(redundancy.get(), strlen(kData[0]));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, num_packets,
105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                  fec));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuicPacketHeader header;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char recovered[kMaxPacketSize];
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(group.CanRevive());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t len = group.Revive(&header, recovered, arraysize(recovered));
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_NE(0u, len)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Failed to revive packet " << lost_packet << " out of "
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << num_packets;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(lost_packet, header.packet_sequence_number)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Failed to revive packet " << lost_packet << " out of "
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << num_packets;
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Revived packets have an unknown entropy.
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_FALSE(header.entropy_flag);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_GE(len, strlen(kData[lost_packet])) << "Incorrect length";
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < strlen(kData[lost_packet]); i++) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(kData[lost_packet][i], recovered[i]);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(group.IsFinished());
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(QuicFecGroupTest, UpdateAndRevive) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(2, 0, false);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(2, 1, false);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(3, 0, false);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(3, 1, false);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(3, 2, false);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(QuicFecGroupTest, UpdateAndReviveOutOfOrder) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(2, 0, true);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(2, 1, true);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(3, 0, true);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(3, 1, true);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(3, 2, true);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(QuicFecGroupTest, UpdateFecIfReceivedPacketIsNotCovered) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char data1[] = "abc123";
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char redundancy[arraysize(data1)];
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(data1); i++) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    redundancy[i] = data1[i];
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicFecGroup group;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicPacketHeader header;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header.packet_sequence_number = 3;
156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  group.Update(ENCRYPTION_FORWARD_SECURE, header, data1);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicFecData fec;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fec.fec_group = 1;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fec.redundancy = redundancy;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  header.packet_sequence_number = 2;
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ASSERT_FALSE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, 2, fec));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(QuicFecGroupTest, ProtectsPacketsBefore) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicPacketHeader header;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header.packet_sequence_number = 3;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicFecGroup group;
171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0]));
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(group.ProtectsPacketsBefore(1));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(group.ProtectsPacketsBefore(2));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(group.ProtectsPacketsBefore(3));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(4));
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(5));
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(50));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(QuicFecGroupTest, ProtectsPacketsBeforeWithSeveralPackets) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicPacketHeader header;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header.packet_sequence_number = 3;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicFecGroup group;
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0]));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header.packet_sequence_number = 7;
189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0]));
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header.packet_sequence_number = 5;
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0]));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(group.ProtectsPacketsBefore(1));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(group.ProtectsPacketsBefore(2));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(group.ProtectsPacketsBefore(3));
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(4));
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(5));
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(6));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(7));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(8));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(9));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(50));
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(QuicFecGroupTest, ProtectsPacketsBeforeWithFecData) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicFecData fec;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fec.fec_group = 2;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fec.redundancy = kData[0];
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicFecGroup group;
212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, 3, fec));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(group.ProtectsPacketsBefore(1));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(group.ProtectsPacketsBefore(2));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(3));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(4));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(5));
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(group.ProtectsPacketsBefore(50));
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(QuicFecGroupTest, EffectiveEncryptionLevel) {
223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  QuicFecGroup group;
224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(NUM_ENCRYPTION_LEVELS, group.effective_encryption_level());
225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  QuicPacketHeader header;
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  header.packet_sequence_number = 5;
228010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ASSERT_TRUE(group.Update(ENCRYPTION_INITIAL, header, kData[0]));
229010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(ENCRYPTION_INITIAL, group.effective_encryption_level());
230010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  QuicFecData fec;
232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  fec.fec_group = 0;
233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  fec.redundancy = kData[0];
234010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, 7, fec));
235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(ENCRYPTION_INITIAL, group.effective_encryption_level());
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  header.packet_sequence_number = 3;
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ASSERT_TRUE(group.Update(ENCRYPTION_NONE, header, kData[0]));
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(ENCRYPTION_NONE, group.effective_encryption_level());
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
243