From 4f5203e661928cb5b69d07a27646f9b4a57b4a0a Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 16 Mar 2022 19:12:00 +0000 Subject: [PATCH] Fix some core:encoding/hxa stuff (error handling, header, max -> min) Also add missing f16 case to core:reflect as_u64 & as_f64 Add tests for above & add previous tests missing from test/core/build.bat --- core/encoding/hxa/read.odin | 29 ++- core/encoding/hxa/write.odin | 6 +- core/reflect/reflect.odin | 2 + tests/common/common.odin | 35 +++ tests/core/Makefile | 6 +- tests/core/assets/HXA/teapot.hxa | Bin 0 -> 21867 bytes tests/core/build.bat | 20 +- tests/core/encoding/hxa/test_core_hxa.odin | 232 +++++++++++++++++ tests/core/reflect/test_core_reflect.odin | 288 +++++++++++++++++++++ 9 files changed, 608 insertions(+), 10 deletions(-) create mode 100644 tests/core/assets/HXA/teapot.hxa create mode 100644 tests/core/encoding/hxa/test_core_hxa.odin create mode 100644 tests/core/reflect/test_core_reflect.odin diff --git a/core/encoding/hxa/read.odin b/core/encoding/hxa/read.odin index ef7edc8b7..abe295530 100644 --- a/core/encoding/hxa/read.odin +++ b/core/encoding/hxa/read.odin @@ -39,6 +39,9 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato read_value :: proc(r: ^Reader, $T: typeid) -> (value: T, err: Read_Error) { remaining := len(r.data) - r.offset if remaining < size_of(T) { + if r.print_error { + fmt.eprintf("file '%s' failed to read value at offset %v\n", r.filename, r.offset) + } err = .Short_Read return } @@ -51,6 +54,10 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato read_array :: proc(r: ^Reader, $T: typeid, count: int) -> (value: []T, err: Read_Error) { remaining := len(r.data) - r.offset if remaining < size_of(T)*count { + if r.print_error { + fmt.eprintf("file '%s' failed to read array of %d elements at offset %v\n", + r.filename, count, r.offset) + } err = .Short_Read return } @@ -82,7 +89,8 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato type := read_value(r, Meta_Value_Type) or_return if type > max(Meta_Value_Type) { if r.print_error { - fmt.eprintf("HxA Error: file '%s' has meta value type %d. Maximum value is ", r.filename, u8(type), u8(max(Meta_Value_Type))) + fmt.eprintf("HxA Error: file '%s' has meta value type %d. Maximum value is %d\n", + r.filename, u8(type), u8(max(Meta_Value_Type))) } err = .Invalid_Data return @@ -114,7 +122,8 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato type := read_value(r, Layer_Data_Type) or_return if type > max(type) { if r.print_error { - fmt.eprintf("HxA Error: file '%s' has layer data type %d. Maximum value is ", r.filename, u8(type), u8(max(Layer_Data_Type))) + fmt.eprintf("HxA Error: file '%s' has layer data type %d. Maximum value is %d\n", + r.filename, u8(type), u8(max(Layer_Data_Type))) } err = .Invalid_Data return @@ -134,13 +143,23 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato } if len(data) < size_of(Header) { + if print_error { + fmt.eprintf("HxA Error: file '%s' has no header\n", filename) + } + err = .Short_Read return } context.allocator = allocator header := cast(^Header)raw_data(data) - assert(header.magic_number == MAGIC_NUMBER) + if (header.magic_number != MAGIC_NUMBER) { + if print_error { + fmt.eprintf("HxA Error: file '%s' has invalid magic number 0x%x\n", filename, header.magic_number) + } + err = .Invalid_Data + return + } r := &Reader{ filename = filename, @@ -150,6 +169,7 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato } node_count := 0 + file.header = header^ file.nodes = make([]Node, header.internal_node_count) defer if err != nil { nodes_destroy(file.nodes) @@ -162,7 +182,8 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato type := read_value(r, Node_Type) or_return if type > max(Node_Type) { if r.print_error { - fmt.eprintf("HxA Error: file '%s' has node type %d. Maximum value is ", r.filename, u8(type), u8(max(Node_Type))) + fmt.eprintf("HxA Error: file '%s' has node type %d. Maximum value is %d\n", + r.filename, u8(type), u8(max(Node_Type))) } err = .Invalid_Data return diff --git a/core/encoding/hxa/write.odin b/core/encoding/hxa/write.odin index e774018b2..5bb950e81 100644 --- a/core/encoding/hxa/write.odin +++ b/core/encoding/hxa/write.odin @@ -84,7 +84,7 @@ write_internal :: proc(w: ^Writer, file: File) { write_metadata :: proc(w: ^Writer, meta_data: []Meta) { for m in meta_data { - name_len := max(len(m.name), 255) + name_len := min(len(m.name), 255) write_value(w, u8(name_len)) write_string(w, m.name[:name_len]) @@ -127,7 +127,7 @@ write_internal :: proc(w: ^Writer, file: File) { write_layer_stack :: proc(w: ^Writer, layers: Layer_Stack) { write_value(w, u32(len(layers))) for layer in layers { - name_len := max(len(layer.name), 255) + name_len := min(len(layer.name), 255) write_value(w, u8(name_len)) write_string(w, layer .name[:name_len]) @@ -152,7 +152,7 @@ write_internal :: proc(w: ^Writer, file: File) { return } - write_value(w, &Header{ + write_value(w, Header{ magic_number = MAGIC_NUMBER, version = LATEST_VERSION, internal_node_count = u32le(len(file.nodes)), diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index d05026532..49d7ef9b5 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -1054,6 +1054,7 @@ as_u64 :: proc(a: any) -> (value: u64, valid: bool) { case Type_Info_Float: valid = true switch v in a { + case f16: value = u64(v) case f32: value = u64(v) case f64: value = u64(v) case f32le: value = u64(v) @@ -1159,6 +1160,7 @@ as_f64 :: proc(a: any) -> (value: f64, valid: bool) { case Type_Info_Float: valid = true switch v in a { + case f16: value = f64(v) case f32: value = f64(v) case f64: value = (v) case f32le: value = f64(v) diff --git a/tests/common/common.odin b/tests/common/common.odin index 9a715d38e..07b6afef9 100644 --- a/tests/common/common.odin +++ b/tests/common/common.odin @@ -4,6 +4,7 @@ package common import "core:testing" import "core:fmt" import "core:os" +import "core:strings" TEST_count := 0 TEST_fail := 0 @@ -38,3 +39,37 @@ report :: proc(t: ^testing.T) { fmt.printf("%v/%v tests successful.\n", TEST_count, TEST_count) } } + +// Returns absolute path to `sub_path` where `sub_path` is within the "tests/" sub-directory of the Odin project root +// and we're being run from the Odin project root or from a sub-directory of "tests/" +// e.g. get_data_path("assets/blah") will return "/Odin_root/tests/assets/blah" if run within "/Odin_root", +// "/Odin_root/tests" or "/Odin_root/tests/subdir" etc +get_data_path :: proc(t: ^testing.T, sub_path: string) -> (data_path: string) { + + cwd := os.get_current_directory() + defer delete(cwd) + + when ODIN_OS == .Windows { + norm, was_allocation := strings.replace_all(cwd, "\\", "/") + if !was_allocation { + norm = strings.clone(norm) + } + defer delete(norm) + } else { + norm := cwd + } + + last_index := strings.last_index(norm, "/tests/") + if last_index == -1 { + len := len(norm) + if len >= 6 && norm[len-6:] == "/tests" { + data_path = fmt.tprintf("%s/%s", norm, sub_path) + } else { + data_path = fmt.tprintf("%s/tests/%s", norm, sub_path) + } + } else { + data_path = fmt.tprintf("%s/tests/%s", norm[:last_index], sub_path) + } + + return data_path +} diff --git a/tests/core/Makefile b/tests/core/Makefile index 1158434bf..a990c5833 100644 --- a/tests/core/Makefile +++ b/tests/core/Makefile @@ -2,7 +2,7 @@ ODIN=../../odin PYTHON=$(shell which python3) all: download_test_assets image_test compress_test strings_test hash_test crypto_test noise_test encoding_test \ - math_test linalg_glsl_math_test + math_test linalg_glsl_math_test reflect_test download_test_assets: $(PYTHON) download_assets.py @@ -26,6 +26,7 @@ noise_test: $(ODIN) run math/noise -out=test_noise encoding_test: + $(ODIN) run encoding/hxa -out=test_hxa -collection:tests=.. $(ODIN) run encoding/json -out=test_json $(ODIN) run encoding/varint -out=test_varint @@ -34,3 +35,6 @@ math_test: linalg_glsl_math_test: $(ODIN) run math/linalg/glsl/test_linalg_glsl_math.odin -out=test_linalg_glsl_math -collection:tests=.. + +reflect_test: + $(ODIN) run reflect/test_core_reflect.odin -out=test_core_reflect -collection:tests=.. diff --git a/tests/core/assets/HXA/teapot.hxa b/tests/core/assets/HXA/teapot.hxa new file mode 100644 index 0000000000000000000000000000000000000000..954ab5a1012cee96592adde842c6e88f8783aab7 GIT binary patch literal 21867 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 b61V|dQGP@o#B*$a{=nR3{sf%+761Jo9F4Mr literal 0 HcmV?d00001 diff --git a/tests/core/build.bat b/tests/core/build.bat index 0227ac6bb..c94aac10a 100644 --- a/tests/core/build.bat +++ b/tests/core/build.bat @@ -1,5 +1,5 @@ @echo off -set COMMON=-show-timings -no-bounds-check -vet -strict-style +set COMMON=-show-timings -no-bounds-check -vet -strict-style -collection:tests=.. set PATH_TO_ODIN==..\..\odin python3 download_assets.py echo --- @@ -35,10 +35,26 @@ echo --- echo --- echo Running core:encoding tests echo --- +%PATH_TO_ODIN% run encoding/hxa %COMMON% %PATH_TO_ODIN% run encoding/json %COMMON% %PATH_TO_ODIN% run encoding/varint %COMMON% echo --- echo Running core:math/noise tests echo --- -%PATH_TO_ODIN% run math/noise %COMMON% \ No newline at end of file +%PATH_TO_ODIN% run math/noise %COMMON% + +echo --- +echo Running core:math tests +echo --- +%PATH_TO_ODIN% run math %COMMON% + +echo --- +echo Running core:math/linalg/glsl tests +echo --- +%PATH_TO_ODIN% run math/linalg/glsl %COMMON% + +echo --- +echo Running core:reflect tests +echo --- +%PATH_TO_ODIN% run reflect %COMMON% diff --git a/tests/core/encoding/hxa/test_core_hxa.odin b/tests/core/encoding/hxa/test_core_hxa.odin new file mode 100644 index 000000000..b93562fd5 --- /dev/null +++ b/tests/core/encoding/hxa/test_core_hxa.odin @@ -0,0 +1,232 @@ +// Tests "core:encoding:hxa". +// Must be run with `-collection:tests=` flag, e.g. +// ./odin run tests/core/encoding/hxa/test_core_hxa.odin -out=tests/core/test_core_hxa -collection:tests=./tests +package test_core_hxa + +import "core:encoding/hxa" +import "core:fmt" +import "core:testing" +import tc "tests:common" + +TEAPOT_PATH :: "core/assets/HXA/teapot.hxa" + +main :: proc() { + t := testing.T{} + + test_read(&t) + test_write(&t) + + tc.report(&t) +} + +@test +test_read :: proc(t: ^testing.T) { + + using hxa + + filename := tc.get_data_path(t, TEAPOT_PATH) + defer delete(filename) + + file, err := read_from_file(filename) + e :: hxa.Read_Error.None + tc.expect(t, err == e, fmt.tprintf("%v: read_from_file(%v) -> %v != %v", #procedure, filename, err, e)) + defer file_destroy(file) + + /* Header */ + tc.expect(t, file.magic_number == 0x417848, fmt.tprintf("%v: file.magic_number %v != %v", + #procedure, file.magic_number, 0x417848)) + tc.expect(t, file.version == 1, fmt.tprintf("%v: file.version %v != %v", + #procedure, file.version, 1)) + tc.expect(t, file.internal_node_count == 1, fmt.tprintf("%v: file.internal_node_count %v != %v", + #procedure, file.internal_node_count, 1)) + + /* Nodes (only one) */ + tc.expect(t, len(file.nodes) == 1, fmt.tprintf("%v: len(file.nodes) %v != %v", #procedure, len(file.nodes), 1)) + + m := &file.nodes[0].meta_data + tc.expect(t, len(m^) == 38, fmt.tprintf("%v: len(m^) %v != %v", #procedure, len(m^), 38)) + { + e :: "Texture resolution" + tc.expect(t, m[0].name == e, fmt.tprintf("%v: m[0].name %v != %v", #procedure, m[0].name, e)) + + m_v, m_v_ok := m[0].value.([]i64le) + tc.expect(t, m_v_ok, fmt.tprintf("%v: m_v_ok %v != %v", #procedure, m_v_ok, true)) + tc.expect(t, len(m_v) == 1, fmt.tprintf("%v: len(m_v) %v != %v", #procedure, len(m_v), 1)) + tc.expect(t, m_v[0] == 1024, fmt.tprintf("%v: m_v[0] %v != %v", #procedure, len(m_v), 1024)) + } + { + e :: "Validate" + tc.expect(t, m[37].name == e, fmt.tprintf("%v: m[37].name %v != %v", #procedure, m[37].name, e)) + + m_v, m_v_ok := m[37].value.([]i64le) + tc.expect(t, m_v_ok, fmt.tprintf("%v: m_v_ok %v != %v", #procedure, m_v_ok, true)) + tc.expect(t, len(m_v) == 1, fmt.tprintf("%v: len(m_v) %v != %v", #procedure, len(m_v), 1)) + tc.expect(t, m_v[0] == -2054847231, fmt.tprintf("%v: m_v[0] %v != %v", #procedure, len(m_v), -2054847231)) + } + + /* Node content */ + v, v_ok := file.nodes[0].content.(hxa.Node_Geometry) + tc.expect(t, v_ok, fmt.tprintf("%v: v_ok %v != %v", #procedure, v_ok, true)) + + tc.expect(t, v.vertex_count == 530, fmt.tprintf("%v: v.vertex_count %v != %v", #procedure, v.vertex_count, 530)) + tc.expect(t, v.edge_corner_count == 2026, fmt.tprintf("%v: v.edge_corner_count %v != %v", + #procedure, v.edge_corner_count, 2026)) + tc.expect(t, v.face_count == 517, fmt.tprintf("%v: v.face_count %v != %v", #procedure, v.face_count, 517)) + + /* Vertex stack */ + tc.expect(t, len(v.vertex_stack) == 1, fmt.tprintf("%v: len(v.vertex_stack) %v != %v", + #procedure, len(v.vertex_stack), 1)) + { + e := "vertex" + tc.expect(t, v.vertex_stack[0].name == e, fmt.tprintf("%v: v.vertex_stack[0].name %v != %v", + #procedure, v.vertex_stack[0].name, e)) + } + tc.expect(t, v.vertex_stack[0].components == 3, fmt.tprintf("%v: v.vertex_stack[0].components %v != %v", + #procedure, v.vertex_stack[0].components, 3)) + + /* Vertex stack data */ + vs_d, vs_d_ok := v.vertex_stack[0].data.([]f64le) + tc.expect(t, vs_d_ok, fmt.tprintf("%v: vs_d_ok %v != %v", #procedure, vs_d_ok, true)) + tc.expect(t, len(vs_d) == 1590, fmt.tprintf("%v: len(vs_d) %v != %v", #procedure, len(vs_d), 1590)) + + tc.expect(t, vs_d[0] == 4.06266, fmt.tprintf("%v: vs_d[0] %v (%h) != %v (%h)", + #procedure, vs_d[0], vs_d[0], 4.06266, 4.06266)) + tc.expect(t, vs_d[1] == 2.83457, fmt.tprintf("%v: vs_d[1] %v (%h) != %v (%h)", + #procedure, vs_d[1], vs_d[1], 2.83457, 2.83457)) + tc.expect(t, vs_d[2] == 0hbfbc5da6a4441787, fmt.tprintf("%v: vs_d[2] %v (%h) != %v (%h)", + #procedure, vs_d[2], vs_d[2], + 0hbfbc5da6a4441787, 0hbfbc5da6a4441787)) + tc.expect(t, vs_d[3] == 0h4010074fb549f948, fmt.tprintf("%v: vs_d[3] %v (%h) != %v (%h)", + #procedure, vs_d[3], vs_d[3], + 0h4010074fb549f948, 0h4010074fb549f948)) + tc.expect(t, vs_d[1587] == 0h400befa82e87d2c7, fmt.tprintf("%v: vs_d[1587] %v (%h) != %v (%h)", + #procedure, vs_d[1587], vs_d[1587], + 0h400befa82e87d2c7, 0h400befa82e87d2c7)) + tc.expect(t, vs_d[1588] == 2.83457, fmt.tprintf("%v: vs_d[1588] %v (%h) != %v (%h)", + #procedure, vs_d[1588], vs_d[1588], 2.83457, 2.83457)) + tc.expect(t, vs_d[1589] == -1.56121, fmt.tprintf("%v: vs_d[1589] %v (%h) != %v (%h)", + #procedure, vs_d[1589], vs_d[1589], -1.56121, -1.56121)) + + /* Corner stack */ + tc.expect(t, len(v.corner_stack) == 1, + fmt.tprintf("%v: len(v.corner_stack) %v != %v", #procedure, len(v.corner_stack), 1)) + { + e := "reference" + tc.expect(t, v.corner_stack[0].name == e, fmt.tprintf("%v: v.corner_stack[0].name %v != %v", + #procedure, v.corner_stack[0].name, e)) + } + tc.expect(t, v.corner_stack[0].components == 1, fmt.tprintf("%v: v.corner_stack[0].components %v != %v", + #procedure, v.corner_stack[0].components, 1)) + + /* Corner stack data */ + cs_d, cs_d_ok := v.corner_stack[0].data.([]i32le) + tc.expect(t, cs_d_ok, fmt.tprintf("%v: cs_d_ok %v != %v", #procedure, cs_d_ok, true)) + tc.expect(t, len(cs_d) == 2026, fmt.tprintf("%v: len(cs_d) %v != %v", #procedure, len(cs_d), 2026)) + tc.expect(t, cs_d[0] == 6, fmt.tprintf("%v: cs_d[0] %v != %v", #procedure, cs_d[0], 6)) + tc.expect(t, cs_d[2025] == -32, fmt.tprintf("%v: cs_d[2025] %v != %v", #procedure, cs_d[2025], -32)) + + /* Edge and face stacks (empty) */ + tc.expect(t, len(v.edge_stack) == 0, fmt.tprintf("%v: len(v.edge_stack) %v != %v", + #procedure, len(v.edge_stack), 0)) + tc.expect(t, len(v.face_stack) == 0, fmt.tprintf("%v: len(v.face_stack) %v != %v", + #procedure, len(v.face_stack), 0)) +} + +@test +test_write :: proc(t: ^testing.T) { + + using hxa + + n1 :Node + + n1_m1_value := []f64le{0.4, -1.23, 2341.6, -333.333} + n1_m1 := Meta{"m1", n1_m1_value} + + n1.meta_data = []Meta{n1_m1} + + n1_l1 := Layer{"l1", 2, []f32le{32.1, -41.3}} + n1_l2 := Layer{"l2", 3, []f64le{0.64, 1.64, -2.64}} + + n1_content := Node_Image{Image_Type.Image_1D, [3]u32le{1, 1, 2}, Layer_Stack{n1_l1, n1_l2}} + + n1.content = n1_content + + w_file :File + w_file.nodes = []Node{n1} + + required_size := required_write_size(w_file) + buf := make([]u8, required_size) + + n, write_err := write(buf, w_file) + write_e :: hxa.Write_Error.None + tc.expect(t, write_err == write_e, fmt.tprintf("%v: write_err %v != %v", #procedure, write_err, write_e)) + tc.expect(t, n == required_size, fmt.tprintf("%v: n %v != %v", #procedure, n, required_size)) + + file, read_err := read(buf) + read_e :: hxa.Read_Error.None + tc.expect(t, read_err == read_e, fmt.tprintf("%v: read_err %v != %v", #procedure, read_err, read_e)) + defer file_destroy(file) + + delete(buf) + + tc.expect(t, file.magic_number == 0x417848, fmt.tprintf("%v: file.magic_number %v != %v", + #procedure, file.magic_number, 0x417848)) + tc.expect(t, file.version == 3, fmt.tprintf("%v: file.version %v != %v", #procedure, file.version, 3)) + tc.expect(t, file.internal_node_count == 1, fmt.tprintf("%v: file.internal_node_count %v != %v", + #procedure, file.internal_node_count, 1)) + + tc.expect(t, len(file.nodes) == len(w_file.nodes), fmt.tprintf("%v: len(file.nodes) %v != %v", + #procedure, len(file.nodes), len(w_file.nodes))) + + m := &file.nodes[0].meta_data + w_m := &w_file.nodes[0].meta_data + tc.expect(t, len(m^) == len(w_m^), fmt.tprintf("%v: len(m^) %v != %v", #procedure, len(m^), len(w_m^))) + tc.expect(t, m[0].name == w_m[0].name, fmt.tprintf("%v: m[0].name %v != %v", #procedure, m[0].name, w_m[0].name)) + + m_v, m_v_ok := m[0].value.([]f64le) + tc.expect(t, m_v_ok, fmt.tprintf("%v: m_v_ok %v != %v", #procedure, m_v_ok, true)) + tc.expect(t, len(m_v) == len(n1_m1_value), fmt.tprintf("%v: %v != len(m_v) %v", + #procedure, len(m_v), len(n1_m1_value))) + for i := 0; i < len(m_v); i += 1 { + tc.expect(t, m_v[i] == n1_m1_value[i], fmt.tprintf("%v: m_v[%d] %v != %v", + #procedure, i, m_v[i], n1_m1_value[i])) + } + + v, v_ok := file.nodes[0].content.(hxa.Node_Image) + tc.expect(t, v_ok, fmt.tprintf("%v: v_ok %v != %v", #procedure, v_ok, true)) + tc.expect(t, v.type == n1_content.type, fmt.tprintf("%v: v.type %v != %v", #procedure, v.type, n1_content.type)) + tc.expect(t, len(v.resolution) == 3, fmt.tprintf("%v: len(v.resolution) %v != %v", + #procedure, len(v.resolution), 3)) + tc.expect(t, len(v.image_stack) == len(n1_content.image_stack), fmt.tprintf("%v: len(v.image_stack) %v != %v", + #procedure, len(v.image_stack), len(n1_content.image_stack))) + for i := 0; i < len(v.image_stack); i += 1 { + tc.expect(t, v.image_stack[i].name == n1_content.image_stack[i].name, + fmt.tprintf("%v: v.image_stack[%d].name %v != %v", + #procedure, i, v.image_stack[i].name, n1_content.image_stack[i].name)) + tc.expect(t, v.image_stack[i].components == n1_content.image_stack[i].components, + fmt.tprintf("%v: v.image_stack[%d].components %v != %v", + #procedure, i, v.image_stack[i].components, n1_content.image_stack[i].components)) + + switch n1_t in n1_content.image_stack[i].data { + case []u8: + tc.expect(t, false, fmt.tprintf("%v: n1_content.image_stack[i].data []u8", #procedure)) + case []i32le: + tc.expect(t, false, fmt.tprintf("%v: n1_content.image_stack[i].data []i32le", #procedure)) + case []f32le: + l, l_ok := v.image_stack[i].data.([]f32le) + tc.expect(t, l_ok, fmt.tprintf("%v: l_ok %v != %v", #procedure, l_ok, true)) + tc.expect(t, len(l) == len(n1_t), fmt.tprintf("%v: len(l) %v != %v", #procedure, len(l), len(n1_t))) + for j := 0; j < len(l); j += 1 { + tc.expect(t, l[j] == n1_t[j], fmt.tprintf("%v: l[%d] %v (%h) != %v (%h)", + #procedure, j, l[j], l[j], n1_t[j], n1_t[j])) + } + case []f64le: + l, l_ok := v.image_stack[i].data.([]f64le) + tc.expect(t, l_ok, fmt.tprintf("%v: l_ok %v != %v", #procedure, l_ok, true)) + tc.expect(t, len(l) == len(n1_t), fmt.tprintf("%v: len(l) %v != %v", #procedure, len(l), len(n1_t))) + for j := 0; j < len(l); j += 1 { + tc.expect(t, l[j] == n1_t[j], fmt.tprintf("%v: l[%d] %v != %v", #procedure, j, l[j], n1_t[j])) + } + } + } +} diff --git a/tests/core/reflect/test_core_reflect.odin b/tests/core/reflect/test_core_reflect.odin new file mode 100644 index 000000000..039501735 --- /dev/null +++ b/tests/core/reflect/test_core_reflect.odin @@ -0,0 +1,288 @@ +// Tests "core:reflect/reflect". +// Must be run with `-collection:tests=` flag, e.g. +// ./odin run tests/core/reflect/test_core_reflect.odin -out=tests/core/test_core_reflect -collection:tests=./tests +package test_core_reflect + +import "core:fmt" +import "core:reflect" +import "core:testing" +import tc "tests:common" + +main :: proc() { + t := testing.T{} + + test_as_u64(&t) + test_as_f64(&t) + + tc.report(&t) +} + +@test +test_as_u64 :: proc(t: ^testing.T) { + using reflect + + { + /* i8 */ + Datum :: struct { i: int, v: i8, e: u64 } + @static data := []Datum{ + { 0, 0x7F, 0x7F }, + { 1, -1, 0xFFFF_FFFF_FFFF_FFFF }, + { 2, -0x80, 0xFFFF_FFFF_FFFF_FF80 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_u64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(i8 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(i8 %v) -> %v (0x%X) != %v (0x%X)\n", + i, #procedure, d.v, r, r, d.e, d.e)) + } + } + { + /* i16 */ + Datum :: struct { i: int, v: i16, e: u64 } + @static data := []Datum{ + { 0, 0x7FFF, 0x7FFF }, + { 1, -1, 0xFFFF_FFFF_FFFF_FFFF }, + { 2, -0x8000, 0xFFFF_FFFF_FFFF_8000 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_u64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(i16 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(i16 %v) -> %v (0x%X) != %v (0x%X)\n", + i, #procedure, d.v, r, r, d.e, d.e)) + } + } + { + /* i32 */ + Datum :: struct { i: int, v: i32, e: u64 } + @static data := []Datum{ + { 0, 0x7FFF_FFFF, 0x7FFF_FFFF }, + { 1, -1, 0xFFFF_FFFF_FFFF_FFFF }, + { 2, -0x8000_0000, 0xFFFF_FFFF_8000_0000 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_u64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(i32 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(i32 %v) -> %v (0x%X) != %v (0x%X)\n", + i, #procedure, d.v, r, r, d.e, d.e)) + } + } + { + /* i64 */ + Datum :: struct { i: int, v: i64, e: u64 } + @static data := []Datum{ + { 0, 0x7FFF_FFFF_FFFF_FFFF, 0x7FFF_FFFF_FFFF_FFFF }, + { 1, -1, 0xFFFF_FFFF_FFFF_FFFF }, + { 2, -0x8000_0000_0000_0000, 0x8000_0000_0000_0000 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_u64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(i64 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(i64 %v) -> %v (0x%X) != %v (0x%X)\n", + i, #procedure, d.v, r, r, d.e, d.e)) + } + } + { + /* i128 */ + Datum :: struct { i: int, v: i128, e: u64 } + @static data := []Datum{ + { 0, 0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF }, + { 1, -1, 0xFFFF_FFFF_FFFF_FFFF }, + { 2, 0x8000_0000_0000_0000, 0x8000_0000_0000_0000 }, + { 3, -0x8000_0000_0000_0000, 0x8000_0000_0000_0000 }, + { 4, 0x0001_0000_0000_0000_0000, 0 }, + { 5, -0x8000_0000_0000_0000_0000_0000_0000_0000, 0 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_u64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(i128 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(i128 %v) -> %v (0x%X) != %v (0x%X)\n", + i, #procedure, d.v, r, r, d.e, d.e)) + } + } + { + /* f16 */ + Datum :: struct { i: int, v: f16, e: u64 } + @static data := []Datum{ + { 0, 1.2, 1 }, + { 1, 123.12, 123 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_u64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(f16 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(f16 %v) -> %v != %v\n", i, #procedure, d.v, r, d.e)) + } + } + { + /* f32 */ + Datum :: struct { i: int, v: f32, e: u64 } + @static data := []Datum{ + { 0, 123.3415, 123 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_u64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(f32 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(f32 %v) -> %v != %v\n", i, #procedure, d.v, r, d.e)) + } + } + { + /* f64 */ + Datum :: struct { i: int, v: f64, e: u64 } + @static data := []Datum{ + { 0, 12345345345.3415234234, 12345345345 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_u64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(f64 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(f64 %v) -> %v != %v\n", i, #procedure, d.v, r, d.e)) + } + } +} + +@test +test_as_f64 :: proc(t: ^testing.T) { + using reflect + + { + /* i8 */ + Datum :: struct { i: int, v: i8, e: f64 } + @static data := []Datum{ + { 0, 0x7F, 0x7F }, + { 1, -1, -1 }, + { 2, -0x80, -0x80 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_f64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(i8 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(i8 %v) -> %v != %v\n", i, #procedure, d.v, r, d.e)) + } + } + { + /* i16 */ + Datum :: struct { i: int, v: i16, e: f64 } + @static data := []Datum{ + { 0, 0x7FFF, 0x7FFF }, + { 1, -1, -1 }, + { 2, -0x8000, -0x8000 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_f64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(i16 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(i16 %v) -> %v != %v\n", i, #procedure, d.v, r, d.e)) + } + } + { + /* i32 */ + Datum :: struct { i: int, v: i32, e: f64 } + @static data := []Datum{ + { 0, 0x7FFF_FFFF, 0x7FFF_FFFF }, + { 1, -1, -1 }, + { 2, -0x8000_0000, -0x8000_0000 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_f64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(i32 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(i32 %v) -> %v != %v\n", i, #procedure, d.v, r, d.e)) + } + } + { + /* i64 */ + Datum :: struct { i: int, v: i64, e: f64 } + @static data := []Datum{ + { 0, 0x7FFF_FFFF_FFFF_FFFF, 0x7FFF_FFFF_FFFF_FFFF }, + { 1, -1, -1 }, + { 2, -0x8000_0000_0000_0000, -0x8000_0000_0000_0000 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_f64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(i64 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(i64 %v) -> %v != %v\n", i, #procedure, d.v, r, d.e)) + } + } + { + /* i128 */ + Datum :: struct { i: int, v: i128, e: f64 } + @static data := []Datum{ + { 0, 0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, 0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF }, + { 1, -1, -1 }, + { 2, 0x8000_0000_0000_0000_0000_0000_0000, 0x8000_0000_0000_0000_0000_0000_0000 }, + { 3, -0x8000_0000_0000_0000_0000_0000_0000_0000, -0x8000_0000_0000_0000_0000_0000_0000_0000 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_f64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(i128 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(i128 %v) -> %v (%H) != %v (%H)\n", + i, #procedure, d.v, r, r, d.e, d.e)) + } + } + { + /* f16 */ + Datum :: struct { i: int, v: f16, e: f64 } + @static data := []Datum{ + { 0, 1.2, 0h3FF3_3400_0000_0000 }, // Precision difference TODO: check + { 1, 123.12, 0h405E_C800_0000_0000 }, // Precision difference TODO: check + } + + for d, i in data { + assert(i == d.i) + r, valid := as_f64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(f16 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(f16 %v (%H)) -> %v (%H) != %v (%H)\n", + i, #procedure, d.v, d.v, r, r, d.e, d.e)) + } + } + { + /* f32 */ + Datum :: struct { i: int, v: f32, e: f64 } + @static data := []Datum{ + { 0, 123.3415, 0h405E_D5DB_2000_0000 }, // Precision difference TODO: check + } + + for d, i in data { + assert(i == d.i) + r, valid := as_f64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(f32 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(f32 %v (%H)) -> %v (%H) != %v (%H)\n", + i, #procedure, d.v, d.v, r, r, d.e, d.e)) + } + } + { + /* f64 */ + Datum :: struct { i: int, v: f64, e: f64 } + @static data := []Datum{ + { 0, 12345345345.3415234234, 12345345345.3415234234 }, + } + + for d, i in data { + assert(i == d.i) + r, valid := as_f64(d.v) + tc.expect(t, valid, fmt.tprintf("i:%d %s(f64 %v) !valid\n", i, #procedure, d.v)) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(f64 %v) -> %v != %v\n", i, #procedure, d.v, r, d.e)) + } + } +}