/* * 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 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 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 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 {}; 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 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)