static void test_refill(TestBatchRunner *runner) { RAMFile *file = RAMFile_new(NULL, false); OutStream *outstream = OutStream_open((Obj*)file); InStream *instream; char scratch[5]; InStreamIVARS *ivars; for (int32_t i = 0; i < 1023; i++) { OutStream_Write_U8(outstream, 'x'); } OutStream_Write_U8(outstream, 'y'); OutStream_Write_U8(outstream, 'z'); OutStream_Close(outstream); instream = InStream_open((Obj*)file); ivars = InStream_IVARS(instream); InStream_Refill(instream); TEST_INT_EQ(runner, ivars->limit - ivars->buf, IO_STREAM_BUF_SIZE, "Refill"); TEST_INT_EQ(runner, (long)InStream_Tell(instream), 0, "Correct file pos after standing-start Refill()"); DECREF(instream); instream = InStream_open((Obj*)file); ivars = InStream_IVARS(instream); InStream_Fill(instream, 30); TEST_INT_EQ(runner, ivars->limit - ivars->buf, 30, "Fill()"); TEST_INT_EQ(runner, (long)InStream_Tell(instream), 0, "Correct file pos after standing-start Fill()"); DECREF(instream); instream = InStream_open((Obj*)file); ivars = InStream_IVARS(instream); InStream_Read_Bytes(instream, scratch, 5); TEST_INT_EQ(runner, ivars->limit - ivars->buf, IO_STREAM_BUF_SIZE - 5, "small read triggers refill"); DECREF(instream); instream = InStream_open((Obj*)file); ivars = InStream_IVARS(instream); TEST_INT_EQ(runner, InStream_Read_U8(instream), 'x', "Read_U8"); InStream_Seek(instream, 1023); TEST_INT_EQ(runner, (long)FileWindow_IVARS(ivars->window)->offset, 0, "no unnecessary refill on Seek"); TEST_INT_EQ(runner, (long)InStream_Tell(instream), 1023, "Seek/Tell"); TEST_INT_EQ(runner, InStream_Read_U8(instream), 'y', "correct data after in-buffer Seek()"); TEST_INT_EQ(runner, InStream_Read_U8(instream), 'z', "automatic Refill"); TEST_TRUE(runner, (FileWindow_IVARS(ivars->window)->offset != 0), "refilled"); DECREF(instream); DECREF(outstream); DECREF(file); }
static void test_Align(TestBatchRunner *runner) { RAMFile *file = RAMFile_new(NULL, false); OutStream *outstream = OutStream_open((Obj*)file); for (int32_t i = 1; i < 32; i++) { int64_t random_bytes = TestUtils_random_u64() % 32; while (random_bytes--) { OutStream_Write_U8(outstream, 0); } TEST_TRUE(runner, (OutStream_Align(outstream, i) % i) == 0, "Align to %ld", (long)i); } DECREF(file); DECREF(outstream); }
static void test_Clone_and_Reopen(TestBatchRunner *runner) { String *foo = SSTR_WRAP_C("foo"); String *bar = SSTR_WRAP_C("bar"); RAMFile *file = RAMFile_new(NULL, false); OutStream *outstream = OutStream_open((Obj*)file); RAMFileHandle *fh; InStream *instream; InStream *clone; InStream *reopened; for (uint8_t i = 0; i < 26; i++) { OutStream_Write_U8(outstream, 'a' + i); } OutStream_Close(outstream); fh = RAMFH_open(foo, FH_READ_ONLY, file); instream = InStream_open((Obj*)fh); InStream_Seek(instream, 1); TEST_TRUE(runner, Str_Equals(InStream_Get_Filename(instream), (Obj*)foo), "Get_Filename"); clone = InStream_Clone(instream); TEST_TRUE(runner, Str_Equals(InStream_Get_Filename(clone), (Obj*)foo), "Clones have same filename"); TEST_TRUE(runner, InStream_Length(instream) == InStream_Length(clone), "Clones have same length"); TEST_TRUE(runner, InStream_Read_U8(instream) == InStream_Read_U8(clone), "Clones start at same file position"); reopened = InStream_Reopen(instream, bar, 25, 1); TEST_TRUE(runner, Str_Equals(InStream_Get_Filename(reopened), (Obj*)bar), "Reopened InStreams take new filename"); TEST_TRUE(runner, InStream_Read_U8(reopened) == 'z', "Reopened stream starts at supplied offset"); TEST_TRUE(runner, InStream_Length(reopened) == 1, "Reopened stream uses supplied length"); TEST_TRUE(runner, InStream_Tell(reopened) == 1, "Tell() uses supplied offset for reopened stream"); InStream_Seek(reopened, 0); TEST_TRUE(runner, InStream_Read_U8(reopened) == 'z', "Seek() uses supplied offset for reopened stream"); DECREF(reopened); DECREF(clone); DECREF(instream); DECREF(outstream); DECREF(fh); DECREF(file); }
OutStream* Folder_open_out(Folder *self, const CharBuf *path) { const uint32_t flags = FH_WRITE_ONLY | FH_CREATE | FH_EXCLUSIVE; FileHandle *fh = Folder_Open_FileHandle(self, path, flags); OutStream *outstream = NULL; if (fh) { outstream = OutStream_open((Obj*)fh); DECREF(fh); if (!outstream) { ERR_ADD_FRAME(Err_get_error()); } } else { ERR_ADD_FRAME(Err_get_error()); } return outstream; }
static void test_Read_Write_Bytes(TestBatchRunner *runner) { RAMFile *file = RAMFile_new(NULL, false); OutStream *outstream = OutStream_open((Obj*)file); InStream *instream; char buf[4]; OutStream_Write_Bytes(outstream, "foo", 4); OutStream_Close(outstream); instream = InStream_open((Obj*)file); InStream_Read_Bytes(instream, buf, 4); TEST_TRUE(runner, strcmp(buf, "foo") == 0, "Read_Bytes Write_Bytes"); DECREF(instream); DECREF(outstream); DECREF(file); }
static void test_Buf(TestBatchRunner *runner) { RAMFile *file = RAMFile_new(NULL, false); OutStream *outstream = OutStream_open((Obj*)file); size_t size = IO_STREAM_BUF_SIZE * 2 + 5; InStream *instream; char *buf; for (uint32_t i = 0; i < size; i++) { OutStream_Write_U8(outstream, 'a'); } OutStream_Close(outstream); instream = InStream_open((Obj*)file); InStreamIVARS *const ivars = InStream_IVARS(instream); buf = InStream_Buf(instream, 5); TEST_INT_EQ(runner, ivars->limit - buf, IO_STREAM_BUF_SIZE, "Small request bumped up"); buf += IO_STREAM_BUF_SIZE - 10; // 10 bytes left in buffer. InStream_Advance_Buf(instream, buf); buf = InStream_Buf(instream, 10); TEST_INT_EQ(runner, ivars->limit - buf, 10, "Exact request doesn't trigger refill"); buf = InStream_Buf(instream, 11); TEST_INT_EQ(runner, ivars->limit - buf, IO_STREAM_BUF_SIZE, "Requesting over limit triggers refill"); int64_t expected = InStream_Length(instream) - InStream_Tell(instream); char *buff = InStream_Buf(instream, 100000); int64_t got = PTR_TO_I64(ivars->limit) - PTR_TO_I64(buff); TEST_TRUE(runner, got == expected, "Requests greater than file size get pared down"); DECREF(instream); DECREF(outstream); DECREF(file); }