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