/* * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ #include #include #include #include #include #include #include #include const char* kTempFile = "/tmp/bfs_attribute_iterator_test"; bool gVerbose; bool is_marker(const char* name) { return strstr(name, ":marker") != NULL; } int32 attribute_index(const char* name) { int32 number; if (sscanf(name, "test:%ld", &number) == 1) return number; return 0; } void add_attributes(BFile& file, int32 start, int32 count) { for (int32 index = start; index < start + count; index++) { char name[B_ATTR_NAME_LENGTH]; snprintf(name, sizeof(name), "test:%ld", index); file.WriteAttr(name, B_INT32_TYPE, 0, &index, sizeof(int32)); } } void remove_attributes(BFile& file, int32 start, int32 count) { for (int32 index = start; index < start + count; index++) { char name[B_ATTR_NAME_LENGTH]; snprintf(name, sizeof(name), "test:%ld", index); file.RemoveAttr(name); } } void add_marker_attribute(BFile& file, int32 index) { char name[B_ATTR_NAME_LENGTH]; snprintf(name, sizeof(name), "test:%ld:marker", index); file.WriteAttr(name, B_INT32_TYPE, 0, &index, sizeof(int32)); } void remove_marker_attribute(BFile& file, int32 index) { char name[B_ATTR_NAME_LENGTH]; snprintf(name, sizeof(name), "test:%ld:marker", index); file.RemoveAttr(name); } void test_remove_attributes(BFile& file, int32 start, int32 count, int32 removeAt, int32 removeIndex1, int32 removeIndex2) { int fd = file.Dup(); if (fd < 0) return; int32 index = 0; bool seen[4096] = {0}; if (gVerbose) printf("test removeAt %ld\n", removeAt); DIR* dir = fs_fopen_attr_dir(fd); while (struct dirent* entry = fs_read_attr_dir(dir)) { if (gVerbose) printf(" %ld. %s\n", index, entry->d_name); if (index == removeAt) { if (removeIndex1 > 0) remove_marker_attribute(file, removeIndex1); if (removeIndex2 > 0) remove_marker_attribute(file, removeIndex2); } index++; if (is_marker(entry->d_name)) continue; int32 attributeIndex = attribute_index(entry->d_name); if (attributeIndex > 0) { if (seen[attributeIndex]) { printf("attribute index %ld already listed!\n", attributeIndex); exit(1); } else seen[attributeIndex] = true; } } fs_close_attr_dir(dir); close(fd); for (int32 i = start; i < start + count; i++) { if (!seen[i]) { printf("attribute index %ld not listed, saw only %ld/%ld!\n", i, index, count); exit(1); } } } void test_add_attributes(BFile& file, int32 start, int32 count, int32 addAt, int32 addIndex1, int32 addIndex2) { int fd = file.Dup(); if (fd < 0) return; int32 index = 0; bool seen[4096] = {0}; if (gVerbose) printf("test addAt %ld\n", addAt); DIR* dir = fs_fopen_attr_dir(fd); while (struct dirent* entry = fs_read_attr_dir(dir)) { if (gVerbose) printf(" %ld. %s\n", index, entry->d_name); if (index == addAt) { if (addIndex1 > 0) add_marker_attribute(file, addIndex1); if (addIndex2 > 0) add_marker_attribute(file, addIndex2); } index++; if (is_marker(entry->d_name)) continue; int32 attributeIndex = attribute_index(entry->d_name); if (attributeIndex > 0) { if (seen[attributeIndex]) { printf("attribute index %ld already listed!\n", attributeIndex); exit(1); } else seen[attributeIndex] = true; } } fs_close_attr_dir(dir); close(fd); for (int32 i = start; i < start + count; i++) { if (!seen[i]) { printf("attribute index %ld not listed, saw only %ld/%ld!\n", i, index, count); exit(1); } } } int main(int argc, char** argv) { if (argc > 1 && !strcmp(argv[1], "-v")) gVerbose = true; BFile file; status_t status = file.SetTo(kTempFile, B_CREATE_FILE | B_READ_WRITE); if (status != B_OK) { fprintf(stderr, "Could not create temporary file: %s\n", strerror(status)); return 1; } puts("--------- Remove Tests ----------"); // remove test, many attributes puts("Test 1..."); for (int32 count = 5; count <= 100; count += 5) { add_attributes(file, 1, count); add_marker_attribute(file, count); add_attributes(file, count + 1, count); test_remove_attributes(file, 1, count, count & 1 ? count - 1 : count + 1, count, -1); remove_attributes(file, 1, count * 2); } // remove test, all positions puts("Test 2..."); for (int32 i = 1; i < 100; i++) { add_attributes(file, 1, 50); add_marker_attribute(file, 51); add_attributes(file, 51, 50); test_remove_attributes(file, 1, 100, i, 51, -1); remove_attributes(file, 1, 100); } // remove test, all positions, remove many puts("Test 3..."); for (int32 i = 1; i < 100; i++) { add_attributes(file, 1, 33); add_marker_attribute(file, 33); add_attributes(file, 34, 34); add_marker_attribute(file, 67); add_attributes(file, 68, 33); test_remove_attributes(file, 1, 100, i, 33, 67); remove_attributes(file, 1, 100); } puts("--------- Add Tests ----------"); // add test, many attributes puts("Test 4..."); for (int32 count = 10; count <= 200; count += 10) { add_attributes(file, 1, count); int32 half = count / 2; test_add_attributes(file, 1, count, half & 1 ? half - 1 : half + 1, half - 2, half + 2); remove_attributes(file, 1, count); } // add test, all iterator positions puts("Test 5..."); for (int32 i = 1; i < 100; i++) { add_attributes(file, 1, 100); test_add_attributes(file, 1, 100, i, 50, -1); remove_attributes(file, 1, 100); } // add test, all attribute positions puts("Test 6..."); for (int32 i = 1; i < 100; i++) { add_attributes(file, 1, 100); test_add_attributes(file, 1, 100, 50, i, -1); remove_attributes(file, 1, 100); } // add test, many attributes puts("Test 7..."); for (int32 i = 1; i < 100; i++) { add_attributes(file, 1, 100); test_add_attributes(file, 1, 100, i, 33, 67); remove_attributes(file, 1, 100); } // add test, many attributes puts("Test 8..."); for (int32 i = 1; i < 100; i++) { add_attributes(file, 1, 100); test_add_attributes(file, 1, 100, 50, i - 1, i + 1); remove_attributes(file, 1, 100); } BEntry entry; if (entry.SetTo(kTempFile) == B_OK) entry.Remove(); return 0; }