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 zcmeaMaAaU)V1QsX1_lP9kkpEj(xOy_qSWI2oYIoa{5-HE0}BHf2nVMYBo-x>q$*@2 z7NsbprlhA9Llm^Ow*LSB|38~!aY1Tw2}BI6g@J)9v^Z5EFTW@^F$XNp2vsZYUzS>w zlUShOnUb1Ul9`;Cqfn4oRDx=t7)()aW>HaoQECbnHFBiQ zsYNBJ6$;_0IVoTxVG@FFIf*3-!TD(=3dN;GX^F|HDAKIX`FYS#g6ZG_2`L1DYzHfa z1{4EZa7j^S0jjm^0f{Ba8E6Ku1>_{68_EH4MqX+$L^}fm!vRo)u==JJrK38C8!V)d zlbM@|7Eu93sk*_r`S~RoU}wRc%MJEhX92zmAj(O=hsR~Jn#i=O@X*r1{sd=!tgBikx#cjMn zsRfCdMG9D?*dS71ufSZ)9$Z+OScK+g)}Yj!#0nI3qF^CV1m!7YmZTPeSr9K7L1T-} zwW1&~50Vt1LJZ8#r4V1ioXj3vQj}Vfj2fP-zMv=t+Xqu85tLY5l3J8m1-1x1`#C_( z7YayB&d$tBM|To5cQSBp1?If46^nE5PvFd|tS{;m;)|?7jER-o>X=rAm?yZm;gC zoC%(8-|c&^1zu$lr|gK^E$+P zpJ2C@{sT8Z^LKdItSNjB%LI*o+qi9oi|0&DD75&D5Qo{Dmm>GGxe*}_vv+~lS-A{W zez-X>^;$}YweE2Uz{O$yV!h$MeBB%Y2mkd`Qah4=?uUuP{2Ryf)MYos7N9UhQLptB1ueOYxT!r8pp3-4I@N&;Fy}-Y$aQ`~3&AeCG#eU$m4D+VzyAkorv${h0vj@ik^!Qa{%*whc z#d)B1;)Q9&E5F0jbImK42xg%@);Jt=;bpke$neASb9dUk6`H;y*`4aXY~3A zmY&h;BUpOoj{73Iq*B;nLU4)7^!nfSu>7c;tzOAu0z4r|+zHVDm{ms9EaPzOR1b%1q_+!uh`oGMx z)xvP|MNMb4Jyia0U%|%vSNM(y-29CE53MJsFgW!6Ie4JhUleY>;F*h$zkg$J*uF(d z==%+B2blZgj+7@|^X773N)2B3A&(Dk{_>Iy|IR<;aggd>wt2Fm0Ni}Rj_Y5!xA8e} z>V;iNs1ksi|LLrm`Lc9=2MI-+TNX+G?P2CO+D%mVG#7Mu#`V5PP@WNP{;eXtqoGfQ z9FD|KHhrbY1UKKi&w6RIsE9+>o|4HDElhCp>rL4?o^^=8>o1u3cb_Wl6W%NY7l(!a zx0e-X99j|TVc`!duK%7Bg{y~!|G7U|d;&gV4w|!zTFZC-*$*=x=Kh=gA`=s*{@)KX zALjnaR*b$aXBiH_%!j$(YWky9oAenEz|4oae;=ql(!zBBW^b(14{kmz{AFgk|4UfF4>unc{^Cm{yO#wE!p(=JpMo3PG&VB|!_9}Kp9h~0 zb38N@ftwFYKf<&7vz?cUz|DuHpCa$oiiPKe;O4{9^Ku4>^9vS=z|Dt=t2y}UM!yz? zn-3FDO8Q)wn;`}_A103O{yWt>p6s~%e?PkW`LF%AJQL1%0Nwp>wU+!@62)`?-Tjl> zTca-TVLE^w{txQ4Z*COiIe;GiS_UbltC#Z~Ko9?QAN0gO+6o*%5C3_S@0stLCU5{f z{W#0Keq<&kbO1g5%n9gda6Tb?06qQiff{^2L=K>*9~Dsfk}V3aUtsBH!Qq-p#%aQE zaaj7f4rVeUuIzcBZs zmp`!ZM=yV1;g4Saz``HB{DFl(die=UKj`HrEd8LDpRn|UUVg&T52NsoQgeMV2Ubu8 zuFG@)mToz^m|z}OzJ)J@1?v!j}%Wj7aG9M;cbH4!wkspWx- zpZfgZ-I`hvxcOO2mVPR8VQ{e6d4HkC1|hilbCVsuRh9p>UsiW7WXU4|xcTXIrtBPP zzu^5TnE9~wXBRlY`QhdpeYjJ-Lxs!D}A4`OmC+w}ixTJG58Ue0pJhnfGl zW9tu*20^$u%zRisXiEOJorbjx2VmyI-TyPO<-?1=`(ft8+`mgCd}{6WU;AO^!`u&R zAHvLsxqp(ZbYn#=`CT$c5Nmb&mee2iuO6969hl7xH@}hd&aT<&U+oKcbEYO3GQrKiY46X>=K0Eg zZ%@+BrJ)>fbLRYed(D2R=7Edt691a-(+@>D>A;*;Qz-S=FSXo!{DdA zY`GWv>-yjJF#nb^&Ek;0$LnDBN>S>r;}3h7e5-%$y*d?OUXRc;M<`?s?htYnr7jlY`F3hE1B+f9!{u19J~(*hz5a z*ZnYaVD6a)9&dTQA7&2BJx5Od<#T0ZKL9fa7Cv2NqCs^+EC*obz`|#@IzRW;Wk2EO zz`|$#*;VJSit)kCfyLLZy-N(E+_~W9z~ZaIi~aTgI}8V4?t#VE7lGb)3Sk0pb719R z&G+NgSG#!N=D@_gH(1R18Oj7V2PTg09&q~j__^l=$5(Z|dO(9<)_ zJ?QBf<{tF)408{9{(^-Mdj5ii4|@KBg%5guhs76qeuu>uSRN_A!{UprrcOffj^Kf5 zeAoV4`uu^9KPX>&6wII_e&Al&!kvD~2=PSG{1iD!=>y>L8y3Vk#z#$tW5yk_2SCkL z?%&_x=DY}s3H=r;cc75j&b~+B6I}dc$iWp$)(IYH<@H}b<>_DhfAsA4^{G#E-ej`N9hm!N-^Z=bf563?#A{hI zpCRmpnSUW>`NU~nf(H!136H^HPQJ_cHLoAouUCE2Ja4V|0k0XEzr&{?#F;s}UFylH0QWCU{q>aIs*Yy@2j+t6 z*K#HYn0vl-+Ia3_lQ_@=YX1fz#Fv8VTV>e;8g)H8vppH%>K#-6{O*xfIG}02^4rTF zh;XnvGhIAkKEhs@`LOnqSbmD!PiJQM{Ek)W)6F*e5(iYl1tCIw$)6>+mN&~DU{6_J zUjK&?uDCO?qsMQ0V_CZh^NaoH@e312k6)NLdi=t~(c>2;j-H-j?mCB&oFWH z^b8Yczid$B@<#T+cR4-FcT*n1^VhAezp39_WDcBVXR(@Wb{IZRI5}&6-*FzP0~@W1 zmKYnnhKu7GSJ}ZhU*0W4?tmntXrIE=`|$h~b$QQYk-IVn>^JSqnx}kjKPL|T$P3|0`2)Kb|9={_fcXraj!2%T~Dux9#}cwTy*7zzi{z| z8W+?*xhNcn-V-6AwER5W{YOCqPYH4dTq1f^*YrMyyXU~Eg|6E+OC5leo8RE##@!ZgrcsTz7 zjo)69I`F$Pcp_Kw54gC{)oA8uSJ49xH7ZN{91-IK=96Gu-!FmX^bIBlh{!(GLr44rBl;Nd@c z;^qy@WhEU#&Bg0)3*Uf?gU9Qtq#e-fBZ1?)cJv;TamcU_a%l@?fR}rq;#`wM9zM?t zE8k%DMsshza4z%m{trjih&x-pvrm2(A=@|{@THVyX;S`_1v!d>6LvB%cIi2 zOfn9U-}_r%2)wtS1{$x}^Vr^gqPpkx99f6|(I@+Q5B#@3-1M7~pXa7MxSzzM0JqmO zr=0&n?InAdy~kRa6(bLP+`s;up+fcEFZMab$yJAnq#Qn5@H|^T;r{+eleu$w`aao* zztP{Vt}hE8Ki^z?B6?ljYkMcV7dO}3l5>dJxc|+(J%8=bw3$wIefZGcE#7g~Mhiu_ zy`NkJo=G;OuzwaaOL57^{V@N=wN9BI5-sPz*6KLZ zZSqC9e;1dAm^!K`IB1;)h4^o{fA`Io(!ZOc1h*I6zv%e_WbNJK(hiDDd<(tKeud{F z&~k?3kL4UP!?y8Pp56Hc94_M^wI3wR>o z$A0wq1^0s_zwO6}-?P0hIlVvbM~~mBGtyPp{&=w;J$_wHb~WFa`2=n+EIq^gi=Lig z{zXsEF#n>bXPAG{(=*J!JRAD`VsFYj1l%`TetHo*Jm1y4ovF%brQqn) zcu{}?hWhkMxjS=35%~ockNs&nv(D8iIDp6F*ReZnv8_5>`{aT>C^@JfR&e0|{FL=3cS^sF@>LR`f)CE{o_!hBfxqr2ZL@!n$};rsj1-5+J2Z8GZ=yv&XkCOp^IvpLg`%rs_|EaP^ne+WoC2KC!=bXU4n@E&_1zSJ$uk z|G)Xf-n#0~y=C>haB+dNHanL&yoZ}#?6S{$rT0a9fmcecn?AgSn;-VRz}iITg1y|G zxm$1RJ%*c~_Dl8A+RwY~`7Z@O5h#2NH{bDwW*G0GJ@(tKt}))X{sr9p6;I~eaISu2 zKYO#?(-~`?!_DtLq}L@^@zB0{VZ+;mBlqCu$AQMZqA%G$?n(5!pmrZ_{;^e#Gj8v_ zWIs{u9^{i(z4j|+6v!oMZ^ z-HZC2ci`f%@ZStBpYPhgZDrclEO>c8%zT*p&l_xA%J=Ewewg_%_p3C_KHA-Sa6im^ znEQqD=hp9jb8tV*e3<)FS@-iA#yy6c4-0>f#{v7fqaVS|hlT$&hNTPL6tBR|hlRi0 z8<0bunsj_!W0 z45gfks{8xV-TxNcFu%7S-TelO-p<&ieRV&&`K zkDh++{MrBNgy56?=;`Oor&7s(!B6(1r~f5ppb_kkaB*1rREWE-f1~#UTpX4@``lNy zsFys2i^J0A(jPxs-t2k0A3guV+>f4rVeUuIzcBZs=UTn+(j?k87oM%2siIF_^OTOrop!qPuzx$2dQFL3j3yzeYs zRddrmN!O0`zz;^a`4jhfUS9CxrF|viw~H%ZbHL5FS&(x|^xh|X&~kwl@44aacJTVn z{IB+_I2XNR7We=+-#{-kv-|Z+`v&lY+;4lB`yuB1u>Z;yKf@=K8E*d7ikE7JCm0<* zN6up}U(O0Qe>!MFREovn_lql2&wqLZH=k)1hxEL-kM`hYe|#U{=Cj+*4xOLP-~bx_ z5C8Gi9u__kpke7ac8A0q#S@O5Kj7{-Fk1D}^t7gqsgbKZYD@WTKWZ9DunWmVQ9ZW6$aA zaPuMdezHH$uiWB3n+t9}Ed5MT=`>!AS z(Zm1m{KGYsjUV=-hySIZO6x#Mk7$qA zt1tV}(@)P2zcW>aOa~zLBGS*|Gi)7(ikmGv59G|6iPefdM22GUM(4|NkWz7#KieAT!?l z|Nmc#fq_91YR0So|Nl!fFff3`KxVxB|Np-X0|Ns{3}nWO|NsBXGB7ZJ#6V^||NsBL zA_D`10#wc8|Ns9hF)%QI#6W5u{r~@8g@J)VnSp^pj)8&U!Tk(6zcB*?18Aob$c&5s|Nl2(U|;}=fy}t@|Nnne1_lO@ z7|4wC|Ns9tV_;waiGj>G_y7NY3kC)TbEp|-{{R1P$-uw>5(AlW`v3p`RtyXbATf{` zr~d!{Z_U8K01^Y4aq|EF|F#Sa3^q_Rj{pDv-;RNS0VD=89_1_p1a89V;}|L@DdzyJ~hnX&!<|Nnjr3=AMKkQv+l|NrmLz`y_!1DUb) z|NsA>d(ATu`q|NkG94?$ueGdBJI|DTzGfdM22GGpWa|NlW-xIkhcGdBGH|38F* zfdQ0fLE`KG|NkG#z`y_!3t(ViSoi<`|1bsy29Q`F0|Ud_|NsAoGcYiK#DW+Y7}os% z|389(fdQ0fL1wJ}|Nnm^0|Ns{3}nWt|Ns9-F)%QI#6V`O{Qv)dGy?+zNDO4givR!r z$1pH3fbuNJjOG9T|Bq#0U;v4M%vkpS|Nl4!1_qEA$c&}`|NoC?U|;}=fy`L)|Ns94 z1_lODo&}k)`2YX^i3|)3ATf{`i~j%rpTxkx01^Y4vGD)@|H%vt3?MO(84LdZ|DVFZ zzyQj#AT#Fw|NlRgfq?-e1~Oyb|NsBf7#J8pVjwf-{{R0!oq>S?BnC2L&j0`aGZ+{c zKzSNu#_a$9|7S8VFo48BX3YBk|9=((0|Q75WX8<@|Nmz*Fff3`KxWMN|Nnmu0|Nsn zPlL>u{{R2~Tm}XPkQm5}Y5)KK&tqU<0EvOjnELGNbwb|No5) z3=AMKkQq(?|Nn1dU|;}=fy`+9|Nnn80|Ns{3}i;b|NsA67#J8pc^YI!{r~^}TNxM_ zKw=;>>i+-#-^Ree01^Y6@&Et-b_NCpkQm5}n*aa*cQ7z8fbulRjOzdY|93JlFo48B zW>o$E|G$fYfdM22GNbbU|Nq?#3=AMKkQo*K|Nrk{U|;~{X^0 z`~Uxc9|HpeNDO2~>Hq)#`xzJ*Kw=;>O8)=<56Y*YybCg;`2YX^pnM7v1DR3u|Nnnb zJ_U(^%qaZ-|9>z80|Q75WJbaN|No~jFff4fG)O%E|Ns9}85kHqViQ2=?EnA&(-;^S zKw=X?>G1#m|I-;57(il^K7#Ki#8e~TH|NsAIGB7ZJ#6V_b{r~@e76StV zNDO2~=KufyXEQJ`fW$y%Wc>gCe+~l!11L{}%t-(L|NmSD1_qEA$c(iA|NqZpU|;}= zfy_w#|NsAd1_lO@7|4v2|Ns9lU|?VXt~ z|9>?D0|Q75WJbjQ|Nqx8Fff4fG{}tb|NsB51(mB%Gs6D=|Gy4Y?n2E7{r~^}dQiCx zH6!Hz|Nk2p7#Ki#8e~TB|Ns9tGB7ZJ#6ac-{r~@e69WSSNDO3d;Q#;sH#0CWfW$!N z2K@j3e+vTx11L{}%<%vJ|NmA71_qEA$PB;#|Nn1eU|;}=fz0sz|NsAX1_lO@7|0Bt z|NsB*U|?VX`xzJ*Kw=;>T>k(6 ze}I930hFgfW;p-<|NkIpLpsz9r~m)|A7Wr&0EvOjaQy%O|6v9O29OxY42S>!{~uvs zU;yQ5kQw&>|NlSAz`y_!1DR|0|NsAE3=9k)F_0Oy|Ns9#&cMI`5(AlG^Z)<<6ATOt zpgavS!}|aK|0fw37(ikmGpzpq|9^^sfdM22GQ;x!|No~M7#KieATuof|Nno6fq?;( zr$J_z|NsC0ECT}rNDO3#+5i9l&oMACfW$y%nEwC&|2zW&14s;HhROf`|3Uc_ly^a9 z82|tOACyl)Vjwe&{{R0E%BLVPkQs*m|No!Nz`y_!1DRp)|Ns9h3=9mQJPi`p|NsC0 zRR#tIkk|!KJMjPi|JN887(ikdLG8r<|NmcRU|;}=>Hh!!|2hK$11LX(^lShB|NjO9 z0|Q75q+jd*|Nl1`7#KieApM$9y&y3V`xXNO11K+p^lSY8|Nk}v0|Q75q+k92|NnOw z7#KieApL4ky&y3V`z`|m11KMZ^sD~=|NkBX0|Q75q+jL#|Nr+H7#KieApOcvy&y3V z`vC(311JxJ^eg@U|NkMV-3`^R`2YX^M+^)MATf}B1*l$-7>NCtfq?;(e?j`?|NsC0 zgn@wpBnC25?*IS)PZ<~(Kw=>MvQWJsF%bJ10|Nsn?}GHp{Qv*|IRgU&NDQQ3`v3p` zFBljYKw=>MQc%4hF%bJD0|Nsn--7f@{{R2~6$1kUNDQQ3;{X5uuNfE^Kw=>M;!wRH zF%bI=0|Nsn&w})e{r~^}Edv7sNDQQ3^#A|=?-&>uKw=>MB2c{`F%bJb0|Nsnzk>7& z|NsC00|NsCNDQQ3=>Px!9~l@JKw=>Mf>6C6F%bI`0|NsnuY&Xo{Qv*|GXnzyNDQQ( z|NsC0UlMd{Dh0F%bJJ0|NsnpMv!B{{R2~8v_FaNDQQ(=l}oz-x(MfKw=>M z+)%wBF%bI)0|NsnkAn1b{r~^}Cj$cmNDQQ(^Z)<M98kR=F%bJV0|Nsn ze}eS0|NsC052z0d)z9|-|Npwbf=*@tu|atal>b2b8UO$P56WvGF_3(Mg|5xsG6_;{{I(bWMB}0s`>oy|9=ri1_oiM znh*c}{}*FqU=W3>dH3)Ce{n_z29Ov?-`jux|4T43Fo48_7#SGe{QLi3l97P{BnC3$ z^}qlBr5PC*q@ZTJ{P+LA3?l;rNDO4gi+}(B%Q7-BfW$y%JpcFqzZ@e214s;H#pfCriIrs1Xe=|k~29Ov?&Dnqd|64LLFo41o zq~_GW|NpHR85lrfAT=ld{r_*x$iM&+1L-^Q@Be=rMg|6um^mW@!|{Lr|JyP$Fo41o zWX7?7|Nq-DGBAL|KxQ2M_y4~=BLf3S3}nWUfB*kGFfuTJ#6V^o{`ddCBO?O?D9k}- z9QybFzY`+^14s;H#=(F8|GP3WFo41wq-Nj0|Nq?>85lrfAT@jc{r?XNCs5dd)a?5A z|34_4Kw=;@JOBOv4+v z|NjFS85jZ>85q1785lPI`~N?Pk%0ju=EKOqu<76b{~?SF48c%68~*+OAIZqT5CIii z{qO((I7SABSg6>tfB*l-GcquM#6aqn{`>zwfsug$Bo@WUz_8@s|NqI13=Bz7Jq!Q+ z|DVFhzyJ~h=~?ja|Nm4*1_qEANYDI#|Nmz&GBBh=_00MA|9=)E14AZM&8&a_|K~C? zFyuhhO#k=)zZcYRAhAjR{{IL01LU_nMh1on|Nj5?Wn^FgiRCjgF!cZX|G%7(fuW3% zfuV?zfuZN$|Nr%j3=DOQ3=FOR{{OFHWMHUfWMF9c_y2!0BLhPdBLhR@zyJS1@*s6J z|Nj4PXJlY#V`N~c{rCSrNFJoF;@|)O-HZ$jU5pG2mH+<#2g!rfmHhkvzn_tTp^uS) zq4eMX{~&pgx`KcI{})5u0FndoCo(cHOal4!-~a#985tO+LHRlV{{NrB$iM&+o6N|- zkp1uf|Cx*o3?Q*7j0_A}|Nj36=>@4z{rCU>Y(@r#Sy25M|Nj4FkV{r|rdlpdh^LdUC|G%7(fnga` zf6TxC|5q?FFo48B`lJ8-|G$!vfdM22GBXOQ7oLG?%c`~QCpBLf3S z45UB&-~az>85tNrVj%rtP`x1af&c#hU(d+Eunwv}M!Ti7Tm|NmA-1_qEANWULc? zc18wGy)_1*v!a_y7NHMh1pmQ2ieN{{P>@ z$iM&+1DWam@Bjb3j0_AQF_3;Ys9unI$AAC-?`LFS*ay|`^6&ru1B?s|ATf}B=YRkI zA7o@;0EvP0J3;k=)Z701|Nk%}1H&Pxeusbm{~uvwU;v4M^xOaY|Nkf>0|Q75q~8vz z7o^_u-~a!|85tOkLG|1G`~Uw0sBDGmxBmD4|4Bv$29Ov?zZFz3NWJO5|Nl=jGBBKi z>bLm!|Nj|A1_qEA$V~Hp|Noz5WMBY^f%Ka}^@7wJ{`>#`JR<|cIjDYNDQRk2&xyPKKI}M|De1E%8wwv!N33iL3s@%2GXzp@Bja)j0_AQ zF_3<}fB*kqV`N|e@ui){`dd?O;CLa zs`D5b7_|QV|9^{-fdP~^L1t+F`~UwoBLf3S3}lAJzyJU5FfuTJ#6V`K|NH;{E+Yd2 zNDO4I+Q0w*?=dnkfbu8E4Ap=C|KDe1U;v4M%uxCF|NjF<1_qEA$PDFw|NlQ^WMBY^ zfy_|)_y7MRMg|5@9tD}9`0xM!$BYaNATf{`3jhB9f5OPX01^Y4A^-3H|EG)$3?MO( z8FK&r|9{5FzyQjpATwnD{r~@*k%0ju1~NnD-~azF7#SEqVjwf5|NZ~}l97P{BnC1= z>fitWuNWB^KzS8phUCBh|6emQFo48BW=Q<||Njjm0|Q75WQO>^|Nq~D+DlL~#Qy#N z|BjJ?0hC`sW{Cd#|NlKB0|Q75WQNGU|NlQQGBAL|KxPR4`~UwVBLf3S3}mj*zyJR~ zf$B%78G`@*|NqR$zyJ~hnIZ7+|Nk$H3=AMKkQw~{{{R2V$iM&+1DV11@BjaAj0_B* zd<)9=y#N0H|IWz301^Y4!SnC`{~wGD3?MO(8QlN=|NqIzzyJ~hnZfn%|Nmc%3=E*W z3o?WA-~a!=LG4ed865xq|NjGOpF+)G|M&m@Ur_rMY6jcC|Ns9nGBAMhFUSm5&_om? z0|Q75WG>6U|NlXQ+@Qg5kh#qN{{LqL4SF*%Fo4Wu0=4s)7#Ki#7-R+`sGY~ez`(== zF#|NQ#lpnEz|6$J05aqM-~azvnHU&AVjy$>{r&%+jfsH)l#fAX{Qdj?KRXix14s;H z#-G3c|8p=gFo48BX8iv9|34=a0|Q75WX7+*|NnC_F))DgGRTadfB*mIW@2CfiGj@c z@%R6K9wr6`kQm5}?|=XQ=VfAG0EvOj`1beze?BG#22g$mnep}S|Ns0<3=AMKkQrb8 z{{Jt)#J~U&1DWyp@BjaTObiSlF_0Ob{{H_D%BP^b3o_&5-~azX`4l7uGULPF|NpOm z+M}ShC=&z2`@jGHUxnsfkQwj({{OGY$iM(Sut&zyJIHA4G%tBA~tth!5&NfcPMBka|$N(wUKg z0o3jTwF^OQP!Jy^4r*t*FfuTBK;`#9+o>QikeUO~cDD&51A{TBO#Ju%KZtF?$iM(< z2cP-(|363^)b<9o)h|HX*&seh9MoA^|9?0m149_J?Ys8h|NkI$AU;TZ@xTB7 zL2QuQKyBr9|Nj36wP!(mkT|Ga+snwnP{_!@0BT=?+LfU8B!~|d|M&kti0*{82@C)I z{||B}hz}A6sc&UuU;yz!;vn~c+J+!LNF3CL1ksJqHYkV>ayN(%5(lXVv1_4iS5R9t z2Gk}6wO2uHuz&ymgXAh185lrqT2LDn|4-#MT@Be?0 zUqF12IH+F$YBPiQAo1RR|NoaTGB8vyGBAMJ)1Y?r1V#o1kQk_43u@2yfZE@nxB-bn z+sz%IHaC %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)) + } + } +}