blob: 06a422a7005dc6dd6e09bad7e68fbc4389ff3424 [file] [log] [blame]
/*
* Copyright 2010 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <stdio.h>
#include "native_client/src/shared/gio/gio_test_base.h"
#include "gtest/gtest.h"
#define EXPECT_RETCODE(_E_, _R_) \
EXPECT_EQ(_E_, _R_);
/* Uncomment and connect to above macro for debugging.
if (0 > _R_) { \
perror("Bad return code"); \
}
*/
char GioExpectedCharAt(char initial_char, int file_pos) {
return static_cast<char>(initial_char + file_pos);
}
void GioReadTestWithOffset(struct Gio* my_file,
char initial_char) {
char* out_buffer;
int out_size = 16;
ssize_t ret_code;
out_buffer = reinterpret_cast<char*>(malloc(out_size));
// mf_curpos = 0, 32 left, read 16
ret_code = my_file->vtbl->Read(my_file, out_buffer, 16);
EXPECT_RETCODE(16, ret_code);
for (int i = 0; i < 16; ++i)
EXPECT_EQ(GioExpectedCharAt(initial_char, i), out_buffer[i]);
// mf_curpos = 16, 16 left, read 10
ret_code = my_file->vtbl->Read(my_file, out_buffer, 10);
EXPECT_RETCODE(10, ret_code);
for (int i = 0; i < 10; ++i)
EXPECT_EQ(GioExpectedCharAt(initial_char, i + 16), out_buffer[i]);
// residual value after idx 10
EXPECT_EQ(GioExpectedCharAt(initial_char, 10), out_buffer[10]);
// mf_curpos = 26, 6 left, read 8
ret_code = my_file->vtbl->Read(my_file, out_buffer, 8);
EXPECT_RETCODE(6, ret_code);
for (int i = 0; i < 6; ++i)
EXPECT_EQ(GioExpectedCharAt(initial_char, i + 26), out_buffer[i]);
// residual value after idx 6
EXPECT_EQ(GioExpectedCharAt(initial_char, 16 + 6), out_buffer[6]);
// mf_curpos = 32, 0 left, read 16
ret_code = my_file->vtbl->Read(my_file, out_buffer, 16);
EXPECT_EQ(0, ret_code);
free(out_buffer);
}
/** Should be given a scratch file that can be written to without worry. */
void GioWriteTest(struct Gio* my_file,
bool fixed_length) {
char* in_buffer;
int in_size = 44;
char initial_char = 'A';
char out_char;
ssize_t ret_code;
in_buffer = reinterpret_cast<char*>(malloc(in_size));
for (int i = 0; i < in_size; ++i)
in_buffer[i] = GioExpectedCharAt(initial_char, i);
// mf_curpos = 0, 64 left, write 44
ret_code = my_file->vtbl->Write(my_file, in_buffer, in_size);
EXPECT_RETCODE(in_size, ret_code);
EXPECT_EQ(0, my_file->vtbl->Flush(my_file));
ret_code = my_file->vtbl->Seek(my_file, -1, SEEK_CUR);
EXPECT_RETCODE(in_size - 1, ret_code);
ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_EQ(1, ret_code);
EXPECT_EQ(GioExpectedCharAt(initial_char, in_size - 1), out_char);
// Windows *requires* hitting EOF before writing more.
// See _flsbuf in _flsbuf.c.
if (!fixed_length) {
ret_code = my_file->vtbl->Seek(my_file, 0, SEEK_END);
EXPECT_EQ(in_size, ret_code);
}
// mf_curpos = 44, 20 left, write 10
ret_code = my_file->vtbl->Write(my_file, in_buffer, 10);
EXPECT_RETCODE(10, ret_code);
EXPECT_EQ(0, my_file->vtbl->Flush(my_file));
// Sample a couple of other spots
// seek mf_curpos = 40
ret_code = my_file->vtbl->Seek(my_file, in_size - 4, SEEK_SET);
EXPECT_RETCODE(in_size - 4, ret_code);
ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_EQ(1, ret_code);
EXPECT_EQ(GioExpectedCharAt(initial_char, in_size - 4), out_char);
// mf_curpose = 41, advance by 12 and read to get back to 54
ret_code = my_file->vtbl->Seek(my_file, 12, SEEK_CUR);
EXPECT_RETCODE(in_size - 3 + 12, ret_code);
ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_EQ(1, ret_code);
EXPECT_EQ(GioExpectedCharAt(initial_char, 9), out_char);
// Back at the mf_curpos = 54
if (fixed_length) {
// mf_curpos = 54, 10 left, write 20
ret_code = my_file->vtbl->Write(my_file, in_buffer, 20);
EXPECT_RETCODE(10, ret_code);
my_file->vtbl->Seek(my_file, -1, SEEK_CUR);
my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_EQ(GioExpectedCharAt(initial_char, 9), out_char);
// mf_curpos = 64, 0 left, write 20
ret_code = my_file->vtbl->Write(my_file, in_buffer, 20);
EXPECT_RETCODE(0, ret_code);
}
free(in_buffer);
}
void GioSeekTestWithOffset(struct Gio* my_file,
char initial_char,
bool wrap_err) {
char out_char;
ssize_t ret_code;
// mf_curpos = 0
ret_code = my_file->vtbl->Seek(my_file, 15, SEEK_SET);
EXPECT_RETCODE(15, ret_code);
ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_RETCODE(1, ret_code);
EXPECT_EQ(GioExpectedCharAt(initial_char, 15), out_char);
// mf_curpos = 16
ret_code = my_file->vtbl->Seek(my_file, 4, SEEK_CUR);
EXPECT_RETCODE(20, ret_code);
ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_RETCODE(1, ret_code);
EXPECT_EQ(GioExpectedCharAt(initial_char, 20), out_char);
// mf_curpos = 21
ret_code = my_file->vtbl->Seek(my_file, -4, SEEK_CUR);
EXPECT_RETCODE(17, ret_code);
ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_RETCODE(1, ret_code);
EXPECT_EQ(GioExpectedCharAt(initial_char, 17), out_char);
// mf_curpos = 17
ret_code = my_file->vtbl->Seek(my_file, -4, SEEK_END);
EXPECT_RETCODE(28, ret_code);
my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_EQ(GioExpectedCharAt(initial_char, 28), out_char);
// At this point we try to seek out of bounds in various ways.
if (wrap_err) {
const int BAD_SEEK_WHENCE = SEEK_END + 3;
// mf_curpos = 29
ret_code = my_file->vtbl->Seek(my_file, 4, SEEK_END);
EXPECT_RETCODE(-1, ret_code);
my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_EQ(GioExpectedCharAt(initial_char, 29), out_char);
// mf_curpos = 30
ret_code = my_file->vtbl->Seek(my_file, 4, BAD_SEEK_WHENCE);
EXPECT_RETCODE(-1, ret_code);
my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_EQ(GioExpectedCharAt(initial_char, 30), out_char);
// mf_curpos = 31
ret_code = my_file->vtbl->Seek(my_file, -5, SEEK_SET);
EXPECT_RETCODE(-1, ret_code);
my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_EQ(GioExpectedCharAt(initial_char, 31), out_char);
} else {
// Not testing seek past end and then READING.
// mf_curpos = 29
ret_code = my_file->vtbl->Seek(my_file, -5, SEEK_SET);
EXPECT_RETCODE(-1, ret_code);
/* Different behavior on Windows vs Posix.
It appears that file_pos after a bad seek is undefined.
TODO(jvoung): Once gio library makes seek behavior standard,
we can re-enable this test. See:
http://code.google.com/p/nativeclient/issues/detail?id=850
my_file->vtbl->Read(my_file, &out_char, 1);
EXPECT_EQ(GioExpectedCharAt(initial_char, 29), out_char);
*/
}
}
void GioCloseTest(struct Gio* my_file) {
int ret_code;
ret_code = my_file->vtbl->Close(my_file);
EXPECT_RETCODE(0, ret_code);
my_file->vtbl->Dtor(my_file);
}