• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <filesystem>
18 #include <fstream>
19 #include <string>
20 
21 #include <errno.h>
22 
23 #include <android-base/file.h>
24 #include <android-base/result.h>
25 #include <android-base/scopeguard.h>
26 #include <android-base/stringprintf.h>
27 #include <android-base/strings.h>
28 #include <gtest/gtest.h>
29 
30 #include "apexd_session.h"
31 #include "apexd_test_utils.h"
32 #include "apexd_utils.h"
33 #include "session_state.pb.h"
34 
35 namespace android {
36 namespace apex {
37 namespace {
38 
39 using android::apex::testing::IsOk;
40 using android::base::Join;
41 using android::base::make_scope_guard;
42 using ::apex::proto::SessionState;
43 
44 // TODO(b/170329726): add unit tests for apexd_sessions.h
45 
TEST(ApexdSessionTest,GetSessionsDirSessionsStoredInMetadata)46 TEST(ApexdSessionTest, GetSessionsDirSessionsStoredInMetadata) {
47   if (access("/metadata", F_OK) != 0) {
48     GTEST_SKIP() << "Device doesn't have /metadata partition";
49   }
50 
51   std::string result = ApexSession::GetSessionsDir();
52   ASSERT_EQ(result, "/metadata/apex/sessions");
53 }
54 
TEST(ApexdSessionTest,GetSessionsDirNoMetadataPartitionFallbackToData)55 TEST(ApexdSessionTest, GetSessionsDirNoMetadataPartitionFallbackToData) {
56   if (access("/metadata", F_OK) == 0) {
57     GTEST_SKIP() << "Device has /metadata partition";
58   }
59 
60   std::string result = ApexSession::GetSessionsDir();
61   ASSERT_EQ(result, "/data/apex/sessions");
62 }
63 
TEST(ApexdSessionTest,MigrateToMetadataSessionsDir)64 TEST(ApexdSessionTest, MigrateToMetadataSessionsDir) {
65   namespace fs = std::filesystem;
66 
67   if (access("/metadata", F_OK) != 0) {
68     GTEST_SKIP() << "Device doesn't have /metadata partition";
69   }
70 
71   // This is ugly, but does the job. To have a truly hermetic unit tests we
72   // need to refactor ApexSession class.
73   for (const auto& entry : fs::directory_iterator("/metadata/apex/sessions")) {
74     fs::remove_all(entry.path());
75   }
76 
77   // This is a very ugly test set up, but to have something better we need to
78   // refactor ApexSession class.
79   class TestApexSession {
80    public:
81     TestApexSession(int id, const SessionState::State& state) {
82       path_ = "/data/apex/sessions/" + std::to_string(id);
83       if (auto status = CreateDirIfNeeded(path_, 0700); !status.ok()) {
84         ADD_FAILURE() << "Failed to create " << path_ << " : "
85                       << status.error();
86       }
87       SessionState session;
88       session.set_id(id);
89       session.set_state(state);
90       std::fstream state_file(
91           path_ + "/state", std::ios::out | std::ios::trunc | std::ios::binary);
92       if (!session.SerializeToOstream(&state_file)) {
93         ADD_FAILURE() << "Failed to write to " << path_;
94       }
95     }
96 
97     ~TestApexSession() { fs::remove_all(path_); }
98 
99    private:
100     std::string path_;
101   };
102 
103   auto deleter = make_scope_guard([&]() {
104     fs::remove_all("/metadata/apex/sessions/239");
105     fs::remove_all("/metadata/apex/sessions/1543");
106   });
107 
108   TestApexSession session1(239, SessionState::SUCCESS);
109   TestApexSession session2(1543, SessionState::ACTIVATION_FAILED);
110 
111   ASSERT_TRUE(IsOk(ApexSession::MigrateToMetadataSessionsDir()));
112 
113   auto sessions = ApexSession::GetSessions();
114   ASSERT_EQ(2u, sessions.size()) << Join(sessions, ',');
115 
116   auto migrated_session_1 = ApexSession::GetSession(239);
117   ASSERT_TRUE(IsOk(migrated_session_1));
118   ASSERT_EQ(SessionState::SUCCESS, migrated_session_1->GetState());
119 
120   auto migrated_session_2 = ApexSession::GetSession(1543);
121   ASSERT_TRUE(IsOk(migrated_session_2));
122   ASSERT_EQ(SessionState::ACTIVATION_FAILED, migrated_session_2->GetState());
123 }
124 
125 }  // namespace
126 }  // namespace apex
127 }  // namespace android
128