add unit tests
This commit is contained in:
@@ -36,6 +36,15 @@ Character_Data :: struct {
|
||||
height: int,
|
||||
}
|
||||
|
||||
parse_char_def :: proc(file_data: []u8) -> (Char_Def, bool) {
|
||||
def: Char_Def
|
||||
if err := json.unmarshal(file_data, &def); err != nil {
|
||||
fmt.eprintfln("json unmarshal failed: %v", err)
|
||||
return {}, false
|
||||
}
|
||||
return def, true
|
||||
}
|
||||
|
||||
load_character_data :: proc(app: ^App, character_json_path: string) -> (Character_Data, bool) {
|
||||
file_data, read_err := os.read_entire_file(character_json_path, context.allocator)
|
||||
if read_err != nil {
|
||||
@@ -46,8 +55,9 @@ load_character_data :: proc(app: ^App, character_json_path: string) -> (Characte
|
||||
defer delete(file_data)
|
||||
|
||||
out: Character_Data
|
||||
if err := json.unmarshal(file_data, &out.def); err != nil {
|
||||
fmt.eprintfln("json unmarshal failed: %v", err)
|
||||
ok: bool
|
||||
out.def, ok = parse_char_def(file_data)
|
||||
if !ok {
|
||||
return {}, false
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package engine
|
||||
|
||||
import "core:testing"
|
||||
|
||||
@(test)
|
||||
parse_char_def_happy_path :: proc(t: ^testing.T) {
|
||||
src := transmute([]u8)string(
|
||||
`{"version":1,"id":"toad","atlas":"toad.atlas.png","pixels_per_unit":160.0,"pivot":[0.5,1.0],"clips":{"idle":{"loop":true,"fps":8.0,"frames":[{"rect":[1,2,3,4],"source_size":[3,4],"trim_offset":[0,0]}]}}}`,
|
||||
)
|
||||
|
||||
def, ok := parse_char_def(src)
|
||||
defer destroy_char_def(&def)
|
||||
|
||||
testing.expect(t, ok)
|
||||
testing.expect_value(t, def.id, "toad")
|
||||
testing.expect_value(t, def.atlas, "toad.atlas.png")
|
||||
testing.expect_value(t, def.version, 1)
|
||||
testing.expect_value(t, def.pixels_per_unit, f32(160.0))
|
||||
testing.expect_value(t, def.pivot[0], f32(0.5))
|
||||
testing.expect_value(t, def.pivot[1], f32(1.0))
|
||||
|
||||
idle, found := def.clips["idle"]
|
||||
testing.expect(t, found)
|
||||
testing.expect(t, idle.loop)
|
||||
testing.expect_value(t, idle.fps, f32(8.0))
|
||||
testing.expect_value(t, len(idle.frames), 1)
|
||||
testing.expect_value(t, idle.frames[0].rect, [4]int{1, 2, 3, 4})
|
||||
}
|
||||
|
||||
@(test)
|
||||
parse_char_def_bad_json :: proc(t: ^testing.T) {
|
||||
_, ok := parse_char_def(transmute([]u8)string("{ not json"))
|
||||
testing.expect(t, !ok)
|
||||
}
|
||||
|
||||
@(test)
|
||||
character_frame_rect_hit_and_miss :: proc(t: ^testing.T) {
|
||||
data: Character_Data
|
||||
data.def.clips = make(map[string]Clip_Def)
|
||||
defer delete(data.def.clips)
|
||||
|
||||
frames := make([]Frame_Def, 2)
|
||||
frames[0] = {rect = {10, 20, 30, 40}}
|
||||
frames[1] = {rect = {50, 60, 70, 80}}
|
||||
defer delete(frames)
|
||||
|
||||
data.def.clips["idle"] = Clip_Def {
|
||||
loop = true,
|
||||
fps = 10,
|
||||
frames = frames,
|
||||
}
|
||||
|
||||
rect, ok := character_frame_rect(&data, "idle", 1)
|
||||
testing.expect(t, ok)
|
||||
testing.expect_value(t, rect, [4]int{50, 60, 70, 80})
|
||||
|
||||
_, ok = character_frame_rect(&data, "missing", 0)
|
||||
testing.expect(t, !ok)
|
||||
|
||||
_, ok = character_frame_rect(&data, "idle", -1)
|
||||
testing.expect(t, !ok)
|
||||
|
||||
_, ok = character_frame_rect(&data, "idle", 2)
|
||||
testing.expect(t, !ok)
|
||||
}
|
||||
|
||||
destroy_char_def :: proc(def: ^Char_Def) {
|
||||
if def == nil do return
|
||||
|
||||
keys := make([dynamic]string, context.temp_allocator)
|
||||
for key, clip in def.clips {
|
||||
delete(clip.frames)
|
||||
append(&keys, key)
|
||||
}
|
||||
for key in keys {
|
||||
delete_key(&def.clips, key)
|
||||
delete(key)
|
||||
}
|
||||
delete(def.clips)
|
||||
delete(def.id)
|
||||
delete(def.atlas)
|
||||
def^ = {}
|
||||
}
|
||||
+27
-24
@@ -4,43 +4,46 @@ import "core:fmt"
|
||||
import "core:os"
|
||||
import sdl "vendor:sdl3"
|
||||
|
||||
choose_shader_runtime :: proc(device: ^sdl.GPUDevice) -> (Shader_Runtime, bool) {
|
||||
supported := sdl.GetGPUShaderFormats(device)
|
||||
|
||||
choose_shader_runtime_from_formats :: proc(
|
||||
supported: sdl.GPUShaderFormat,
|
||||
) -> (
|
||||
Shader_Runtime,
|
||||
bool,
|
||||
) {
|
||||
if .MSL in supported {
|
||||
return {
|
||||
backend = .Metal_MSL,
|
||||
format = {.MSL},
|
||||
shader_dir = "shaders/metal",
|
||||
entrypoint = "main",
|
||||
},
|
||||
true
|
||||
|
||||
backend = .Metal_MSL,
|
||||
format = {.MSL},
|
||||
shader_dir = "shaders/metal",
|
||||
entrypoint = "main",
|
||||
}, true
|
||||
}
|
||||
if .DXIL in supported {
|
||||
return {
|
||||
backend = .DSD12_DXIL,
|
||||
format = {.DXIL},
|
||||
shader_dir = "shaders/d3d12",
|
||||
entrypoint = "main",
|
||||
},
|
||||
true
|
||||
|
||||
backend = .DSD12_DXIL,
|
||||
format = {.DXIL},
|
||||
shader_dir = "shaders/d3d12",
|
||||
entrypoint = "main",
|
||||
}, true
|
||||
}
|
||||
if .SPIRV in supported {
|
||||
return {
|
||||
backend = .Vulkan_SPIRV,
|
||||
format = {.SPIRV},
|
||||
shader_dir = "shaders/vulkan",
|
||||
entrypoint = "main",
|
||||
},
|
||||
true
|
||||
backend = .Vulkan_SPIRV,
|
||||
format = {.SPIRV},
|
||||
shader_dir = "shaders/vulkan",
|
||||
entrypoint = "main",
|
||||
}, true
|
||||
}
|
||||
|
||||
fmt.eprintfln("No supported shader format from device {got %v}", supported)
|
||||
fmt.eprintfln("No supported shader format from device (got %v)", supported)
|
||||
return {}, false
|
||||
}
|
||||
|
||||
choose_shader_runtime :: proc(device: ^sdl.GPUDevice) -> (Shader_Runtime, bool) {
|
||||
supported := sdl.GetGPUShaderFormats(device)
|
||||
return choose_shader_runtime_from_formats(supported)
|
||||
}
|
||||
|
||||
load_shader_blob :: proc(path: string) -> ([]u8, bool) {
|
||||
data, err := os.read_entire_file(path, context.allocator)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package engine
|
||||
|
||||
import "core:testing"
|
||||
import sdl "vendor:sdl3"
|
||||
|
||||
@(test)
|
||||
shader_filenames_per_backend :: proc(t: ^testing.T) {
|
||||
vert, frag := shader_filenames(.Vulkan_SPIRV)
|
||||
testing.expect_value(t, vert, "sprite.vert.spv")
|
||||
testing.expect_value(t, frag, "sprite.frag.spv")
|
||||
|
||||
vert, frag = shader_filenames(.DSD12_DXIL)
|
||||
testing.expect_value(t, vert, "sprite.vert.dxil")
|
||||
testing.expect_value(t, frag, "sprite.frag.dxil")
|
||||
|
||||
vert, frag = shader_filenames(.Metal_MSL)
|
||||
testing.expect_value(t, vert, "sprite.vert.msl")
|
||||
testing.expect_value(t, frag, "sprite.frag.msl")
|
||||
}
|
||||
|
||||
@(test)
|
||||
choose_shader_runtime_prefers_msl :: proc(t: ^testing.T) {
|
||||
rt, ok := choose_shader_runtime_from_formats({.MSL, .SPIRV, .DXIL})
|
||||
testing.expect(t, ok)
|
||||
testing.expect_value(t, rt.backend, Shader_Backend.Metal_MSL)
|
||||
testing.expect_value(t, rt.shader_dir, "shaders/metal")
|
||||
testing.expect_value(t, rt.format, sdl.GPUShaderFormat{.MSL})
|
||||
}
|
||||
|
||||
@(test)
|
||||
choose_shader_runtime_spirv_only :: proc(t: ^testing.T) {
|
||||
rt, ok := choose_shader_runtime_from_formats({.SPIRV})
|
||||
testing.expect(t, ok)
|
||||
testing.expect_value(t, rt.backend, Shader_Backend.Vulkan_SPIRV)
|
||||
testing.expect_value(t, rt.shader_dir, "shaders/vulkan")
|
||||
testing.expect_value(t, rt.format, sdl.GPUShaderFormat{.SPIRV})
|
||||
}
|
||||
|
||||
@(test)
|
||||
choose_shader_runtime_empty_fails :: proc(t: ^testing.T) {
|
||||
_, ok := choose_shader_runtime_from_formats({})
|
||||
testing.expect(t, !ok)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package engine
|
||||
|
||||
import "core:testing"
|
||||
|
||||
@(test)
|
||||
to_clip_corners :: proc(t: ^testing.T) {
|
||||
// top-left pixel (0,0) -> clip (-1, 1) with y-flip
|
||||
p := to_clip(0, 0, 800, 600)
|
||||
testing.expect_value(t, p[0], f32(-1))
|
||||
testing.expect_value(t, p[1], f32(1))
|
||||
|
||||
// bottom-right pixel (sw, sh) -> clip (1, -1)
|
||||
p = to_clip(800, 600, 800, 600)
|
||||
testing.expect_value(t, p[0], f32(1))
|
||||
testing.expect_value(t, p[1], f32(-1))
|
||||
|
||||
// center
|
||||
p = to_clip(400, 300, 800, 600)
|
||||
testing.expect_value(t, p[0], f32(0))
|
||||
testing.expect_value(t, p[1], f32(0))
|
||||
}
|
||||
Reference in New Issue
Block a user