blob: e7d32f23ad0cf855e48ce64407a0dfecd3436a8e [file] [log] [blame]
/* 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.
*/
#define C_TESTLUCY_TESTINSTREAM
#define C_LUCY_INSTREAM
#define C_LUCY_FILEWINDOW
#include <stdlib.h>
#include <time.h>
#include "charmony.h"
#define TESTLUCY_USE_SHORT_NAMES
#include "Lucy/Util/ToolSet.h"
#include "Clownfish/TestHarness/TestBatchRunner.h"
#include "Clownfish/TestHarness/TestUtils.h"
#include "Lucy/Test.h"
#include "Lucy/Test/TestUtils.h"
#include "Lucy/Test/Store/TestIOPrimitives.h"
#include "Lucy/Store/InStream.h"
#include "Lucy/Store/OutStream.h"
#include "Lucy/Store/RAMFile.h"
#include "Lucy/Store/RAMFileHandle.h"
#include "Lucy/Util/NumberUtils.h"
TestIOPrimitives*
TestIOPrimitives_new() {
return (TestIOPrimitives*)Class_Make_Obj(TESTIOPRIMITIVES);
}
static void
test_i8(TestBatchRunner *runner) {
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
int i;
for (i = -128; i < 128; i++) {
OutStream_Write_I8(outstream, (int8_t)i);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = -128; i < 128; i++) {
if (InStream_Read_I8(instream) != i) { break; }
}
TEST_INT_EQ(runner, i, 128, "round trip i8 successful for %d out of 256",
i + 128);
DECREF(instream);
DECREF(outstream);
DECREF(file);
}
static void
test_u8(TestBatchRunner *runner) {
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
int i;
for (i = 0; i < 256; i++) {
OutStream_Write_U8(outstream, (uint8_t)i);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 256; i++) {
if (InStream_Read_U8(instream) != i) { break; }
}
TEST_INT_EQ(runner, i, 256,
"round trip u8 successful for %d out of 256", i);
DECREF(instream);
DECREF(outstream);
DECREF(file);
}
static void
test_i32(TestBatchRunner *runner) {
int64_t *ints = TestUtils_random_i64s(NULL, 1000, INT32_MIN, INT32_MAX);
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
uint32_t i;
// Test boundaries.
ints[0] = INT32_MIN;
ints[1] = INT32_MIN + 1;
ints[2] = INT32_MAX;
ints[3] = INT32_MAX - 1;
for (i = 0; i < 1000; i++) {
OutStream_Write_I32(outstream, (int32_t)ints[i]);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 1000; i++) {
int32_t got = InStream_Read_I32(instream);
if (got != ints[i]) {
FAIL(runner, "i32 round trip failed: %ld, %ld", (long)got,
(long)ints[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "i32 round trip");
}
DECREF(instream);
DECREF(outstream);
DECREF(file);
FREEMEM(ints);
}
static void
test_u32(TestBatchRunner *runner) {
uint64_t *ints = TestUtils_random_u64s(NULL, 1000, 0, UINT32_MAX);
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
uint32_t i;
// Test boundaries.
ints[0] = 0;
ints[1] = 1;
ints[2] = UINT32_MAX;
ints[3] = UINT32_MAX - 1;
for (i = 0; i < 1000; i++) {
OutStream_Write_U32(outstream, (uint32_t)ints[i]);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 1000; i++) {
uint32_t got = InStream_Read_U32(instream);
if (got != ints[i]) {
FAIL(runner, "u32 round trip failed: %lu, %lu", (unsigned long)got,
(unsigned long)ints[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "u32 round trip");
}
DECREF(instream);
DECREF(outstream);
DECREF(file);
FREEMEM(ints);
}
static void
test_i64(TestBatchRunner *runner) {
int64_t *ints = TestUtils_random_i64s(NULL, 1000, INT64_MIN, INT64_MAX);
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
uint32_t i;
// Test boundaries.
ints[0] = INT64_MIN;
ints[1] = INT64_MIN + 1;
ints[2] = INT64_MAX;
ints[3] = INT64_MAX - 1;
for (i = 0; i < 1000; i++) {
OutStream_Write_I64(outstream, ints[i]);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 1000; i++) {
int64_t got = InStream_Read_I64(instream);
if (got != ints[i]) {
FAIL(runner, "i64 round trip failed: %" PRId64 ", %" PRId64,
got, ints[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "i64 round trip");
}
DECREF(instream);
DECREF(outstream);
DECREF(file);
FREEMEM(ints);
}
static void
test_u64(TestBatchRunner *runner) {
uint64_t *ints = TestUtils_random_u64s(NULL, 1000, 0, UINT64_MAX);
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
uint32_t i;
// Test boundaries.
ints[0] = 0;
ints[1] = 1;
ints[2] = UINT64_MAX;
ints[3] = UINT64_MAX - 1;
for (i = 0; i < 1000; i++) {
OutStream_Write_U64(outstream, ints[i]);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 1000; i++) {
uint64_t got = InStream_Read_U64(instream);
if (got != ints[i]) {
FAIL(runner, "u64 round trip failed: %" PRIu64 ", %" PRIu64,
got, ints[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "u64 round trip");
}
DECREF(instream);
DECREF(outstream);
DECREF(file);
FREEMEM(ints);
}
static void
test_ci32(TestBatchRunner *runner) {
int64_t *ints = TestUtils_random_i64s(NULL, 1000, INT32_MIN, INT32_MAX);
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
size_t i;
// Test boundaries.
ints[0] = 0;
ints[1] = 1;
ints[2] = -1;
ints[3] = INT32_MAX;
ints[4] = INT32_MIN;
for (i = 0; i < 1000; i++) {
OutStream_Write_CI32(outstream, (int32_t)ints[i]);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 1000; i++) {
int32_t got = InStream_Read_CI32(instream);
if ((int64_t)got != ints[i]) {
FAIL(runner, "ci32 round trip failed: %" PRId64 ", %" PRId64,
(int64_t)got, ints[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "ci32 round trip");
}
DECREF(instream);
DECREF(outstream);
DECREF(file);
FREEMEM(ints);
}
static void
test_cu32(TestBatchRunner *runner) {
uint64_t *ints = TestUtils_random_u64s(NULL, 1000, 0, UINT32_MAX);
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
uint32_t i;
// Test boundaries.
ints[0] = 0;
ints[1] = 1;
ints[2] = UINT32_MAX;
ints[3] = UINT32_MAX - 1;
for (i = 0; i < 1000; i++) {
OutStream_Write_CU32(outstream, (uint32_t)ints[i]);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 1000; i++) {
uint32_t got = InStream_Read_CU32(instream);
if (got != ints[i]) {
FAIL(runner, "cu32 round trip failed: %lu, %lu", (unsigned long)got,
(unsigned long)ints[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "cu32 round trip");
}
DECREF(instream);
DECREF(outstream);
DECREF(file);
FREEMEM(ints);
}
static void
test_ci64(TestBatchRunner *runner) {
int64_t *ints = TestUtils_random_i64s(NULL, 1000, INT64_MIN, INT64_MAX);
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
uint32_t i;
// Test boundaries.
ints[0] = 0;
ints[1] = 1;
ints[2] = -1;
ints[3] = INT64_MAX;
ints[4] = INT64_MIN;
for (i = 0; i < 1000; i++) {
OutStream_Write_CI64(outstream, ints[i]);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 1000; i++) {
int64_t got = InStream_Read_CI64(instream);
if (got != ints[i]) {
FAIL(runner, "ci64 round trip failed: %" PRId64 ", %" PRId64,
got, ints[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "ci64 round trip");
}
DECREF(instream);
DECREF(outstream);
DECREF(file);
FREEMEM(ints);
}
static void
test_cu64(TestBatchRunner *runner) {
uint64_t *ints = TestUtils_random_u64s(NULL, 1000, 0, UINT64_MAX);
RAMFile *file = RAMFile_new(NULL, false);
RAMFile *raw_file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
OutStream *raw_outstream = OutStream_open((Obj*)raw_file);
InStream *instream;
InStream *raw_instream;
uint32_t i;
// Test boundaries.
ints[0] = 0;
ints[1] = 1;
ints[2] = UINT64_MAX;
ints[3] = UINT64_MAX - 1;
for (i = 0; i < 1000; i++) {
OutStream_Write_CU64(outstream, ints[i]);
OutStream_Write_CU64(raw_outstream, ints[i]);
}
OutStream_Close(outstream);
OutStream_Close(raw_outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 1000; i++) {
uint64_t got = InStream_Read_CU64(instream);
if (got != ints[i]) {
FAIL(runner, "cu64 round trip failed: %" PRIu64 ", %" PRIu64,
got, ints[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "cu64 round trip");
}
raw_instream = InStream_open((Obj*)raw_file);
for (i = 0; i < 1000; i++) {
char buffer[10];
const char *buf = buffer;
int size = InStream_Read_Raw_C64(raw_instream, buffer);
uint64_t got = NumUtil_decode_cu64(&buf);
UNUSED_VAR(size);
if (got != ints[i]) {
FAIL(runner, "Read_Raw_C64 failed: %" PRIu64 ", %" PRIu64,
got, ints[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "Read_Raw_C64");
}
DECREF(raw_instream);
DECREF(instream);
DECREF(raw_outstream);
DECREF(outstream);
DECREF(raw_file);
DECREF(file);
FREEMEM(ints);
}
static void
test_f32(TestBatchRunner *runner) {
double *f64s = TestUtils_random_f64s(NULL, 1000);
float *values = (float*)MALLOCATE(1000 * sizeof(float));
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
uint32_t i;
// Truncate.
for (i = 0; i < 1000; i++) {
values[i] = (float)f64s[i];
}
// Test boundaries.
values[0] = 0.0f;
values[1] = 1.0f;
for (i = 0; i < 1000; i++) {
OutStream_Write_F32(outstream, values[i]);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 1000; i++) {
float got = InStream_Read_F32(instream);
if (got != values[i]) {
FAIL(runner, "f32 round trip failed: %f, %f", got, values[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "f32 round trip");
}
DECREF(instream);
DECREF(outstream);
DECREF(file);
FREEMEM(values);
FREEMEM(f64s);
}
static void
test_f64(TestBatchRunner *runner) {
double *values = TestUtils_random_f64s(NULL, 1000);
RAMFile *file = RAMFile_new(NULL, false);
OutStream *outstream = OutStream_open((Obj*)file);
InStream *instream;
uint32_t i;
// Test boundaries.
values[0] = 0.0;
values[1] = 1.0;
for (i = 0; i < 1000; i++) {
OutStream_Write_F64(outstream, values[i]);
}
OutStream_Close(outstream);
instream = InStream_open((Obj*)file);
for (i = 0; i < 1000; i++) {
double got = InStream_Read_F64(instream);
if (got != values[i]) {
FAIL(runner, "f64 round trip failed: %f, %f", got, values[i]);
break;
}
}
if (i == 1000) {
PASS(runner, "f64 round trip");
}
DECREF(instream);
DECREF(outstream);
DECREF(file);
FREEMEM(values);
}
void
TestIOPrimitives_Run_IMP(TestIOPrimitives *self, TestBatchRunner *runner) {
TestBatchRunner_Plan(runner, (TestBatch*)self, 13);
srand((unsigned int)time((time_t*)NULL));
test_i8(runner);
test_u8(runner);
test_i32(runner);
test_u32(runner);
test_i64(runner);
test_u64(runner);
test_ci32(runner);
test_cu32(runner);
test_ci64(runner);
test_cu64(runner);
test_f32(runner);
test_f64(runner);
}