| /* |
| * Copyright (C) 2024 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "aconfigd.h" |
| |
| #include <android-base/file.h> |
| #include <android-base/logging.h> |
| #include <android-base/properties.h> |
| #include <flag_macros.h> |
| #include <gtest/gtest.h> |
| #include <sys/stat.h> |
| |
| #include "aconfigd_test_mock.h" |
| #include "aconfigd_util.h" |
| #include "com_android_aconfig_new_storage.h" |
| |
| #define ACONFIGD_NS com::android::aconfig_new_storage |
| |
| namespace android { |
| namespace aconfigd { |
| |
| class AconfigdTest : public ::testing::Test { |
| protected: |
| |
| StorageRequestMessage new_storage_message(const std::string& container, |
| const std::string& package_map_file, |
| const std::string& flag_map_file, |
| const std::string& flag_value_file, |
| const std::string& flag_info_file) { |
| auto message = StorageRequestMessage(); |
| auto* msg = message.mutable_new_storage_message(); |
| msg->set_container(container); |
| msg->set_package_map(package_map_file); |
| msg->set_flag_map(flag_map_file); |
| msg->set_flag_value(flag_value_file); |
| msg->set_flag_info(flag_info_file); |
| return message; |
| } |
| |
| StorageRequestMessage new_storage_message(const ContainerMock& mock) { |
| return new_storage_message(mock.container, mock.package_map, mock.flag_map, |
| mock.flag_val, mock.flag_info); |
| } |
| |
| StorageRequestMessage flag_override_message(const std::string& package, |
| const std::string& flag, |
| const std::string& value, |
| bool is_local, |
| bool is_immediate) { |
| auto message = StorageRequestMessage(); |
| auto* msg = message.mutable_flag_override_message(); |
| |
| StorageRequestMessage::FlagOverrideType override_type; |
| if (is_local && is_immediate) { |
| override_type = StorageRequestMessage::LOCAL_IMMEDIATE; |
| } else if (is_local && !is_immediate) { |
| override_type = StorageRequestMessage::LOCAL_ON_REBOOT; |
| } else { |
| override_type = StorageRequestMessage::SERVER_ON_REBOOT; |
| } |
| |
| msg->set_package_name(package); |
| msg->set_flag_name(flag); |
| msg->set_flag_value(value); |
| msg->set_override_type(override_type); |
| return message; |
| } |
| |
| StorageRequestMessage flag_query_message(const std::string& package, |
| const std::string& flag) { |
| auto message = StorageRequestMessage(); |
| auto* msg = message.mutable_flag_query_message(); |
| msg->set_package_name(package); |
| msg->set_flag_name(flag); |
| return message; |
| } |
| |
| StorageRequestMessage flag_local_override_remove_message( |
| const std::string& package, |
| const std::string& flag, |
| bool remove_all = false) { |
| auto message = StorageRequestMessage(); |
| auto* msg = message.mutable_remove_local_override_message(); |
| msg->set_package_name(package); |
| msg->set_flag_name(flag); |
| msg->set_remove_all(remove_all); |
| return message; |
| } |
| |
| StorageRequestMessage reset_storage_message() { |
| auto message = StorageRequestMessage(); |
| auto* msg = message.mutable_reset_storage_message(); |
| return message; |
| } |
| |
| StorageRequestMessage list_storage_message() { |
| auto message = StorageRequestMessage(); |
| auto* msg = message.mutable_list_storage_message(); |
| msg->set_all(true); |
| return message; |
| } |
| |
| StorageRequestMessage list_container_storage_message(const std::string& container) { |
| auto message = StorageRequestMessage(); |
| auto* msg = message.mutable_list_storage_message(); |
| msg->set_container(container); |
| return message; |
| } |
| |
| StorageRequestMessage list_package_storage_message(const std::string& package) { |
| auto message = StorageRequestMessage(); |
| auto* msg = message.mutable_list_storage_message(); |
| msg->set_package_name(package); |
| return message; |
| } |
| |
| void verify_new_storage_return_message(base::Result<StorageReturnMessage> msg_result, |
| bool ensure_updated = false) { |
| ASSERT_TRUE(msg_result.ok()) << msg_result.error(); |
| auto msg = *msg_result; |
| ASSERT_TRUE(msg.has_new_storage_message()) << msg.error_message(); |
| if (ensure_updated) { |
| auto message = msg.new_storage_message(); |
| ASSERT_TRUE(message.storage_updated()); |
| } |
| } |
| |
| void verify_flag_override_return_message( |
| base::Result<StorageReturnMessage> msg_result) { |
| ASSERT_TRUE(msg_result.ok()) << msg_result.error(); |
| auto msg = *msg_result; |
| ASSERT_TRUE(msg.has_flag_override_message()) << msg.error_message(); |
| } |
| |
| void verify_flag_query_return_message( |
| const StorageReturnMessage::FlagQueryReturnMessage& message, |
| const std::string& package_name, |
| const std::string& flag_name, |
| const std::string& server_value, |
| const std::string& local_value, |
| const std::string& boot_value, |
| const std::string& default_value, |
| bool is_readwrite, |
| bool has_server_override, |
| bool has_local_override) { |
| ASSERT_EQ(message.package_name(), package_name); |
| ASSERT_EQ(message.flag_name(), flag_name); |
| ASSERT_EQ(message.server_flag_value(), server_value); |
| ASSERT_EQ(message.local_flag_value(), local_value); |
| ASSERT_EQ(message.boot_flag_value(), boot_value); |
| ASSERT_EQ(message.default_flag_value(), default_value); |
| ASSERT_EQ(message.is_readwrite(), is_readwrite); |
| ASSERT_EQ(message.has_server_override(), has_server_override); |
| ASSERT_EQ(message.has_local_override(), has_local_override); |
| } |
| |
| void verify_flag_query_return_message(base::Result<StorageReturnMessage> msg_result, |
| const std::string& package_name, |
| const std::string& flag_name, |
| const std::string& server_value, |
| const std::string& local_value, |
| const std::string& boot_value, |
| const std::string& default_value, |
| bool is_readwrite, |
| bool has_server_override, |
| bool has_local_override) { |
| ASSERT_TRUE(msg_result.ok()) << msg_result.error(); |
| auto msg = *msg_result; |
| ASSERT_TRUE(msg.has_flag_query_message()) << msg.error_message(); |
| auto message = msg.flag_query_message(); |
| verify_flag_query_return_message( |
| message, package_name, flag_name, server_value, local_value, boot_value, |
| default_value, is_readwrite, has_server_override, has_local_override); |
| } |
| |
| void verify_local_override_remove_return_message( |
| base::Result<StorageReturnMessage> msg_result) { |
| ASSERT_TRUE(msg_result.ok()) << msg_result.error(); |
| auto msg = *msg_result; |
| ASSERT_TRUE(msg.has_remove_local_override_message()) << msg.error_message(); |
| } |
| |
| void verify_reset_storage_message(base::Result<StorageReturnMessage> msg_result) { |
| ASSERT_TRUE(msg_result.ok()) << msg_result.error(); |
| auto msg = *msg_result; |
| ASSERT_TRUE(msg.has_reset_storage_message()) << msg.error_message(); |
| } |
| |
| void verify_error_message(base::Result<StorageReturnMessage> msg_result, |
| const std::string& errmsg) { |
| ASSERT_FALSE(msg_result.ok()); |
| ASSERT_TRUE(msg_result.error().message().find(errmsg) != std::string::npos) |
| << msg_result.error().message(); |
| } |
| |
| void verify_equal_file_content(const std::string& file_one, |
| const std::string& file_two) { |
| ASSERT_TRUE(FileExists(file_one)) << file_one << " does not exist"; |
| ASSERT_TRUE(FileExists(file_two)) << file_one << " does not exist"; |
| auto content_one = std::string(); |
| auto content_two = std::string(); |
| ASSERT_TRUE(base::ReadFileToString(file_one, &content_one)) << strerror(errno); |
| ASSERT_TRUE(base::ReadFileToString(file_two, &content_two)) << strerror(errno); |
| ASSERT_EQ(content_one, content_two) << file_one << " is different from " |
| << file_two; |
| } |
| |
| // setup test suites |
| static void SetUpTestSuite() { |
| auto test_dir = base::GetExecutableDirectory(); |
| package_map_ = test_dir + "/tests/data/v1/package.map"; |
| flag_map_ = test_dir + "/tests/data/v1/flag.map"; |
| flag_val_ = test_dir + "/tests/data/v1/flag.val"; |
| flag_info_ = test_dir + "/tests/data/v1/flag.info"; |
| updated_package_map_ = test_dir + "/tests/data/v2/package.map"; |
| updated_flag_map_ = test_dir + "/tests/data/v2/flag.map"; |
| updated_flag_val_ = test_dir + "/tests/data/v2/flag.val"; |
| updated_flag_info_ = test_dir + "/tests/data/v2/flag.info"; |
| } |
| |
| static std::string package_map_; |
| static std::string flag_map_; |
| static std::string flag_val_; |
| static std::string flag_info_; |
| static std::string updated_package_map_; |
| static std::string updated_flag_map_; |
| static std::string updated_flag_val_; |
| static std::string updated_flag_info_; |
| }; // class AconfigdTest |
| |
| std::string AconfigdTest::package_map_; |
| std::string AconfigdTest::flag_map_; |
| std::string AconfigdTest::flag_val_; |
| std::string AconfigdTest::flag_info_; |
| std::string AconfigdTest::updated_package_map_; |
| std::string AconfigdTest::updated_flag_map_; |
| std::string AconfigdTest::updated_flag_val_; |
| std::string AconfigdTest::updated_flag_info_; |
| |
| TEST_F(AconfigdTest, init_platform_storage_fresh) { |
| auto a_mock = AconfigdMock(); |
| auto init_result = a_mock.aconfigd.InitializePlatformStorage(); |
| ASSERT_TRUE(init_result.ok()) << init_result.error(); |
| |
| auto partitions = std::vector<std::pair<std::string, std::string>>{ |
| {"system", "/system/etc/aconfig"}, |
| {"vendor", "/vendor/etc/aconfig"}, |
| {"product", "/product/etc/aconfig"}}; |
| |
| for (auto const& [container, storage_dir] : partitions) { |
| auto package_map = std::string(storage_dir) + "/package.map"; |
| auto flag_map = std::string(storage_dir) + "/flag.map"; |
| auto flag_val = std::string(storage_dir) + "/flag.val"; |
| auto flag_info = std::string(storage_dir) + "/flag.info"; |
| if (!FileNonZeroSize(flag_val)) { |
| continue; |
| } |
| |
| verify_equal_file_content(a_mock.maps_dir + "/" + container + ".package.map", package_map); |
| verify_equal_file_content(a_mock.maps_dir + "/" + container + ".flag.map", flag_map); |
| verify_equal_file_content(a_mock.flags_dir + "/" + container + ".val", flag_val); |
| verify_equal_file_content(a_mock.boot_dir + "/" + container + ".val", flag_val); |
| verify_equal_file_content(a_mock.flags_dir + "/" + container + ".info", flag_info); |
| verify_equal_file_content(a_mock.boot_dir + "/" + container + ".info", flag_info); |
| } |
| } |
| |
| TEST_F(AconfigdTest, init_platform_storage_reboot) { |
| auto a_mock = AconfigdMock(); |
| auto init_result = a_mock.aconfigd.InitializePlatformStorage(); |
| ASSERT_TRUE(init_result.ok()) << init_result.error(); |
| |
| init_result = a_mock.aconfigd.InitializePlatformStorage(); |
| ASSERT_TRUE(init_result.ok()) << init_result.error(); |
| |
| auto partitions = std::vector<std::pair<std::string, std::string>>{ |
| {"system", "/system/etc/aconfig"}, |
| {"vendor", "/vendor/etc/aconfig"}, |
| {"product", "/product/etc/aconfig"}}; |
| |
| for (auto const& [container, storage_dir] : partitions) { |
| auto package_map = std::string(storage_dir) + "/package.map"; |
| auto flag_map = std::string(storage_dir) + "/flag.map"; |
| auto flag_val = std::string(storage_dir) + "/flag.val"; |
| auto flag_info = std::string(storage_dir) + "/flag.info"; |
| if (!FileNonZeroSize(flag_val)) { |
| continue; |
| } |
| |
| verify_equal_file_content(a_mock.maps_dir + "/" + container + ".package.map", package_map); |
| verify_equal_file_content(a_mock.maps_dir + "/" + container + ".flag.map", flag_map); |
| verify_equal_file_content(a_mock.flags_dir + "/" + container + ".val", flag_val); |
| verify_equal_file_content(a_mock.boot_dir + "/" + container + ".val", flag_val); |
| verify_equal_file_content(a_mock.flags_dir + "/" + container + ".info", flag_info); |
| verify_equal_file_content(a_mock.boot_dir + "/" + container + ".info", flag_info); |
| } |
| } |
| |
| TEST_F(AconfigdTest, init_mainline_storage_fresh) { |
| auto a_mock = AconfigdMock(); |
| auto init_result = a_mock.aconfigd.InitializeMainlineStorage(); |
| ASSERT_TRUE(init_result.ok()) << init_result.error(); |
| } |
| |
| TEST_F(AconfigdTest, add_new_storage) { |
| // create mocks |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| // mock a socket request |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| auto digest = GetFilesDigest( |
| {c_mock.package_map, c_mock.flag_map, c_mock.flag_val, c_mock.flag_info}); |
| ASSERT_TRUE(digest.ok()); |
| |
| // verify the record exists in persist records pb |
| auto persist_records_pb = PersistStorageRecords(); |
| auto content = std::string(); |
| ASSERT_TRUE(base::ReadFileToString(a_mock.persist_pb, &content)) << strerror(errno); |
| ASSERT_TRUE(persist_records_pb.ParseFromString(content)) << strerror(errno); |
| bool found = false; |
| for (auto& entry : persist_records_pb.records()) { |
| if (entry.container() == "mockup") { |
| found = true; |
| ASSERT_EQ(entry.version(), 1); |
| ASSERT_EQ(entry.package_map(), c_mock.package_map); |
| ASSERT_EQ(entry.flag_map(), c_mock.flag_map); |
| ASSERT_EQ(entry.flag_val(), c_mock.flag_val); |
| ASSERT_EQ(entry.flag_info(), c_mock.flag_info); |
| ASSERT_EQ(entry.digest(), *digest); |
| break; |
| } |
| } |
| ASSERT_TRUE(found); |
| |
| // verify persist and boot files |
| verify_equal_file_content(a_mock.maps_dir + "/mockup.package.map", package_map_); |
| verify_equal_file_content(a_mock.maps_dir + "/mockup.flag.map", flag_map_); |
| verify_equal_file_content(a_mock.flags_dir + "/mockup.val", flag_val_); |
| verify_equal_file_content(a_mock.boot_dir + "/mockup.val", flag_val_); |
| verify_equal_file_content(a_mock.flags_dir + "/mockup.info", flag_info_); |
| verify_equal_file_content(a_mock.boot_dir + "/mockup.info", flag_info_); |
| } |
| |
| TEST_F(AconfigdTest, container_update_in_ota) { |
| // create mocks |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| // mock a socket request |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| // mock an ota container update |
| c_mock.UpdateFiles( |
| updated_package_map_, updated_flag_map_, updated_flag_val_, updated_flag_info_); |
| |
| // force update |
| request_msg = new_storage_message(c_mock); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| auto digest = GetFilesDigest( |
| {c_mock.package_map, c_mock.flag_map, c_mock.flag_val, c_mock.flag_info}); |
| ASSERT_TRUE(digest.ok()); |
| |
| // verify the record exists in persist records pb |
| auto persist_records_pb = PersistStorageRecords(); |
| auto content = std::string(); |
| ASSERT_TRUE(base::ReadFileToString(a_mock.persist_pb, &content)) |
| << strerror(errno); |
| ASSERT_TRUE(persist_records_pb.ParseFromString(content)) << strerror(errno); |
| bool found = false; |
| for (auto& entry : persist_records_pb.records()) { |
| if (entry.container() == "mockup") { |
| found = true; |
| ASSERT_EQ(entry.version(), 1); |
| ASSERT_EQ(entry.package_map(), c_mock.package_map); |
| ASSERT_EQ(entry.flag_map(), c_mock.flag_map); |
| ASSERT_EQ(entry.flag_val(), c_mock.flag_val); |
| ASSERT_EQ(entry.flag_info(), c_mock.flag_info); |
| ASSERT_EQ(entry.digest(), *digest); |
| break; |
| } |
| } |
| ASSERT_TRUE(found); |
| |
| // verify persist and boot files |
| verify_equal_file_content(a_mock.maps_dir + "/mockup.package.map", updated_package_map_); |
| verify_equal_file_content(a_mock.maps_dir + "/mockup.flag.map", updated_flag_map_); |
| verify_equal_file_content(a_mock.flags_dir + "/mockup.val", updated_flag_val_); |
| verify_equal_file_content(a_mock.flags_dir + "/mockup.info", updated_flag_info_); |
| |
| // the boot copy should never be updated |
| verify_equal_file_content(a_mock.boot_dir + "/mockup.val", flag_val_); |
| verify_equal_file_content(a_mock.boot_dir + "/mockup.info", flag_info_); |
| } |
| |
| TEST_F(AconfigdTest, server_override) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_rw", "false", false, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "false", "", |
| "true", "true", true, true, false); |
| |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_rw", "true", false, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "true", "", |
| "true", "true", true, true, false); |
| } |
| |
| TEST_F(AconfigdTest, server_override_survive_update) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| // create a server override |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_rw", "false", false, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "false", "", |
| "true", "true", true, true, false); |
| |
| // mock an ota container update |
| c_mock.UpdateFiles( |
| updated_package_map_, updated_flag_map_, updated_flag_val_, updated_flag_info_); |
| |
| // force update |
| request_msg = new_storage_message(c_mock); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| // server override should persist |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "false", "", |
| "true", "true", true, true, false); |
| } |
| |
| TEST_F_WITH_FLAGS(AconfigdTest, local_override_immediate, |
| REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG( |
| ACONFIGD_NS, support_immediate_local_overrides))) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_rw", "false", true, true); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| request_msg = |
| flag_query_message("com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "", |
| "false", "false", "true", true, false, true); |
| } |
| |
| TEST_F(AconfigdTest, local_override) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_rw", "false", true, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "", "false", |
| "true", "true", true, false, true); |
| |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_rw", "true", true, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "", "true", |
| "true", "true", true, false, true); |
| } |
| |
| TEST_F(AconfigdTest, local_override_survive_update) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| // create a local override |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_rw", "false", true, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "", "false", |
| "true", "true", true, false, true); |
| |
| // mock an ota container update |
| c_mock.UpdateFiles( |
| updated_package_map_, updated_flag_map_, updated_flag_val_, updated_flag_info_); |
| |
| // force update |
| request_msg = new_storage_message(c_mock); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| // local override should persist |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "", "false", |
| "true", "true", true, false, true); |
| } |
| |
| TEST_F(AconfigdTest, single_local_override_remove) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| // local override enabled_rw |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_rw", "false", true, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| // local override disabled_rw |
| request_msg = flag_override_message("com.android.aconfig.storage.test_2", |
| "disabled_rw", "true", true, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| // remove local override enabled_rw |
| request_msg = flag_local_override_remove_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_local_override_remove_return_message(return_msg); |
| |
| // enabled_rw local override should be gone |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "", "", |
| "true", "true", true, false, false); |
| |
| // disabled_rw local override should still exists |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_2", "disabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_2", "disabled_rw", "", "true", |
| "false", "false", true, false, true); |
| } |
| |
| TEST_F(AconfigdTest, readonly_flag_override) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_ro", "false", false, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_error_message(return_msg, "Cannot update read only flag"); |
| |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_ro", "false", true, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_error_message(return_msg, "Cannot update read only flag"); |
| } |
| |
| TEST_F(AconfigdTest, nonexist_flag_override) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| request_msg = |
| flag_override_message("unknown", "enabled_rw", "false", false, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_error_message(return_msg, "Failed to find owning container"); |
| |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "unknown", "false", false, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_error_message(return_msg, "Flag does not exist"); |
| } |
| |
| TEST_F(AconfigdTest, nonexist_flag_query) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| request_msg = flag_query_message("unknown", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_error_message(return_msg, "Failed to find owning container"); |
| |
| request_msg = flag_query_message("com.android.aconfig.storage.test_1", "unknown"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_error_message(return_msg, "unknown does not exist"); |
| } |
| |
| TEST_F(AconfigdTest, storage_reset) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| // server override enabled_rw |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_rw", "false", false, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| // local override disabled_rw |
| request_msg = flag_override_message("com.android.aconfig.storage.test_2", |
| "disabled_rw", "true", true, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| // storage reset |
| request_msg = reset_storage_message(); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_reset_storage_message(return_msg); |
| |
| // enabled_rw server override should be gone |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_1", "enabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_1", "enabled_rw", "", "", |
| "true", "true", true, false, false); |
| |
| // disabled_rw local override should be gone |
| request_msg = flag_query_message( |
| "com.android.aconfig.storage.test_2", "disabled_rw"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_query_return_message( |
| return_msg, "com.android.aconfig.storage.test_2", "disabled_rw", "", "", |
| "false", "false", true, false, false); |
| } |
| |
| TEST_F(AconfigdTest, list_package) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| // server override disabled_rw |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "disabled_rw", "true", false, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| // local override enabled_rw |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "enabled_rw", "false", true, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| // list package |
| request_msg = list_package_storage_message("com.android.aconfig.storage.test_1"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| ASSERT_TRUE(return_msg.ok()) << return_msg.error(); |
| auto flags_msg = return_msg->list_storage_message(); |
| ASSERT_EQ(flags_msg.flags_size(), 3); |
| verify_flag_query_return_message( |
| flags_msg.flags(0), "com.android.aconfig.storage.test_1", "disabled_rw", |
| "true", "", "false", "false", true, true, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(1), "com.android.aconfig.storage.test_1", "enabled_ro", |
| "", "", "true", "true", false, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(2), "com.android.aconfig.storage.test_1", "enabled_rw", |
| "", "false", "true", "true", true, false, true); |
| } |
| |
| TEST_F(AconfigdTest, list_container) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| // server override test1.disabled_rw |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "disabled_rw", "true", false, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| // local override test2.disabled_rw |
| request_msg = flag_override_message("com.android.aconfig.storage.test_2", |
| "disabled_rw", "false", true, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| // list container |
| request_msg = list_container_storage_message("mockup"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| ASSERT_TRUE(return_msg.ok()) << return_msg.error(); |
| auto flags_msg = return_msg->list_storage_message(); |
| ASSERT_EQ(flags_msg.flags_size(), 8); |
| verify_flag_query_return_message( |
| flags_msg.flags(0), "com.android.aconfig.storage.test_1", "disabled_rw", |
| "true", "", "false", "false", true, true, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(1), "com.android.aconfig.storage.test_1", "enabled_ro", |
| "", "", "true", "true", false, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(2), "com.android.aconfig.storage.test_1", "enabled_rw", |
| "", "", "true", "true", true, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(3), "com.android.aconfig.storage.test_2", "disabled_rw", |
| "", "false", "false", "false", true, false, true); |
| verify_flag_query_return_message( |
| flags_msg.flags(4), "com.android.aconfig.storage.test_2", "enabled_fixed_ro", |
| "", "", "true", "true", false, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(5), "com.android.aconfig.storage.test_2", "enabled_ro", |
| "", "", "true", "true", false, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(6), "com.android.aconfig.storage.test_4", "enabled_fixed_ro", |
| "", "", "true", "true", false, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(7), "com.android.aconfig.storage.test_4", "enabled_rw", |
| "", "", "true", "true", true, false, false); |
| } |
| |
| TEST_F(AconfigdTest, list_all) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| // server override test1.disabled_rw |
| request_msg = flag_override_message("com.android.aconfig.storage.test_1", |
| "disabled_rw", "true", false, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| // local override test2.disabled_rw |
| request_msg = flag_override_message("com.android.aconfig.storage.test_2", |
| "disabled_rw", "false", true, false); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_flag_override_return_message(return_msg); |
| |
| // list all storage |
| request_msg = list_storage_message(); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| ASSERT_TRUE(return_msg.ok()) << return_msg.error(); |
| auto flags_msg = return_msg->list_storage_message(); |
| ASSERT_EQ(flags_msg.flags_size(), 8); |
| verify_flag_query_return_message( |
| flags_msg.flags(0), "com.android.aconfig.storage.test_1", "disabled_rw", |
| "true", "", "false", "false", true, true, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(1), "com.android.aconfig.storage.test_1", "enabled_ro", |
| "", "", "true", "true", false, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(2), "com.android.aconfig.storage.test_1", "enabled_rw", |
| "", "", "true", "true", true, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(3), "com.android.aconfig.storage.test_2", "disabled_rw", |
| "", "false", "false", "false", true, false, true); |
| verify_flag_query_return_message( |
| flags_msg.flags(4), "com.android.aconfig.storage.test_2", "enabled_fixed_ro", |
| "", "", "true", "true", false, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(5), "com.android.aconfig.storage.test_2", "enabled_ro", |
| "", "", "true", "true", false, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(6), "com.android.aconfig.storage.test_4", "enabled_fixed_ro", |
| "", "", "true", "true", false, false, false); |
| verify_flag_query_return_message( |
| flags_msg.flags(7), "com.android.aconfig.storage.test_4", "enabled_rw", |
| "", "", "true", "true", true, false, false); |
| } |
| |
| TEST_F(AconfigdTest, list_nonexist_package) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| request_msg = list_package_storage_message("unknown"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_error_message(return_msg, "container not found"); |
| } |
| |
| TEST_F(AconfigdTest, list_nonexist_container) { |
| auto a_mock = AconfigdMock(); |
| auto c_mock = ContainerMock("mockup", package_map_, flag_map_, flag_val_, flag_info_); |
| |
| auto request_msg = new_storage_message(c_mock); |
| auto return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_new_storage_return_message(return_msg, true); |
| |
| request_msg = list_container_storage_message("unknown"); |
| return_msg = a_mock.SendRequestToSocket(request_msg); |
| verify_error_message(return_msg, "Missing storage files object"); |
| } |
| |
| } // namespace aconfigd |
| } // namespace android |