diff options
author | Treehugger Robot | 2018-06-25 17:28:10 -0500 |
---|---|---|
committer | Gerrit Code Review | 2018-06-25 17:28:10 -0500 |
commit | 9d254f0dacc95a296df268eaa6a61cf3e7d144d2 (patch) | |
tree | ea9ae663e8709b0dc029ab6ac96365355c16c61e | |
parent | 516ec4c2570411039975e0fcdba9b5f8d9b31b3b (diff) | |
parent | 2d3e79f5d5f04274e5415a30417b1f05ac65ab1d (diff) | |
download | platform-system-core-9d254f0dacc95a296df268eaa6a61cf3e7d144d2.tar.gz platform-system-core-9d254f0dacc95a296df268eaa6a61cf3e7d144d2.tar.xz platform-system-core-9d254f0dacc95a296df268eaa6a61cf3e7d144d2.zip |
Merge "libdm: Add unit tests for dm-linear."android-p-preview-4
-rw-r--r-- | fs_mgr/libdm/Android.bp | 1 | ||||
-rw-r--r-- | fs_mgr/libdm/dm_test.cpp | 129 | ||||
-rw-r--r-- | fs_mgr/libdm/loop_control_test.cpp | 5 | ||||
-rw-r--r-- | fs_mgr/libdm/test_util.cpp | 52 | ||||
-rw-r--r-- | fs_mgr/libdm/test_util.h | 35 |
5 files changed, 219 insertions, 3 deletions
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp index 21a4cb5bd..22af1238e 100644 --- a/fs_mgr/libdm/Android.bp +++ b/fs_mgr/libdm/Android.bp | |||
@@ -49,5 +49,6 @@ cc_test { | |||
49 | srcs: [ | 49 | srcs: [ |
50 | "dm_test.cpp", | 50 | "dm_test.cpp", |
51 | "loop_control_test.cpp", | 51 | "loop_control_test.cpp", |
52 | "test_util.cpp", | ||
52 | ] | 53 | ] |
53 | } | 54 | } |
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp index adbe82088..67dc958d4 100644 --- a/fs_mgr/libdm/dm_test.cpp +++ b/fs_mgr/libdm/dm_test.cpp | |||
@@ -14,13 +14,29 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <fcntl.h> | ||
18 | #include <stdint.h> | ||
19 | #include <stdio.h> | ||
20 | #include <sys/ioctl.h> | ||
21 | #include <sys/types.h> | ||
22 | #include <time.h> | ||
23 | #include <unistd.h> | ||
24 | |||
25 | #include <chrono> | ||
26 | #include <ctime> | ||
17 | #include <map> | 27 | #include <map> |
28 | #include <thread> | ||
18 | 29 | ||
30 | #include <android-base/file.h> | ||
31 | #include <android-base/unique_fd.h> | ||
19 | #include <gtest/gtest.h> | 32 | #include <gtest/gtest.h> |
20 | #include <libdm/dm.h> | 33 | #include <libdm/dm.h> |
34 | #include <libdm/loop_control.h> | ||
35 | #include "test_util.h" | ||
21 | 36 | ||
22 | using namespace std; | 37 | using namespace std; |
23 | using namespace android::dm; | 38 | using namespace android::dm; |
39 | using unique_fd = android::base::unique_fd; | ||
24 | 40 | ||
25 | TEST(libdm, HasMinimumTargets) { | 41 | TEST(libdm, HasMinimumTargets) { |
26 | DeviceMapper& dm = DeviceMapper::Instance(); | 42 | DeviceMapper& dm = DeviceMapper::Instance(); |
@@ -35,3 +51,116 @@ TEST(libdm, HasMinimumTargets) { | |||
35 | auto iter = by_name.find("linear"); | 51 | auto iter = by_name.find("linear"); |
36 | EXPECT_NE(iter, by_name.end()); | 52 | EXPECT_NE(iter, by_name.end()); |
37 | } | 53 | } |
54 | |||
55 | // Helper to ensure that device mapper devices are released. | ||
56 | class TempDevice { | ||
57 | public: | ||
58 | TempDevice(const std::string& name, const DmTable& table) | ||
59 | : dm_(DeviceMapper::Instance()), name_(name), valid_(false) { | ||
60 | valid_ = dm_.CreateDevice(name, table); | ||
61 | } | ||
62 | TempDevice(TempDevice&& other) : dm_(other.dm_), name_(other.name_), valid_(other.valid_) { | ||
63 | other.valid_ = false; | ||
64 | } | ||
65 | ~TempDevice() { | ||
66 | if (valid_) { | ||
67 | dm_.DeleteDevice(name_); | ||
68 | } | ||
69 | } | ||
70 | bool Destroy() { | ||
71 | if (!valid_) { | ||
72 | return false; | ||
73 | } | ||
74 | valid_ = false; | ||
75 | return dm_.DeleteDevice(name_); | ||
76 | } | ||
77 | bool WaitForUdev() const { | ||
78 | auto start_time = std::chrono::steady_clock::now(); | ||
79 | while (true) { | ||
80 | if (!access(path().c_str(), F_OK)) { | ||
81 | return true; | ||
82 | } | ||
83 | if (errno != ENOENT) { | ||
84 | return false; | ||
85 | } | ||
86 | std::this_thread::sleep_for(50ms); | ||
87 | std::chrono::duration elapsed = std::chrono::steady_clock::now() - start_time; | ||
88 | if (elapsed >= 5s) { | ||
89 | return false; | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | std::string path() const { | ||
94 | std::string device_path; | ||
95 | if (!dm_.GetDmDevicePathByName(name_, &device_path)) { | ||
96 | return ""; | ||
97 | } | ||
98 | return device_path; | ||
99 | } | ||
100 | const std::string& name() const { return name_; } | ||
101 | bool valid() const { return valid_; } | ||
102 | |||
103 | TempDevice(const TempDevice&) = delete; | ||
104 | TempDevice& operator=(const TempDevice&) = delete; | ||
105 | |||
106 | TempDevice& operator=(TempDevice&& other) { | ||
107 | name_ = other.name_; | ||
108 | valid_ = other.valid_; | ||
109 | other.valid_ = false; | ||
110 | return *this; | ||
111 | } | ||
112 | |||
113 | private: | ||
114 | DeviceMapper& dm_; | ||
115 | std::string name_; | ||
116 | bool valid_; | ||
117 | }; | ||
118 | |||
119 | TEST(libdm, DmLinear) { | ||
120 | unique_fd tmp1(CreateTempFile("file_1", 4096)); | ||
121 | ASSERT_GE(tmp1, 0); | ||
122 | unique_fd tmp2(CreateTempFile("file_2", 4096)); | ||
123 | ASSERT_GE(tmp2, 0); | ||
124 | |||
125 | // Create two different files. These will back two separate loop devices. | ||
126 | const char message1[] = "Hello! This is sector 1."; | ||
127 | const char message2[] = "Goodbye. This is sector 2."; | ||
128 | ASSERT_TRUE(android::base::WriteFully(tmp1, message1, sizeof(message1))); | ||
129 | ASSERT_TRUE(android::base::WriteFully(tmp2, message2, sizeof(message2))); | ||
130 | |||
131 | LoopDevice loop_a(tmp1); | ||
132 | ASSERT_TRUE(loop_a.valid()); | ||
133 | LoopDevice loop_b(tmp2); | ||
134 | ASSERT_TRUE(loop_b.valid()); | ||
135 | |||
136 | // Define a 2-sector device, with each sector mapping to the first sector | ||
137 | // of one of our loop devices. | ||
138 | DmTable table; | ||
139 | ASSERT_TRUE(table.AddTarget(make_unique<DmTargetLinear>(0, 1, loop_a.device(), 0))); | ||
140 | ASSERT_TRUE(table.AddTarget(make_unique<DmTargetLinear>(1, 1, loop_b.device(), 0))); | ||
141 | ASSERT_TRUE(table.valid()); | ||
142 | |||
143 | TempDevice dev("libdm-test-dm-linear", table); | ||
144 | ASSERT_TRUE(dev.valid()); | ||
145 | ASSERT_FALSE(dev.path().empty()); | ||
146 | ASSERT_TRUE(dev.WaitForUdev()); | ||
147 | |||
148 | // Note: a scope is needed to ensure that there are no open descriptors | ||
149 | // when we go to close the device. | ||
150 | { | ||
151 | unique_fd dev_fd(open(dev.path().c_str(), O_RDWR)); | ||
152 | ASSERT_GE(dev_fd, 0); | ||
153 | |||
154 | // Test that each sector of our device is correctly mapped to each loop | ||
155 | // device. | ||
156 | char sector[512]; | ||
157 | ASSERT_TRUE(android::base::ReadFully(dev_fd, sector, sizeof(sector))); | ||
158 | ASSERT_EQ(strncmp(sector, message1, sizeof(message1)), 0); | ||
159 | ASSERT_TRUE(android::base::ReadFully(dev_fd, sector, sizeof(sector))); | ||
160 | ASSERT_EQ(strncmp(sector, message2, sizeof(message2)), 0); | ||
161 | } | ||
162 | |||
163 | // Normally the TestDevice destructor would delete this, but at least one | ||
164 | // test should ensure that device deletion works. | ||
165 | ASSERT_TRUE(dev.Destroy()); | ||
166 | } | ||
diff --git a/fs_mgr/libdm/loop_control_test.cpp b/fs_mgr/libdm/loop_control_test.cpp index cd1d015ff..08bdc00a3 100644 --- a/fs_mgr/libdm/loop_control_test.cpp +++ b/fs_mgr/libdm/loop_control_test.cpp | |||
@@ -17,17 +17,16 @@ | |||
17 | #include "libdm/loop_control.h" | 17 | #include "libdm/loop_control.h" |
18 | 18 | ||
19 | #include <fcntl.h> | 19 | #include <fcntl.h> |
20 | #include <linux/memfd.h> | ||
21 | #include <stdio.h> | 20 | #include <stdio.h> |
22 | #include <stdlib.h> | 21 | #include <stdlib.h> |
23 | #include <sys/stat.h> | 22 | #include <sys/stat.h> |
24 | #include <sys/syscall.h> | ||
25 | #include <sys/types.h> | 23 | #include <sys/types.h> |
26 | #include <unistd.h> | 24 | #include <unistd.h> |
27 | 25 | ||
28 | #include <android-base/file.h> | 26 | #include <android-base/file.h> |
29 | #include <android-base/unique_fd.h> | 27 | #include <android-base/unique_fd.h> |
30 | #include <gtest/gtest.h> | 28 | #include <gtest/gtest.h> |
29 | #include "test_util.h" | ||
31 | 30 | ||
32 | using namespace std; | 31 | using namespace std; |
33 | using namespace android::dm; | 32 | using namespace android::dm; |
@@ -36,7 +35,7 @@ using unique_fd = android::base::unique_fd; | |||
36 | static unique_fd TempFile() { | 35 | static unique_fd TempFile() { |
37 | // A loop device needs to be at least one sector to actually work, so fill | 36 | // A loop device needs to be at least one sector to actually work, so fill |
38 | // up the file with a message. | 37 | // up the file with a message. |
39 | unique_fd fd(syscall(__NR_memfd_create, "fake_disk", 0)); | 38 | unique_fd fd(CreateTempFile("temp", 0)); |
40 | if (fd < 0) { | 39 | if (fd < 0) { |
41 | return {}; | 40 | return {}; |
42 | } | 41 | } |
diff --git a/fs_mgr/libdm/test_util.cpp b/fs_mgr/libdm/test_util.cpp new file mode 100644 index 000000000..307251cda --- /dev/null +++ b/fs_mgr/libdm/test_util.cpp | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 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 <fcntl.h> | ||
18 | #include <linux/memfd.h> | ||
19 | #include <stdio.h> | ||
20 | #include <sys/syscall.h> | ||
21 | #include <sys/types.h> | ||
22 | #include <unistd.h> | ||
23 | |||
24 | #include "test_util.h" | ||
25 | |||
26 | namespace android { | ||
27 | namespace dm { | ||
28 | |||
29 | using unique_fd = android::base::unique_fd; | ||
30 | |||
31 | // Create a temporary in-memory file. If size is non-zero, the file will be | ||
32 | // created with a fixed size. | ||
33 | unique_fd CreateTempFile(const std::string& name, size_t size) { | ||
34 | unique_fd fd(syscall(__NR_memfd_create, name.c_str(), MFD_ALLOW_SEALING)); | ||
35 | if (fd < 0) { | ||
36 | return {}; | ||
37 | } | ||
38 | if (size) { | ||
39 | if (ftruncate(fd, size) < 0) { | ||
40 | perror("ftruncate"); | ||
41 | return {}; | ||
42 | } | ||
43 | if (fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK) < 0) { | ||
44 | perror("fcntl"); | ||
45 | return {}; | ||
46 | } | ||
47 | } | ||
48 | return fd; | ||
49 | } | ||
50 | |||
51 | } // namespace dm | ||
52 | } // namespace android | ||
diff --git a/fs_mgr/libdm/test_util.h b/fs_mgr/libdm/test_util.h new file mode 100644 index 000000000..96b051ca2 --- /dev/null +++ b/fs_mgr/libdm/test_util.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 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 | #ifndef _LIBDM_TEST_UTILS_H_ | ||
18 | #define _LIBDM_TEST_UTILS_H_ | ||
19 | |||
20 | #include <android-base/unique_fd.h> | ||
21 | #include <stddef.h> | ||
22 | |||
23 | #include <string> | ||
24 | |||
25 | namespace android { | ||
26 | namespace dm { | ||
27 | |||
28 | // Create a temporary in-memory file. If size is non-zero, the file will be | ||
29 | // created with a fixed size. | ||
30 | android::base::unique_fd CreateTempFile(const std::string& name, size_t size); | ||
31 | |||
32 | } // namespace dm | ||
33 | } // namespace android | ||
34 | |||
35 | #endif // _LIBDM_TEST_UTILS_H_ | ||