blob: 62bd488be3ec378d4d74ce23f726bca03dbf5441 [file] [log] [blame]
/*
* 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 <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <flag_macros.h>
#include <gtest/gtest.h>
#include "aconfigd_test_mock.h"
#include "aconfigd_util.h"
namespace android {
namespace aconfigd {
class AconfigdProtonColliderTest : public ::testing::Test {
protected:
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 ota_flag_staging_message(
const std::string& build_id,
const std::vector<std::tuple<std::string, std::string, std::string>> flags) {
auto message = StorageRequestMessage();
auto* msg = message.mutable_ota_staging_message();
msg->set_build_id(build_id);
for (auto const& [package_name, flag_name, flag_value] : flags) {
auto* flag = msg->add_overrides();
flag->set_package_name(package_name);
flag->set_flag_name(flag_name);
flag->set_flag_value(flag_value);
}
return message;
}
void verify_ota_staging_return_message(base::Result<StorageReturnMessage> msg_result) {
ASSERT_TRUE(msg_result.ok()) << msg_result.error();
auto msg = *msg_result;
ASSERT_TRUE(msg.has_ota_staging_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();
}
}; // class AconfigdProtonColliderTest
TEST_F(AconfigdProtonColliderTest, ota_flag_staging) {
auto a_mock = AconfigdMock();
auto request_msg = ota_flag_staging_message(
"mock_build_id",
{{"package_1", "flag_1", "true"},
{"package_2", "flag_1", "false"}});
auto return_msg = a_mock.SendRequestToSocket(request_msg);
verify_ota_staging_return_message(return_msg);
ASSERT_TRUE(FileExists(a_mock.flags_dir + "/ota.pb"));
auto pb = ReadPbFromFile<StorageRequestMessage::OTAFlagStagingMessage>(
a_mock.flags_dir + "/ota.pb");
ASSERT_TRUE(pb.ok());
ASSERT_EQ(pb->build_id(), "mock_build_id");
auto flags = pb->overrides();
ASSERT_EQ(flags.size(), 2);
auto flag = pb->overrides(0);
ASSERT_EQ(flag.package_name(), "package_1");
ASSERT_EQ(flag.flag_name(), "flag_1");
ASSERT_EQ(flag.flag_value(), "true");
flag = pb->overrides(1);
ASSERT_EQ(flag.package_name(), "package_2");
ASSERT_EQ(flag.flag_name(), "flag_1");
ASSERT_EQ(flag.flag_value(), "false");
}
TEST_F(AconfigdProtonColliderTest, ota_flag_unstaging) {
// cerate mock aconfigd and initialize platform storage
auto a_mock = AconfigdMock();
auto init_result = a_mock.aconfigd.InitializePlatformStorage();
ASSERT_TRUE(init_result.ok()) << init_result.error();
auto flags_to_stage =
std::vector<std::tuple<std::string, std::string, std::string>>();
// for fake OTA flag overrides, flip all RW flag value
auto request_msg = list_container_storage_message("system");
auto return_msg = a_mock.SendRequestToSocket(request_msg);
ASSERT_TRUE(return_msg.ok()) << return_msg.error();
auto flags_msg = return_msg->list_storage_message();
for (auto const& flag : flags_msg.flags()) {
if (flag.is_readwrite()) {
flags_to_stage.push_back({
flag.package_name(),
flag.flag_name(),
flag.server_flag_value() == "true" ? "false" : "true"
});
}
}
// fake an OTA staging request, using current build id
auto build_id = base::GetProperty("ro.build.fingerprint", "");
request_msg = ota_flag_staging_message(build_id, flags_to_stage);
return_msg = a_mock.SendRequestToSocket(request_msg);
verify_ota_staging_return_message(return_msg);
ASSERT_TRUE(FileExists(a_mock.flags_dir + "/ota.pb"));
init_result = a_mock.aconfigd.InitializePlatformStorage();
ASSERT_TRUE(init_result.ok()) << init_result.error();
ASSERT_FALSE(FileExists(a_mock.flags_dir + "/ota.pb"));
// list container
request_msg = list_container_storage_message("system");
return_msg = a_mock.SendRequestToSocket(request_msg);
ASSERT_TRUE(return_msg.ok()) << return_msg.error();
flags_msg = return_msg->list_storage_message();
size_t i = 0;
for (auto const& flag : flags_msg.flags()) {
if (flag.is_readwrite()) {
ASSERT_EQ(flag.package_name(), std::get<0>(flags_to_stage[i]));
ASSERT_EQ(flag.flag_name(), std::get<1>(flags_to_stage[i]));
ASSERT_EQ(flag.server_flag_value(), std::get<2>(flags_to_stage[i]));
++i;
}
}
}
TEST_F(AconfigdProtonColliderTest, ota_flag_unstaging_negative) {
// cerate mock aconfigd and initialize platform storage
auto a_mock = AconfigdMock();
auto init_result = a_mock.aconfigd.InitializePlatformStorage();
ASSERT_TRUE(init_result.ok()) << init_result.error();
// fake an OTA staging request, using fake build id
auto request_msg = ota_flag_staging_message(
"some_fake_build_id",
{{"abc", "def", "true"}});
auto return_msg = a_mock.SendRequestToSocket(request_msg);
verify_ota_staging_return_message(return_msg);
ASSERT_TRUE(FileExists(a_mock.flags_dir + "/ota.pb"));
init_result = a_mock.aconfigd.InitializePlatformStorage();
ASSERT_TRUE(init_result.ok()) << init_result.error();
// the ota overrides file should still exist
ASSERT_TRUE(FileExists(a_mock.flags_dir + "/ota.pb"));
}
} // namespace aconfigd
} // namespace android