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