dm_test.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. #include <fcntl.h>
  17. #include <stdint.h>
  18. #include <stdio.h>
  19. #include <sys/ioctl.h>
  20. #include <sys/types.h>
  21. #include <time.h>
  22. #include <unistd.h>
  23. #include <chrono>
  24. #include <ctime>
  25. #include <map>
  26. #include <thread>
  27. #include <android-base/file.h>
  28. #include <android-base/unique_fd.h>
  29. #include <gtest/gtest.h>
  30. #include <libdm/dm.h>
  31. #include <libdm/loop_control.h>
  32. #include "test_util.h"
  33. using namespace std;
  34. using namespace android::dm;
  35. using unique_fd = android::base::unique_fd;
  36. TEST(libdm, HasMinimumTargets) {
  37. DeviceMapper& dm = DeviceMapper::Instance();
  38. vector<DmTargetTypeInfo> targets;
  39. ASSERT_TRUE(dm.GetAvailableTargets(&targets));
  40. map<string, DmTargetTypeInfo> by_name;
  41. for (const auto& target : targets) {
  42. by_name[target.name()] = target;
  43. }
  44. auto iter = by_name.find("linear");
  45. EXPECT_NE(iter, by_name.end());
  46. }
  47. // Helper to ensure that device mapper devices are released.
  48. class TempDevice {
  49. public:
  50. TempDevice(const std::string& name, const DmTable& table)
  51. : dm_(DeviceMapper::Instance()), name_(name), valid_(false) {
  52. valid_ = dm_.CreateDevice(name, table);
  53. }
  54. TempDevice(TempDevice&& other) noexcept
  55. : dm_(other.dm_), name_(other.name_), valid_(other.valid_) {
  56. other.valid_ = false;
  57. }
  58. ~TempDevice() {
  59. if (valid_) {
  60. dm_.DeleteDevice(name_);
  61. }
  62. }
  63. bool Destroy() {
  64. if (!valid_) {
  65. return false;
  66. }
  67. valid_ = false;
  68. return dm_.DeleteDevice(name_);
  69. }
  70. bool WaitForUdev() const {
  71. auto start_time = std::chrono::steady_clock::now();
  72. while (true) {
  73. if (!access(path().c_str(), F_OK)) {
  74. return true;
  75. }
  76. if (errno != ENOENT) {
  77. return false;
  78. }
  79. std::this_thread::sleep_for(50ms);
  80. std::chrono::duration elapsed = std::chrono::steady_clock::now() - start_time;
  81. if (elapsed >= 5s) {
  82. return false;
  83. }
  84. }
  85. }
  86. std::string path() const {
  87. std::string device_path;
  88. if (!dm_.GetDmDevicePathByName(name_, &device_path)) {
  89. return "";
  90. }
  91. return device_path;
  92. }
  93. const std::string& name() const { return name_; }
  94. bool valid() const { return valid_; }
  95. TempDevice(const TempDevice&) = delete;
  96. TempDevice& operator=(const TempDevice&) = delete;
  97. TempDevice& operator=(TempDevice&& other) noexcept {
  98. name_ = other.name_;
  99. valid_ = other.valid_;
  100. other.valid_ = false;
  101. return *this;
  102. }
  103. private:
  104. DeviceMapper& dm_;
  105. std::string name_;
  106. bool valid_;
  107. };
  108. TEST(libdm, DmLinear) {
  109. unique_fd tmp1(CreateTempFile("file_1", 4096));
  110. ASSERT_GE(tmp1, 0);
  111. unique_fd tmp2(CreateTempFile("file_2", 4096));
  112. ASSERT_GE(tmp2, 0);
  113. // Create two different files. These will back two separate loop devices.
  114. const char message1[] = "Hello! This is sector 1.";
  115. const char message2[] = "Goodbye. This is sector 2.";
  116. ASSERT_TRUE(android::base::WriteFully(tmp1, message1, sizeof(message1)));
  117. ASSERT_TRUE(android::base::WriteFully(tmp2, message2, sizeof(message2)));
  118. LoopDevice loop_a(tmp1);
  119. ASSERT_TRUE(loop_a.valid());
  120. LoopDevice loop_b(tmp2);
  121. ASSERT_TRUE(loop_b.valid());
  122. // Define a 2-sector device, with each sector mapping to the first sector
  123. // of one of our loop devices.
  124. DmTable table;
  125. ASSERT_TRUE(table.AddTarget(make_unique<DmTargetLinear>(0, 1, loop_a.device(), 0)));
  126. ASSERT_TRUE(table.AddTarget(make_unique<DmTargetLinear>(1, 1, loop_b.device(), 0)));
  127. ASSERT_TRUE(table.valid());
  128. TempDevice dev("libdm-test-dm-linear", table);
  129. ASSERT_TRUE(dev.valid());
  130. ASSERT_FALSE(dev.path().empty());
  131. ASSERT_TRUE(dev.WaitForUdev());
  132. // Note: a scope is needed to ensure that there are no open descriptors
  133. // when we go to close the device.
  134. {
  135. unique_fd dev_fd(open(dev.path().c_str(), O_RDWR));
  136. ASSERT_GE(dev_fd, 0);
  137. // Test that each sector of our device is correctly mapped to each loop
  138. // device.
  139. char sector[512];
  140. ASSERT_TRUE(android::base::ReadFully(dev_fd, sector, sizeof(sector)));
  141. ASSERT_EQ(strncmp(sector, message1, sizeof(message1)), 0);
  142. ASSERT_TRUE(android::base::ReadFully(dev_fd, sector, sizeof(sector)));
  143. ASSERT_EQ(strncmp(sector, message2, sizeof(message2)), 0);
  144. }
  145. // Test GetTableStatus.
  146. DeviceMapper& dm = DeviceMapper::Instance();
  147. vector<DeviceMapper::TargetInfo> targets;
  148. ASSERT_TRUE(dm.GetTableStatus(dev.name(), &targets));
  149. ASSERT_EQ(targets.size(), 2);
  150. EXPECT_EQ(strcmp(targets[0].spec.target_type, "linear"), 0);
  151. EXPECT_TRUE(targets[0].data.empty());
  152. EXPECT_EQ(targets[0].spec.sector_start, 0);
  153. EXPECT_EQ(targets[0].spec.length, 1);
  154. EXPECT_EQ(strcmp(targets[1].spec.target_type, "linear"), 0);
  155. EXPECT_TRUE(targets[1].data.empty());
  156. EXPECT_EQ(targets[1].spec.sector_start, 1);
  157. EXPECT_EQ(targets[1].spec.length, 1);
  158. // Normally the TestDevice destructor would delete this, but at least one
  159. // test should ensure that device deletion works.
  160. ASSERT_TRUE(dev.Destroy());
  161. }
  162. TEST(libdm, DmVerityArgsAvb2) {
  163. std::string device = "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a";
  164. std::string algorithm = "sha1";
  165. std::string digest = "4be7e823b8c40f7bd5c8ccd5123f0722c5baca21";
  166. std::string salt = "cc99f81ecb9484220a003b0719ee59dcf9be7e5d";
  167. DmTargetVerity target(0, 10000, 1, device, device, 4096, 4096, 125961, 125961, algorithm,
  168. digest, salt);
  169. target.UseFec(device, 2, 126955, 126955);
  170. target.SetVerityMode("restart_on_corruption");
  171. target.IgnoreZeroBlocks();
  172. // Verity table from a walleye build.
  173. std::string expected =
  174. "1 /dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a "
  175. "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a 4096 4096 125961 125961 sha1 "
  176. "4be7e823b8c40f7bd5c8ccd5123f0722c5baca21 cc99f81ecb9484220a003b0719ee59dcf9be7e5d 10 "
  177. "use_fec_from_device /dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a fec_roots "
  178. "2 fec_blocks 126955 fec_start 126955 restart_on_corruption ignore_zero_blocks";
  179. EXPECT_EQ(target.GetParameterString(), expected);
  180. }