| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <stdlib.h> |
| |
| #define TESTLUCY_USE_SHORT_NAMES |
| #include "Lucy/Util/ToolSet.h" |
| |
| #include "charmony.h" |
| |
| #include "Clownfish/HashIterator.h" |
| #include "Clownfish/TestHarness/TestBatchRunner.h" |
| #include "Lucy/Test.h" |
| #include "Lucy/Test/Store/TestCompoundFileWriter.h" |
| #include "Lucy/Store/CompoundFileWriter.h" |
| #include "Lucy/Store/FileHandle.h" |
| #include "Lucy/Store/OutStream.h" |
| #include "Lucy/Store/RAMFolder.h" |
| #include "Lucy/Util/Json.h" |
| |
| static String *cfmeta_file = NULL; |
| static String *cfmeta_temp = NULL; |
| static String *cf_file = NULL; |
| static String *foo = NULL; |
| static String *bar = NULL; |
| static String *seg_1 = NULL; |
| |
| TestCompoundFileWriter* |
| TestCFWriter_new() { |
| return (TestCompoundFileWriter*)Class_Make_Obj(TESTCOMPOUNDFILEWRITER); |
| } |
| |
| static void |
| S_init_strings(void) { |
| cfmeta_file = Str_newf("cfmeta.json"); |
| cfmeta_temp = Str_newf("cfmeta.json.temp"); |
| cf_file = Str_newf("cf.dat"); |
| foo = Str_newf("foo"); |
| bar = Str_newf("bar"); |
| seg_1 = Str_newf("seg_1"); |
| } |
| |
| static void |
| S_destroy_strings(void) { |
| DECREF(cfmeta_file); |
| DECREF(cfmeta_temp); |
| DECREF(cf_file); |
| DECREF(foo); |
| DECREF(bar); |
| DECREF(seg_1); |
| } |
| |
| static Folder* |
| S_folder_with_contents() { |
| RAMFolder *folder = RAMFolder_new(seg_1); |
| OutStream *foo_out = RAMFolder_Open_Out(folder, foo); |
| OutStream *bar_out = RAMFolder_Open_Out(folder, bar); |
| OutStream_Write_Bytes(foo_out, "foo", 3); |
| OutStream_Write_Bytes(bar_out, "bar", 3); |
| OutStream_Close(foo_out); |
| OutStream_Close(bar_out); |
| DECREF(foo_out); |
| DECREF(bar_out); |
| return (Folder*)folder; |
| } |
| |
| static void |
| test_Consolidate(TestBatchRunner *runner) { |
| Folder *folder = S_folder_with_contents(); |
| FileHandle *fh; |
| |
| // Fake up detritus from failed consolidation. |
| fh = Folder_Open_FileHandle(folder, cf_file, |
| FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE); |
| DECREF(fh); |
| fh = Folder_Open_FileHandle(folder, cfmeta_temp, |
| FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE); |
| DECREF(fh); |
| |
| CompoundFileWriter *cf_writer = CFWriter_new(folder); |
| CFWriter_Consolidate(cf_writer); |
| PASS(runner, "Consolidate completes despite leftover files"); |
| DECREF(cf_writer); |
| |
| TEST_TRUE(runner, Folder_Exists(folder, cf_file), |
| "cf.dat file written"); |
| TEST_TRUE(runner, Folder_Exists(folder, cfmeta_file), |
| "cfmeta.json file written"); |
| TEST_FALSE(runner, Folder_Exists(folder, foo), |
| "original file zapped"); |
| TEST_FALSE(runner, Folder_Exists(folder, cfmeta_temp), |
| "detritus from failed consolidation zapped"); |
| |
| DECREF(folder); |
| } |
| |
| static void |
| test_offsets(TestBatchRunner *runner) { |
| Folder *folder = S_folder_with_contents(); |
| CompoundFileWriter *cf_writer = CFWriter_new(folder); |
| Hash *cf_metadata; |
| Hash *files; |
| |
| CFWriter_Consolidate(cf_writer); |
| |
| cf_metadata = (Hash*)CERTIFY( |
| Json_slurp_json(folder, cfmeta_file), HASH); |
| files = (Hash*)CERTIFY( |
| Hash_Fetch_Utf8(cf_metadata, "files", 5), HASH); |
| |
| bool offsets_ok = true; |
| |
| TEST_TRUE(runner, Hash_Get_Size(files) > 0, "Multiple files"); |
| |
| HashIterator *iter = HashIter_new(files); |
| while (HashIter_Next(iter)) { |
| String *file = HashIter_Get_Key(iter); |
| Hash *stats = (Hash*)CERTIFY(HashIter_Get_Value(iter), HASH); |
| Obj *offset = CERTIFY(Hash_Fetch_Utf8(stats, "offset", 6), OBJ); |
| int64_t offs = Json_obj_to_i64(offset); |
| if (offs % 8 != 0) { |
| offsets_ok = false; |
| char *str = Str_To_Utf8(file); |
| FAIL(runner, "Offset %" PRId64 " for %s not a multiple of 8", |
| offset, str); |
| free(str); |
| break; |
| } |
| } |
| DECREF(iter); |
| if (offsets_ok) { |
| PASS(runner, "All offsets are multiples of 8"); |
| } |
| |
| DECREF(cf_metadata); |
| DECREF(cf_writer); |
| DECREF(folder); |
| } |
| |
| void |
| TestCFWriter_Run_IMP(TestCompoundFileWriter *self, TestBatchRunner *runner) { |
| TestBatchRunner_Plan(runner, (TestBatch*)self, 7); |
| S_init_strings(); |
| test_Consolidate(runner); |
| test_offsets(runner); |
| S_destroy_strings(); |
| } |
| |
| |