Upstream version 7.36.149.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(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