diff options
author | Nikita Ioffe <ioffe@google.com> | 2020-10-05 15:53:16 +0100 |
---|---|---|
committer | Nikita Ioffe <ioffe@google.com> | 2021-01-21 21:31:02 +0000 |
commit | 66bd61adb95077787c37bf4aa914cb242a52d413 (patch) | |
tree | b83253037c2515255867bf9e24cbbd49191a291f /apexd/apexd_utils_test.cpp | |
parent | 22613b7917e90d3f75cbd107bc49f82895381388 (diff) |
Fallback to /data/apex/sessions if /metadata partition is absent
There might be devices that support updatable apex, but don't have
/metadata partition. For them we need to fallback to storing sessions on
/data/apex/sessions.
This change implements this logic by introducing GetSessionsDir static
method which will pick first existing directory between
/metadata/apex/sessions and /data/apex/sessions. The evaluation will
happen only once, all other calls to GetSessionsDir will return the
cached value.
Additionally, the logic for migrating sessions from /data/apex/sessions
to /metadata/apex/sessions is changed a little bit. Now apexd will
iterate over entires in /data/apex/sessions, and then recursively
copy their content to the corresponding directory under
/metadata/apex/sessions, and then delete the entry under
/data/apex/sessions. This way a directory created by init
(/data/apex/sessions) is kept, which makes it easier to write unit tests
for apexd.
Logic is implemented as function inside apexd_utils.h for the ease of
unit testing.
Test: atest ApexTestCases
Test: atest apexd_host_tests
Test: atest CtsStagedInstallHostTestCases
Bug: 169932155
Bug: 176314162
Merged-In: Ifea8840ee5f1e56428d80bbb3b4e5e078176a578
Change-Id: Ia5e31e53edb411a023c8b090b7eb53ae977adc3e
(cherry picked from commit 7ffc3f6bd74b0b5567e6425090e9d13b6f5d4172)
(cherry picked from commit 69e06a1ddf509e4fc0734e044655d2b876b2bf45)
Diffstat (limited to 'apexd/apexd_utils_test.cpp')
-rw-r--r-- | apexd/apexd_utils_test.cpp | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/apexd/apexd_utils_test.cpp b/apexd/apexd_utils_test.cpp new file mode 100644 index 0000000..06b9c46 --- /dev/null +++ b/apexd/apexd_utils_test.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2020 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 <filesystem> +#include <string> + +#include <errno.h> + +#include <android-base/file.h> +#include <android-base/result.h> +#include <android-base/stringprintf.h> +#include <gtest/gtest.h> + +#include "apexd_test_utils.h" +#include "apexd_utils.h" + +namespace android { +namespace apex { +namespace { + +using android::apex::testing::IsOk; +using android::base::Basename; +using android::base::StringPrintf; +using ::testing::UnorderedElementsAre; +using ::testing::UnorderedElementsAreArray; + +// TODO(b/170327382): add unit tests for apexd_utils.h + +TEST(ApexdUtilTest, FindFirstExistingDirectoryBothExist) { + TemporaryDir first_dir; + TemporaryDir second_dir; + auto result = FindFirstExistingDirectory(first_dir.path, second_dir.path); + ASSERT_TRUE(IsOk(result)); + ASSERT_EQ(*result, first_dir.path); +} + +TEST(ApexdUtilTest, FindFirstExistingDirectoryOnlyFirstExist) { + TemporaryDir first_dir; + auto second_dir = "/data/local/tmp/does/not/exist"; + auto result = FindFirstExistingDirectory(first_dir.path, second_dir); + ASSERT_TRUE(IsOk(result)); + ASSERT_EQ(*result, first_dir.path); +} + +TEST(ApexdUtilTest, FindFirstExistingDirectoryOnlySecondExist) { + auto first_dir = "/data/local/tmp/does/not/exist"; + TemporaryDir second_dir; + auto result = FindFirstExistingDirectory(first_dir, second_dir.path); + ASSERT_TRUE(IsOk(result)); + ASSERT_EQ(*result, second_dir.path); +} + +TEST(ApexdUtilTest, FindFirstExistingDirectoryNoneExist) { + auto first_dir = "/data/local/tmp/does/not/exist"; + auto second_dir = "/data/local/tmp/also/does/not/exist"; + auto result = FindFirstExistingDirectory(first_dir, second_dir); + ASSERT_FALSE(IsOk(result)); +} + +TEST(ApexdUtilTest, FindFirstExistingDirectoryFirstFileSecondDir) { + TemporaryFile first_file; + TemporaryDir second_dir; + auto result = FindFirstExistingDirectory(first_file.path, second_dir.path); + ASSERT_TRUE(IsOk(result)); + ASSERT_EQ(*result, second_dir.path); +} + +TEST(ApexdUtilTest, FindFirstExistingDirectoryFirstDirSecondFile) { + TemporaryDir first_dir; + TemporaryFile second_file; + auto result = FindFirstExistingDirectory(first_dir.path, second_file.path); + ASSERT_TRUE(IsOk(result)); + ASSERT_EQ(*result, first_dir.path); +} + +TEST(ApexdUtilTest, FindFirstExistingDirectoryBothFiles) { + TemporaryFile first_file; + TemporaryFile second_file; + auto result = FindFirstExistingDirectory(first_file.path, second_file.path); + ASSERT_FALSE(IsOk(result)); +} + +TEST(ApexdUtilTest, FindFirstExistingDirectoryFirstFileSecondDoesNotExist) { + TemporaryFile first_file; + auto second_dir = "/data/local/tmp/does/not/exist"; + auto result = FindFirstExistingDirectory(first_file.path, second_dir); + ASSERT_FALSE(IsOk(result)); +} + +TEST(ApexdUtilTest, FindFirstExistingDirectoryFirsDoesNotExistSecondFile) { + auto first_dir = "/data/local/tmp/does/not/exist"; + TemporaryFile second_file; + auto result = FindFirstExistingDirectory(first_dir, second_file.path); + ASSERT_FALSE(IsOk(result)); +} + +TEST(ApexdUtilTest, MoveDir) { + namespace fs = std::filesystem; + + TemporaryDir from; + TemporaryDir to; + + TemporaryFile from_1(from.path); + auto from_subdir = StringPrintf("%s/subdir", from.path); + if (mkdir(from_subdir.c_str(), 07000) != 0) { + FAIL() << "Failed to mkdir " << from_subdir << " : " << strerror(errno); + } + TemporaryFile from_2(from_subdir); + + auto result = MoveDir(from.path, to.path); + ASSERT_TRUE(IsOk(result)); + ASSERT_TRUE(fs::is_empty(from.path)); + + std::vector<std::string> content; + for (const auto& it : fs::recursive_directory_iterator(to.path)) { + content.push_back(it.path()); + } + + static const std::vector<std::string> expected = { + StringPrintf("%s/%s", to.path, Basename(from_1.path).c_str()), + StringPrintf("%s/subdir", to.path), + StringPrintf("%s/subdir/%s", to.path, Basename(from_2.path).c_str()), + }; + ASSERT_THAT(content, UnorderedElementsAreArray(expected)); +} + +TEST(ApexdUtilTest, MoveDirFromIsNotDirectory) { + TemporaryFile from; + TemporaryDir to; + ASSERT_FALSE(IsOk(MoveDir(from.path, to.path))); +} + +TEST(ApexdUtilTest, MoveDirToIsNotDirectory) { + TemporaryDir from; + TemporaryFile to; + TemporaryFile from_1(from.path); + ASSERT_FALSE(IsOk(MoveDir(from.path, to.path))); +} + +TEST(ApexdUtilTest, MoveDirFromDoesNotExist) { + TemporaryDir to; + ASSERT_FALSE(IsOk(MoveDir("/data/local/tmp/does/not/exist", to.path))); +} + +TEST(ApexdUtilTest, MoveDirToDoesNotExist) { + namespace fs = std::filesystem; + + TemporaryDir from; + TemporaryFile from_1(from.path); + auto from_subdir = StringPrintf("%s/subdir", from.path); + if (mkdir(from_subdir.c_str(), 07000) != 0) { + FAIL() << "Failed to mkdir " << from_subdir << " : " << strerror(errno); + } + TemporaryFile from_2(from_subdir); + + ASSERT_FALSE(IsOk(MoveDir(from.path, "/data/local/tmp/does/not/exist"))); + + // Check that |from| directory is not empty. + std::vector<std::string> content; + for (const auto& it : fs::recursive_directory_iterator(from.path)) { + content.push_back(it.path()); + } + + ASSERT_THAT(content, + UnorderedElementsAre(from_1.path, from_subdir, from_2.path)); +} + +} // namespace +} // namespace apex +} // namespace android |