Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_fec_group_test.cc
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(num_packets, fec));
73         } else {
74           QuicPacketHeader header;
75           header.packet_sequence_number = packet;
76           header.entropy_flag = kEntropyFlag[packet];
77           ASSERT_TRUE(group.Update(header, kData[packet]));
78         }
79         ASSERT_TRUE(group.CanRevive() == (packet == num_packets - 1));
80       }
81     } else {
82     // Update the FEC state for each non-lost packet.
83       for (size_t packet = 0; packet < num_packets; packet++) {
84         if (packet == lost_packet) {
85           continue;
86         }
87
88         QuicPacketHeader header;
89         header.packet_sequence_number = packet;
90         header.entropy_flag = kEntropyFlag[packet];
91         ASSERT_TRUE(group.Update(header, kData[packet]));
92         ASSERT_FALSE(group.CanRevive());
93       }
94
95       ASSERT_FALSE(group.IsFinished());
96       // Attempt to revive the missing packet.
97       QuicFecData fec;
98       fec.fec_group = 0;
99       fec.redundancy = StringPiece(redundancy.get(), strlen(kData[0]));
100
101       ASSERT_TRUE(group.UpdateFec(num_packets, fec));
102     }
103     QuicPacketHeader header;
104     char recovered[kMaxPacketSize];
105     ASSERT_TRUE(group.CanRevive());
106     size_t len = group.Revive(&header, recovered, arraysize(recovered));
107     ASSERT_NE(0u, len)
108         << "Failed to revive packet " << lost_packet << " out of "
109         << num_packets;
110     EXPECT_EQ(lost_packet, header.packet_sequence_number)
111         << "Failed to revive packet " << lost_packet << " out of "
112         << num_packets;
113     // Revived packets have an unknown entropy.
114     EXPECT_FALSE(header.entropy_flag);
115     ASSERT_GE(len, strlen(kData[lost_packet])) << "Incorrect length";
116     for (size_t i = 0; i < strlen(kData[lost_packet]); i++) {
117       EXPECT_EQ(kData[lost_packet][i], recovered[i]);
118     }
119     ASSERT_TRUE(group.IsFinished());
120   }
121 };
122
123 TEST_F(QuicFecGroupTest, UpdateAndRevive) {
124   RunTest(2, 0, false);
125   RunTest(2, 1, false);
126
127   RunTest(3, 0, false);
128   RunTest(3, 1, false);
129   RunTest(3, 2, false);
130 }
131
132 TEST_F(QuicFecGroupTest, UpdateAndReviveOutOfOrder) {
133   RunTest(2, 0, true);
134   RunTest(2, 1, true);
135
136   RunTest(3, 0, true);
137   RunTest(3, 1, true);
138   RunTest(3, 2, true);
139 }
140
141 TEST_F(QuicFecGroupTest, UpdateFecIfReceivedPacketIsNotCovered) {
142   char data1[] = "abc123";
143   char redundancy[arraysize(data1)];
144   for (size_t i = 0; i < arraysize(data1); i++) {
145     redundancy[i] = data1[i];
146   }
147
148   QuicFecGroup group;
149
150   QuicPacketHeader header;
151   header.packet_sequence_number = 3;
152   group.Update(header, data1);
153
154   QuicFecData fec;
155   fec.fec_group = 1;
156   fec.redundancy = redundancy;
157
158   header.packet_sequence_number = 2;
159   ASSERT_FALSE(group.UpdateFec(2, fec));
160 }
161
162 TEST_F(QuicFecGroupTest, ProtectsPacketsBefore) {
163   QuicPacketHeader header;
164   header.packet_sequence_number = 3;
165
166   QuicFecGroup group;
167   ASSERT_TRUE(group.Update(header, kData[0]));
168
169   EXPECT_FALSE(group.ProtectsPacketsBefore(1));
170   EXPECT_FALSE(group.ProtectsPacketsBefore(2));
171   EXPECT_FALSE(group.ProtectsPacketsBefore(3));
172   EXPECT_TRUE(group.ProtectsPacketsBefore(4));
173   EXPECT_TRUE(group.ProtectsPacketsBefore(5));
174   EXPECT_TRUE(group.ProtectsPacketsBefore(50));
175 }
176
177 TEST_F(QuicFecGroupTest, ProtectsPacketsBeforeWithSeveralPackets) {
178   QuicPacketHeader header;
179   header.packet_sequence_number = 3;
180
181   QuicFecGroup group;
182   ASSERT_TRUE(group.Update(header, kData[0]));
183
184   header.packet_sequence_number = 7;
185   ASSERT_TRUE(group.Update(header, kData[0]));
186
187   header.packet_sequence_number = 5;
188   ASSERT_TRUE(group.Update(header, kData[0]));
189
190   EXPECT_FALSE(group.ProtectsPacketsBefore(1));
191   EXPECT_FALSE(group.ProtectsPacketsBefore(2));
192   EXPECT_FALSE(group.ProtectsPacketsBefore(3));
193   EXPECT_TRUE(group.ProtectsPacketsBefore(4));
194   EXPECT_TRUE(group.ProtectsPacketsBefore(5));
195   EXPECT_TRUE(group.ProtectsPacketsBefore(6));
196   EXPECT_TRUE(group.ProtectsPacketsBefore(7));
197   EXPECT_TRUE(group.ProtectsPacketsBefore(8));
198   EXPECT_TRUE(group.ProtectsPacketsBefore(9));
199   EXPECT_TRUE(group.ProtectsPacketsBefore(50));
200 }
201
202 TEST_F(QuicFecGroupTest, ProtectsPacketsBeforeWithFecData) {
203   QuicFecData fec;
204   fec.fec_group = 2;
205   fec.redundancy = kData[0];
206
207   QuicFecGroup group;
208   ASSERT_TRUE(group.UpdateFec(3, fec));
209
210   EXPECT_FALSE(group.ProtectsPacketsBefore(1));
211   EXPECT_FALSE(group.ProtectsPacketsBefore(2));
212   EXPECT_TRUE(group.ProtectsPacketsBefore(3));
213   EXPECT_TRUE(group.ProtectsPacketsBefore(4));
214   EXPECT_TRUE(group.ProtectsPacketsBefore(5));
215   EXPECT_TRUE(group.ProtectsPacketsBefore(50));
216 }
217
218 }  // namespace net