1 /*
2  *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "pc/used_ids.h"
12 
13 #include "test/gtest.h"
14 
15 using cricket::UsedIds;
16 using cricket::UsedRtpHeaderExtensionIds;
17 
18 struct Foo {
19   int id;
20 };
21 
TEST(UsedIdsTest,UniqueIdsAreUnchanged)22 TEST(UsedIdsTest, UniqueIdsAreUnchanged) {
23   UsedIds<Foo> used_ids(1, 5);
24   for (int i = 1; i <= 5; ++i) {
25     Foo id = {i};
26     used_ids.FindAndSetIdUsed(&id);
27     EXPECT_EQ(id.id, i);
28   }
29 }
30 
TEST(UsedIdsTest,IdsOutsideRangeAreUnchanged)31 TEST(UsedIdsTest, IdsOutsideRangeAreUnchanged) {
32   UsedIds<Foo> used_ids(1, 5);
33 
34   Foo id_11 = {11};
35   Foo id_12 = {12};
36   Foo id_12_collision = {12};
37   Foo id_13 = {13};
38   Foo id_13_collision = {13};
39 
40   used_ids.FindAndSetIdUsed(&id_11);
41   EXPECT_EQ(id_11.id, 11);
42   used_ids.FindAndSetIdUsed(&id_12);
43   EXPECT_EQ(id_12.id, 12);
44   used_ids.FindAndSetIdUsed(&id_12_collision);
45   EXPECT_EQ(id_12_collision.id, 12);
46   used_ids.FindAndSetIdUsed(&id_13);
47   EXPECT_EQ(id_13.id, 13);
48   used_ids.FindAndSetIdUsed(&id_13_collision);
49   EXPECT_EQ(id_13_collision.id, 13);
50 }
51 
TEST(UsedIdsTest,CollisionsAreReassignedIdsInReverseOrder)52 TEST(UsedIdsTest, CollisionsAreReassignedIdsInReverseOrder) {
53   UsedIds<Foo> used_ids(1, 10);
54   Foo id_1 = {1};
55   Foo id_2 = {2};
56   Foo id_2_collision = {2};
57   Foo id_3 = {3};
58   Foo id_3_collision = {3};
59 
60   used_ids.FindAndSetIdUsed(&id_1);
61   used_ids.FindAndSetIdUsed(&id_2);
62   used_ids.FindAndSetIdUsed(&id_2_collision);
63   EXPECT_EQ(id_2_collision.id, 10);
64   used_ids.FindAndSetIdUsed(&id_3);
65   used_ids.FindAndSetIdUsed(&id_3_collision);
66   EXPECT_EQ(id_3_collision.id, 9);
67 }
68 
69 struct TestParams {
70   UsedRtpHeaderExtensionIds::IdDomain id_domain;
71   int max_id;
72 };
73 
74 class UsedRtpHeaderExtensionIdsTest
75     : public ::testing::TestWithParam<TestParams> {};
76 
77 constexpr TestParams kOneByteTestParams = {
78     UsedRtpHeaderExtensionIds::IdDomain::kOneByteOnly, 14};
79 constexpr TestParams kTwoByteTestParams = {
80     UsedRtpHeaderExtensionIds::IdDomain::kTwoByteAllowed, 255};
81 
82 INSTANTIATE_TEST_SUITE_P(All,
83                          UsedRtpHeaderExtensionIdsTest,
84                          ::testing::Values(kOneByteTestParams,
85                                            kTwoByteTestParams));
86 
TEST_P(UsedRtpHeaderExtensionIdsTest,UniqueIdsAreUnchanged)87 TEST_P(UsedRtpHeaderExtensionIdsTest, UniqueIdsAreUnchanged) {
88   UsedRtpHeaderExtensionIds used_ids(GetParam().id_domain);
89 
90   // Fill all IDs.
91   for (int j = 1; j <= GetParam().max_id; ++j) {
92     webrtc::RtpExtension extension("", j);
93     used_ids.FindAndSetIdUsed(&extension);
94     EXPECT_EQ(extension.id, j);
95   }
96 }
97 
TEST_P(UsedRtpHeaderExtensionIdsTest,PrioritizeReassignmentToOneByteIds)98 TEST_P(UsedRtpHeaderExtensionIdsTest, PrioritizeReassignmentToOneByteIds) {
99   UsedRtpHeaderExtensionIds used_ids(GetParam().id_domain);
100   webrtc::RtpExtension id_1("", 1);
101   webrtc::RtpExtension id_2("", 2);
102   webrtc::RtpExtension id_2_collision("", 2);
103   webrtc::RtpExtension id_3("", 3);
104   webrtc::RtpExtension id_3_collision("", 3);
105 
106   // Expect that colliding IDs are reassigned to one-byte IDs.
107   used_ids.FindAndSetIdUsed(&id_1);
108   used_ids.FindAndSetIdUsed(&id_2);
109   used_ids.FindAndSetIdUsed(&id_2_collision);
110   EXPECT_EQ(id_2_collision.id, 14);
111   used_ids.FindAndSetIdUsed(&id_3);
112   used_ids.FindAndSetIdUsed(&id_3_collision);
113   EXPECT_EQ(id_3_collision.id, 13);
114 }
115 
TEST_F(UsedRtpHeaderExtensionIdsTest,TwoByteIdsAllowed)116 TEST_F(UsedRtpHeaderExtensionIdsTest, TwoByteIdsAllowed) {
117   UsedRtpHeaderExtensionIds used_ids(
118       UsedRtpHeaderExtensionIds::IdDomain::kTwoByteAllowed);
119 
120   // Fill all one byte IDs.
121   for (int i = 1; i < 15; ++i) {
122     webrtc::RtpExtension id("", i);
123     used_ids.FindAndSetIdUsed(&id);
124   }
125 
126   // Add new extensions with colliding IDs.
127   webrtc::RtpExtension id1_collision("", 1);
128   webrtc::RtpExtension id2_collision("", 2);
129   webrtc::RtpExtension id3_collision("", 3);
130 
131   // Expect to reassign to two-byte header extension IDs.
132   used_ids.FindAndSetIdUsed(&id1_collision);
133   EXPECT_EQ(id1_collision.id, 15);
134   used_ids.FindAndSetIdUsed(&id2_collision);
135   EXPECT_EQ(id2_collision.id, 16);
136   used_ids.FindAndSetIdUsed(&id3_collision);
137   EXPECT_EQ(id3_collision.id, 17);
138 }
139 
140 // Death tests.
141 // Disabled on Android because death tests misbehave on Android, see
142 // base/test/gtest_util.h.
143 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST(UsedIdsDeathTest,DieWhenAllIdsAreOccupied)144 TEST(UsedIdsDeathTest, DieWhenAllIdsAreOccupied) {
145   UsedIds<Foo> used_ids(1, 5);
146   for (int i = 1; i <= 5; ++i) {
147     Foo id = {i};
148     used_ids.FindAndSetIdUsed(&id);
149   }
150   Foo id_collision = {3};
151   EXPECT_DEATH(used_ids.FindAndSetIdUsed(&id_collision), "");
152 }
153 
154 using UsedRtpHeaderExtensionIdsDeathTest = UsedRtpHeaderExtensionIdsTest;
155 INSTANTIATE_TEST_SUITE_P(All,
156                          UsedRtpHeaderExtensionIdsDeathTest,
157                          ::testing::Values(kOneByteTestParams,
158                                            kTwoByteTestParams));
159 
TEST_P(UsedRtpHeaderExtensionIdsDeathTest,DieWhenAllIdsAreOccupied)160 TEST_P(UsedRtpHeaderExtensionIdsDeathTest, DieWhenAllIdsAreOccupied) {
161   UsedRtpHeaderExtensionIds used_ids(GetParam().id_domain);
162 
163   // Fill all IDs.
164   for (int j = 1; j <= GetParam().max_id; ++j) {
165     webrtc::RtpExtension id("", j);
166     used_ids.FindAndSetIdUsed(&id);
167   }
168 
169   webrtc::RtpExtension id1_collision("", 1);
170   webrtc::RtpExtension id2_collision("", 2);
171   webrtc::RtpExtension id3_collision("", GetParam().max_id);
172 
173   EXPECT_DEATH(used_ids.FindAndSetIdUsed(&id1_collision), "");
174   EXPECT_DEATH(used_ids.FindAndSetIdUsed(&id2_collision), "");
175   EXPECT_DEATH(used_ids.FindAndSetIdUsed(&id3_collision), "");
176 }
177 #endif  // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
178