// Try allocating two filemaps and try a data_fill that // crosses the boundary between them void test_file_boundary() { const int test_filemap1 = 1; const int test_filemap2 = 2; const int test_clusters = 3; uint32_t clust_nr1 = fat_alloc_filemap(test_filemap1, test_clusters); uint32_t clust_nr2 = fat_alloc_filemap(test_filemap2, test_clusters); // Check that they were allocated next to each other QCOMPARE(clust_nr2, clust_nr1 - test_clusters); fat_finalize(DATA_CLUSTERS); int ret = data_fill(datapage, 4096, clust_nr1 - 1, 512, &filled); QCOMPARE(ret, 0); const uint32_t expected_end = 4096 - 512; const uint32_t expected_offset = (test_clusters - 1) * 4096 + 512; // data_fill is allowed to go past the end of the cluster, // but doesn't have to. QVERIFY(filled >= expected_end); QVERIFY(filled <= 4096); check_fill(datapage, MOCK_FILEMAP_FILL, expected_end, test_filemap2, expected_offset); if (filled > expected_end) { check_fill(datapage + expected_end, MOCK_FILEMAP_FILL, filled - expected_end, test_filemap1, 0); } }
// Test Fill() with different combinations of dimensions, alignment, and padding DEF_TEST(SwizzlerFill, r) { // Set up a color table SkPMColor colorTable[kFillIndex + 1]; colorTable[kFillIndex] = kFillColor; // Apart from the fill index, we will leave the other colors in the color table uninitialized. // If we incorrectly try to fill with this uninitialized memory, the bots will catch it. // Test on an invalid width and representative widths const uint32_t widths[] = { 0, 10, 50 }; // In order to call Fill(), there must be at least one row to fill // Test on the smallest possible height and representative heights const uint32_t heights[] = { 1, 5, 10 }; // Test on interesting possibilities for row padding const uint32_t paddings[] = { 0, 1, 2, 3, 4 }; // Iterate over test dimensions for (uint32_t width : widths) { for (uint32_t height : heights) { // Create image info objects const SkImageInfo colorInfo = SkImageInfo::MakeN32(width, height, kUnknown_SkAlphaType); const SkImageInfo indexInfo = colorInfo.makeColorType(kIndex_8_SkColorType); for (uint32_t padding : paddings) { // Calculate row bytes size_t colorRowBytes = SkColorTypeBytesPerPixel(kN32_SkColorType) * width + padding; size_t indexRowBytes = width + padding; // If there is padding, we can invent an offset to change the memory alignment for (uint32_t offset = 0; offset <= padding; offset++) { // Test all possible start rows with all possible end rows for (uint32_t startRow = 0; startRow < height; startRow++) { for (uint32_t endRow = startRow; endRow < height; endRow++) { // Fill with an index that we use to look up a color check_fill(r, colorInfo, startRow, endRow, colorRowBytes, offset, kFillIndex, colorTable); // Fill with a color check_fill(r, colorInfo, startRow, endRow, colorRowBytes, offset, kFillColor, NULL); // Fill with an index check_fill(r, indexInfo, startRow, endRow, indexRowBytes, offset, kFillIndex, NULL); } } } } } } }
// Test Fill() with different combinations of dimensions, alignment, and padding DEF_TEST(SwizzlerFill, r) { // Test on an invalid width and representative widths const uint32_t widths[] = { 0, 10, 50 }; // In order to call Fill(), there must be at least one row to fill // Test on the smallest possible height and representative heights const uint32_t heights[] = { 1, 5, 10 }; // Test on interesting possibilities for row padding const uint32_t paddings[] = { 0, 4 }; // Iterate over test dimensions for (uint32_t width : widths) { for (uint32_t height : heights) { // Create image info objects const SkImageInfo colorInfo = SkImageInfo::MakeN32(width, height, kUnknown_SkAlphaType); const SkImageInfo grayInfo = colorInfo.makeColorType(kGray_8_SkColorType); const SkImageInfo indexInfo = colorInfo.makeColorType(kIndex_8_SkColorType); const SkImageInfo color565Info = colorInfo.makeColorType(kRGB_565_SkColorType); for (uint32_t padding : paddings) { // Calculate row bytes const size_t colorRowBytes = SkColorTypeBytesPerPixel(kN32_SkColorType) * width + padding; const size_t indexRowBytes = width + padding; const size_t grayRowBytes = indexRowBytes; const size_t color565RowBytes = SkColorTypeBytesPerPixel(kRGB_565_SkColorType) * width + padding; // If there is padding, we can invent an offset to change the memory alignment for (uint32_t offset = 0; offset <= padding; offset += 4) { // Test all possible start rows with all possible end rows for (uint32_t startRow = 0; startRow < height; startRow++) { for (uint32_t endRow = startRow; endRow < height; endRow++) { // Test fill with each color type check_fill(r, colorInfo, startRow, endRow, colorRowBytes, offset, kFillColor); check_fill(r, indexInfo, startRow, endRow, indexRowBytes, offset, kFillIndex); check_fill(r, grayInfo, startRow, endRow, grayRowBytes, offset, kFillGray); check_fill(r, color565Info, startRow, endRow, color565RowBytes, offset, kFill565); } } } } } } }
// Try allocating one filemap and check the result void test_one_filemap() { const int test_filemap = 8; const int test_clusters = 17; const uint32_t expected_entry = FAT_ENTRIES - test_clusters; uint32_t clust_nr = fat_alloc_filemap(test_filemap, test_clusters); // Check that filemap was allocated at the end of the image QCOMPARE(clust_nr, expected_entry); fat_finalize(DATA_CLUSTERS); // Check that the last fat page shows the file uint32_t *buf = (uint32_t *) alloc_guarded( (test_clusters + 2) * sizeof(uint32_t)); fat_fill(buf, expected_entry - 1, test_clusters + 2); QCOMPARE(buf[0], (uint32_t) 0); // empty before file // ascending chain except last entry for (uint32_t i = 0; i < test_clusters - 1; i++) { QCOMPARE(buf[i + 1], expected_entry + i + 1); } // end of chain marker QCOMPARE(buf[test_clusters], (uint32_t) 0x0fffffff); // bad cluster marker after file (because it's at the end of // allocatable space) QCOMPARE(buf[test_clusters + 1], (uint32_t) 0x0ffffff7); // Check that an arbitrary cluster can be loaded from the file int ret = data_fill(datapage, 4096, expected_entry + 3, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); check_fill(datapage, MOCK_FILEMAP_FILL, 4096, test_filemap, 3 * 4096); }
// Try allocating one directory and check the result void test_one_dir() { const int test_dir_index = 5; uint32_t clust_nr = fat_alloc_dir(test_dir_index); QCOMPARE(clust_nr, (uint32_t) 2); QCOMPARE(fat_dir_index(0), -1); QCOMPARE(fat_dir_index(1), -1); QCOMPARE(fat_dir_index(2), test_dir_index); QCOMPARE(fat_dir_index(3), -1); QCOMPARE(fat_dir_index(4), -1); fat_finalize(DATA_CLUSTERS); // Check that fat_finalize didn't mess up the entries QCOMPARE(fat_dir_index(0), -1); QCOMPARE(fat_dir_index(1), -1); QCOMPARE(fat_dir_index(2), test_dir_index); QCOMPARE(fat_dir_index(3), -1); QCOMPARE(fat_dir_index(4), -1); // Check that the first fat page shows the directory fat_fill(fatpage, 0, 1024); // Check the special first two fat entries QCOMPARE(fatpage[0], (uint32_t) 0x0ffffff8); // media byte marker QCOMPARE(fatpage[1], (uint32_t) 0x0fffffff); // end of chain marker // Check the new directory entry QCOMPARE(fatpage[2], (uint32_t) 0x0fffffff); // end of chain marker VERIFY_ARRAY(fatpage, 3, 1024, (uint32_t) 0); // everything else 0 // Check that data_fill accesses the directory int ret = data_fill(datapage, 8192, 2, 0, &filled); QCOMPARE(ret, 0); // Check that the whole directory cluster was filled QVERIFY2(filled >= 4096, QTest::toString(filled)); // Check that dir_fill did the filling check_fill(datapage, MOCK_DIR_FILL, 4096, test_dir_index, 0); // and any extra fill is from an empty cluster // (current code does not fill more than the dir but it's allowed to) VERIFY_ARRAY(datapage, 4096, (int) filled, (char) 0); }
// Try allocating two directories and then extending the first twice void test_extend_dir_twice() { const int test_dir_index1 = 7; const int test_dir_index2 = 11; uint32_t clust_nr1 = fat_alloc_dir(test_dir_index1); uint32_t clust_nr2 = fat_alloc_dir(test_dir_index2); QCOMPARE(clust_nr1, (uint32_t) 2); QCOMPARE(clust_nr2, (uint32_t) 3); bool ret1 = fat_extend(clust_nr1, 1); QCOMPARE(ret1, true); bool ret2 = fat_extend(clust_nr1, 1); QCOMPARE(ret2, true); QCOMPARE(fat_dir_index(0), -1); QCOMPARE(fat_dir_index(1), -1); QCOMPARE(fat_dir_index(2), test_dir_index1); QCOMPARE(fat_dir_index(3), test_dir_index2); QCOMPARE(fat_dir_index(4), test_dir_index1); QCOMPARE(fat_dir_index(5), test_dir_index1); QCOMPARE(fat_dir_index(6), -1); fat_finalize(DATA_CLUSTERS); QCOMPARE(fat_dir_index(0), -1); QCOMPARE(fat_dir_index(1), -1); QCOMPARE(fat_dir_index(2), test_dir_index1); QCOMPARE(fat_dir_index(3), test_dir_index2); QCOMPARE(fat_dir_index(4), test_dir_index1); QCOMPARE(fat_dir_index(5), test_dir_index1); QCOMPARE(fat_dir_index(6), -1); // Check the first fat page fat_fill(fatpage, 0, 1024); QCOMPARE(fatpage[0], (uint32_t) 0x0ffffff8); // media byte marker QCOMPARE(fatpage[1], (uint32_t) 0x0fffffff); // end of chain marker QCOMPARE(fatpage[2], (uint32_t) 4); // next cluster of dir 1 QCOMPARE(fatpage[3], (uint32_t) 0x0fffffff); // end of chain marker QCOMPARE(fatpage[4], (uint32_t) 5); // next cluster of dir 1 QCOMPARE(fatpage[5], (uint32_t) 0x0fffffff); // end of chain marker VERIFY_ARRAY(fatpage, 6, 1024, (uint32_t) 0); // everything else 0 // Check that data_fill gets it right int ret = data_fill(datapage, 4096, 2, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); check_fill(datapage, MOCK_DIR_FILL, 4096, test_dir_index1, 0); ret = data_fill(datapage, 4096, 3, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); check_fill(datapage, MOCK_DIR_FILL, 4096, test_dir_index2, 0); ret = data_fill(datapage, 4096, 4, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); check_fill(datapage, MOCK_DIR_FILL, 4096, test_dir_index1, 4096); ret = data_fill(datapage, 4096, 5, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); check_fill(datapage, MOCK_DIR_FILL, 4096, test_dir_index1, 2 * 4096); }