static void test_Local_Open_Dir(TestBatchRunner *runner) { Folder *real_folder = S_folder_with_contents(); CompoundFileReader *cf_reader = CFReader_open(real_folder); bool saw_foo = false; bool saw_stuff = false; bool stuff_was_dir = false; CFReader_MkDir(cf_reader, stuff); DirHandle *dh = CFReader_Local_Open_Dir(cf_reader); while (DH_Next(dh)) { String *entry = DH_Get_Entry(dh); if (Str_Equals(entry, (Obj*)foo)) { saw_foo = true; } else if (Str_Equals(entry, (Obj*)stuff)) { saw_stuff = true; stuff_was_dir = DH_Entry_Is_Dir(dh); } DECREF(entry); } TEST_TRUE(runner, saw_foo, "DirHandle iterated over virtual file"); TEST_TRUE(runner, saw_stuff, "DirHandle iterated over real directory"); TEST_TRUE(runner, stuff_was_dir, "DirHandle knew that real entry was dir"); DECREF(dh); DECREF(cf_reader); DECREF(real_folder); }
static void test_Local_Open_In(TestBatchRunner *runner) { Folder *real_folder = S_folder_with_contents(); CompoundFileReader *cf_reader = CFReader_open(real_folder); InStream *instream; instream = CFReader_Local_Open_In(cf_reader, foo); TEST_TRUE(runner, instream != NULL, "Local_Open_In for virtual file"); TEST_TRUE(runner, Str_Starts_With(InStream_Get_Filename(instream), CFReader_Get_Path(cf_reader)), "InStream's path includes directory"); DECREF(instream); OutStream *outstream = CFReader_Open_Out(cf_reader, baz); OutStream_Write_Bytes(outstream, "baz", 3); OutStream_Close(outstream); DECREF(outstream); instream = CFReader_Local_Open_In(cf_reader, baz); TEST_TRUE(runner, instream != NULL, "Local_Open_In pass-through for real file"); DECREF(instream); Err_set_error(NULL); instream = CFReader_Local_Open_In(cf_reader, stuff); TEST_TRUE(runner, instream == NULL, "Local_Open_In for non-existent file returns NULL"); TEST_TRUE(runner, Err_get_error() != NULL, "Local_Open_In for non-existent file sets global error"); DECREF(cf_reader); DECREF(real_folder); }
void Folder_consolidate(Folder *self, const CharBuf *path) { Folder *folder = Folder_Find_Folder(self, path); Folder *enclosing_folder = Folder_Enclosing_Folder(self, path); if (!folder) { THROW(ERR, "Can't consolidate %o", path); } else if (Folder_Is_A(folder, COMPOUNDFILEREADER)) { THROW(ERR, "Can't consolidate %o twice", path); } else { CompoundFileWriter *cf_writer = CFWriter_new(folder); CFWriter_Consolidate(cf_writer); DECREF(cf_writer); if (CB_Get_Size(path)) { ZombieCharBuf *name = IxFileNames_local_part(path, ZCB_BLANK()); CompoundFileReader *cf_reader = CFReader_open(folder); if (!cf_reader) { RETHROW(INCREF(Err_get_error())); } Hash_Store(enclosing_folder->entries, (Obj*)name, (Obj*)cf_reader); } } }
static void test_Close(TestBatchRunner *runner) { Folder *real_folder = S_folder_with_contents(); CompoundFileReader *cf_reader = CFReader_open(real_folder); CFReader_Close(cf_reader); PASS(runner, "Close completes without incident"); CFReader_Close(cf_reader); PASS(runner, "Calling Close() multiple times is ok"); DECREF(cf_reader); DECREF(real_folder); }
Folder* FSFolder_Local_Find_Folder_IMP(FSFolder *self, String *name) { FSFolderIVARS *const ivars = FSFolder_IVARS(self); Folder *subfolder = NULL; if (!name || !Str_Get_Size(name)) { // No entity can be identified by NULL or empty string. return NULL; } else if (!S_is_local_entry(name)) { return NULL; } else if (Str_Starts_With_Utf8(name, ".", 1)) { // Don't allow access outside of the main dir. return NULL; } else if (NULL != (subfolder = (Folder*)Hash_Fetch(ivars->entries, (Obj*)name))) { if (Folder_Is_A(subfolder, FOLDER)) { return subfolder; } else { return NULL; } } String *fullpath = S_fullpath(self, name); if (S_dir_ok(fullpath)) { subfolder = (Folder*)FSFolder_new(fullpath); if (!subfolder) { DECREF(fullpath); THROW(ERR, "Failed to open FSFolder at '%o'", fullpath); } // Try to open a CompoundFileReader. On failure, just use the // existing folder. String *cfmeta_file = (String*)SSTR_WRAP_UTF8("cfmeta.json", 11); if (Folder_Local_Exists(subfolder, cfmeta_file)) { CompoundFileReader *cf_reader = CFReader_open(subfolder); if (cf_reader) { DECREF(subfolder); subfolder = (Folder*)cf_reader; } } Hash_Store(ivars->entries, (Obj*)name, (Obj*)subfolder); } DECREF(fullpath); return subfolder; }
static void test_Local_MkDir_and_Find_Folder(TestBatchRunner *runner) { Folder *real_folder = S_folder_with_contents(); CompoundFileReader *cf_reader = CFReader_open(real_folder); TEST_FALSE(runner, CFReader_Local_Is_Directory(cf_reader, stuff), "Local_Is_Directory returns false for non-existent entry"); TEST_TRUE(runner, CFReader_MkDir(cf_reader, stuff), "MkDir returns true"); TEST_TRUE(runner, Folder_Find_Folder(real_folder, stuff) != NULL, "Local_MkDir pass-through"); TEST_TRUE(runner, Folder_Find_Folder(real_folder, stuff) == CFReader_Find_Folder(cf_reader, stuff), "Local_Find_Folder pass-through"); TEST_TRUE(runner, CFReader_Local_Is_Directory(cf_reader, stuff), "Local_Is_Directory pass through"); Err_set_error(NULL); TEST_FALSE(runner, CFReader_MkDir(cf_reader, stuff), "MkDir returns false when dir already exists"); TEST_TRUE(runner, Err_get_error() != NULL, "MkDir sets global error when dir already exists"); Err_set_error(NULL); TEST_FALSE(runner, CFReader_MkDir(cf_reader, foo), "MkDir returns false when virtual file exists"); TEST_TRUE(runner, Err_get_error() != NULL, "MkDir sets global error when virtual file exists"); TEST_TRUE(runner, CFReader_Find_Folder(cf_reader, foo) == NULL, "Virtual file not reported as directory"); TEST_FALSE(runner, CFReader_Local_Is_Directory(cf_reader, foo), "Local_Is_Directory returns false for virtual file"); DECREF(real_folder); DECREF(cf_reader); }
static void test_Local_Delete_and_Exists(TestBatchRunner *runner) { Folder *real_folder = S_folder_with_contents(); CompoundFileReader *cf_reader = CFReader_open(real_folder); CFReader_MkDir(cf_reader, stuff); TEST_TRUE(runner, CFReader_Local_Exists(cf_reader, stuff), "pass through for Local_Exists"); TEST_TRUE(runner, CFReader_Local_Exists(cf_reader, foo), "Local_Exists returns true for virtual file"); TEST_TRUE(runner, CFReader_Local_Exists(cf_reader, cfmeta_file), "cfmeta file exists"); TEST_TRUE(runner, CFReader_Local_Delete(cf_reader, stuff), "Local_Delete returns true when zapping real entity"); TEST_FALSE(runner, CFReader_Local_Exists(cf_reader, stuff), "Local_Exists returns false after real entity zapped"); TEST_TRUE(runner, CFReader_Local_Delete(cf_reader, foo), "Local_Delete returns true when zapping virtual file"); TEST_FALSE(runner, CFReader_Local_Exists(cf_reader, foo), "Local_Exists returns false after virtual file zapped"); TEST_TRUE(runner, CFReader_Local_Delete(cf_reader, bar), "Local_Delete returns true when zapping last virtual file"); TEST_FALSE(runner, CFReader_Local_Exists(cf_reader, cfmeta_file), "cfmeta file deleted when last virtual file deleted"); TEST_FALSE(runner, CFReader_Local_Exists(cf_reader, cf_file), "compound data file deleted when last virtual file deleted"); DECREF(cf_reader); DECREF(real_folder); }
static void test_Local_Open_FileHandle(TestBatchRunner *runner) { Folder *real_folder = S_folder_with_contents(); CompoundFileReader *cf_reader = CFReader_open(real_folder); FileHandle *fh; OutStream *outstream = CFReader_Open_Out(cf_reader, baz); OutStream_Write_Bytes(outstream, "baz", 3); OutStream_Close(outstream); DECREF(outstream); fh = CFReader_Local_Open_FileHandle(cf_reader, baz, FH_READ_ONLY); TEST_TRUE(runner, fh != NULL, "Local_Open_FileHandle pass-through for real file"); DECREF(fh); Err_set_error(NULL); fh = CFReader_Local_Open_FileHandle(cf_reader, stuff, FH_READ_ONLY); TEST_TRUE(runner, fh == NULL, "Local_Open_FileHandle for non-existent file returns NULL"); TEST_TRUE(runner, Err_get_error() != NULL, "Local_Open_FileHandle for non-existent file sets global error"); Err_set_error(NULL); fh = CFReader_Local_Open_FileHandle(cf_reader, foo, FH_READ_ONLY); TEST_TRUE(runner, fh == NULL, "Local_Open_FileHandle for virtual file returns NULL"); TEST_TRUE(runner, Err_get_error() != NULL, "Local_Open_FileHandle for virtual file sets global error"); DECREF(cf_reader); DECREF(real_folder); }
static void test_open(TestBatchRunner *runner) { Folder *real_folder; CompoundFileReader *cf_reader; Hash *metadata; Err_set_error(NULL); real_folder = S_folder_with_contents(); Folder_Delete(real_folder, cfmeta_file); cf_reader = CFReader_open(real_folder); TEST_TRUE(runner, cf_reader == NULL, "Return NULL when cfmeta file missing"); TEST_TRUE(runner, Err_get_error() != NULL, "Set global error when cfmeta file missing"); DECREF(real_folder); Err_set_error(NULL); real_folder = S_folder_with_contents(); Folder_Delete(real_folder, cf_file); cf_reader = CFReader_open(real_folder); TEST_TRUE(runner, cf_reader == NULL, "Return NULL when cf.dat file missing"); TEST_TRUE(runner, Err_get_error() != NULL, "Set global error when cf.dat file missing"); DECREF(real_folder); Err_set_error(NULL); real_folder = S_folder_with_contents(); metadata = (Hash*)Json_slurp_json(real_folder, cfmeta_file); Hash_Store_Utf8(metadata, "format", 6, (Obj*)Str_newf("%i32", -1)); Folder_Delete(real_folder, cfmeta_file); Json_spew_json((Obj*)metadata, real_folder, cfmeta_file); cf_reader = CFReader_open(real_folder); TEST_TRUE(runner, cf_reader == NULL, "Return NULL when format is invalid"); TEST_TRUE(runner, Err_get_error() != NULL, "Set global error when format is invalid"); Err_set_error(NULL); Hash_Store_Utf8(metadata, "format", 6, (Obj*)Str_newf("%i32", 1000)); Folder_Delete(real_folder, cfmeta_file); Json_spew_json((Obj*)metadata, real_folder, cfmeta_file); cf_reader = CFReader_open(real_folder); TEST_TRUE(runner, cf_reader == NULL, "Return NULL when format is too recent"); TEST_TRUE(runner, Err_get_error() != NULL, "Set global error when format too recent"); Err_set_error(NULL); DECREF(Hash_Delete_Utf8(metadata, "format", 6)); Folder_Delete(real_folder, cfmeta_file); Json_spew_json((Obj*)metadata, real_folder, cfmeta_file); cf_reader = CFReader_open(real_folder); TEST_TRUE(runner, cf_reader == NULL, "Return NULL when format key is missing"); TEST_TRUE(runner, Err_get_error() != NULL, "Set global error when format key is missing"); Hash_Store_Utf8(metadata, "format", 6, (Obj*)Str_newf("%i32", CFWriter_current_file_format)); DECREF(Hash_Delete_Utf8(metadata, "files", 5)); Folder_Delete(real_folder, cfmeta_file); Json_spew_json((Obj*)metadata, real_folder, cfmeta_file); cf_reader = CFReader_open(real_folder); TEST_TRUE(runner, cf_reader == NULL, "Return NULL when files key is missing"); TEST_TRUE(runner, Err_get_error() != NULL, "Set global error when files key is missing"); DECREF(metadata); DECREF(real_folder); }