xref: /aosp_15_r20/system/server_configurable_flags/aconfigd/aconfigd_proton_collider_test.cpp (revision 207333786ba243bc7d4d69ef6b05487aa7071806)
1 /*
2  * Copyright (C) 2024 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 
18 #include <android-base/file.h>
19 #include <android-base/logging.h>
20 #include <android-base/properties.h>
21 #include <flag_macros.h>
22 #include <gtest/gtest.h>
23 
24 #include "aconfigd_test_mock.h"
25 #include "aconfigd_util.h"
26 
27 namespace android {
28 namespace aconfigd {
29 
30 class AconfigdProtonColliderTest : public ::testing::Test {
31  protected:
32 
list_container_storage_message(const std::string & container)33   StorageRequestMessage list_container_storage_message(const std::string& container) {
34     auto message = StorageRequestMessage();
35     auto* msg = message.mutable_list_storage_message();
36     msg->set_container(container);
37     return message;
38   }
39 
ota_flag_staging_message(const std::string & build_id,const std::vector<std::tuple<std::string,std::string,std::string>> flags)40   StorageRequestMessage ota_flag_staging_message(
41       const std::string& build_id,
42       const std::vector<std::tuple<std::string, std::string, std::string>> flags) {
43     auto message = StorageRequestMessage();
44     auto* msg = message.mutable_ota_staging_message();
45     msg->set_build_id(build_id);
46     for (auto const& [package_name, flag_name, flag_value] : flags) {
47       auto* flag = msg->add_overrides();
48       flag->set_package_name(package_name);
49       flag->set_flag_name(flag_name);
50       flag->set_flag_value(flag_value);
51     }
52     return message;
53   }
54 
verify_ota_staging_return_message(base::Result<StorageReturnMessage> msg_result)55   void verify_ota_staging_return_message(base::Result<StorageReturnMessage> msg_result) {
56     ASSERT_TRUE(msg_result.ok()) << msg_result.error();
57     auto msg = *msg_result;
58     ASSERT_TRUE(msg.has_ota_staging_message()) << msg.error_message();
59   }
60 
verify_error_message(base::Result<StorageReturnMessage> msg_result,const std::string & errmsg)61   void verify_error_message(base::Result<StorageReturnMessage> msg_result,
62                             const std::string& errmsg) {
63     ASSERT_FALSE(msg_result.ok());
64     ASSERT_TRUE(msg_result.error().message().find(errmsg) != std::string::npos)
65         << msg_result.error().message();
66   }
67 }; // class AconfigdProtonColliderTest
68 
69 
TEST_F(AconfigdProtonColliderTest,ota_flag_staging)70 TEST_F(AconfigdProtonColliderTest, ota_flag_staging) {
71   auto a_mock = AconfigdMock();
72   auto request_msg = ota_flag_staging_message(
73       "mock_build_id",
74       {{"package_1", "flag_1", "true"},
75        {"package_2", "flag_1", "false"}});
76   auto return_msg = a_mock.SendRequestToSocket(request_msg);
77   verify_ota_staging_return_message(return_msg);
78   ASSERT_TRUE(FileExists(a_mock.flags_dir + "/ota.pb"));
79   auto pb = ReadPbFromFile<StorageRequestMessage::OTAFlagStagingMessage>(
80       a_mock.flags_dir + "/ota.pb");
81   ASSERT_TRUE(pb.ok());
82   ASSERT_EQ(pb->build_id(), "mock_build_id");
83   auto flags = pb->overrides();
84   ASSERT_EQ(flags.size(), 2);
85   auto flag = pb->overrides(0);
86   ASSERT_EQ(flag.package_name(), "package_1");
87   ASSERT_EQ(flag.flag_name(), "flag_1");
88   ASSERT_EQ(flag.flag_value(), "true");
89   flag = pb->overrides(1);
90   ASSERT_EQ(flag.package_name(), "package_2");
91   ASSERT_EQ(flag.flag_name(), "flag_1");
92   ASSERT_EQ(flag.flag_value(), "false");
93 }
94 
TEST_F(AconfigdProtonColliderTest,ota_flag_unstaging)95 TEST_F(AconfigdProtonColliderTest, ota_flag_unstaging) {
96   // cerate mock aconfigd and initialize platform storage
97   auto a_mock = AconfigdMock();
98   auto init_result = a_mock.aconfigd.InitializePlatformStorage();
99   ASSERT_TRUE(init_result.ok()) << init_result.error();
100 
101   auto flags_to_stage =
102       std::vector<std::tuple<std::string, std::string, std::string>>();
103 
104   // for fake OTA flag overrides, flip all RW flag value
105   auto request_msg = list_container_storage_message("system");
106   auto return_msg = a_mock.SendRequestToSocket(request_msg);
107   ASSERT_TRUE(return_msg.ok()) << return_msg.error();
108   auto flags_msg = return_msg->list_storage_message();
109 
110   for (auto const& flag : flags_msg.flags()) {
111     if (flag.is_readwrite()) {
112       flags_to_stage.push_back({
113           flag.package_name(),
114           flag.flag_name(),
115           flag.server_flag_value() == "true" ? "false" : "true"
116         });
117     }
118   }
119 
120   // fake an OTA staging request, using current build id
121   auto build_id = base::GetProperty("ro.build.fingerprint", "");
122   request_msg = ota_flag_staging_message(build_id, flags_to_stage);
123   return_msg = a_mock.SendRequestToSocket(request_msg);
124   verify_ota_staging_return_message(return_msg);
125   ASSERT_TRUE(FileExists(a_mock.flags_dir + "/ota.pb"));
126 
127   init_result = a_mock.aconfigd.InitializePlatformStorage();
128   ASSERT_TRUE(init_result.ok()) << init_result.error();
129   ASSERT_FALSE(FileExists(a_mock.flags_dir + "/ota.pb"));
130 
131   // list container
132   request_msg = list_container_storage_message("system");
133   return_msg = a_mock.SendRequestToSocket(request_msg);
134   ASSERT_TRUE(return_msg.ok()) << return_msg.error();
135   flags_msg = return_msg->list_storage_message();
136 
137   size_t i = 0;
138   for (auto const& flag : flags_msg.flags()) {
139     if (flag.is_readwrite()) {
140       ASSERT_EQ(flag.package_name(), std::get<0>(flags_to_stage[i]));
141       ASSERT_EQ(flag.flag_name(), std::get<1>(flags_to_stage[i]));
142       ASSERT_EQ(flag.server_flag_value(), std::get<2>(flags_to_stage[i]));
143       ++i;
144     }
145   }
146 }
147 
TEST_F(AconfigdProtonColliderTest,ota_flag_unstaging_negative)148 TEST_F(AconfigdProtonColliderTest, ota_flag_unstaging_negative) {
149   // cerate mock aconfigd and initialize platform storage
150   auto a_mock = AconfigdMock();
151   auto init_result = a_mock.aconfigd.InitializePlatformStorage();
152   ASSERT_TRUE(init_result.ok()) << init_result.error();
153 
154   // fake an OTA staging request, using fake build id
155   auto request_msg = ota_flag_staging_message(
156       "some_fake_build_id",
157       {{"abc", "def", "true"}});
158   auto return_msg = a_mock.SendRequestToSocket(request_msg);
159   verify_ota_staging_return_message(return_msg);
160   ASSERT_TRUE(FileExists(a_mock.flags_dir + "/ota.pb"));
161 
162   init_result = a_mock.aconfigd.InitializePlatformStorage();
163   ASSERT_TRUE(init_result.ok()) << init_result.error();
164 
165   // the ota overrides file should still exist
166   ASSERT_TRUE(FileExists(a_mock.flags_dir + "/ota.pb"));
167 }
168 
169 } // namespace aconfigd
170 } // namespace android
171