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