Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2011 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include "base/flags.h" |
| 18 | |
| 19 | #include <optional> |
| 20 | |
| 21 | #include "android-base/properties.h" |
| 22 | #include "common_runtime_test.h" |
| 23 | |
| 24 | |
| 25 | namespace art { |
| 26 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 27 | // Tests may be run in parallel so this helper class ensures |
| 28 | // that we generate a unique test flag each time to avoid |
| 29 | // tests stepping on each other |
| 30 | class TestFlag { |
| 31 | public: |
| 32 | // Takes control of the tmp_file pointer. |
Calin Juravle | 1ff9056 | 2021-06-16 14:37:42 -0700 | [diff] [blame] | 33 | TestFlag(ScratchFile* tmp_file, FlagType flag_type) { |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 34 | tmp_file_.reset(tmp_file); |
| 35 | |
| 36 | std::string tmp_name = tmp_file_->GetFilename(); |
| 37 | size_t tmp_last_slash = tmp_name.rfind('/'); |
| 38 | tmp_name = tmp_name.substr(tmp_last_slash + 1); |
| 39 | |
| 40 | flag_name_ = "art.gtest." + tmp_name; |
| 41 | system_prop_name_ = "dalvik.vm." + flag_name_; |
| 42 | server_name_ = "persist.device_config.runtime_native." + flag_name_; |
| 43 | cmd_line_name_ = flag_name_; |
| 44 | std::replace(cmd_line_name_.begin(), cmd_line_name_.end(), '.', '-'); |
| 45 | |
Calin Juravle | 1ff9056 | 2021-06-16 14:37:42 -0700 | [diff] [blame] | 46 | flag_.reset(new Flag<int>(flag_name_, /*default_value=*/ 42, flag_type)); |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 47 | } |
| 48 | |
| 49 | void AssertCmdlineValue(bool has_value, int expected) { |
| 50 | ASSERT_EQ(flag_->from_command_line_.has_value(), has_value); |
| 51 | if (has_value) { |
| 52 | ASSERT_EQ(flag_->from_command_line_.value(), expected); |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | void AssertSysPropValue(bool has_value, int expected) { |
| 57 | ASSERT_EQ(flag_->from_system_property_.has_value(), has_value); |
| 58 | if (has_value) { |
| 59 | ASSERT_EQ(flag_->from_system_property_.value(), expected); |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | void AssertServerSettingValue(bool has_value, int expected) { |
| 64 | ASSERT_EQ(flag_->from_server_setting_.has_value(), has_value); |
| 65 | if (has_value) { |
| 66 | ASSERT_EQ(flag_->from_server_setting_.value(), expected); |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | void AssertDefaultValue(int expected) { |
| 71 | ASSERT_EQ(flag_->default_, expected); |
| 72 | } |
| 73 | |
| 74 | int Value() { |
| 75 | return (*flag_)(); |
| 76 | } |
| 77 | |
| 78 | std::string SystemProperty() const { |
| 79 | return system_prop_name_; |
| 80 | } |
| 81 | |
| 82 | std::string ServerSetting() const { |
| 83 | return server_name_; |
| 84 | } |
| 85 | |
| 86 | std::string CmdLineName() const { |
| 87 | return cmd_line_name_; |
| 88 | } |
| 89 | |
| 90 | private: |
| 91 | std::unique_ptr<ScratchFile> tmp_file_; |
| 92 | std::unique_ptr<Flag<int>> flag_; |
| 93 | std::string flag_name_; |
| 94 | std::string cmd_line_name_; |
| 95 | std::string system_prop_name_; |
| 96 | std::string server_name_; |
| 97 | }; |
| 98 | |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 99 | class FlagsTests : public CommonRuntimeTest { |
| 100 | protected: |
Vladimir Marko | 483c41a | 2021-11-12 12:45:23 +0000 | [diff] [blame] | 101 | FlagsTests() { |
| 102 | this->use_boot_image_ = true; // Make the Runtime creation cheaper. |
| 103 | } |
| 104 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 105 | // We need to initialize the flag after the ScratchDir is created |
| 106 | // but before we configure the runtime options (so that we can get |
| 107 | // the right name for the config). |
| 108 | // |
| 109 | // So we do it in SetUpRuntimeOptions. |
| 110 | virtual void SetUpRuntimeOptions(RuntimeOptions* options) { |
Calin Juravle | 1ff9056 | 2021-06-16 14:37:42 -0700 | [diff] [blame] | 111 | test_flag_.reset(new TestFlag(new ScratchFile(), FlagType::kDeviceConfig)); |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 112 | CommonRuntimeTest::SetUpRuntimeOptions(options); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 113 | } |
| 114 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 115 | virtual void TearDown() { |
| 116 | test_flag_ = nullptr; |
| 117 | CommonRuntimeTest::TearDown(); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 118 | } |
| 119 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 120 | std::unique_ptr<TestFlag> test_flag_; |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 121 | }; |
| 122 | |
Calin Juravle | 1ff9056 | 2021-06-16 14:37:42 -0700 | [diff] [blame] | 123 | class FlagsTestsWithCmdLineBase : public FlagsTests { |
| 124 | public: |
| 125 | explicit FlagsTestsWithCmdLineBase(FlagType type) : flag_type_(type) { |
| 126 | } |
| 127 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 128 | protected: |
| 129 | virtual void TearDown() { |
Calin Juravle | b390ba9 | 2021-06-07 09:05:08 -0700 | [diff] [blame] | 130 | android::base::SetProperty(test_flag_->SystemProperty(), ""); |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 131 | android::base::SetProperty(test_flag_->ServerSetting(), ""); |
| 132 | FlagsTests::TearDown(); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 133 | } |
| 134 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 135 | virtual void SetUpRuntimeOptions(RuntimeOptions* options) { |
Calin Juravle | 1ff9056 | 2021-06-16 14:37:42 -0700 | [diff] [blame] | 136 | test_flag_.reset(new TestFlag(new ScratchFile(), flag_type_)); |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 137 | std::string option = "-X" + test_flag_->CmdLineName() + ":1"; |
| 138 | options->emplace_back(option.c_str(), nullptr); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 139 | } |
Calin Juravle | 1ff9056 | 2021-06-16 14:37:42 -0700 | [diff] [blame] | 140 | |
| 141 | FlagType flag_type_; |
| 142 | }; |
| 143 | |
| 144 | class FlagsTestsWithCmdLine : public FlagsTestsWithCmdLineBase { |
| 145 | public: |
| 146 | FlagsTestsWithCmdLine() : FlagsTestsWithCmdLineBase(FlagType::kDeviceConfig) { |
| 147 | } |
| 148 | }; |
| 149 | |
| 150 | class FlagsTestsCmdLineOnly : public FlagsTestsWithCmdLineBase { |
| 151 | public: |
| 152 | FlagsTestsCmdLineOnly() : FlagsTestsWithCmdLineBase(FlagType::kCmdlineOnly) { |
| 153 | } |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 154 | }; |
| 155 | |
| 156 | // Validate that when no flag is set, the default is taken and none of the other |
| 157 | // locations are populated |
| 158 | TEST_F(FlagsTests, ValidateDefaultValue) { |
| 159 | FlagBase::ReloadAllFlags("test"); |
| 160 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 161 | test_flag_->AssertCmdlineValue(false, 1); |
| 162 | test_flag_->AssertSysPropValue(false, 2); |
| 163 | test_flag_->AssertServerSettingValue(false, 3); |
| 164 | test_flag_->AssertDefaultValue(42); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 165 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 166 | ASSERT_EQ(test_flag_->Value(), 42); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | // Validate that the server side config is picked when it is set. |
| 170 | TEST_F(FlagsTestsWithCmdLine, FlagsTestsGetValueServerSetting) { |
Calin Juravle | b390ba9 | 2021-06-07 09:05:08 -0700 | [diff] [blame] | 171 | // On older releases (e.g. nougat) the system properties have very strict |
| 172 | // limitations (e.g. for length) and setting the properties will fail. |
| 173 | // On modern platforms this should not be the case, so condition the test |
| 174 | // based on the success of setting the properties. |
| 175 | if (!android::base::SetProperty(test_flag_->SystemProperty(), "2")) { |
| 176 | LOG(ERROR) << "Release does not support property setting, skipping test: " |
| 177 | << test_flag_->SystemProperty(); |
| 178 | return; |
| 179 | } |
| 180 | |
Roland Levillain | 96d8f4f | 2021-09-17 12:15:22 +0100 | [diff] [blame] | 181 | if (!android::base::SetProperty(test_flag_->ServerSetting(), "3")) { |
Calin Juravle | b390ba9 | 2021-06-07 09:05:08 -0700 | [diff] [blame] | 182 | LOG(ERROR) << "Release does not support property setting, skipping test: " |
| 183 | << test_flag_->ServerSetting(); |
| 184 | return; |
| 185 | } |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 186 | |
| 187 | FlagBase::ReloadAllFlags("test"); |
| 188 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 189 | test_flag_->AssertCmdlineValue(true, 1); |
| 190 | test_flag_->AssertSysPropValue(true, 2); |
| 191 | test_flag_->AssertServerSettingValue(true, 3); |
| 192 | test_flag_->AssertDefaultValue(42); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 193 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 194 | ASSERT_EQ(test_flag_->Value(), 3); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | // Validate that the system property value is picked when the server one is not set. |
| 198 | TEST_F(FlagsTestsWithCmdLine, FlagsTestsGetValueSysProperty) { |
Calin Juravle | b390ba9 | 2021-06-07 09:05:08 -0700 | [diff] [blame] | 199 | if (!android::base::SetProperty(test_flag_->SystemProperty(), "2")) { |
| 200 | LOG(ERROR) << "Release does not support property setting, skipping test: " |
| 201 | << test_flag_->SystemProperty(); |
| 202 | return; |
| 203 | } |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 204 | |
| 205 | FlagBase::ReloadAllFlags("test"); |
| 206 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 207 | test_flag_->AssertCmdlineValue(true, 1); |
| 208 | test_flag_->AssertSysPropValue(true, 2); |
| 209 | test_flag_->AssertServerSettingValue(false, 3); |
| 210 | test_flag_->AssertDefaultValue(42); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 211 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 212 | ASSERT_EQ(test_flag_->Value(), 2); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 213 | } |
| 214 | |
| 215 | // Validate that the cmdline value is picked when no properties are set. |
| 216 | TEST_F(FlagsTestsWithCmdLine, FlagsTestsGetValueCmdline) { |
| 217 | FlagBase::ReloadAllFlags("test"); |
| 218 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 219 | test_flag_->AssertCmdlineValue(true, 1); |
| 220 | test_flag_->AssertSysPropValue(false, 2); |
| 221 | test_flag_->AssertServerSettingValue(false, 3); |
| 222 | test_flag_->AssertDefaultValue(42); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 223 | |
Calin Juravle | 14a5151 | 2021-06-04 12:57:16 -0700 | [diff] [blame] | 224 | ASSERT_EQ(test_flag_->Value(), 1); |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 225 | } |
| 226 | |
Calin Juravle | 1ff9056 | 2021-06-16 14:37:42 -0700 | [diff] [blame] | 227 | // Validate that cmdline only flags don't read system properties. |
| 228 | TEST_F(FlagsTestsCmdLineOnly, CmdlineOnlyFlags) { |
| 229 | if (!android::base::SetProperty(test_flag_->SystemProperty(), "2")) { |
| 230 | LOG(ERROR) << "Release does not support property setting, skipping test: " |
| 231 | << test_flag_->SystemProperty(); |
| 232 | return; |
| 233 | } |
| 234 | |
Roland Levillain | 96d8f4f | 2021-09-17 12:15:22 +0100 | [diff] [blame] | 235 | if (!android::base::SetProperty(test_flag_->ServerSetting(), "3")) { |
Calin Juravle | 1ff9056 | 2021-06-16 14:37:42 -0700 | [diff] [blame] | 236 | LOG(ERROR) << "Release does not support property setting, skipping test: " |
| 237 | << test_flag_->ServerSetting(); |
| 238 | return; |
| 239 | } |
| 240 | |
| 241 | FlagBase::ReloadAllFlags("test"); |
| 242 | |
| 243 | test_flag_->AssertCmdlineValue(true, 1); |
| 244 | test_flag_->AssertSysPropValue(false, 2); |
| 245 | test_flag_->AssertServerSettingValue(false, 3); |
| 246 | test_flag_->AssertDefaultValue(42); |
| 247 | |
| 248 | ASSERT_EQ(test_flag_->Value(), 1); |
| 249 | } |
| 250 | |
Calin Juravle | 09eacd9 | 2021-05-19 17:03:55 -0700 | [diff] [blame] | 251 | } // namespace art |