Files
gram/tests/helpers.odin

227 lines
5.3 KiB
Odin

package tests
import "core:fmt"
import "core:os"
import "core:testing"
import "gram:chunks"
import "gram:file"
TEST_INPUT_DIR :: "./build/tests/in"
TEST_OUTPUT_DIR :: "./build/tests/out"
// -----------------------------------------
Test_State :: struct {
input_dir: string,
output_dir: string,
working_dir: string,
}
// -----------------------------------------
test_state_init :: proc(
t: ^testing.T,
name: string,
allocator := context.allocator,
) -> Test_State {
ensure_dir(t, TEST_INPUT_DIR)
ensure_dir(t, TEST_OUTPUT_DIR)
// Use the test name as the pattern so parallel tests with the same
// RNG seed generate distinct temp directory names.
temp_input_path, err := os.mkdir_temp(TEST_INPUT_DIR, name, allocator)
testing.expect(t, err == nil, os.error_string(err))
temp_output_path, err2 := os.mkdir_temp(TEST_OUTPUT_DIR, name, allocator)
testing.expect(t, err2 == nil, os.error_string(err2))
working_dir, err3 := os.get_working_directory(context.allocator)
testing.expect(t, err3 == nil, os.error_string(err3))
return Test_State {
input_dir = temp_input_path,
output_dir = temp_output_path,
working_dir = working_dir,
}
}
test_state_destroy :: proc(
ts: ^Test_State,
t: ^testing.T,
allocator := context.allocator,
) {
if os.exists(ts.input_dir) {
err := os.remove_all(ts.input_dir)
testing.expect(t, err == nil, os.error_string(err))
}
delete(ts.input_dir, allocator)
if os.exists(ts.output_dir) {
err := os.remove_all(ts.output_dir)
testing.expect(t, err == nil, os.error_string(err))
}
delete(ts.output_dir, allocator)
}
// -----------------------------------------
ensure_dir :: proc(t: ^testing.T, dir: string) {
err := os.make_directory_all(dir)
testing.expect(t, err == nil || err == .Exist, os.error_string(err)) // TOCTOU safe
}
create_file :: proc(
ts: ^Test_State,
t: ^testing.T,
path: string,
content: string,
is_output_file := false,
allocator := context.allocator,
) {
relpath, err := os.join_path(
{!is_output_file ? ts.input_dir : ts.output_dir, path},
allocator,
)
testing.expect(t, err == nil, os.error_string(err))
defer delete(relpath, allocator)
dir := os.dir(relpath)
err2 := os.make_directory_all(dir)
testing.expect(t, err2 == nil || err2 == .Exist, os.error_string(err2)) // TOCTOU safe
file, err3 := os.create(relpath)
testing.expect(t, err3 == nil, os.error_string(err3))
defer os.close(file)
_, err4 := os.write(file, transmute([]u8)content)
testing.expect(t, err4 == nil, os.error_string(err4))
}
delete_path :: proc(
ts: ^Test_State,
t: ^testing.T,
path: string,
allocator := context.allocator,
) {
relpath, err := os.join_path({ts.input_dir, path}, allocator)
defer delete(relpath, allocator)
testing.expect(t, err == nil, os.error_string(err))
if os.exists(relpath) {
err2 := os.remove_all(relpath)
testing.expect(t, err2 == nil, os.error_string(err2))
}
}
pack :: proc(
ts: ^Test_State,
t: ^testing.T,
size: u64,
compression: u16 = 0,
) -> (
wa_err: chunks.Error,
wm_err: chunks.Error,
) {
entries, err := file.list_dir_recursive_by_path(
ts.input_dir,
ts.working_dir,
)
testing.expect(t, err == nil, file.error_string(err))
w := chunks.writer_init(cast(u64)len(entries))
defer chunks.writer_destroy(&w)
output_file, err2 := os.open(ts.output_dir, {.Read})
testing.expect(t, err2 == nil, os.error_string(err2))
defer os.close(output_file)
wa_err = chunks.write_assets(
&w,
output_file,
entries[:],
size,
compression,
)
if wa_err != nil do return wa_err, nil
wm_err = chunks.write_metadata(
&w,
output_file,
entries[:],
size,
compression,
)
return wa_err, wm_err
}
read_asset :: proc(
ts: ^Test_State,
t: ^testing.T,
path: string,
allocator := context.allocator,
) -> (
bool,
string,
) {
relpath, err := os.join_path({ts.input_dir, path}, allocator)
testing.expect(t, err == nil, os.error_string(err))
defer delete(relpath, allocator)
file, err2 := os.open(ts.output_dir, {.Read})
testing.expect(t, err2 == nil, os.error_string(err2))
defer os.close(file)
r, err3 := chunks.reader_init(file)
testing.expect(t, err3 == nil, chunks.error_string(err3))
defer chunks.reader_destroy(&r)
exists, i, err4 := chunks.asset_exists(&r, relpath)
testing.expect(t, err4 == nil, chunks.error_string(err4))
if exists {
bytes, err5 := chunks.read_asset(&r, relpath)
testing.expect(t, err5 == nil, chunks.error_string(err5))
return true, string(bytes)
}
return false, {}
}
read_asset_raw :: proc(
ts: ^Test_State,
t: ^testing.T,
path: string,
allocator := context.allocator,
) -> (
bytes: []u8,
err: chunks.Error,
) {
relpath, err2 := os.join_path({ts.input_dir, path}, allocator)
testing.expect(t, err2 == nil, os.error_string(err2))
defer delete(relpath, allocator)
output_file, err3 := os.open(ts.output_dir, {.Read})
testing.expect(t, err3 == nil, os.error_string(err3))
defer os.close(output_file)
r, err4 := chunks.reader_init(output_file)
testing.expect(t, err4 == nil, chunks.error_string(err4))
defer chunks.reader_destroy(&r)
bytes, err = chunks.read_asset(&r, relpath)
return bytes, err
}
reader_init_raw :: proc(ts: ^Test_State, t: ^testing.T) -> chunks.Error {
output_file, err2 := os.open(ts.output_dir, {.Read})
testing.expect(t, err2 == nil, os.error_string(err2))
defer os.close(output_file)
r, err := chunks.reader_init(output_file)
defer chunks.reader_destroy(&r)
return err
}