summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'fs_mgr/libdm/dm_test.cpp')
-rw-r--r--fs_mgr/libdm/dm_test.cpp129
1 files changed, 129 insertions, 0 deletions
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
22using namespace std; 37using namespace std;
23using namespace android::dm; 38using namespace android::dm;
39using unique_fd = android::base::unique_fd;
24 40
25TEST(libdm, HasMinimumTargets) { 41TEST(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.
56class 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
119TEST(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}