1// Copyright 2016 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <time.h> 6 7#include <fbl/alloc_checker.h> 8#include <fbl/unique_ptr.h> 9 10#include "util.h" 11 12static unsigned count = 0; 13template <size_t WriteOffset, size_t ReadOffset, size_t WriteSize> 14bool test_sparse(void) { 15 BEGIN_TEST; 16 17 char filename[20]; 18 sprintf(filename, "::my_file_%u", count++); 19 20 int fd = emu_open(filename, O_RDWR | O_CREAT, 0644); 21 ASSERT_GT(fd, 0); 22 23 // Create a random write buffer of data 24 fbl::AllocChecker ac; 25 fbl::unique_ptr<uint8_t[]> wbuf(new (&ac) uint8_t[WriteSize]); 26 ASSERT_EQ(ac.check(), true); 27 unsigned int seed = static_cast<unsigned int>(time(NULL)); 28 unittest_printf("Sparse test using seed: %u\n", seed); 29 for (size_t i = 0; i < WriteSize; i++) { 30 wbuf[i] = (uint8_t) rand_r(&seed); 31 } 32 33 // Dump write buffer to file 34 ASSERT_EQ(emu_pwrite(fd, &wbuf[0], WriteSize, WriteOffset), WriteSize); 35 // Reopen file 36 ASSERT_EQ(emu_close(fd), 0); 37 fd = emu_open(filename, O_RDWR, 0644); 38 ASSERT_GT(fd, 0); 39 40 // Access read buffer from file 41 constexpr size_t kFileSize = WriteOffset + WriteSize; 42 constexpr size_t kBytesToRead = (kFileSize - ReadOffset) > WriteSize ? 43 WriteSize : (kFileSize - ReadOffset); 44 static_assert(kBytesToRead > 0, "We want to test writing AND reading"); 45 fbl::unique_ptr<uint8_t[]> rbuf(new (&ac) uint8_t[kBytesToRead]); 46 ASSERT_EQ(ac.check(), true); 47 ASSERT_EQ(emu_pread(fd, &rbuf[0], kBytesToRead, ReadOffset), kBytesToRead); 48 49 constexpr size_t kSparseLength = (ReadOffset < WriteOffset) ? 50 WriteOffset - ReadOffset : 0; 51 52 if (kSparseLength > 0) { 53 for (size_t i = 0; i < kSparseLength; i++) { 54 ASSERT_EQ(rbuf[i], 0, "This portion of file should be sparse; but isn't"); 55 } 56 } 57 58 constexpr size_t kWbufOffset = (ReadOffset < WriteOffset) ? 59 0 : ReadOffset - WriteOffset; 60 constexpr size_t kValidLength = kBytesToRead - kSparseLength; 61 62 if (kValidLength > 0) { 63 for (size_t i = 0; i < kValidLength; i++) { 64 ASSERT_EQ(rbuf[kSparseLength + i], wbuf[kWbufOffset + i]); 65 } 66 } 67 68 ASSERT_EQ(emu_close(fd), 0); 69 ASSERT_EQ(run_fsck(), 0); 70 END_TEST; 71} 72 73constexpr size_t kBlockSize = 8192; 74constexpr size_t kDirectBlocks = 16; 75 76RUN_MINFS_TESTS(sparse_tests, 77 RUN_TEST_MEDIUM((test_sparse<0, 0, kBlockSize>)) 78 RUN_TEST_MEDIUM((test_sparse<kBlockSize / 2, 0, kBlockSize>)) 79 RUN_TEST_MEDIUM((test_sparse<kBlockSize / 2, kBlockSize, kBlockSize>)) 80 RUN_TEST_MEDIUM((test_sparse<kBlockSize, 0, kBlockSize>)) 81 RUN_TEST_MEDIUM((test_sparse<kBlockSize, kBlockSize / 2, kBlockSize>)) 82 83 RUN_TEST_MEDIUM((test_sparse<kBlockSize * kDirectBlocks, 84 kBlockSize * kDirectBlocks - kBlockSize, 85 kBlockSize * 2>)) 86 RUN_TEST_MEDIUM((test_sparse<kBlockSize * kDirectBlocks, 87 kBlockSize * kDirectBlocks - kBlockSize, 88 kBlockSize * 32>)) 89 RUN_TEST_MEDIUM((test_sparse<kBlockSize * kDirectBlocks + kBlockSize, 90 kBlockSize * kDirectBlocks - kBlockSize, 91 kBlockSize * 32>)) 92 RUN_TEST_MEDIUM((test_sparse<kBlockSize * kDirectBlocks + kBlockSize, 93 kBlockSize * kDirectBlocks + 2 * kBlockSize, 94 kBlockSize * 32>)) 95) 96