1 //
2 // Copyright (C) 2019 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 <linux/fs.h>
18 #include <sys/stat.h>
19 #include <sys/sysmacros.h>
20 #include <sys/types.h>
21 #include <sys/vfs.h>
22 #include <unistd.h>
23 
24 #include <android-base/properties.h>
25 #include <android-base/unique_fd.h>
26 #include <android/hardware/weaver/1.0/IWeaver.h>
27 #include <ext4_utils/ext4_utils.h>
28 #include <fstab/fstab.h>
29 #include <gtest/gtest.h>
30 
31 using namespace android::fs_mgr;
32 
33 using android::base::unique_fd;
34 using android::hardware::weaver::V1_0::IWeaver;
35 using android::hardware::weaver::V1_0::WeaverConfig;
36 using android::hardware::weaver::V1_0::WeaverStatus;
37 
38 
IsAutomotiveDevice()39 static bool IsAutomotiveDevice() {
40     auto hw_type = android::base::GetProperty("ro.hardware.type", "");
41     return hw_type == "automotive";
42 }
43 
ShouldRequireMetadata()44 bool ShouldRequireMetadata() {
45     int api_level = android::base::GetIntProperty("ro.product.first_api_level", -1);
46     return api_level >= __ANDROID_API_R__;
47 }
48 
TEST(MetadataPartition,FirstStageMount)49 TEST(MetadataPartition, FirstStageMount) {
50     if (!ShouldRequireMetadata()) {
51         GTEST_SKIP();
52     }
53     Fstab fstab;
54     if (ReadFstabFromDt(&fstab)) {
55         auto entry = GetEntryForMountPoint(&fstab, "/metadata");
56         ASSERT_NE(entry, nullptr);
57     } else {
58         ASSERT_TRUE(ReadDefaultFstab(&fstab));
59         auto entry = GetEntryForMountPoint(&fstab, "/metadata");
60         ASSERT_NE(entry, nullptr);
61         EXPECT_TRUE(entry->fs_mgr_flags.first_stage_mount);
62     }
63 }
64 
GetVsrLevel()65 static int GetVsrLevel() {
66     return android::base::GetIntProperty("ro.vendor.api_level", -1);
67 }
68 
TEST(MetadataPartition,MinimumSize)69 TEST(MetadataPartition, MinimumSize) {
70     if (!ShouldRequireMetadata()) {
71         GTEST_SKIP();
72     }
73     Fstab fstab;
74     ASSERT_TRUE(ReadDefaultFstab(&fstab));
75 
76     auto entry = GetEntryForMountPoint(&fstab, "/metadata");
77     ASSERT_NE(entry, nullptr);
78 
79     unique_fd fd(open(entry->blk_device.c_str(), O_RDONLY | O_CLOEXEC));
80     ASSERT_GE(fd, 0);
81 
82     uint64_t size = get_block_device_size(fd);
83     ASSERT_GE(size, 16777216);
84 }
85 
TEST(Weaver,MinimumSlots)86 TEST(Weaver, MinimumSlots) {
87     auto weaver = IWeaver::getService();
88     if (!weaver) {
89         return;
90     }
91 
92     WeaverStatus hw_status;
93     WeaverConfig hw_config;
94 
95     auto res = weaver->getConfig([&](WeaverStatus status, const WeaverConfig& config) {
96             hw_status = status;
97             hw_config = config;
98     });
99     ASSERT_TRUE(res.isOk());
100     ASSERT_EQ(hw_status, WeaverStatus::OK);
101     EXPECT_GE(hw_config.slots, 16);
102 }
103 
TEST(MetadataPartition,FsType)104 TEST(MetadataPartition, FsType) {
105     if (GetVsrLevel() < __ANDROID_API_T__ || IsAutomotiveDevice()) {
106         GTEST_SKIP();
107     }
108 
109     Fstab fstab;
110     ASSERT_TRUE(ReadDefaultFstab(&fstab));
111 
112     std::vector<std::string> mount_points = {"/data"};
113     for (const auto& mount_point : mount_points) {
114         auto path = mount_point + "/gsi";
115 
116         // These paths should not be symlinks.
117         struct stat s;
118         ASSERT_GE(lstat(path.c_str(), &s), 0) << path;
119         ASSERT_FALSE(S_ISLNK(s.st_mode));
120 
121         struct statfs64 fs;
122         ASSERT_GE(statfs64(path.c_str(), &fs), 0) << path;
123         ASSERT_TRUE(fs.f_type == F2FS_SUPER_MAGIC || fs.f_type == EXT4_SUPER_MAGIC)
124                 << "Unexpected filesystem type: " << fs.f_type;
125 
126         auto entry = GetEntryForMountPoint(&fstab, mount_point);
127         ASSERT_NE(entry, nullptr);
128         ASSERT_TRUE(entry->fs_type == "f2fs" || entry->fs_type == "ext4")
129                 << "Unexpected filesystem type: " << entry->fs_type;
130     }
131 }
132