1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <fcntl.h>
16 #include <linux/fs.h>
17 #include <linux/memfd.h>
18 #include <sys/ioctl.h>
19 #include <sys/stat.h>
20 #include <sys/syscall.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include <chrono>
25 #include <iostream>
26 #include <memory>
27 #include <string_view>
28
29 #include <android-base/file.h>
30 #include <android-base/unique_fd.h>
31 #include <fs_mgr/file_wait.h>
32 #include <gtest/gtest.h>
33 #include <libdm/dm.h>
34 #include <libdm/loop_control.h>
35 #include <libsnapshot/cow_writer.h>
36 #include <snapuserd/snapuserd_buffer.h>
37 #include <snapuserd/snapuserd_client.h>
38 #include <storage_literals/storage_literals.h>
39
40 #include "snapuserd.h"
41
42 namespace android {
43 namespace snapshot {
44
45 using namespace android::storage_literals;
46 using android::base::unique_fd;
47 using LoopDevice = android::dm::LoopDevice;
48 using namespace std::chrono_literals;
49 using namespace android::dm;
50 using namespace std;
51
52 static constexpr char kSnapuserdSocketTest[] = "snapuserdTest";
53
54 class TempDevice {
55 public:
TempDevice(const std::string & name,const DmTable & table)56 TempDevice(const std::string& name, const DmTable& table)
57 : dm_(DeviceMapper::Instance()), name_(name), valid_(false) {
58 valid_ = dm_.CreateDevice(name, table, &path_, std::chrono::seconds(5));
59 }
TempDevice(TempDevice && other)60 TempDevice(TempDevice&& other) noexcept
61 : dm_(other.dm_), name_(other.name_), path_(other.path_), valid_(other.valid_) {
62 other.valid_ = false;
63 }
~TempDevice()64 ~TempDevice() {
65 if (valid_) {
66 dm_.DeleteDevice(name_);
67 }
68 }
Destroy()69 bool Destroy() {
70 if (!valid_) {
71 return false;
72 }
73 valid_ = false;
74 return dm_.DeleteDevice(name_);
75 }
path() const76 const std::string& path() const { return path_; }
name() const77 const std::string& name() const { return name_; }
valid() const78 bool valid() const { return valid_; }
79
80 TempDevice(const TempDevice&) = delete;
81 TempDevice& operator=(const TempDevice&) = delete;
82
operator =(TempDevice && other)83 TempDevice& operator=(TempDevice&& other) noexcept {
84 name_ = other.name_;
85 valid_ = other.valid_;
86 other.valid_ = false;
87 return *this;
88 }
89
90 private:
91 DeviceMapper& dm_;
92 std::string name_;
93 std::string path_;
94 bool valid_;
95 };
96
97 class CowSnapuserdTest final {
98 public:
99 bool Setup();
100 bool SetupOrderedOps();
101 bool SetupOrderedOpsInverted();
102 bool SetupCopyOverlap_1();
103 bool SetupCopyOverlap_2();
104 bool Merge();
105 void ValidateMerge();
106 void ReadSnapshotDeviceAndValidate();
107 void Shutdown();
108 void MergeInterrupt();
109 void MergeInterruptFixed(int duration);
110 void MergeInterruptRandomly(int max_duration);
111 void ReadDmUserBlockWithoutDaemon();
112 void ReadLastBlock();
113
snapshot_dev() const114 std::string snapshot_dev() const { return snapshot_dev_->path(); }
115
116 static const uint64_t kSectorSize = 512;
117
118 private:
119 void SetupImpl();
120
121 void MergeImpl();
122 void SimulateDaemonRestart();
123 void StartMerge();
124
125 void CreateCowDevice();
126 void CreateCowDeviceOrderedOps();
127 void CreateCowDeviceOrderedOpsInverted();
128 void CreateCowDeviceWithCopyOverlap_1();
129 void CreateCowDeviceWithCopyOverlap_2();
130 bool SetupDaemon();
131 void CreateBaseDevice();
132 void InitCowDevice();
133 void SetDeviceControlName();
134 void InitDaemon();
135 void CreateDmUserDevice();
136 void StartSnapuserdDaemon();
137 void CreateSnapshotDevice();
138
139 unique_ptr<LoopDevice> base_loop_;
140 unique_ptr<TempDevice> dmuser_dev_;
141 unique_ptr<TempDevice> snapshot_dev_;
142
143 std::string system_device_ctrl_name_;
144 std::string system_device_name_;
145
146 unique_fd base_fd_;
147 std::unique_ptr<TemporaryFile> cow_system_;
148 std::unique_ptr<SnapuserdClient> client_;
149 std::unique_ptr<uint8_t[]> orig_buffer_;
150 std::unique_ptr<uint8_t[]> merged_buffer_;
151 bool setup_ok_ = false;
152 bool merge_ok_ = false;
153 size_t size_ = 50_MiB;
154 int cow_num_sectors_;
155 int total_base_size_;
156 };
157
158 class CowSnapuserdMetadataTest final {
159 public:
160 void Setup();
161 void SetupPartialArea();
162 void ValidateMetadata();
163 void ValidatePartialFilledArea();
164
165 private:
166 void InitMetadata();
167 void CreateCowDevice();
168 void CreateCowPartialFilledArea();
169
170 std::unique_ptr<Snapuserd> snapuserd_;
171 std::unique_ptr<TemporaryFile> cow_system_;
172 size_t size_ = 1_MiB;
173 };
174
CreateTempFile(const std::string & name,size_t size)175 static unique_fd CreateTempFile(const std::string& name, size_t size) {
176 unique_fd fd(syscall(__NR_memfd_create, name.c_str(), MFD_ALLOW_SEALING));
177 if (fd < 0) {
178 return {};
179 }
180 if (size) {
181 if (ftruncate(fd, size) < 0) {
182 perror("ftruncate");
183 return {};
184 }
185 if (fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK) < 0) {
186 perror("fcntl");
187 return {};
188 }
189 }
190 return fd;
191 }
192
Shutdown()193 void CowSnapuserdTest::Shutdown() {
194 ASSERT_TRUE(snapshot_dev_->Destroy());
195 ASSERT_TRUE(dmuser_dev_->Destroy());
196
197 auto misc_device = "/dev/dm-user/" + system_device_ctrl_name_;
198 ASSERT_TRUE(client_->WaitForDeviceDelete(system_device_ctrl_name_));
199 ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted(misc_device, 10s));
200 ASSERT_TRUE(client_->DetachSnapuserd());
201 }
202
Setup()203 bool CowSnapuserdTest::Setup() {
204 SetupImpl();
205 return setup_ok_;
206 }
207
SetupOrderedOps()208 bool CowSnapuserdTest::SetupOrderedOps() {
209 CreateBaseDevice();
210 CreateCowDeviceOrderedOps();
211 return SetupDaemon();
212 }
213
SetupOrderedOpsInverted()214 bool CowSnapuserdTest::SetupOrderedOpsInverted() {
215 CreateBaseDevice();
216 CreateCowDeviceOrderedOpsInverted();
217 return SetupDaemon();
218 }
219
SetupCopyOverlap_1()220 bool CowSnapuserdTest::SetupCopyOverlap_1() {
221 CreateBaseDevice();
222 CreateCowDeviceWithCopyOverlap_1();
223 return SetupDaemon();
224 }
225
SetupCopyOverlap_2()226 bool CowSnapuserdTest::SetupCopyOverlap_2() {
227 CreateBaseDevice();
228 CreateCowDeviceWithCopyOverlap_2();
229 return SetupDaemon();
230 }
231
SetupDaemon()232 bool CowSnapuserdTest::SetupDaemon() {
233 SetDeviceControlName();
234
235 StartSnapuserdDaemon();
236 InitCowDevice();
237
238 CreateDmUserDevice();
239 InitDaemon();
240
241 CreateSnapshotDevice();
242 setup_ok_ = true;
243
244 return setup_ok_;
245 }
246
StartSnapuserdDaemon()247 void CowSnapuserdTest::StartSnapuserdDaemon() {
248 pid_t pid = fork();
249 ASSERT_GE(pid, 0);
250 if (pid == 0) {
251 std::string arg0 = "/system/bin/snapuserd";
252 std::string arg1 = "-socket="s + kSnapuserdSocketTest;
253 char* const argv[] = {arg0.data(), arg1.data(), nullptr};
254 ASSERT_GE(execv(arg0.c_str(), argv), 0);
255 } else {
256 client_ = SnapuserdClient::Connect(kSnapuserdSocketTest, 10s);
257 ASSERT_NE(client_, nullptr);
258 }
259 }
260
ReadLastBlock()261 void CowSnapuserdTest::ReadLastBlock() {
262 unique_fd rnd_fd;
263 total_base_size_ = BLOCK_SZ * 2;
264
265 base_fd_ = CreateTempFile("base_device", total_base_size_);
266 ASSERT_GE(base_fd_, 0);
267
268 rnd_fd.reset(open("/dev/random", O_RDONLY));
269 ASSERT_TRUE(rnd_fd > 0);
270
271 std::unique_ptr<uint8_t[]> random_buffer = std::make_unique<uint8_t[]>(BLOCK_SZ);
272
273 for (size_t j = 0; j < ((total_base_size_) / BLOCK_SZ); j++) {
274 ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer.get(), BLOCK_SZ, 0), true);
275 ASSERT_EQ(android::base::WriteFully(base_fd_, random_buffer.get(), BLOCK_SZ), true);
276 }
277
278 ASSERT_EQ(lseek(base_fd_, 0, SEEK_SET), 0);
279
280 base_loop_ = std::make_unique<LoopDevice>(base_fd_, 10s);
281 ASSERT_TRUE(base_loop_->valid());
282
283 std::string path = android::base::GetExecutableDirectory();
284 cow_system_ = std::make_unique<TemporaryFile>(path);
285
286 std::unique_ptr<uint8_t[]> random_buffer_1_ = std::make_unique<uint8_t[]>(total_base_size_);
287 loff_t offset = 0;
288
289 // Fill random data
290 for (size_t j = 0; j < (total_base_size_ / BLOCK_SZ); j++) {
291 ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer_1_.get() + offset, BLOCK_SZ, 0),
292 true);
293
294 offset += BLOCK_SZ;
295 }
296
297 CowOptions options;
298 options.compression = "gz";
299 CowWriter writer(options);
300
301 ASSERT_TRUE(writer.Initialize(cow_system_->fd));
302
303 ASSERT_TRUE(writer.AddRawBlocks(0, random_buffer_1_.get(), BLOCK_SZ));
304 ASSERT_TRUE(writer.AddRawBlocks(1, (char*)random_buffer_1_.get() + BLOCK_SZ, BLOCK_SZ));
305
306 ASSERT_TRUE(writer.Finalize());
307
308 SetDeviceControlName();
309
310 StartSnapuserdDaemon();
311 InitCowDevice();
312
313 CreateDmUserDevice();
314 InitDaemon();
315
316 CreateSnapshotDevice();
317
318 unique_fd snapshot_fd(open(snapshot_dev_->path().c_str(), O_RDONLY));
319 ASSERT_TRUE(snapshot_fd > 0);
320
321 std::unique_ptr<uint8_t[]> snapuserd_buffer = std::make_unique<uint8_t[]>(BLOCK_SZ);
322
323 offset = 7680;
324 ASSERT_EQ(ReadFullyAtOffset(snapshot_fd, snapuserd_buffer.get(), 512, offset), true);
325 ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)random_buffer_1_.get() + offset, 512), 0);
326 }
327
CreateBaseDevice()328 void CowSnapuserdTest::CreateBaseDevice() {
329 unique_fd rnd_fd;
330
331 total_base_size_ = (size_ * 5);
332 base_fd_ = CreateTempFile("base_device", total_base_size_);
333 ASSERT_GE(base_fd_, 0);
334
335 rnd_fd.reset(open("/dev/random", O_RDONLY));
336 ASSERT_TRUE(rnd_fd > 0);
337
338 std::unique_ptr<uint8_t[]> random_buffer = std::make_unique<uint8_t[]>(1_MiB);
339
340 for (size_t j = 0; j < ((total_base_size_) / 1_MiB); j++) {
341 ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer.get(), 1_MiB, 0), true);
342 ASSERT_EQ(android::base::WriteFully(base_fd_, random_buffer.get(), 1_MiB), true);
343 }
344
345 ASSERT_EQ(lseek(base_fd_, 0, SEEK_SET), 0);
346
347 base_loop_ = std::make_unique<LoopDevice>(base_fd_, 10s);
348 ASSERT_TRUE(base_loop_->valid());
349 }
350
ReadSnapshotDeviceAndValidate()351 void CowSnapuserdTest::ReadSnapshotDeviceAndValidate() {
352 unique_fd snapshot_fd(open(snapshot_dev_->path().c_str(), O_RDONLY));
353 ASSERT_TRUE(snapshot_fd > 0);
354
355 std::unique_ptr<uint8_t[]> snapuserd_buffer = std::make_unique<uint8_t[]>(size_);
356
357 // COPY
358 loff_t offset = 0;
359 ASSERT_EQ(ReadFullyAtOffset(snapshot_fd, snapuserd_buffer.get(), size_, offset), true);
360 ASSERT_EQ(memcmp(snapuserd_buffer.get(), orig_buffer_.get(), size_), 0);
361
362 // REPLACE
363 offset += size_;
364 ASSERT_EQ(ReadFullyAtOffset(snapshot_fd, snapuserd_buffer.get(), size_, offset), true);
365 ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + size_, size_), 0);
366
367 // ZERO
368 offset += size_;
369 ASSERT_EQ(ReadFullyAtOffset(snapshot_fd, snapuserd_buffer.get(), size_, offset), true);
370 ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + (size_ * 2), size_), 0);
371
372 // REPLACE
373 offset += size_;
374 ASSERT_EQ(ReadFullyAtOffset(snapshot_fd, snapuserd_buffer.get(), size_, offset), true);
375 ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + (size_ * 3), size_), 0);
376
377 // XOR
378 offset += size_;
379 ASSERT_EQ(ReadFullyAtOffset(snapshot_fd, snapuserd_buffer.get(), size_, offset), true);
380 ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + (size_ * 4), size_), 0);
381 }
382
CreateCowDeviceWithCopyOverlap_2()383 void CowSnapuserdTest::CreateCowDeviceWithCopyOverlap_2() {
384 std::string path = android::base::GetExecutableDirectory();
385 cow_system_ = std::make_unique<TemporaryFile>(path);
386
387 CowOptions options;
388 options.compression = "gz";
389 CowWriter writer(options);
390
391 ASSERT_TRUE(writer.Initialize(cow_system_->fd));
392
393 size_t num_blocks = size_ / options.block_size;
394 size_t x = num_blocks;
395 size_t blk_src_copy = 0;
396
397 // Create overlapping copy operations
398 while (1) {
399 ASSERT_TRUE(writer.AddCopy(blk_src_copy, blk_src_copy + 1));
400 x -= 1;
401 if (x == 1) {
402 break;
403 }
404 blk_src_copy += 1;
405 }
406
407 // Flush operations
408 ASSERT_TRUE(writer.Finalize());
409
410 // Construct the buffer required for validation
411 orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
412
413 // Read the entire base device
414 ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), total_base_size_, 0),
415 true);
416
417 // Merged operations required for validation
418 int block_size = 4096;
419 x = num_blocks;
420 loff_t src_offset = block_size;
421 loff_t dest_offset = 0;
422
423 while (1) {
424 memmove((char*)orig_buffer_.get() + dest_offset, (char*)orig_buffer_.get() + src_offset,
425 block_size);
426 x -= 1;
427 if (x == 1) {
428 break;
429 }
430 src_offset += block_size;
431 dest_offset += block_size;
432 }
433 }
434
CreateCowDeviceWithCopyOverlap_1()435 void CowSnapuserdTest::CreateCowDeviceWithCopyOverlap_1() {
436 std::string path = android::base::GetExecutableDirectory();
437 cow_system_ = std::make_unique<TemporaryFile>(path);
438
439 CowOptions options;
440 options.compression = "gz";
441 CowWriter writer(options);
442
443 ASSERT_TRUE(writer.Initialize(cow_system_->fd));
444
445 size_t num_blocks = size_ / options.block_size;
446 size_t x = num_blocks;
447 size_t blk_src_copy = num_blocks - 1;
448
449 // Create overlapping copy operations
450 while (1) {
451 ASSERT_TRUE(writer.AddCopy(blk_src_copy + 1, blk_src_copy));
452 x -= 1;
453 if (x == 0) {
454 ASSERT_EQ(blk_src_copy, 0);
455 break;
456 }
457 blk_src_copy -= 1;
458 }
459
460 // Flush operations
461 ASSERT_TRUE(writer.Finalize());
462
463 // Construct the buffer required for validation
464 orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
465
466 // Read the entire base device
467 ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), total_base_size_, 0),
468 true);
469
470 // Merged operations
471 ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), options.block_size, 0),
472 true);
473 ASSERT_EQ(android::base::ReadFullyAtOffset(
474 base_fd_, (char*)orig_buffer_.get() + options.block_size, size_, 0),
475 true);
476 }
477
CreateCowDeviceOrderedOpsInverted()478 void CowSnapuserdTest::CreateCowDeviceOrderedOpsInverted() {
479 unique_fd rnd_fd;
480 loff_t offset = 0;
481
482 std::string path = android::base::GetExecutableDirectory();
483 cow_system_ = std::make_unique<TemporaryFile>(path);
484
485 rnd_fd.reset(open("/dev/random", O_RDONLY));
486 ASSERT_TRUE(rnd_fd > 0);
487
488 std::unique_ptr<uint8_t[]> random_buffer_1_ = std::make_unique<uint8_t[]>(size_);
489
490 // Fill random data
491 for (size_t j = 0; j < (size_ / 1_MiB); j++) {
492 ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer_1_.get() + offset, 1_MiB, 0),
493 true);
494
495 offset += 1_MiB;
496 }
497
498 CowOptions options;
499 options.compression = "gz";
500 CowWriter writer(options);
501
502 ASSERT_TRUE(writer.Initialize(cow_system_->fd));
503
504 size_t num_blocks = size_ / options.block_size;
505 size_t blk_end_copy = num_blocks * 3;
506 size_t source_blk = num_blocks - 1;
507 size_t blk_src_copy = blk_end_copy - 1;
508 uint16_t xor_offset = 5;
509
510 size_t x = num_blocks;
511 while (1) {
512 ASSERT_TRUE(writer.AddCopy(source_blk, blk_src_copy));
513 x -= 1;
514 if (x == 0) {
515 break;
516 }
517 source_blk -= 1;
518 blk_src_copy -= 1;
519 }
520
521 for (size_t i = num_blocks; i > 0; i--) {
522 ASSERT_TRUE(writer.AddXorBlocks(num_blocks + i - 1,
523 &random_buffer_1_.get()[options.block_size * (i - 1)],
524 options.block_size, 2 * num_blocks + i - 1, xor_offset));
525 }
526 // Flush operations
527 ASSERT_TRUE(writer.Finalize());
528 // Construct the buffer required for validation
529 orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
530 // Read the entire base device
531 ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), total_base_size_, 0),
532 true);
533 // Merged Buffer
534 memmove(orig_buffer_.get(), (char*)orig_buffer_.get() + 2 * size_, size_);
535 memmove(orig_buffer_.get() + size_, (char*)orig_buffer_.get() + 2 * size_ + xor_offset, size_);
536 for (int i = 0; i < size_; i++) {
537 orig_buffer_.get()[size_ + i] ^= random_buffer_1_.get()[i];
538 }
539 }
540
CreateCowDeviceOrderedOps()541 void CowSnapuserdTest::CreateCowDeviceOrderedOps() {
542 unique_fd rnd_fd;
543 loff_t offset = 0;
544
545 std::string path = android::base::GetExecutableDirectory();
546 cow_system_ = std::make_unique<TemporaryFile>(path);
547
548 rnd_fd.reset(open("/dev/random", O_RDONLY));
549 ASSERT_TRUE(rnd_fd > 0);
550
551 std::unique_ptr<uint8_t[]> random_buffer_1_ = std::make_unique<uint8_t[]>(size_);
552
553 // Fill random data
554 for (size_t j = 0; j < (size_ / 1_MiB); j++) {
555 ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer_1_.get() + offset, 1_MiB, 0),
556 true);
557
558 offset += 1_MiB;
559 }
560 memset(random_buffer_1_.get(), 0, size_);
561
562 CowOptions options;
563 options.compression = "gz";
564 CowWriter writer(options);
565
566 ASSERT_TRUE(writer.Initialize(cow_system_->fd));
567
568 size_t num_blocks = size_ / options.block_size;
569 size_t x = num_blocks;
570 size_t source_blk = 0;
571 size_t blk_src_copy = 2 * num_blocks;
572 uint16_t xor_offset = 5;
573
574 while (1) {
575 ASSERT_TRUE(writer.AddCopy(source_blk, blk_src_copy));
576
577 x -= 1;
578 if (x == 0) {
579 break;
580 }
581 source_blk += 1;
582 blk_src_copy += 1;
583 }
584
585 ASSERT_TRUE(writer.AddXorBlocks(num_blocks, random_buffer_1_.get(), size_, 2 * num_blocks,
586 xor_offset));
587 // Flush operations
588 ASSERT_TRUE(writer.Finalize());
589 // Construct the buffer required for validation
590 orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
591 // Read the entire base device
592 ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), total_base_size_, 0),
593 true);
594 // Merged Buffer
595 memmove(orig_buffer_.get(), (char*)orig_buffer_.get() + 2 * size_, size_);
596 memmove(orig_buffer_.get() + size_, (char*)orig_buffer_.get() + 2 * size_ + xor_offset, size_);
597 for (int i = 0; i < size_; i++) {
598 orig_buffer_.get()[size_ + i] ^= random_buffer_1_.get()[i];
599 }
600 }
601
CreateCowDevice()602 void CowSnapuserdTest::CreateCowDevice() {
603 unique_fd rnd_fd;
604 loff_t offset = 0;
605
606 std::string path = android::base::GetExecutableDirectory();
607 cow_system_ = std::make_unique<TemporaryFile>(path);
608
609 rnd_fd.reset(open("/dev/random", O_RDONLY));
610 ASSERT_TRUE(rnd_fd > 0);
611
612 std::unique_ptr<uint8_t[]> random_buffer_1_ = std::make_unique<uint8_t[]>(size_);
613
614 // Fill random data
615 for (size_t j = 0; j < (size_ / 1_MiB); j++) {
616 ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer_1_.get() + offset, 1_MiB, 0),
617 true);
618
619 offset += 1_MiB;
620 }
621
622 CowOptions options;
623 options.compression = "gz";
624 CowWriter writer(options);
625
626 ASSERT_TRUE(writer.Initialize(cow_system_->fd));
627
628 size_t num_blocks = size_ / options.block_size;
629 size_t blk_end_copy = num_blocks * 2;
630 size_t source_blk = num_blocks - 1;
631 size_t blk_src_copy = blk_end_copy - 1;
632
633 uint32_t sequence[num_blocks * 2];
634 // Sequence for Copy ops
635 for (int i = 0; i < num_blocks; i++) {
636 sequence[i] = num_blocks - 1 - i;
637 }
638 // Sequence for Xor ops
639 for (int i = 0; i < num_blocks; i++) {
640 sequence[num_blocks + i] = 5 * num_blocks - 1 - i;
641 }
642 ASSERT_TRUE(writer.AddSequenceData(2 * num_blocks, sequence));
643
644 size_t x = num_blocks;
645 while (1) {
646 ASSERT_TRUE(writer.AddCopy(source_blk, blk_src_copy));
647 x -= 1;
648 if (x == 0) {
649 break;
650 }
651 source_blk -= 1;
652 blk_src_copy -= 1;
653 }
654
655 source_blk = num_blocks;
656 blk_src_copy = blk_end_copy;
657
658 ASSERT_TRUE(writer.AddRawBlocks(source_blk, random_buffer_1_.get(), size_));
659
660 size_t blk_zero_copy_start = source_blk + num_blocks;
661 size_t blk_zero_copy_end = blk_zero_copy_start + num_blocks;
662
663 ASSERT_TRUE(writer.AddZeroBlocks(blk_zero_copy_start, num_blocks));
664
665 size_t blk_random2_replace_start = blk_zero_copy_end;
666
667 ASSERT_TRUE(writer.AddRawBlocks(blk_random2_replace_start, random_buffer_1_.get(), size_));
668
669 size_t blk_xor_start = blk_random2_replace_start + num_blocks;
670 size_t xor_offset = BLOCK_SZ / 2;
671 ASSERT_TRUE(writer.AddXorBlocks(blk_xor_start, random_buffer_1_.get(), size_, num_blocks,
672 xor_offset));
673
674 // Flush operations
675 ASSERT_TRUE(writer.Finalize());
676 // Construct the buffer required for validation
677 orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
678 std::string zero_buffer(size_, 0);
679 ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), size_, size_), true);
680 memcpy((char*)orig_buffer_.get() + size_, random_buffer_1_.get(), size_);
681 memcpy((char*)orig_buffer_.get() + (size_ * 2), (void*)zero_buffer.c_str(), size_);
682 memcpy((char*)orig_buffer_.get() + (size_ * 3), random_buffer_1_.get(), size_);
683 ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, &orig_buffer_.get()[size_ * 4], size_,
684 size_ + xor_offset),
685 true);
686 for (int i = 0; i < size_; i++) {
687 orig_buffer_.get()[(size_ * 4) + i] =
688 (uint8_t)(orig_buffer_.get()[(size_ * 4) + i] ^ random_buffer_1_.get()[i]);
689 }
690 }
691
InitCowDevice()692 void CowSnapuserdTest::InitCowDevice() {
693 cow_num_sectors_ = client_->InitDmUserCow(system_device_ctrl_name_, cow_system_->path,
694 base_loop_->device());
695 ASSERT_NE(cow_num_sectors_, 0);
696 }
697
SetDeviceControlName()698 void CowSnapuserdTest::SetDeviceControlName() {
699 system_device_name_.clear();
700 system_device_ctrl_name_.clear();
701
702 std::string str(cow_system_->path);
703 std::size_t found = str.find_last_of("/\\");
704 ASSERT_NE(found, std::string::npos);
705 system_device_name_ = str.substr(found + 1);
706
707 system_device_ctrl_name_ = system_device_name_ + "-ctrl";
708 }
709
CreateDmUserDevice()710 void CowSnapuserdTest::CreateDmUserDevice() {
711 DmTable dmuser_table;
712 ASSERT_TRUE(dmuser_table.AddTarget(
713 std::make_unique<DmTargetUser>(0, cow_num_sectors_, system_device_ctrl_name_)));
714 ASSERT_TRUE(dmuser_table.valid());
715
716 dmuser_dev_ = std::make_unique<TempDevice>(system_device_name_, dmuser_table);
717 ASSERT_TRUE(dmuser_dev_->valid());
718 ASSERT_FALSE(dmuser_dev_->path().empty());
719
720 auto misc_device = "/dev/dm-user/" + system_device_ctrl_name_;
721 ASSERT_TRUE(android::fs_mgr::WaitForFile(misc_device, 10s));
722 }
723
ReadDmUserBlockWithoutDaemon()724 void CowSnapuserdTest::ReadDmUserBlockWithoutDaemon() {
725 DmTable dmuser_table;
726 std::string dm_user_name = "dm-test-device";
727 unique_fd fd;
728
729 // Create a dm-user block device
730 ASSERT_TRUE(dmuser_table.AddTarget(std::make_unique<DmTargetUser>(0, 123456, dm_user_name)));
731 ASSERT_TRUE(dmuser_table.valid());
732
733 dmuser_dev_ = std::make_unique<TempDevice>(dm_user_name, dmuser_table);
734 ASSERT_TRUE(dmuser_dev_->valid());
735 ASSERT_FALSE(dmuser_dev_->path().empty());
736
737 fd.reset(open(dmuser_dev_->path().c_str(), O_RDONLY));
738 ASSERT_GE(fd, 0);
739
740 std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(1_MiB);
741
742 loff_t offset = 0;
743 // Every IO should fail as there is no daemon to process the IO
744 for (size_t j = 0; j < 10; j++) {
745 ASSERT_EQ(ReadFullyAtOffset(fd, (char*)buffer.get() + offset, BLOCK_SZ, offset), false);
746
747 offset += BLOCK_SZ;
748 }
749
750 fd = {};
751 ASSERT_TRUE(dmuser_dev_->Destroy());
752 }
753
InitDaemon()754 void CowSnapuserdTest::InitDaemon() {
755 bool ok = client_->AttachDmUser(system_device_ctrl_name_);
756 ASSERT_TRUE(ok);
757 }
758
CreateSnapshotDevice()759 void CowSnapuserdTest::CreateSnapshotDevice() {
760 DmTable snap_table;
761 ASSERT_TRUE(snap_table.AddTarget(std::make_unique<DmTargetSnapshot>(
762 0, total_base_size_ / kSectorSize, base_loop_->device(), dmuser_dev_->path(),
763 SnapshotStorageMode::Persistent, 8)));
764 ASSERT_TRUE(snap_table.valid());
765
766 snap_table.set_readonly(true);
767
768 snapshot_dev_ = std::make_unique<TempDevice>("cowsnapuserd-test-dm-snapshot", snap_table);
769 ASSERT_TRUE(snapshot_dev_->valid());
770 ASSERT_FALSE(snapshot_dev_->path().empty());
771 }
772
SetupImpl()773 void CowSnapuserdTest::SetupImpl() {
774 CreateBaseDevice();
775 CreateCowDevice();
776
777 SetDeviceControlName();
778
779 StartSnapuserdDaemon();
780 InitCowDevice();
781
782 CreateDmUserDevice();
783 InitDaemon();
784
785 CreateSnapshotDevice();
786 setup_ok_ = true;
787 }
788
Merge()789 bool CowSnapuserdTest::Merge() {
790 MergeImpl();
791 return merge_ok_;
792 }
793
StartMerge()794 void CowSnapuserdTest::StartMerge() {
795 DmTable merge_table;
796 ASSERT_TRUE(merge_table.AddTarget(std::make_unique<DmTargetSnapshot>(
797 0, total_base_size_ / kSectorSize, base_loop_->device(), dmuser_dev_->path(),
798 SnapshotStorageMode::Merge, 8)));
799 ASSERT_TRUE(merge_table.valid());
800 ASSERT_EQ(total_base_size_ / kSectorSize, merge_table.num_sectors());
801
802 DeviceMapper& dm = DeviceMapper::Instance();
803 ASSERT_TRUE(dm.LoadTableAndActivate("cowsnapuserd-test-dm-snapshot", merge_table));
804 }
805
MergeImpl()806 void CowSnapuserdTest::MergeImpl() {
807 StartMerge();
808 DeviceMapper& dm = DeviceMapper::Instance();
809
810 while (true) {
811 vector<DeviceMapper::TargetInfo> status;
812 ASSERT_TRUE(dm.GetTableStatus("cowsnapuserd-test-dm-snapshot", &status));
813 ASSERT_EQ(status.size(), 1);
814 ASSERT_EQ(strncmp(status[0].spec.target_type, "snapshot-merge", strlen("snapshot-merge")),
815 0);
816
817 DmTargetSnapshot::Status merge_status;
818 ASSERT_TRUE(DmTargetSnapshot::ParseStatusText(status[0].data, &merge_status));
819 ASSERT_TRUE(merge_status.error.empty());
820 if (merge_status.sectors_allocated == merge_status.metadata_sectors) {
821 break;
822 }
823
824 std::this_thread::sleep_for(250ms);
825 }
826
827 merge_ok_ = true;
828 }
829
ValidateMerge()830 void CowSnapuserdTest::ValidateMerge() {
831 merged_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
832 ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, merged_buffer_.get(), total_base_size_, 0),
833 true);
834 ASSERT_EQ(memcmp(merged_buffer_.get(), orig_buffer_.get(), total_base_size_), 0);
835 }
836
SimulateDaemonRestart()837 void CowSnapuserdTest::SimulateDaemonRestart() {
838 Shutdown();
839 std::this_thread::sleep_for(500ms);
840 SetDeviceControlName();
841 StartSnapuserdDaemon();
842 InitCowDevice();
843 CreateDmUserDevice();
844 InitDaemon();
845 CreateSnapshotDevice();
846 }
847
MergeInterruptRandomly(int max_duration)848 void CowSnapuserdTest::MergeInterruptRandomly(int max_duration) {
849 std::srand(std::time(nullptr));
850 StartMerge();
851
852 for (int i = 0; i < 20; i++) {
853 int duration = std::rand() % max_duration;
854 std::this_thread::sleep_for(std::chrono::milliseconds(duration));
855 SimulateDaemonRestart();
856 StartMerge();
857 }
858
859 SimulateDaemonRestart();
860 ASSERT_TRUE(Merge());
861 }
862
MergeInterruptFixed(int duration)863 void CowSnapuserdTest::MergeInterruptFixed(int duration) {
864 StartMerge();
865
866 for (int i = 0; i < 25; i++) {
867 std::this_thread::sleep_for(std::chrono::milliseconds(duration));
868 SimulateDaemonRestart();
869 StartMerge();
870 }
871
872 SimulateDaemonRestart();
873 ASSERT_TRUE(Merge());
874 }
875
MergeInterrupt()876 void CowSnapuserdTest::MergeInterrupt() {
877 // Interrupt merge at various intervals
878 StartMerge();
879 std::this_thread::sleep_for(250ms);
880 SimulateDaemonRestart();
881
882 StartMerge();
883 std::this_thread::sleep_for(250ms);
884 SimulateDaemonRestart();
885
886 StartMerge();
887 std::this_thread::sleep_for(150ms);
888 SimulateDaemonRestart();
889
890 StartMerge();
891 std::this_thread::sleep_for(100ms);
892 SimulateDaemonRestart();
893
894 StartMerge();
895 std::this_thread::sleep_for(800ms);
896 SimulateDaemonRestart();
897
898 StartMerge();
899 std::this_thread::sleep_for(600ms);
900 SimulateDaemonRestart();
901
902 ASSERT_TRUE(Merge());
903 }
904
CreateCowPartialFilledArea()905 void CowSnapuserdMetadataTest::CreateCowPartialFilledArea() {
906 std::string path = android::base::GetExecutableDirectory();
907 cow_system_ = std::make_unique<TemporaryFile>(path);
908
909 CowOptions options;
910 options.compression = "gz";
911 CowWriter writer(options);
912
913 ASSERT_TRUE(writer.Initialize(cow_system_->fd));
914
915 // Area 0 is completely filled with 256 exceptions
916 for (int i = 0; i < 256; i++) {
917 ASSERT_TRUE(writer.AddCopy(i, 256 + i));
918 }
919
920 // Area 1 is partially filled with 2 copy ops and 10 zero ops
921 ASSERT_TRUE(writer.AddCopy(500, 1000));
922 ASSERT_TRUE(writer.AddCopy(501, 1001));
923
924 ASSERT_TRUE(writer.AddZeroBlocks(300, 10));
925
926 // Flush operations
927 ASSERT_TRUE(writer.Finalize());
928 }
929
ValidatePartialFilledArea()930 void CowSnapuserdMetadataTest::ValidatePartialFilledArea() {
931 int area_sz = snapuserd_->GetMetadataAreaSize();
932
933 ASSERT_EQ(area_sz, 2);
934
935 // Verify the partially filled area
936 void* buffer = snapuserd_->GetExceptionBuffer(1);
937 loff_t offset = 0;
938 struct disk_exception* de;
939 for (int i = 11; i >= 0; i--) {
940 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
941 ASSERT_EQ(de->old_chunk, i);
942 offset += sizeof(struct disk_exception);
943 }
944
945 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
946 ASSERT_EQ(de->old_chunk, 0);
947 ASSERT_EQ(de->new_chunk, 0);
948 }
949
SetupPartialArea()950 void CowSnapuserdMetadataTest::SetupPartialArea() {
951 CreateCowPartialFilledArea();
952 InitMetadata();
953 }
954
CreateCowDevice()955 void CowSnapuserdMetadataTest::CreateCowDevice() {
956 unique_fd rnd_fd;
957 loff_t offset = 0;
958
959 std::string path = android::base::GetExecutableDirectory();
960 cow_system_ = std::make_unique<TemporaryFile>(path);
961
962 rnd_fd.reset(open("/dev/random", O_RDONLY));
963 ASSERT_TRUE(rnd_fd > 0);
964
965 std::unique_ptr<uint8_t[]> random_buffer_1_ = std::make_unique<uint8_t[]>(size_);
966
967 // Fill random data
968 for (size_t j = 0; j < (size_ / 1_MiB); j++) {
969 ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer_1_.get() + offset, 1_MiB, 0),
970 true);
971
972 offset += 1_MiB;
973 }
974
975 CowOptions options;
976 options.compression = "gz";
977 CowWriter writer(options);
978
979 ASSERT_TRUE(writer.Initialize(cow_system_->fd));
980
981 size_t num_blocks = size_ / options.block_size;
982
983 // Overlapping region. This has to be split
984 // into two batch operations
985 ASSERT_TRUE(writer.AddCopy(23, 20));
986 ASSERT_TRUE(writer.AddCopy(22, 19));
987 ASSERT_TRUE(writer.AddCopy(21, 18));
988 ASSERT_TRUE(writer.AddCopy(20, 17));
989 ASSERT_TRUE(writer.AddCopy(19, 16));
990 ASSERT_TRUE(writer.AddCopy(18, 15));
991
992 // Contiguous region but blocks in ascending order
993 // Daemon has to ensure that these blocks are merged
994 // in a batch
995 ASSERT_TRUE(writer.AddCopy(50, 75));
996 ASSERT_TRUE(writer.AddCopy(51, 76));
997 ASSERT_TRUE(writer.AddCopy(52, 77));
998 ASSERT_TRUE(writer.AddCopy(53, 78));
999
1000 // Dis-contiguous region
1001 ASSERT_TRUE(writer.AddCopy(110, 130));
1002 ASSERT_TRUE(writer.AddCopy(105, 125));
1003 ASSERT_TRUE(writer.AddCopy(100, 120));
1004
1005 // Overlap
1006 ASSERT_TRUE(writer.AddCopy(25, 30));
1007 ASSERT_TRUE(writer.AddCopy(30, 31));
1008
1009 size_t source_blk = num_blocks;
1010
1011 ASSERT_TRUE(writer.AddRawBlocks(source_blk, random_buffer_1_.get(), size_));
1012
1013 size_t blk_zero_copy_start = source_blk + num_blocks;
1014
1015 ASSERT_TRUE(writer.AddZeroBlocks(blk_zero_copy_start, num_blocks));
1016
1017 // Flush operations
1018 ASSERT_TRUE(writer.Finalize());
1019 }
1020
InitMetadata()1021 void CowSnapuserdMetadataTest::InitMetadata() {
1022 snapuserd_ = std::make_unique<Snapuserd>("", cow_system_->path, "");
1023 ASSERT_TRUE(snapuserd_->InitCowDevice());
1024 }
1025
Setup()1026 void CowSnapuserdMetadataTest::Setup() {
1027 CreateCowDevice();
1028 InitMetadata();
1029 }
1030
ValidateMetadata()1031 void CowSnapuserdMetadataTest::ValidateMetadata() {
1032 int area_sz = snapuserd_->GetMetadataAreaSize();
1033 ASSERT_EQ(area_sz, 3);
1034
1035 size_t old_chunk;
1036 size_t new_chunk;
1037
1038 for (int i = 0; i < area_sz; i++) {
1039 void* buffer = snapuserd_->GetExceptionBuffer(i);
1040 loff_t offset = 0;
1041 if (i == 0) {
1042 old_chunk = 256;
1043 new_chunk = 2;
1044 } else if (i == 1) {
1045 old_chunk = 512;
1046 new_chunk = 259;
1047 }
1048 for (int j = 0; j < 256; j++) {
1049 struct disk_exception* de =
1050 reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1051
1052 if (i != 2) {
1053 ASSERT_EQ(de->old_chunk, old_chunk);
1054 ASSERT_EQ(de->new_chunk, new_chunk);
1055 old_chunk += 1;
1056 new_chunk += 1;
1057 } else {
1058 break;
1059 }
1060 offset += sizeof(struct disk_exception);
1061 }
1062
1063 if (i == 2) {
1064 // The first 5 copy operation is not batch merged
1065 // as the sequence is discontiguous
1066 struct disk_exception* de =
1067 reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1068 ASSERT_EQ(de->old_chunk, 30);
1069 ASSERT_EQ(de->new_chunk, 518);
1070 offset += sizeof(struct disk_exception);
1071
1072 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1073 ASSERT_EQ(de->old_chunk, 25);
1074 ASSERT_EQ(de->new_chunk, 520);
1075 offset += sizeof(struct disk_exception);
1076
1077 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1078 ASSERT_EQ(de->old_chunk, 100);
1079 ASSERT_EQ(de->new_chunk, 521);
1080 offset += sizeof(struct disk_exception);
1081
1082 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1083 ASSERT_EQ(de->old_chunk, 105);
1084 ASSERT_EQ(de->new_chunk, 522);
1085 offset += sizeof(struct disk_exception);
1086
1087 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1088 ASSERT_EQ(de->old_chunk, 110);
1089 ASSERT_EQ(de->new_chunk, 523);
1090 offset += sizeof(struct disk_exception);
1091
1092 // The next 4 operations are batch merged as
1093 // both old and new chunk are contiguous
1094 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1095 ASSERT_EQ(de->old_chunk, 53);
1096 ASSERT_EQ(de->new_chunk, 524);
1097 offset += sizeof(struct disk_exception);
1098
1099 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1100 ASSERT_EQ(de->old_chunk, 52);
1101 ASSERT_EQ(de->new_chunk, 525);
1102 offset += sizeof(struct disk_exception);
1103
1104 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1105 ASSERT_EQ(de->old_chunk, 51);
1106 ASSERT_EQ(de->new_chunk, 526);
1107 offset += sizeof(struct disk_exception);
1108
1109 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1110 ASSERT_EQ(de->old_chunk, 50);
1111 ASSERT_EQ(de->new_chunk, 527);
1112 offset += sizeof(struct disk_exception);
1113
1114 // This is handling overlap operation with
1115 // two batch merge operations.
1116 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1117 ASSERT_EQ(de->old_chunk, 18);
1118 ASSERT_EQ(de->new_chunk, 528);
1119 offset += sizeof(struct disk_exception);
1120
1121 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1122 ASSERT_EQ(de->old_chunk, 19);
1123 ASSERT_EQ(de->new_chunk, 529);
1124 offset += sizeof(struct disk_exception);
1125
1126 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1127 ASSERT_EQ(de->old_chunk, 20);
1128 ASSERT_EQ(de->new_chunk, 530);
1129 offset += sizeof(struct disk_exception);
1130
1131 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1132 ASSERT_EQ(de->old_chunk, 21);
1133 ASSERT_EQ(de->new_chunk, 532);
1134 offset += sizeof(struct disk_exception);
1135
1136 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1137 ASSERT_EQ(de->old_chunk, 22);
1138 ASSERT_EQ(de->new_chunk, 533);
1139 offset += sizeof(struct disk_exception);
1140
1141 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1142 ASSERT_EQ(de->old_chunk, 23);
1143 ASSERT_EQ(de->new_chunk, 534);
1144 offset += sizeof(struct disk_exception);
1145
1146 // End of metadata
1147 de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
1148 ASSERT_EQ(de->old_chunk, 0);
1149 ASSERT_EQ(de->new_chunk, 0);
1150 offset += sizeof(struct disk_exception);
1151 }
1152 }
1153 }
1154
TEST(Snapuserd_Test,Snapshot_Metadata)1155 TEST(Snapuserd_Test, Snapshot_Metadata) {
1156 CowSnapuserdMetadataTest harness;
1157 harness.Setup();
1158 harness.ValidateMetadata();
1159 }
1160
TEST(Snapuserd_Test,Snapshot_Metadata_Overlap)1161 TEST(Snapuserd_Test, Snapshot_Metadata_Overlap) {
1162 CowSnapuserdMetadataTest harness;
1163 harness.SetupPartialArea();
1164 harness.ValidatePartialFilledArea();
1165 }
1166
TEST(Snapuserd_Test,Snapshot_Merge_Resume)1167 TEST(Snapuserd_Test, Snapshot_Merge_Resume) {
1168 CowSnapuserdTest harness;
1169 ASSERT_TRUE(harness.Setup());
1170 harness.MergeInterrupt();
1171 harness.ValidateMerge();
1172 harness.Shutdown();
1173 }
1174
TEST(Snapuserd_Test,Snapshot_IO_TEST)1175 TEST(Snapuserd_Test, Snapshot_IO_TEST) {
1176 CowSnapuserdTest harness;
1177 ASSERT_TRUE(harness.Setup());
1178 harness.ReadSnapshotDeviceAndValidate();
1179 ASSERT_TRUE(harness.Merge());
1180 harness.ValidateMerge();
1181 harness.Shutdown();
1182 }
1183
TEST(Snapuserd_Test,Snapshot_END_IO_TEST)1184 TEST(Snapuserd_Test, Snapshot_END_IO_TEST) {
1185 CowSnapuserdTest harness;
1186 harness.ReadLastBlock();
1187 harness.Shutdown();
1188 }
1189
TEST(Snapuserd_Test,Snapshot_COPY_Overlap_TEST_1)1190 TEST(Snapuserd_Test, Snapshot_COPY_Overlap_TEST_1) {
1191 CowSnapuserdTest harness;
1192 ASSERT_TRUE(harness.SetupCopyOverlap_1());
1193 ASSERT_TRUE(harness.Merge());
1194 harness.ValidateMerge();
1195 harness.Shutdown();
1196 }
1197
TEST(Snapuserd_Test,Snapshot_COPY_Overlap_TEST_2)1198 TEST(Snapuserd_Test, Snapshot_COPY_Overlap_TEST_2) {
1199 CowSnapuserdTest harness;
1200 ASSERT_TRUE(harness.SetupCopyOverlap_2());
1201 ASSERT_TRUE(harness.Merge());
1202 harness.ValidateMerge();
1203 harness.Shutdown();
1204 }
1205
TEST(Snapuserd_Test,Snapshot_COPY_Overlap_Merge_Resume_TEST)1206 TEST(Snapuserd_Test, Snapshot_COPY_Overlap_Merge_Resume_TEST) {
1207 CowSnapuserdTest harness;
1208 ASSERT_TRUE(harness.SetupCopyOverlap_1());
1209 harness.MergeInterrupt();
1210 harness.ValidateMerge();
1211 harness.Shutdown();
1212 }
1213
TEST(Snapuserd_Test,ReadDmUserBlockWithoutDaemon)1214 TEST(Snapuserd_Test, ReadDmUserBlockWithoutDaemon) {
1215 CowSnapuserdTest harness;
1216 harness.ReadDmUserBlockWithoutDaemon();
1217 }
1218
TEST(Snapuserd_Test,Snapshot_Merge_Crash_Fixed_Ordered)1219 TEST(Snapuserd_Test, Snapshot_Merge_Crash_Fixed_Ordered) {
1220 CowSnapuserdTest harness;
1221 ASSERT_TRUE(harness.SetupOrderedOps());
1222 harness.MergeInterruptFixed(300);
1223 harness.ValidateMerge();
1224 harness.Shutdown();
1225 }
1226
TEST(Snapuserd_Test,Snapshot_Merge_Crash_Random_Ordered)1227 TEST(Snapuserd_Test, Snapshot_Merge_Crash_Random_Ordered) {
1228 CowSnapuserdTest harness;
1229 ASSERT_TRUE(harness.SetupOrderedOps());
1230 harness.MergeInterruptRandomly(500);
1231 harness.ValidateMerge();
1232 harness.Shutdown();
1233 }
1234
TEST(Snapuserd_Test,Snapshot_Merge_Crash_Fixed_Inverted)1235 TEST(Snapuserd_Test, Snapshot_Merge_Crash_Fixed_Inverted) {
1236 CowSnapuserdTest harness;
1237 ASSERT_TRUE(harness.SetupOrderedOpsInverted());
1238 harness.MergeInterruptFixed(50);
1239 harness.ValidateMerge();
1240 harness.Shutdown();
1241 }
1242
TEST(Snapuserd_Test,Snapshot_Merge_Crash_Random_Inverted)1243 TEST(Snapuserd_Test, Snapshot_Merge_Crash_Random_Inverted) {
1244 CowSnapuserdTest harness;
1245 ASSERT_TRUE(harness.SetupOrderedOpsInverted());
1246 harness.MergeInterruptRandomly(50);
1247 harness.ValidateMerge();
1248 harness.Shutdown();
1249 }
1250
1251 } // namespace snapshot
1252 } // namespace android
1253
main(int argc,char ** argv)1254 int main(int argc, char** argv) {
1255 ::testing::InitGoogleTest(&argc, argv);
1256 return RUN_ALL_TESTS();
1257 }
1258