field_trials_unittest.cc (6121B)
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 15 #include "absl/strings/str_cat.h" 16 #include "api/field_trials_view.h" 17 #include "rtc_base/checks.h" 18 #include "rtc_base/containers/flat_set.h" 19 #include "test/gmock.h" 20 #include "test/gtest.h" 21 22 namespace webrtc { 23 namespace { 24 25 using ::testing::AllOf; 26 using ::testing::HasSubstr; 27 using ::testing::IsNull; 28 using ::testing::Not; 29 using ::testing::NotNull; 30 31 TEST(FieldTrialsTest, EmptyStringHasNoEffect) { 32 FieldTrials f(""); 33 f.RegisterKeysForTesting({"MyCoolTrial"}); 34 35 EXPECT_FALSE(f.IsEnabled("MyCoolTrial")); 36 EXPECT_FALSE(f.IsDisabled("MyCoolTrial")); 37 } 38 39 TEST(FieldTrialsTest, EnabledDisabledMustBeFirstInValue) { 40 FieldTrials f( 41 "MyCoolTrial/EnabledFoo/" 42 "MyUncoolTrial/DisabledBar/" 43 "AnotherTrial/BazEnabled/"); 44 f.RegisterKeysForTesting({"MyCoolTrial", "MyUncoolTrial", "AnotherTrial"}); 45 46 EXPECT_TRUE(f.IsEnabled("MyCoolTrial")); 47 EXPECT_TRUE(f.IsDisabled("MyUncoolTrial")); 48 EXPECT_FALSE(f.IsEnabled("AnotherTrial")); 49 } 50 51 TEST(FieldTrialsTest, FieldTrialsSupportSimultaneousInstances) { 52 FieldTrials f1("SomeString/Enabled/"); 53 FieldTrials f2("SomeOtherString/Enabled/"); 54 f1.RegisterKeysForTesting({"SomeString", "SomeOtherString"}); 55 f2.RegisterKeysForTesting({"SomeString", "SomeOtherString"}); 56 57 EXPECT_TRUE(f1.IsEnabled("SomeString")); 58 EXPECT_FALSE(f1.IsEnabled("SomeOtherString")); 59 60 EXPECT_FALSE(f2.IsEnabled("SomeString")); 61 EXPECT_TRUE(f2.IsEnabled("SomeOtherString")); 62 } 63 64 TEST(FieldTrialsTest, CreateAcceptsValidInputs) { 65 EXPECT_THAT(FieldTrials::Create(""), NotNull()); 66 EXPECT_THAT(FieldTrials::Create("Audio/Enabled/"), NotNull()); 67 EXPECT_THAT(FieldTrials::Create("Audio/Enabled/Video/Disabled/"), NotNull()); 68 69 // Duplicate trials with the same value is fine 70 EXPECT_THAT(FieldTrials::Create("Audio/Enabled/Audio/Enabled/"), NotNull()); 71 EXPECT_THAT(FieldTrials::Create("Audio/Enabled/B/C/Audio/Enabled/"), 72 NotNull()); 73 } 74 75 TEST(FieldTrialsTest, CreateRejectsBadInputs) { 76 // Bad delimiters 77 EXPECT_THAT(FieldTrials::Create("Audio/EnabledVideo/Disabled/"), IsNull()); 78 EXPECT_THAT(FieldTrials::Create("Audio/Enabled//Video/Disabled/"), IsNull()); 79 EXPECT_THAT(FieldTrials::Create("/Audio/Enabled/Video/Disabled/"), IsNull()); 80 EXPECT_THAT(FieldTrials::Create("Audio/Enabled/Video/Disabled"), IsNull()); 81 EXPECT_THAT(FieldTrials::Create("Audio/Enabled/Video/Disabled/garbage"), 82 IsNull()); 83 84 // Empty trial or group 85 EXPECT_THAT(FieldTrials::Create("Audio//"), IsNull()); 86 EXPECT_THAT(FieldTrials::Create("/Enabled/"), IsNull()); 87 EXPECT_THAT(FieldTrials::Create("//"), IsNull()); 88 EXPECT_THAT(FieldTrials::Create("//Enabled"), IsNull()); 89 90 // Duplicate trials with different values is not fine 91 EXPECT_THAT(FieldTrials::Create("Audio/Enabled/Audio/Disabled/"), IsNull()); 92 EXPECT_THAT(FieldTrials::Create("Audio/Enabled/B/C/Audio/Disabled/"), 93 IsNull()); 94 EXPECT_THAT(FieldTrials::Create("Audio/Enabled/Audio/Disabled/"), IsNull()); 95 EXPECT_THAT(FieldTrials::Create("Audio/Enabled/B/C/Audio/Disabled/"), 96 IsNull()); 97 } 98 99 TEST(FieldTrialsTest, StringfiyMentionsKeysAndValues) { 100 // Exact format of the stringification is undefined. 101 EXPECT_THAT(absl::StrCat(FieldTrials("Audio/Enabled/Video/Value/")), 102 AllOf(HasSubstr("Audio"), HasSubstr("Enabled"), 103 HasSubstr("Video"), HasSubstr("Value"))); 104 } 105 106 TEST(FieldTrialsTest, MergeCombinesFieldTrials) { 107 FieldTrials f("Video/Value1/"); 108 FieldTrials other("Audio/Value2/"); 109 110 f.Merge(other); 111 112 f.RegisterKeysForTesting({"Audio", "Video"}); 113 EXPECT_EQ(f.Lookup("Video"), "Value1"); 114 EXPECT_EQ(f.Lookup("Audio"), "Value2"); 115 } 116 117 TEST(FieldTrialsTest, MergeGivesPrecedenceToOther) { 118 FieldTrials f("Audio/Disabled/Video/Enabled/"); 119 FieldTrials other("Audio/Enabled/"); 120 121 f.Merge(other); 122 123 f.RegisterKeysForTesting({"Audio"}); 124 EXPECT_EQ(f.Lookup("Audio"), "Enabled"); 125 } 126 127 TEST(FieldTrialsTest, MergeDoesntChangeTrialAbsentInOther) { 128 FieldTrials f("Audio/Enabled/Video/Enabled/"); 129 FieldTrials other("Audio/Enabled/"); 130 131 f.Merge(other); 132 133 f.RegisterKeysForTesting({"Video"}); 134 EXPECT_EQ(f.Lookup("Video"), "Enabled"); 135 } 136 137 TEST(FieldTrialsTest, SetUpdatesTrial) { 138 FieldTrials f("Audio/Enabled/Video/Enabled/"); 139 140 f.Set("Audio", "Disabled"); 141 142 f.RegisterKeysForTesting({"Audio"}); 143 EXPECT_EQ(f.Lookup("Audio"), "Disabled"); 144 } 145 146 TEST(FieldTrialsTest, SettingEmptyValueRemovesFieldTrial) { 147 FieldTrials f("Audio/Enabled/Video/Enabled/"); 148 149 f.Set("Audio", ""); 150 151 f.RegisterKeysForTesting({"Audio"}); 152 EXPECT_EQ(f.Lookup("Audio"), ""); 153 EXPECT_THAT(absl::StrCat(f), Not(HasSubstr("Audio"))); 154 155 // Absent field trials shouldn't override previous value during merge. 156 FieldTrials f2("Audio/Disabled/"); 157 f2.Merge(f); 158 f2.RegisterKeysForTesting({"Audio"}); 159 EXPECT_EQ(f2.Lookup("Audio"), "Disabled"); 160 } 161 162 TEST(FieldTrialsTest, CreateCopy) { 163 auto f = std::make_unique<FieldTrials>("Audio/Enabled/"); 164 f->RegisterKeysForTesting({"Audio"}); 165 166 FieldTrialsView* view = f.get(); 167 auto copy = view->CreateCopy(); 168 f.reset(); 169 EXPECT_EQ(copy->Lookup("Audio"), "Enabled"); 170 } 171 172 TEST(FieldTrials, Immutable) { 173 FieldTrials f("Audio/Enabled/"); 174 f.RegisterKeysForTesting({"Audio"}); 175 176 // Has never been read, modifyable 177 f.Set("Audio", "Disabled"); 178 EXPECT_EQ(f.Lookup("Audio"), "Disabled"); 179 180 // A copy can be modified. 181 FieldTrials c(f); 182 c.Set("Audio", "Enabled"); 183 184 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 185 // But FieldTrials that have been read from, 186 // must not be modified (as documented in FieldTrialsView). 187 EXPECT_DEATH(f.Set("Audio", "Enabled"), ""); 188 #endif 189 } 190 191 } // namespace 192 } // namespace webrtc