namespace art { namespace dexopt_chroot_setup { namespace {
using ::android::base::GetProperty; using ::android::base::ScopeGuard; using ::android::base::SetProperty; using ::android::base::WaitForProperty; using ::android::base::testing::HasError; using ::android::base::testing::HasValue; using ::android::base::testing::WithMessage; using ::art::tools::CmdlineBuilder;
class DexoptChrootSetupTest : public CommonArtTest { protected: void SetUp() override {
CommonArtTest::SetUp();
dexopt_chroot_setup_ = ndk::SharedRefBase::make<DexoptChrootSetup>();
// Note that if a real Pre-reboot Dexopt is kicked off after this check, the test will still // fail, but that should be very rare. if (std::filesystem::exists(DexoptChrootSetup::CHROOT_DIR)) {
GTEST_SKIP() << "A real Pre-reboot Dexopt is running";
}
TEST_F(DexoptChrootSetupTest, Run) { // We only test the Mainline update case here. There isn't an easy way to test the OTA update case // in such a unit test. The OTA update case is assumed to be covered by the E2E test.
ASSERT_STATUS_OK(
dexopt_chroot_setup_->setUp(/*in_otaSlot=*/std::nullopt, /*in_mapSnapshotsForOta=*/false));
ASSERT_STATUS_OK(dexopt_chroot_setup_->init());
// Some important dirs that should be the same as outside.
std::vector<constchar*> same_dirs = { "/", "/system", "/system_ext", "/vendor", "/product", "/data", "/mnt/expand", "/dev", "/dev/cpuctl", "/dev/cpuset", "/proc", "/sys", "/sys/fs/cgroup", "/sys/fs/selinux", "/metadata", "/odm", "/system_dlkm",
};
for (const std::string& dir : same_dirs) { struct stat st_outside;
ASSERT_EQ(stat(dir.c_str(), &st_outside), 0); struct stat st_inside;
ASSERT_EQ(stat(PathInChroot(dir).c_str(), &st_inside), 0);
EXPECT_EQ(std::make_pair(st_outside.st_dev, st_outside.st_ino),
std::make_pair(st_inside.st_dev, st_inside.st_ino))
<< ART_FORMAT("Unexpected different directory in chroot: '{}'\n", dir) << mounts;
}
// Some important dirs that are expected to be writable.
std::vector<constchar*> writable_dirs = { "/data", "/mnt/expand",
};
for (const std::string& dir : writable_dirs) {
EXPECT_EQ(access(PathInChroot(dir).c_str(), W_OK), 0);
}
// Some important dirs that are not the same as outside but should be prepared.
std::vector<constchar*> prepared_dirs = { "/apex/com.android.art", "/linkerconfig/com.android.art",
};
for (const std::string& dir : prepared_dirs) {
EXPECT_FALSE(std::filesystem::is_empty(PathInChroot(dir)));
}
// Check that the chroot environment is capable to run programs. `dex2oat` is arbitrarily picked // here. The test dex file and the scratch dir in /data are the same inside the chroot as outside.
CmdlineBuilder args;
args.Add(GetArtBinDir() + "/art_exec")
.Add("--chroot=%s", DexoptChrootSetup::CHROOT_DIR)
.Add("--")
.Add(GetArtBinDir() + "/dex2oat" + (Is64BitInstructionSet(kRuntimeISA) ? "64" : "32"))
.Add("--dex-file=%s", GetTestDexFileName("Main"))
.Add("--oat-file=%s", scratch_path_ + "/output.odex")
.Add("--output-vdex=%s", scratch_path_ + "/output.vdex")
.Add("--compiler-filter=speed")
.Add("--boot-image=/nonx/boot.art");
std::string error_msg;
EXPECT_TRUE(Exec(args.Get(), &error_msg)) << error_msg;
// Check that `setUp` can be repeatedly called, to simulate the case where an instance of the // caller (typically system_server) called `setUp` and crashed later, and a new instance called // `setUp` again.
ASSERT_STATUS_OK(
dexopt_chroot_setup_->setUp(/*in_otaSlot=*/std::nullopt, /*in_mapSnapshotsForOta=*/false));
ASSERT_STATUS_OK(dexopt_chroot_setup_->init());
// Check that `init` cannot be repeatedly called.
ndk::ScopedAStatus status = dexopt_chroot_setup_->init();
EXPECT_FALSE(status.isOk());
EXPECT_EQ(status.getExceptionCode(), EX_ILLEGAL_STATE);
EXPECT_STREQ(status.getMessage(), "init must not be repeatedly called");
// Check that `tearDown` can be repeatedly called too.
ASSERT_STATUS_OK(dexopt_chroot_setup_->tearDown(/*in_allowConcurrent=*/false));
// Check that `setUp` can be followed directly by a `tearDown`.
ASSERT_STATUS_OK(
dexopt_chroot_setup_->setUp(/*in_otaSlot=*/std::nullopt, /*in_mapSnapshotsForOta=*/false));
ASSERT_STATUS_OK(dexopt_chroot_setup_->tearDown(/*in_allowConcurrent=*/false));
EXPECT_FALSE(std::filesystem::exists(DexoptChrootSetup::CHROOT_DIR));
}
EXPECT_THAT(ConstructLinkerConfigCompatEnvSection(art_linker_config_content),
HasError(WithMessage("No matching lines to patch in ART linker config")));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.