aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHolger Lindner <mole.coding@googlemail.com>2022-03-22 17:24:40 +0100
committerHolger Lindner <mole.coding@googlemail.com>2022-03-22 17:24:40 +0100
commit64601ac439c715a3d478775b6b761f22586038cb (patch)
treebc9080090b176d4e86d108c681e1b4537a74b1e9
parentedce27812f191f23846f55cc6359f30e3be45c82 (diff)
parent0446d9721b6dab157f4e15412b069871414c12e9 (diff)
Merge remote-tracking branch 'origin/master'
-rw-r--r--core/encoding/hxa/read.odin29
-rw-r--r--core/encoding/hxa/write.odin6
-rw-r--r--core/reflect/reflect.odin2
-rw-r--r--tests/common/common.odin35
-rw-r--r--tests/core/Makefile6
-rw-r--r--tests/core/assets/HXA/teapot.hxabin0 -> 21867 bytes
-rw-r--r--tests/core/build.bat20
-rw-r--r--tests/core/encoding/hxa/test_core_hxa.odin232
-rw-r--r--tests/core/reflect/test_core_reflect.odin288
9 files changed, 608 insertions, 10 deletions
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 := "<input>", 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 := "<input>", 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 := "<input>", 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 := "<input>", 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 := "<input>", 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 := "<input>", 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 := "<input>", 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 000000000..954ab5a10
--- /dev/null
+++ b/tests/core/assets/HXA/teapot.hxa
Binary files differ
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))
+ }
+ }
+}