| /* | 
 |  *  Copyright 2019 The WebRTC project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #include "pc/used_ids.h" | 
 |  | 
 | #include "absl/strings/string_view.h" | 
 | #include "test/gtest.h" | 
 |  | 
 | using cricket::UsedIds; | 
 | using cricket::UsedRtpHeaderExtensionIds; | 
 |  | 
 | struct Foo { | 
 |   int id; | 
 | }; | 
 |  | 
 | TEST(UsedIdsTest, UniqueIdsAreUnchanged) { | 
 |   UsedIds<Foo> used_ids(1, 5); | 
 |   for (int i = 1; i <= 5; ++i) { | 
 |     Foo id = {i}; | 
 |     used_ids.FindAndSetIdUsed(&id); | 
 |     EXPECT_EQ(id.id, i); | 
 |   } | 
 | } | 
 |  | 
 | TEST(UsedIdsTest, IdsOutsideRangeAreUnchanged) { | 
 |   UsedIds<Foo> used_ids(1, 5); | 
 |  | 
 |   Foo id_11 = {11}; | 
 |   Foo id_12 = {12}; | 
 |   Foo id_12_collision = {12}; | 
 |   Foo id_13 = {13}; | 
 |   Foo id_13_collision = {13}; | 
 |  | 
 |   used_ids.FindAndSetIdUsed(&id_11); | 
 |   EXPECT_EQ(id_11.id, 11); | 
 |   used_ids.FindAndSetIdUsed(&id_12); | 
 |   EXPECT_EQ(id_12.id, 12); | 
 |   used_ids.FindAndSetIdUsed(&id_12_collision); | 
 |   EXPECT_EQ(id_12_collision.id, 12); | 
 |   used_ids.FindAndSetIdUsed(&id_13); | 
 |   EXPECT_EQ(id_13.id, 13); | 
 |   used_ids.FindAndSetIdUsed(&id_13_collision); | 
 |   EXPECT_EQ(id_13_collision.id, 13); | 
 | } | 
 |  | 
 | TEST(UsedIdsTest, CollisionsAreReassignedIdsInReverseOrder) { | 
 |   UsedIds<Foo> used_ids(1, 10); | 
 |   Foo id_1 = {1}; | 
 |   Foo id_2 = {2}; | 
 |   Foo id_2_collision = {2}; | 
 |   Foo id_3 = {3}; | 
 |   Foo id_3_collision = {3}; | 
 |  | 
 |   used_ids.FindAndSetIdUsed(&id_1); | 
 |   used_ids.FindAndSetIdUsed(&id_2); | 
 |   used_ids.FindAndSetIdUsed(&id_2_collision); | 
 |   EXPECT_EQ(id_2_collision.id, 10); | 
 |   used_ids.FindAndSetIdUsed(&id_3); | 
 |   used_ids.FindAndSetIdUsed(&id_3_collision); | 
 |   EXPECT_EQ(id_3_collision.id, 9); | 
 | } | 
 |  | 
 | struct TestParams { | 
 |   UsedRtpHeaderExtensionIds::IdDomain id_domain; | 
 |   int max_id; | 
 | }; | 
 |  | 
 | class UsedRtpHeaderExtensionIdsTest | 
 |     : public ::testing::TestWithParam<TestParams> {}; | 
 |  | 
 | constexpr TestParams kOneByteTestParams = { | 
 |     UsedRtpHeaderExtensionIds::IdDomain::kOneByteOnly, 14}; | 
 | constexpr TestParams kTwoByteTestParams = { | 
 |     UsedRtpHeaderExtensionIds::IdDomain::kTwoByteAllowed, 255}; | 
 |  | 
 | INSTANTIATE_TEST_SUITE_P(All, | 
 |                          UsedRtpHeaderExtensionIdsTest, | 
 |                          ::testing::Values(kOneByteTestParams, | 
 |                                            kTwoByteTestParams)); | 
 |  | 
 | TEST_P(UsedRtpHeaderExtensionIdsTest, UniqueIdsAreUnchanged) { | 
 |   UsedRtpHeaderExtensionIds used_ids(GetParam().id_domain); | 
 |  | 
 |   // Fill all IDs. | 
 |   for (int j = 1; j <= GetParam().max_id; ++j) { | 
 |     webrtc::RtpExtension extension("", j); | 
 |     used_ids.FindAndSetIdUsed(&extension); | 
 |     EXPECT_EQ(extension.id, j); | 
 |   } | 
 | } | 
 |  | 
 | TEST_P(UsedRtpHeaderExtensionIdsTest, PrioritizeReassignmentToOneByteIds) { | 
 |   UsedRtpHeaderExtensionIds used_ids(GetParam().id_domain); | 
 |   webrtc::RtpExtension id_1("", 1); | 
 |   webrtc::RtpExtension id_2("", 2); | 
 |   webrtc::RtpExtension id_2_collision("", 2); | 
 |   webrtc::RtpExtension id_3("", 3); | 
 |   webrtc::RtpExtension id_3_collision("", 3); | 
 |  | 
 |   // Expect that colliding IDs are reassigned to one-byte IDs. | 
 |   used_ids.FindAndSetIdUsed(&id_1); | 
 |   used_ids.FindAndSetIdUsed(&id_2); | 
 |   used_ids.FindAndSetIdUsed(&id_2_collision); | 
 |   EXPECT_EQ(id_2_collision.id, 14); | 
 |   used_ids.FindAndSetIdUsed(&id_3); | 
 |   used_ids.FindAndSetIdUsed(&id_3_collision); | 
 |   EXPECT_EQ(id_3_collision.id, 13); | 
 | } | 
 |  | 
 | TEST_F(UsedRtpHeaderExtensionIdsTest, TwoByteIdsAllowed) { | 
 |   UsedRtpHeaderExtensionIds used_ids( | 
 |       UsedRtpHeaderExtensionIds::IdDomain::kTwoByteAllowed); | 
 |  | 
 |   // Fill all one byte IDs. | 
 |   for (int i = 1; i <= webrtc::RtpExtension::kOneByteHeaderExtensionMaxId; | 
 |        ++i) { | 
 |     webrtc::RtpExtension id("", i); | 
 |     used_ids.FindAndSetIdUsed(&id); | 
 |   } | 
 |  | 
 |   // Add new extensions with colliding IDs. | 
 |   webrtc::RtpExtension id1_collision("", 1); | 
 |   webrtc::RtpExtension id2_collision("", 2); | 
 |   webrtc::RtpExtension id3_collision("", 3); | 
 |  | 
 |   // Expect to reassign to two-byte header extension IDs. | 
 |   used_ids.FindAndSetIdUsed(&id1_collision); | 
 |   EXPECT_EQ(id1_collision.id, 16); | 
 |   used_ids.FindAndSetIdUsed(&id2_collision); | 
 |   EXPECT_EQ(id2_collision.id, 17); | 
 |   used_ids.FindAndSetIdUsed(&id3_collision); | 
 |   EXPECT_EQ(id3_collision.id, 18); | 
 | } | 
 |  | 
 | // Death tests. | 
 | // Disabled on Android because death tests misbehave on Android, see | 
 | // base/test/gtest_util.h. | 
 | #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | 
 | TEST(UsedIdsDeathTest, DieWhenAllIdsAreOccupied) { | 
 |   UsedIds<Foo> used_ids(1, 5); | 
 |   for (int i = 1; i <= 5; ++i) { | 
 |     Foo id = {i}; | 
 |     used_ids.FindAndSetIdUsed(&id); | 
 |   } | 
 |   Foo id_collision = {3}; | 
 |   EXPECT_DEATH(used_ids.FindAndSetIdUsed(&id_collision), ""); | 
 | } | 
 |  | 
 | using UsedRtpHeaderExtensionIdsDeathTest = UsedRtpHeaderExtensionIdsTest; | 
 | INSTANTIATE_TEST_SUITE_P(All, | 
 |                          UsedRtpHeaderExtensionIdsDeathTest, | 
 |                          ::testing::Values(kOneByteTestParams, | 
 |                                            kTwoByteTestParams)); | 
 |  | 
 | TEST_P(UsedRtpHeaderExtensionIdsDeathTest, DieWhenAllIdsAreOccupied) { | 
 |   UsedRtpHeaderExtensionIds used_ids(GetParam().id_domain); | 
 |  | 
 |   // Fill all IDs. | 
 |   for (int j = 1; j <= GetParam().max_id; ++j) { | 
 |     webrtc::RtpExtension id("", j); | 
 |     used_ids.FindAndSetIdUsed(&id); | 
 |   } | 
 |  | 
 |   webrtc::RtpExtension id1_collision("", 1); | 
 |   webrtc::RtpExtension id2_collision("", 2); | 
 |   webrtc::RtpExtension id3_collision("", GetParam().max_id); | 
 |  | 
 |   EXPECT_DEATH(used_ids.FindAndSetIdUsed(&id1_collision), ""); | 
 |   EXPECT_DEATH(used_ids.FindAndSetIdUsed(&id2_collision), ""); | 
 |   EXPECT_DEATH(used_ids.FindAndSetIdUsed(&id3_collision), ""); | 
 | } | 
 | #endif  // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) |