static void test_fields(TestBatch *batch) { Segment *segment = Seg_new(1); ZombieCharBuf *foo = ZCB_WRAP_STR("foo",3 ); ZombieCharBuf *bar = ZCB_WRAP_STR("bar", 3); ZombieCharBuf *baz = ZCB_WRAP_STR("baz", 3); int32_t field_num; field_num = Seg_Add_Field(segment, (CharBuf*)foo); TEST_TRUE(batch, field_num == 1, "Add_Field returns field number, and field numbers start at 1"); field_num = Seg_Add_Field(segment, (CharBuf*)bar); TEST_TRUE(batch, field_num == 2, "add a second field"); field_num = Seg_Add_Field(segment, (CharBuf*)foo); TEST_TRUE(batch, field_num == 1, "Add_Field returns existing field number if field is already known"); TEST_TRUE(batch, ZCB_Equals(bar, (Obj*)Seg_Field_Name(segment, 2)), "Field_Name"); TEST_TRUE(batch, Seg_Field_Name(segment, 3) == NULL, "Field_Name returns NULL for unknown field number"); TEST_TRUE(batch, Seg_Field_Num(segment, (CharBuf*)bar) == 2, "Field_Num"); TEST_TRUE(batch, Seg_Field_Num(segment, (CharBuf*)baz) == 0, "Field_Num returns 0 for unknown field name"); DECREF(segment); }
static void test_Store_and_Fetch(TestBatch *batch) { Hash *hash = Hash_new(100); Hash *dupe = Hash_new(100); const uint32_t starting_cap = Hash_Get_Capacity(hash); VArray *expected = VA_new(100); VArray *got = VA_new(100); ZombieCharBuf *twenty = ZCB_WRAP_STR("20", 2); ZombieCharBuf *forty = ZCB_WRAP_STR("40", 2); ZombieCharBuf *foo = ZCB_WRAP_STR("foo", 3); for (int32_t i = 0; i < 100; i++) { CharBuf *cb = CB_newf("%i32", i); Hash_Store(hash, (Obj*)cb, (Obj*)cb); Hash_Store(dupe, (Obj*)cb, INCREF(cb)); VA_Push(expected, INCREF(cb)); } TEST_TRUE(batch, Hash_Equals(hash, (Obj*)dupe), "Equals"); TEST_INT_EQ(batch, Hash_Get_Capacity(hash), starting_cap, "Initial capacity sufficient (no rebuilds)"); for (int32_t i = 0; i < 100; i++) { Obj *key = VA_Fetch(expected, i); Obj *elem = Hash_Fetch(hash, key); VA_Push(got, (Obj*)INCREF(elem)); } TEST_TRUE(batch, VA_Equals(got, (Obj*)expected), "basic Store and Fetch"); TEST_INT_EQ(batch, Hash_Get_Size(hash), 100, "size incremented properly by Hash_Store"); TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)foo) == NULL, "Fetch against non-existent key returns NULL"); Hash_Store(hash, (Obj*)forty, INCREF(foo)); TEST_TRUE(batch, ZCB_Equals(foo, Hash_Fetch(hash, (Obj*)forty)), "Hash_Store replaces existing value"); TEST_FALSE(batch, Hash_Equals(hash, (Obj*)dupe), "replacement value spoils equals"); TEST_INT_EQ(batch, Hash_Get_Size(hash), 100, "size unaffected after value replaced"); TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == (Obj*)foo, "Delete returns value"); DECREF(foo); TEST_INT_EQ(batch, Hash_Get_Size(hash), 99, "size decremented by successful Delete"); TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == NULL, "Delete returns NULL when key not found"); TEST_INT_EQ(batch, Hash_Get_Size(hash), 99, "size not decremented by unsuccessful Delete"); DECREF(Hash_Delete(dupe, (Obj*)forty)); TEST_TRUE(batch, VA_Equals(got, (Obj*)expected), "Equals after Delete"); Hash_Clear(hash); TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)twenty) == NULL, "Clear"); TEST_TRUE(batch, Hash_Get_Size(hash) == 0, "size is 0 after Clear"); DECREF(hash); DECREF(dupe); DECREF(got); DECREF(expected); }
static bool_t S_rename_or_hard_link(RAMFolder *self, const CharBuf* from, const CharBuf *to, Folder *from_folder, Folder *to_folder, ZombieCharBuf *from_name, ZombieCharBuf *to_name, int op) { Obj *elem = NULL; RAMFolder *inner_from_folder = NULL; RAMFolder *inner_to_folder = NULL; UNUSED_VAR(self); // Make sure the source and destination folders exist. if (!from_folder) { Err_set_error(Err_new(CB_newf("File not found: '%o'", from))); return false; } if (!to_folder) { Err_set_error(Err_new(CB_newf( "Invalid file path (can't find dir): '%o'", to))); return false; } // Extract RAMFolders from compound reader wrappers, if necessary. if (Folder_Is_A(from_folder, COMPOUNDFILEREADER)) { inner_from_folder = (RAMFolder*)CFReader_Get_Real_Folder( (CompoundFileReader*)from_folder); } else { inner_from_folder = (RAMFolder*)from_folder; } if (Folder_Is_A(to_folder, COMPOUNDFILEREADER)) { inner_to_folder = (RAMFolder*)CFReader_Get_Real_Folder( (CompoundFileReader*)to_folder); } else { inner_to_folder = (RAMFolder*)to_folder; } if (!RAMFolder_Is_A(inner_from_folder, RAMFOLDER)) { Err_set_error(Err_new(CB_newf("Not a RAMFolder, but a '%o'", Obj_Get_Class_Name((Obj*)inner_from_folder)))); return false; } if (!RAMFolder_Is_A(inner_to_folder, RAMFOLDER)) { Err_set_error(Err_new(CB_newf("Not a RAMFolder, but a '%o'", Obj_Get_Class_Name((Obj*)inner_to_folder)))); return false; } // Find the original element. elem = Hash_Fetch(inner_from_folder->entries, (Obj*)from_name); if (!elem) { if ( Folder_Is_A(from_folder, COMPOUNDFILEREADER) && Folder_Local_Exists(from_folder, (CharBuf*)from_name) ) { Err_set_error(Err_new(CB_newf("Source file '%o' is virtual", from))); } else { Err_set_error(Err_new(CB_newf("File not found: '%o'", from))); } return false; } // Execute the rename/hard-link. if (op == OP_RENAME) { Obj *existing = Hash_Fetch(inner_to_folder->entries, (Obj*)to_name); if (existing) { bool_t conflict = false; // Return success fast if file is copied on top of itself. if ( inner_from_folder == inner_to_folder && ZCB_Equals(from_name, (Obj*)to_name) ) { return true; } // Don't allow clobbering of different entry type. if (Obj_Is_A(elem, RAMFILE)) { if (!Obj_Is_A(existing, RAMFILE)) { conflict = true; } } else if (Obj_Is_A(elem, FOLDER)) { if (!Obj_Is_A(existing, FOLDER)) { conflict = true; } } if (conflict) { Err_set_error(Err_new(CB_newf("Can't clobber a %o with a %o", Obj_Get_Class_Name(existing), Obj_Get_Class_Name(elem)))); return false; } } // Perform the store first, then the delete. Inform Folder objects // about the relocation. Hash_Store(inner_to_folder->entries, (Obj*)to_name, INCREF(elem)); DECREF(Hash_Delete(inner_from_folder->entries, (Obj*)from_name)); if (Obj_Is_A(elem, FOLDER)) { CharBuf *newpath = S_fullpath(inner_to_folder, (CharBuf*)to_name); Folder_Set_Path((Folder*)elem, newpath); DECREF(newpath); } } else if (op == OP_HARD_LINK) { if (!Obj_Is_A(elem, RAMFILE)) { Err_set_error(Err_new(CB_newf("'%o' isn't a file, it's a %o", from, Obj_Get_Class_Name(elem)))); return false; } else { Obj *existing = Hash_Fetch(inner_to_folder->entries, (Obj*)to_name); if (existing) { Err_set_error(Err_new(CB_newf("'%o' already exists", to))); return false; } else { Hash_Store(inner_to_folder->entries, (Obj*)to_name, INCREF(elem)); } } } else { THROW(ERR, "Unexpected op: %i32", (int32_t)op); } return true; }