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 #include <sys/socket.h>
18 #include <sys/un.h>
19
20 #include <gtest/gtest.h>
21 #include <cutils/sockets.h>
22 #include <android-base/file.h>
23 #include <android-base/result.h>
24 #include <android-base/logging.h>
25 #include <android-base/unique_fd.h>
26
27 #include <aconfigd.pb.h>
28 #include "com_android_aconfig_new_storage.h"
29
30 using namespace android::base;
31
32 namespace android {
33 namespace aconfigd {
34
35 class AconfigdSocketTest : public ::testing::Test {
36 protected:
connect_aconfigd_socket()37 Result<unique_fd> connect_aconfigd_socket() {
38 auto sock_fd = unique_fd(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));
39 if (sock_fd == -1) {
40 return ErrnoError() << "failed create socket";
41 }
42
43 auto addr = sockaddr_un();
44 addr.sun_family = AF_UNIX;
45 auto path = std::string("/dev/socket/aconfigd");
46 strlcpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path));
47
48 bool success = false;
49 for (int retry = 0; retry < 5; retry++) {
50 if (connect(sock_fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == 0) {
51 success = true;
52 break;
53 }
54 sleep(1);
55 }
56
57 if (!success) {
58 return ErrnoError() << "failed to connect to aconfigd socket";
59 }
60
61 return sock_fd;
62 }
63
64 // send a message to aconfigd socket, and capture return message
send_message(const StorageRequestMessages & messages)65 Result<StorageReturnMessages> send_message(const StorageRequestMessages& messages) {
66 auto sock_fd = connect_aconfigd_socket();
67 if (!sock_fd.ok()) {
68 return Error() << sock_fd.error();
69 }
70
71 auto message_string = std::string();
72 if (!messages.SerializeToString(&message_string)) {
73 return Error() << "failed to serialize pb to string";
74 }
75
76 unsigned char bytes[4];
77 uint32_t msg_size = message_string.size();
78 bytes[0] = (msg_size >> 24) & 0xFF;
79 bytes[1] = (msg_size >> 16) & 0xFF;
80 bytes[2] = (msg_size >> 8) & 0xFF;
81 bytes[3] = (msg_size >> 0) & 0xFF;
82
83 auto num_bytes = TEMP_FAILURE_RETRY(send(*sock_fd, bytes, 4, 0));
84 if (num_bytes != 4) {
85 return ErrnoError() << "send() failed for msg size";
86 }
87
88 num_bytes = TEMP_FAILURE_RETRY(
89 send(*sock_fd, message_string.c_str(), message_string.size(), 0));
90 if (num_bytes != static_cast<long>(message_string.size())) {
91 return ErrnoError() << "send() failed for msg";
92 }
93
94 num_bytes = TEMP_FAILURE_RETRY(recv(*sock_fd, bytes, 4, 0));
95 if (num_bytes != 4) {
96 return ErrnoError() << "recv() failed for return msg size";
97 }
98
99 uint32_t payload_size =
100 uint32_t(bytes[0]<<24 | bytes[1]<<16 | bytes[2]<<8 | bytes[3]);
101 char buffer[payload_size];
102 int payload_bytes_received = 0;
103 while (payload_bytes_received < payload_size) {
104 auto chunk_bytes = TEMP_FAILURE_RETRY(
105 recv(*sock_fd, buffer + payload_bytes_received,
106 payload_size - payload_bytes_received, 0));
107 if (chunk_bytes <= 0) {
108 return ErrnoError() << "recv() failed for return msg";
109 }
110 payload_bytes_received += chunk_bytes;
111 }
112
113 auto return_messages = StorageReturnMessages{};
114 if (!return_messages.ParseFromString(std::string(buffer, payload_size))) {
115 return Error() << "failed to parse string into proto";
116 }
117
118 if (return_messages.msgs_size() != messages.msgs_size()) {
119 return Error() << "Send " << messages.msgs_size() << " request messages, get "
120 << return_messages.msgs_size() << " return messages";
121 }
122
123 return return_messages;
124 }
125
add_new_storage_message(StorageRequestMessages & messages)126 void add_new_storage_message(StorageRequestMessages& messages) {
127 auto* message = messages.add_msgs();
128 auto* msg = message->mutable_new_storage_message();
129 auto test_dir = base::GetExecutableDirectory();
130 msg->set_container("mockup");
131 msg->set_package_map(test_dir + "/tests/data/v1/package.map");
132 msg->set_flag_map(test_dir + "/tests/data/v1/flag.map");
133 msg->set_flag_value(test_dir + "/tests/data/v1/flag.val");
134 }
135
add_flag_query_message(StorageRequestMessages & messages,const std::string & package,const std::string & flag)136 void add_flag_query_message(StorageRequestMessages& messages,
137 const std::string& package,
138 const std::string& flag) {
139 auto* message = messages.add_msgs();
140 auto* msg = message->mutable_flag_query_message();
141 msg->set_package_name(package);
142 msg->set_flag_name(flag);
143 }
144
add_list_storage_message(StorageRequestMessages & messages)145 void add_list_storage_message(StorageRequestMessages& messages) {
146 auto* message = messages.add_msgs();
147 auto* msg = message->mutable_list_storage_message();
148 msg->set_all(true);
149 }
150
verify_new_storage_return_message(const StorageReturnMessage & msg)151 void verify_new_storage_return_message(const StorageReturnMessage& msg) {
152 ASSERT_TRUE(msg.has_new_storage_message()) << msg.error_message();
153 auto message = msg.new_storage_message();
154 ASSERT_TRUE(message.storage_updated());
155 }
156
verify_list_storage_return_message(const StorageReturnMessage & msg)157 void verify_list_storage_return_message(const StorageReturnMessage& msg) {
158 ASSERT_TRUE(msg.has_list_storage_message()) << msg.error_message();
159 }
160
verify_error_message(const StorageReturnMessage & msg,const std::string & errmsg)161 void verify_error_message(const StorageReturnMessage& msg,
162 const std::string& errmsg) {
163 ASSERT_TRUE(msg.has_error_message());
164 ASSERT_TRUE(msg.error_message().find(errmsg) != std::string::npos)
165 << msg.error_message();
166 }
167 }; // class AconfigdSocketTest
168
169 // single request test
TEST_F(AconfigdSocketTest,single_request)170 TEST_F(AconfigdSocketTest, single_request) {
171 if (!com::android::aconfig_new_storage::enable_aconfig_storage_daemon()) {
172 return;
173 }
174 auto request_msgs = StorageRequestMessages();
175 add_flag_query_message(request_msgs, "unknown_package", "unknown_flag");
176 auto return_msgs = send_message(request_msgs);
177 ASSERT_TRUE(return_msgs.ok()) << return_msgs.error();
178 verify_error_message(return_msgs->msgs(0), "container not found");
179 }
180
181 // multiple request test
TEST_F(AconfigdSocketTest,multiple_requests)182 TEST_F(AconfigdSocketTest, multiple_requests) {
183 if (!com::android::aconfig_new_storage::enable_aconfig_storage_daemon()) {
184 return;
185 }
186 auto request_msgs = StorageRequestMessages();
187 size_t num_msgs = 10;
188 for (size_t i=0; i<num_msgs; ++i) {
189 add_flag_query_message(request_msgs, "unknown_package", "unknown_flag");
190 }
191 auto return_msgs = send_message(request_msgs);
192 ASSERT_TRUE(return_msgs.ok()) << return_msgs.error();
193 for (size_t i=0; i<num_msgs; ++i) {
194 verify_error_message(return_msgs->msgs(i), "container not found");
195 }
196 }
197
198 // add a mockup container
TEST_F(AconfigdSocketTest,add_new_storage)199 TEST_F(AconfigdSocketTest, add_new_storage) {
200 return;
201 auto request_msgs = StorageRequestMessages();
202 add_new_storage_message(request_msgs);
203 auto return_msgs = send_message(request_msgs);
204 ASSERT_TRUE(return_msgs.ok()) << return_msgs.error();
205 verify_new_storage_return_message(return_msgs->msgs(0));
206 }
207
TEST_F(AconfigdSocketTest,storage_list_package)208 TEST_F(AconfigdSocketTest, storage_list_package) {
209 if (!com::android::aconfig_new_storage::enable_aconfig_storage_daemon()) {
210 return;
211 }
212 auto request_msgs = StorageRequestMessages();
213 add_list_storage_message(request_msgs);
214 auto return_msgs = send_message(request_msgs);
215 ASSERT_TRUE(return_msgs.ok()) << return_msgs.error();
216 verify_list_storage_return_message(return_msgs->msgs(0));
217 }
218
219 } // namespace aconfigd
220 } // namespace android
221