blob: c4f4cbd3a97893fc4012bef48d5aa892cf5b7f9d [file] [log] [blame]
/*
* Copyright (C) 2019 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 "apex_database.h"
#include <android-base/macros.h>
#include <android-base/result-gmock.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <string>
#include <tuple>
using android::base::Error;
using android::base::Result;
using android::base::testing::HasError;
using android::base::testing::Ok;
using android::base::testing::WithMessage;
namespace android {
namespace apex {
namespace {
using MountedApexData = MountedApexDatabase::MountedApexData;
size_t CountPackages(const MountedApexDatabase& db) {
size_t ret = 0;
db.ForallMountedApexes([&ret](const std::string& a ATTRIBUTE_UNUSED,
const MountedApexData& b ATTRIBUTE_UNUSED,
bool c ATTRIBUTE_UNUSED) { ++ret; });
return ret;
}
bool Contains(const MountedApexDatabase& db, const std::string& package,
const MountedApexData& data) {
bool found = false;
db.ForallMountedApexes([&](const std::string& p, const MountedApexData& d,
bool b ATTRIBUTE_UNUSED) {
if (package == p && data == d) {
found = true;
}
});
return found;
}
bool ContainsPackage(const MountedApexDatabase& db, const std::string& package,
const MountedApexData& data) {
bool found = false;
db.ForallMountedApexes(
package, [&](const MountedApexData& d, bool b ATTRIBUTE_UNUSED) {
if (data == d) {
found = true;
}
});
return found;
}
TEST(ApexDatabaseTest, AddRemovedMountedApex) {
constexpr const char* kPackage = "package";
constexpr const char* kPath = "path";
MountedApexDatabase db;
ASSERT_EQ(CountPackages(db), 0u);
MountedApexData data;
data.full_path = kPath;
db.AddMountedApex(kPackage, data);
ASSERT_TRUE(Contains(db, kPackage, data));
ASSERT_TRUE(ContainsPackage(db, kPackage, data));
db.RemoveMountedApex(kPackage, kPath);
EXPECT_FALSE(Contains(db, kPackage, data));
EXPECT_FALSE(ContainsPackage(db, kPackage, data));
}
TEST(ApexDatabaseTest, MountMultiple) {
constexpr const char* kPackage[] = {"package", "package", "package",
"package"};
constexpr const char* kLoopName[] = {"loop", "loop2", "loop3", "loop4"};
constexpr const char* kPath[] = {"path", "path2", "path", "path4"};
constexpr const char* kMountPoint[] = {"mount", "mount2", "mount", "mount4"};
constexpr const char* kDeviceName[] = {"dev", "dev2", "dev3", "dev4"};
MountedApexDatabase db;
ASSERT_EQ(CountPackages(db), 0u);
MountedApexData data[arraysize(kPackage)];
for (size_t i = 0; i < arraysize(kPackage); ++i) {
data[i] = MountedApexData(0, kLoopName[i], kPath[i], kMountPoint[i],
kDeviceName[i], "");
db.AddMountedApex(kPackage[i], data[i]);
}
ASSERT_EQ(CountPackages(db), 4u);
for (size_t i = 0; i < arraysize(kPackage); ++i) {
ASSERT_TRUE(Contains(db, kPackage[i], data[i]));
ASSERT_TRUE(ContainsPackage(db, kPackage[i], data[i]));
}
db.RemoveMountedApex(kPackage[0], kPath[0]);
EXPECT_FALSE(Contains(db, kPackage[0], data[0]));
EXPECT_FALSE(ContainsPackage(db, kPackage[0], data[0]));
EXPECT_TRUE(Contains(db, kPackage[1], data[1]));
EXPECT_TRUE(ContainsPackage(db, kPackage[1], data[1]));
EXPECT_TRUE(Contains(db, kPackage[2], data[2]));
EXPECT_TRUE(ContainsPackage(db, kPackage[2], data[2]));
EXPECT_TRUE(Contains(db, kPackage[3], data[3]));
EXPECT_TRUE(ContainsPackage(db, kPackage[3], data[3]));
}
TEST(ApexDatabaseTest, DoIfLatest) {
// Check by passing error-returning handler
// When handler is triggered, DoIfLatest() returns the expected error.
auto returnError = []() -> Result<void> { return Error() << "expected"; };
MountedApexDatabase db;
// With apex: [{version=0,path=path}]
MountedApexData apex;
apex.version = 0;
apex.full_path = "path";
db.AddMountedApex("package", apex);
// Check if path is the latest
ASSERT_THAT(db.DoIfLatest("package", "path", returnError),
HasError(WithMessage("expected")));
// With apexes: [{version=0,path=path}, {version=5,path=path5}]
MountedApexData apex5;
apex5.version = 5;
apex5.full_path = "path5";
db.AddMountedApex("package", apex5);
// Check if path is NOT the latest
ASSERT_THAT(db.DoIfLatest("package", "path", returnError), Ok());
// Check if path5 is the latest
ASSERT_THAT(db.DoIfLatest("package", "path5", returnError),
HasError(WithMessage("expected")));
}
TEST(ApexDatabaseTest, GetLatestMountedApex) {
constexpr const char* kPackage = "package";
MountedApexDatabase db;
ASSERT_EQ(CountPackages(db), 0u);
MountedApexData data;
data.version = 42;
db.AddMountedApex(kPackage, data);
auto ret = db.GetLatestMountedApex(kPackage);
ASSERT_TRUE(ret.has_value());
ASSERT_EQ(ret.value(), data);
}
TEST(ApexDatabaseTest, GetLatestMountedApexReturnsNullopt) {
MountedApexDatabase db;
auto ret = db.GetLatestMountedApex("no-such-name");
ASSERT_FALSE(ret.has_value());
}
} // namespace
} // namespace apex
} // namespace android