#include #include "Helper.h" #include "../AccessHelper.h" #include "../fat32/FS.h" // dd if=/dev/zero of=/tmp/ram/orig.fat32 bs=8192 count=4096 // mkfs.vfat -F 32 -R 32 -s 8 orig.fat32 // hexdump -v -C -n 512 orig.fat32 TEST(TestCreate, structure) { FAT32::FSHeader header; ASSERT_EQ(0x0B, (uint8_t*)&header.bytesPerSector - (uint8_t*)&header); ASSERT_EQ(0x0D, (uint8_t*)&header.sectorsPerCluster - (uint8_t*)&header); ASSERT_EQ(0x0E, (uint8_t*)&header.numReservedSectors - (uint8_t*)&header); ASSERT_EQ(0x10, (uint8_t*)&header.numberOfFATs - (uint8_t*)&header); ASSERT_EQ(0x15, (uint8_t*)&header.mediaDescriptor - (uint8_t*)&header); ASSERT_EQ(0x20, (uint8_t*)&header.sectorsInPartition - (uint8_t*)&header); ASSERT_EQ(0x24, (uint8_t*)&header.sectorsPerFAT - (uint8_t*)&header); ASSERT_EQ(0x2C, (uint8_t*)&header.rootDirFirstCluster - (uint8_t*)&header); } TEST (TestCreate, writeRead) { using BlockDev = AccessHelper; using FS = FAT32::FS; size_t size = 32*1024*1024; TestDevice dev(size); BlockDev bDev(dev); FS fs(bDev, 0); fs.setup(size, true); for (int i = 0; i < 64; ++i) { char name[64]; sprintf(name, "test%03d.txt", i); const size_t size = 128 + i * 512; const size_t sizeA = (size/4096+1) * 4096; std::cout << name << " - " << size << std::endl; FAT32::FS::File f = fs.getOrCreateFile(name); uint8_t* data = (uint8_t*)malloc(128 + i * 512); for (uint32_t j = 0; j < size; ++j) {data[j] = j;} uint32_t written = f.write(size, data); free(data); ASSERT_EQ(size, written); ASSERT_EQ(size, f.getSize()); ASSERT_EQ(sizeA, f.getAllocatedSize()); } dev.toFile("/tmp/ram/1.fat32"); // mount -t vfat 1.fat32 /mnt/fat/ && ls -l /mnt/fat/ && cat /mnt/fat/test001.txt && umount /mnt/fat // READ AGAIN FS fs2(bDev, 0); FS::DirIterator di = fs2.getRoot(); for (int i = 0; i < 64; ++i) { char name[64]; sprintf(name, "test%03d.txt", i); const size_t size = 128 + i * 512; const size_t sizeA = (size/4096+1) * 4096; FAT32::DirHandle h = di.nextUsable(); FS::File f = fs.open(h); ASSERT_EQ(name, h.getName()); ASSERT_EQ(name, f.getName()); ASSERT_EQ(size, f.getSize()); ASSERT_EQ(sizeA, f.getAllocatedSize()); uint8_t* data = (uint8_t*)malloc(128 + i * 512); uint32_t read = f.read(size, data); ASSERT_EQ(size, read); for (uint32_t j = 0; j < size; ++j) { ASSERT_EQ((uint8_t)j, data[j]); } free(data); } } TEST (TestCreate, init) { using BlockDev = AccessHelper; using FS = FAT32::FS; size_t size = 32*1024*1024; TestDevice dev(size); // write non-zero data into the device's memory for (uint32_t i = 0; i < size; ++i) {dev.buf[i] = 0x55;} BlockDev bDev(dev); FS fs(bDev, 0); // filesystem must not be considered valid, header contains only zeros ASSERT_FALSE(fs.isValid()); // initialize the filesystem fs.setup(size, true); // must be considered valid now ASSERT_TRUE(fs.isValid()); // size indication must match 32 MiB ASSERT_EQ(size, fs.getSize()); // data size indication (32 MiB - FATs and reserved sectors) ASSERT_EQ(size - 81920, fs.getSizeForData()); // currently, one cluster (4096 bytes) is used (for the root dir) ASSERT_EQ(4096, fs.getSizeUsed()); // there MUST NOT be any valid entry in the root dir, as this is a new FS! FS::DirIterator di = fs.getRoot(); ASSERT_FALSE(di.nextUsable().isValid()); } TEST (TestCreate, getOrCreateFile) { using BlockDev = AccessHelper; using FS = FAT32::FS; size_t size = 32*1024*1024; TestDevice dev(size); BlockDev bDev(dev); FS fs(bDev, 0); // filesystem must not be considered valid, header contains only zeros ASSERT_FALSE(fs.isValid()); // initialize the filesystem fs.setup(size, true); // must be considered valid now ASSERT_TRUE(fs.isValid()); // size indication must match 32 MB ASSERT_EQ(size, fs.getSize()); FS::File f1 = fs.getOrCreateFile("test.txt"); ASSERT_EQ(0, f1.getSize()); ASSERT_EQ(4096, f1.getAllocatedSize()); ASSERT_EQ("test.txt", f1.getName()); uint8_t d1[128]; uint8_t d2[128]; for (int i = 0; i < 128; ++i) {d1[i] = 1;} ASSERT_EQ(128, f1.write(128, d1)); FS::File f2 = fs.getOrCreateFile("test.txt"); ASSERT_EQ(128, f2.getSize()); ASSERT_EQ(128, f2.read(128, d2)); for (uint32_t i = 0; i < 128; ++i) {ASSERT_EQ(d1[i], d2[i]);} } template void dumpStructure(FS& fs, DirIter dirIter) { while(true) { auto h = dirIter.nextUsable(); if (!h.isValid()) {return;} std::cout << h.getName() << std::endl; if (h.isDot()) {continue;} if (h.isDotDot()) {continue;} if (h.isDirectory()) { dumpStructure(fs, DirIter(fs, h)); } } } TEST (TestCreate, subfolders) { using BlockDev = AccessHelper; using FS = FAT32::FS; size_t size = 32*1024*1024; TestDevice dev(size); BlockDev bDev(dev); FS fs(bDev, 0); fs.setup(size, true); fs.mkdirs("/test1"); fs.mkdirs("/test1/1"); fs.mkdirs("/test1/2"); fs.mkdirs("/test1/2/3"); fs.mkdirs("/test2/1/2/3"); fs.mkdirs("/test1/a/b"); fs.mkdirs("/test2/x/y"); fs.getOrCreateFile("/hallo.txt"); fs.getOrCreateFile("/test1/x/y/z.txt"); fs.getOrCreateFile("/test3/a/bbbb.txt"); FAT32::DirHandle dh1a = fs.getHandle("/"); FAT32::DirHandle dh1b = fs.getHandle(""); FAT32::DirHandle dh2 = fs.getHandle("/test1"); FAT32::DirHandle dh3 = fs.getHandle("/test1/1"); FS::DirIterator di(fs, 0); ASSERT_EQ(2, dh1a.getFirstCluster()); ASSERT_TRUE(dh1a.isValid()); ASSERT_EQ(2, dh1b.getFirstCluster()); ASSERT_TRUE(dh1b.isValid()); ASSERT_EQ(3, dh2.getFirstCluster()); ASSERT_TRUE(dh2.isValid()); ASSERT_EQ(4, dh3.getFirstCluster()); ASSERT_TRUE(dh3.isValid()); dev.toFile("/tmp/ram/subdirs.fat32"); // mount -t vfat /tmp/ram/subdirs.fat32 /mnt/fat/ && ls -l /mnt/fat/ && umount /mnt/fat dumpStructure(fs, fs.getRoot()); }