xref: /aosp_15_r20/system/apex/apexd/apexd_session_test.cpp (revision 33f3758387333dbd2962d7edbd98681940d895da)
1 /*
2  * Copyright (C) 2020 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 "apexd_session.h"
18 
19 #include <android-base/file.h>
20 #include <android-base/result-gmock.h>
21 #include <android-base/result.h>
22 #include <android-base/scopeguard.h>
23 #include <android-base/stringprintf.h>
24 #include <android-base/strings.h>
25 #include <errno.h>
26 #include <gmock/gmock.h>
27 #include <gtest/gtest.h>
28 
29 #include <algorithm>
30 #include <filesystem>
31 #include <fstream>
32 #include <string>
33 
34 #include "apexd_test_utils.h"
35 #include "apexd_utils.h"
36 #include "session_state.pb.h"
37 
38 namespace android {
39 namespace apex {
40 namespace {
41 
42 using android::base::Join;
43 using android::base::make_scope_guard;
44 using android::base::testing::Ok;
45 using ::apex::proto::SessionState;
46 using ::testing::Not;
47 using ::testing::UnorderedElementsAre;
48 
49 // TODO(b/170329726): add unit tests for apexd_sessions.h
50 
TEST(ApexdSessionTest,GetSessionsDirSessionsStoredInMetadata)51 TEST(ApexdSessionTest, GetSessionsDirSessionsStoredInMetadata) {
52   if (access("/metadata", F_OK) != 0) {
53     GTEST_SKIP() << "Device doesn't have /metadata partition";
54   }
55 
56   std::string result = GetSessionsDir();
57   ASSERT_EQ(result, "/metadata/apex/sessions");
58 }
59 
TEST(ApexdSessionTest,GetSessionsDirNoMetadataPartitionFallbackToData)60 TEST(ApexdSessionTest, GetSessionsDirNoMetadataPartitionFallbackToData) {
61   if (access("/metadata", F_OK) == 0) {
62     GTEST_SKIP() << "Device has /metadata partition";
63   }
64 
65   std::string result = GetSessionsDir();
66   ASSERT_EQ(result, "/data/apex/sessions");
67 }
68 
TEST(ApexSessionManagerTest,CreateSession)69 TEST(ApexSessionManagerTest, CreateSession) {
70   TemporaryDir td;
71   auto manager = ApexSessionManager::Create(std::string(td.path));
72 
73   auto session = manager->CreateSession(239);
74   ASSERT_RESULT_OK(session);
75   ASSERT_EQ(239, session->GetId());
76   std::string session_dir = std::string(td.path) + "/239";
77   ASSERT_EQ(session_dir, session->GetSessionDir());
78 }
79 
TEST(ApexSessionManagerTest,GetSessionsNoSessionReturnsError)80 TEST(ApexSessionManagerTest, GetSessionsNoSessionReturnsError) {
81   TemporaryDir td;
82   auto manager = ApexSessionManager::Create(std::string(td.path));
83 
84   ASSERT_THAT(manager->GetSession(37), Not(Ok()));
85 }
86 
TEST(ApexSessionManagerTest,GetSessionsReturnsErrorSessionNotCommitted)87 TEST(ApexSessionManagerTest, GetSessionsReturnsErrorSessionNotCommitted) {
88   TemporaryDir td;
89   auto manager = ApexSessionManager::Create(std::string(td.path));
90 
91   auto session = manager->CreateSession(73);
92   ASSERT_RESULT_OK(session);
93   ASSERT_THAT(manager->GetSession(73), Not(Ok()));
94 }
95 
TEST(ApexSessionManagerTest,CreateCommitGetSession)96 TEST(ApexSessionManagerTest, CreateCommitGetSession) {
97   TemporaryDir td;
98   auto manager = ApexSessionManager::Create(std::string(td.path));
99 
100   auto session = manager->CreateSession(23);
101   ASSERT_RESULT_OK(session);
102   session->SetErrorMessage("error");
103   ASSERT_RESULT_OK(session->UpdateStateAndCommit(SessionState::STAGED));
104 
105   auto same_session = manager->GetSession(23);
106   ASSERT_RESULT_OK(same_session);
107   ASSERT_EQ(23, same_session->GetId());
108   ASSERT_EQ("error", same_session->GetErrorMessage());
109   ASSERT_EQ(SessionState::STAGED, same_session->GetState());
110 }
111 
TEST(ApexSessionManagerTest,GetSessionsNoSessionsCommitted)112 TEST(ApexSessionManagerTest, GetSessionsNoSessionsCommitted) {
113   TemporaryDir td;
114   auto manager = ApexSessionManager::Create(std::string(td.path));
115 
116   ASSERT_RESULT_OK(manager->CreateSession(3));
117 
118   auto sessions = manager->GetSessions();
119   ASSERT_EQ(0u, sessions.size());
120 }
121 
TEST(ApexSessionManager,GetSessionsCommittedSessions)122 TEST(ApexSessionManager, GetSessionsCommittedSessions) {
123   TemporaryDir td;
124   auto manager = ApexSessionManager::Create(std::string(td.path));
125 
126   auto session1 = manager->CreateSession(1543);
127   ASSERT_RESULT_OK(session1);
128   ASSERT_RESULT_OK(session1->UpdateStateAndCommit(SessionState::ACTIVATED));
129 
130   auto session2 = manager->CreateSession(179);
131   ASSERT_RESULT_OK(session2);
132   ASSERT_RESULT_OK(session2->UpdateStateAndCommit(SessionState::SUCCESS));
133 
134   // This sessions is not committed, it won't be returned in GetSessions.
135   ASSERT_RESULT_OK(manager->CreateSession(101));
136 
137   auto sessions = manager->GetSessions();
138   std::sort(
139       sessions.begin(), sessions.end(),
140       [](const auto& s1, const auto& s2) { return s1.GetId() < s2.GetId(); });
141 
142   ASSERT_EQ(2u, sessions.size());
143 
144   ASSERT_EQ(179, sessions[0].GetId());
145   ASSERT_EQ(SessionState::SUCCESS, sessions[0].GetState());
146 
147   ASSERT_EQ(1543, sessions[1].GetId());
148   ASSERT_EQ(SessionState::ACTIVATED, sessions[1].GetState());
149 }
150 
TEST(ApexSessionManager,GetSessionsInState)151 TEST(ApexSessionManager, GetSessionsInState) {
152   TemporaryDir td;
153   auto manager = ApexSessionManager::Create(std::string(td.path));
154 
155   auto session1 = manager->CreateSession(43);
156   ASSERT_RESULT_OK(session1);
157   ASSERT_RESULT_OK(session1->UpdateStateAndCommit(SessionState::ACTIVATED));
158 
159   auto session2 = manager->CreateSession(41);
160   ASSERT_RESULT_OK(session2);
161   ASSERT_RESULT_OK(session2->UpdateStateAndCommit(SessionState::SUCCESS));
162 
163   auto session3 = manager->CreateSession(23);
164   ASSERT_RESULT_OK(session3);
165   ASSERT_RESULT_OK(session3->UpdateStateAndCommit(SessionState::SUCCESS));
166 
167   auto sessions = manager->GetSessionsInState(SessionState::SUCCESS);
168   std::sort(
169       sessions.begin(), sessions.end(),
170       [](const auto& s1, const auto& s2) { return s1.GetId() < s2.GetId(); });
171 
172   ASSERT_EQ(2u, sessions.size());
173 
174   ASSERT_EQ(23, sessions[0].GetId());
175   ASSERT_EQ(SessionState::SUCCESS, sessions[0].GetState());
176 
177   ASSERT_EQ(41, sessions[1].GetId());
178   ASSERT_EQ(SessionState::SUCCESS, sessions[1].GetState());
179 }
180 
TEST(ApexSessionManager,MigrateFromOldSessionsDir)181 TEST(ApexSessionManager, MigrateFromOldSessionsDir) {
182   TemporaryDir td;
183   auto old_manager = ApexSessionManager::Create(std::string(td.path));
184 
185   auto session1 = old_manager->CreateSession(239);
186   ASSERT_RESULT_OK(session1);
187   ASSERT_RESULT_OK(session1->UpdateStateAndCommit(SessionState::STAGED));
188 
189   auto session2 = old_manager->CreateSession(13);
190   ASSERT_RESULT_OK(session2);
191   ASSERT_RESULT_OK(session2->UpdateStateAndCommit(SessionState::SUCCESS));
192 
193   auto session3 = old_manager->CreateSession(31);
194   ASSERT_RESULT_OK(session3);
195   ASSERT_RESULT_OK(session3->UpdateStateAndCommit(SessionState::ACTIVATED));
196 
197   TemporaryDir td2;
198   auto new_manager = ApexSessionManager::Create(std::string(td2.path));
199 
200   ASSERT_RESULT_OK(
201       new_manager->MigrateFromOldSessionsDir(std::string(td.path)));
202 
203   auto sessions = new_manager->GetSessions();
204   std::sort(
205       sessions.begin(), sessions.end(),
206       [](const auto& s1, const auto& s2) { return s1.GetId() < s2.GetId(); });
207 
208   ASSERT_EQ(3u, sessions.size());
209 
210   ASSERT_EQ(13, sessions[0].GetId());
211   ASSERT_EQ(SessionState::SUCCESS, sessions[0].GetState());
212 
213   ASSERT_EQ(31, sessions[1].GetId());
214   ASSERT_EQ(SessionState::ACTIVATED, sessions[1].GetState());
215 
216   ASSERT_EQ(239, sessions[2].GetId());
217   ASSERT_EQ(SessionState::STAGED, sessions[2].GetState());
218 
219   // Check that old manager directory doesn't have anything
220   auto old_sessions = old_manager->GetSessions();
221   ASSERT_TRUE(old_sessions.empty());
222 }
223 
TEST(ApexSessionManager,MigrateFromOldSessionsDirSameDir)224 TEST(ApexSessionManager, MigrateFromOldSessionsDirSameDir) {
225   TemporaryDir td;
226   auto old_manager = ApexSessionManager::Create(std::string(td.path));
227 
228   auto session1 = old_manager->CreateSession(239);
229   ASSERT_RESULT_OK(session1);
230   ASSERT_RESULT_OK(session1->UpdateStateAndCommit(SessionState::STAGED));
231 
232   auto session2 = old_manager->CreateSession(13);
233   ASSERT_RESULT_OK(session2);
234   ASSERT_RESULT_OK(session2->UpdateStateAndCommit(SessionState::SUCCESS));
235 
236   auto session3 = old_manager->CreateSession(31);
237   ASSERT_RESULT_OK(session3);
238   ASSERT_RESULT_OK(session3->UpdateStateAndCommit(SessionState::ACTIVATED));
239 
240   auto new_manager = ApexSessionManager::Create(std::string(td.path));
241 
242   ASSERT_RESULT_OK(
243       new_manager->MigrateFromOldSessionsDir(std::string(td.path)));
244 
245   auto sessions = new_manager->GetSessions();
246   std::sort(
247       sessions.begin(), sessions.end(),
248       [](const auto& s1, const auto& s2) { return s1.GetId() < s2.GetId(); });
249 
250   ASSERT_EQ(3u, sessions.size());
251 
252   ASSERT_EQ(13, sessions[0].GetId());
253   ASSERT_EQ(SessionState::SUCCESS, sessions[0].GetState());
254 
255   ASSERT_EQ(31, sessions[1].GetId());
256   ASSERT_EQ(SessionState::ACTIVATED, sessions[1].GetState());
257 
258   ASSERT_EQ(239, sessions[2].GetId());
259   ASSERT_EQ(SessionState::STAGED, sessions[2].GetState());
260 
261   // Directory is the same, so using old_manager should also work.
262   auto old_sessions = old_manager->GetSessions();
263   std::sort(
264       old_sessions.begin(), old_sessions.end(),
265       [](const auto& s1, const auto& s2) { return s1.GetId() < s2.GetId(); });
266 
267   ASSERT_EQ(3u, old_sessions.size());
268 
269   ASSERT_EQ(13, old_sessions[0].GetId());
270   ASSERT_EQ(SessionState::SUCCESS, old_sessions[0].GetState());
271 
272   ASSERT_EQ(31, old_sessions[1].GetId());
273   ASSERT_EQ(SessionState::ACTIVATED, old_sessions[1].GetState());
274 
275   ASSERT_EQ(239, old_sessions[2].GetId());
276   ASSERT_EQ(SessionState::STAGED, old_sessions[2].GetState());
277 }
278 
TEST(ApexSessionManagerTest,GetStagedApexDirsSelf)279 TEST(ApexSessionManagerTest, GetStagedApexDirsSelf) {
280   TemporaryDir td;
281   auto manager = ApexSessionManager::Create(std::string(td.path));
282 
283   auto session = manager->CreateSession(239);
284   ASSERT_RESULT_OK(session);
285 
286   ASSERT_THAT(session->GetStagedApexDirs("/path/to/staged_session_dir"),
287               UnorderedElementsAre("/path/to/staged_session_dir/session_239"));
288 }
289 
TEST(ApexSessionManagerTest,GetStagedApexDirsChildren)290 TEST(ApexSessionManagerTest, GetStagedApexDirsChildren) {
291   TemporaryDir td;
292   auto manager = ApexSessionManager::Create(std::string(td.path));
293 
294   auto session = manager->CreateSession(239);
295   ASSERT_RESULT_OK(session);
296   auto child_session_1 = manager->CreateSession(240);
297   ASSERT_RESULT_OK(child_session_1);
298   auto child_session_2 = manager->CreateSession(241);
299   ASSERT_RESULT_OK(child_session_2);
300   session->SetChildSessionIds({240, 241});
301 
302   ASSERT_THAT(session->GetStagedApexDirs("/path/to/staged_session_dir"),
303               UnorderedElementsAre("/path/to/staged_session_dir/session_240",
304                                    "/path/to/staged_session_dir/session_241"));
305 }
306 
307 }  // namespace
308 }  // namespace apex
309 }  // namespace android
310