diff --git a/fs_mgr/tests/Android.bp b/fs_mgr/tests/Android.bp index 335da9e61..262beaaff 100644 --- a/fs_mgr/tests/Android.bp +++ b/fs_mgr/tests/Android.bp @@ -88,3 +88,32 @@ java_test_host { test_suites: ["general-tests"], } + +cc_test { + name: "vts_fs_test", + test_suites: [ + "vts", + "device-tests", + ], + test_options: { + min_shipping_api_level: 33, + }, + require_root: true, + auto_gen_config: true, + cflags: [ + "-Wall", + "-Werror", + ], + srcs: [ + "vts_fs_test.cpp", + ], + shared_libs: [ + "libbase", + "libfs_mgr", + ], + static_libs: [ + "libfstab", + "libgmock", + "libgtest", + ], +} diff --git a/fs_mgr/tests/vts_fs_test.cpp b/fs_mgr/tests/vts_fs_test.cpp new file mode 100644 index 000000000..77900df0a --- /dev/null +++ b/fs_mgr/tests/vts_fs_test.cpp @@ -0,0 +1,102 @@ +// 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +static int GetVsrLevel() { + return android::base::GetIntProperty("ro.vendor.api_level", -1); +} + +TEST(fs, ErofsSupported) { + // S and higher for this test. + if (GetVsrLevel() < 31) { + GTEST_SKIP(); + } + + struct utsname uts; + ASSERT_EQ(uname(&uts), 0); + + unsigned int major, minor; + ASSERT_EQ(sscanf(uts.release, "%u.%u", &major, &minor), 2); + + // EROFS support only required in 5.10+ + if (major < 5 || (major == 5 && minor < 10)) { + GTEST_SKIP(); + } + + std::string fs; + ASSERT_TRUE(android::base::ReadFileToString("/proc/filesystems", &fs)); + EXPECT_THAT(fs, ::testing::HasSubstr("\terofs\n")); +} + +TEST(fs, PartitionTypes) { + android::fs_mgr::Fstab fstab; + ASSERT_TRUE(android::fs_mgr::ReadFstabFromFile("/proc/mounts", &fstab)); + + auto& dm = android::dm::DeviceMapper::Instance(); + + std::string super_bdev, userdata_bdev; + ASSERT_TRUE(android::base::Readlink("/dev/block/by-name/super", &super_bdev)); + ASSERT_TRUE(android::base::Readlink("/dev/block/by-name/userdata", &userdata_bdev)); + + int vsr_level = GetVsrLevel(); + + for (const auto& entry : fstab) { + std::string parent_bdev = entry.blk_device; + while (true) { + auto basename = android::base::Basename(parent_bdev); + if (!android::base::StartsWith(basename, "dm-")) { + break; + } + + auto parent = dm.GetParentBlockDeviceByPath(parent_bdev); + if (!parent || *parent == parent_bdev) { + break; + } + parent_bdev = *parent; + } + + if (parent_bdev == userdata_bdev || + android::base::StartsWith(parent_bdev, "/dev/block/loop")) { + if (entry.flags & MS_RDONLY) { + // APEXes should not be F2FS. + EXPECT_NE(entry.fs_type, "f2fs"); + } + continue; + } + + if (vsr_level <= 32) { + continue; + } + if (vsr_level == 33 && parent_bdev != super_bdev) { + // Only check for dynamic partitions at this VSR level. + continue; + } + + if (entry.flags & MS_RDONLY) { + EXPECT_EQ(entry.fs_type, "erofs") << entry.mount_point; + } else { + EXPECT_NE(entry.fs_type, "ext4") << entry.mount_point; + } + } +}