1 /*
2 * Copyright 2022 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 "api/field_trials.h"
12
13 #include <memory>
14 #include <utility>
15
16 #include "absl/strings/string_view.h"
17 #include "api/transport/field_trial_based_config.h"
18 #include "rtc_base/containers/flat_set.h"
19 #include "system_wrappers/include/field_trial.h"
20 #include "test/field_trial.h"
21 #include "test/gmock.h"
22 #include "test/gtest.h"
23
24 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
25 #include "test/testsupport/rtc_expect_death.h"
26 #endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
27
28 namespace webrtc {
29 namespace {
30
31 using ::testing::NotNull;
32 using ::webrtc::field_trial::FieldTrialsAllowedInScopeForTesting;
33 using ::webrtc::test::ScopedFieldTrials;
34
TEST(FieldTrialsTest,EmptyStringHasNoEffect)35 TEST(FieldTrialsTest, EmptyStringHasNoEffect) {
36 FieldTrialsAllowedInScopeForTesting k({"MyCoolTrial"});
37 FieldTrials f("");
38 f.RegisterKeysForTesting({"MyCoolTrial"});
39
40 EXPECT_FALSE(f.IsEnabled("MyCoolTrial"));
41 EXPECT_FALSE(f.IsDisabled("MyCoolTrial"));
42 }
43
TEST(FieldTrialsTest,EnabledDisabledMustBeFirstInValue)44 TEST(FieldTrialsTest, EnabledDisabledMustBeFirstInValue) {
45 FieldTrials f(
46 "MyCoolTrial/EnabledFoo/"
47 "MyUncoolTrial/DisabledBar/"
48 "AnotherTrial/BazEnabled/");
49 f.RegisterKeysForTesting({"MyCoolTrial", "MyUncoolTrial", "AnotherTrial"});
50
51 EXPECT_TRUE(f.IsEnabled("MyCoolTrial"));
52 EXPECT_TRUE(f.IsDisabled("MyUncoolTrial"));
53 EXPECT_FALSE(f.IsEnabled("AnotherTrial"));
54 }
55
TEST(FieldTrialsTest,FieldTrialsDoesNotReadGlobalString)56 TEST(FieldTrialsTest, FieldTrialsDoesNotReadGlobalString) {
57 FieldTrialsAllowedInScopeForTesting k({"MyCoolTrial", "MyUncoolTrial"});
58 ScopedFieldTrials g("MyCoolTrial/Enabled/MyUncoolTrial/Disabled/");
59 FieldTrials f("");
60 f.RegisterKeysForTesting({"MyCoolTrial", "MyUncoolTrial"});
61
62 EXPECT_FALSE(f.IsEnabled("MyCoolTrial"));
63 EXPECT_FALSE(f.IsDisabled("MyUncoolTrial"));
64 }
65
TEST(FieldTrialsTest,FieldTrialsWritesGlobalString)66 TEST(FieldTrialsTest, FieldTrialsWritesGlobalString) {
67 FieldTrialsAllowedInScopeForTesting k({"MyCoolTrial", "MyUncoolTrial"});
68 FieldTrials f("MyCoolTrial/Enabled/MyUncoolTrial/Disabled/");
69 EXPECT_TRUE(webrtc::field_trial::IsEnabled("MyCoolTrial"));
70 EXPECT_TRUE(webrtc::field_trial::IsDisabled("MyUncoolTrial"));
71 }
72
TEST(FieldTrialsTest,FieldTrialsRestoresGlobalStringAfterDestruction)73 TEST(FieldTrialsTest, FieldTrialsRestoresGlobalStringAfterDestruction) {
74 static constexpr char s[] = "SomeString/Enabled/";
75 ScopedFieldTrials g(s);
76 {
77 FieldTrials f("SomeOtherString/Enabled/");
78 EXPECT_STREQ(webrtc::field_trial::GetFieldTrialString(),
79 "SomeOtherString/Enabled/");
80 }
81 EXPECT_STREQ(webrtc::field_trial::GetFieldTrialString(), s);
82 }
83
84 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST(FieldTrialsTest,FieldTrialsDoesNotSupportSimultaneousInstances)85 TEST(FieldTrialsTest, FieldTrialsDoesNotSupportSimultaneousInstances) {
86 FieldTrials f("SomeString/Enabled/");
87 RTC_EXPECT_DEATH(FieldTrials("SomeOtherString/Enabled/").Lookup("Whatever"),
88 "Only one instance");
89 }
90 #endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
91
TEST(FieldTrialsTest,FieldTrialsSupportsSeparateInstances)92 TEST(FieldTrialsTest, FieldTrialsSupportsSeparateInstances) {
93 { FieldTrials f("SomeString/Enabled/"); }
94 { FieldTrials f("SomeOtherString/Enabled/"); }
95 }
96
TEST(FieldTrialsTest,NonGlobalFieldTrialsInstanceDoesNotModifyGlobalString)97 TEST(FieldTrialsTest, NonGlobalFieldTrialsInstanceDoesNotModifyGlobalString) {
98 FieldTrialsAllowedInScopeForTesting k({"SomeString"});
99 std::unique_ptr<FieldTrials> f =
100 FieldTrials::CreateNoGlobal("SomeString/Enabled/");
101 ASSERT_THAT(f, NotNull());
102 f->RegisterKeysForTesting({"SomeString"});
103
104 EXPECT_TRUE(f->IsEnabled("SomeString"));
105 EXPECT_FALSE(webrtc::field_trial::IsEnabled("SomeString"));
106 }
107
TEST(FieldTrialsTest,NonGlobalFieldTrialsSupportSimultaneousInstances)108 TEST(FieldTrialsTest, NonGlobalFieldTrialsSupportSimultaneousInstances) {
109 std::unique_ptr<FieldTrials> f1 =
110 FieldTrials::CreateNoGlobal("SomeString/Enabled/");
111 std::unique_ptr<FieldTrials> f2 =
112 FieldTrials::CreateNoGlobal("SomeOtherString/Enabled/");
113 ASSERT_THAT(f1, NotNull());
114 ASSERT_THAT(f2, NotNull());
115 f1->RegisterKeysForTesting({"SomeString", "SomeOtherString"});
116 f2->RegisterKeysForTesting({"SomeString", "SomeOtherString"});
117
118 EXPECT_TRUE(f1->IsEnabled("SomeString"));
119 EXPECT_FALSE(f1->IsEnabled("SomeOtherString"));
120
121 EXPECT_FALSE(f2->IsEnabled("SomeString"));
122 EXPECT_TRUE(f2->IsEnabled("SomeOtherString"));
123 }
124
TEST(FieldTrialsTest,GlobalAndNonGlobalFieldTrialsAreDisjoint)125 TEST(FieldTrialsTest, GlobalAndNonGlobalFieldTrialsAreDisjoint) {
126 FieldTrialsAllowedInScopeForTesting k({"SomeString", "SomeOtherString"});
127 FieldTrials f1("SomeString/Enabled/");
128 std::unique_ptr<FieldTrials> f2 =
129 FieldTrials::CreateNoGlobal("SomeOtherString/Enabled/");
130 ASSERT_THAT(f2, NotNull());
131 f1.RegisterKeysForTesting({"SomeString", "SomeOtherString"});
132 f2->RegisterKeysForTesting({"SomeString", "SomeOtherString"});
133
134 EXPECT_TRUE(f1.IsEnabled("SomeString"));
135 EXPECT_FALSE(f1.IsEnabled("SomeOtherString"));
136
137 EXPECT_FALSE(f2->IsEnabled("SomeString"));
138 EXPECT_TRUE(f2->IsEnabled("SomeOtherString"));
139 }
140
TEST(FieldTrialsTest,FieldTrialBasedConfigReadsGlobalString)141 TEST(FieldTrialsTest, FieldTrialBasedConfigReadsGlobalString) {
142 FieldTrialsAllowedInScopeForTesting k({"MyCoolTrial", "MyUncoolTrial"});
143 ScopedFieldTrials g("MyCoolTrial/Enabled/MyUncoolTrial/Disabled/");
144 FieldTrialBasedConfig f;
145 f.RegisterKeysForTesting({"MyCoolTrial", "MyUncoolTrial"});
146
147 EXPECT_TRUE(f.IsEnabled("MyCoolTrial"));
148 EXPECT_TRUE(f.IsDisabled("MyUncoolTrial"));
149 }
150
151 } // namespace
152 } // namespace webrtc
153