aboutsummaryrefslogtreecommitdiff
path: root/tests/core/encoding
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2022-04-27 14:37:15 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2022-04-27 14:37:15 +0200
commitc4e0d1efa1ec655bae9134b95a0fcd060cc7bbea (patch)
treec29bd0b78138e8d67aebe34ac689d13e32d9d15f /tests/core/encoding
parent6e61abc7d06f22129f93110a9f652c3eec21f0c6 (diff)
parent9349dfba8fec53f52f77a0c8928e115ec93ff447 (diff)
Merge branch 'master' into xml
Diffstat (limited to 'tests/core/encoding')
-rw-r--r--tests/core/encoding/hxa/test_core_hxa.odin232
-rw-r--r--tests/core/encoding/json/test_core_json.odin272
-rw-r--r--tests/core/encoding/varint/test_core_varint.odin156
3 files changed, 654 insertions, 6 deletions
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/encoding/json/test_core_json.odin b/tests/core/encoding/json/test_core_json.odin
index 6f2e8c35a..0e6a6412f 100644
--- a/tests/core/encoding/json/test_core_json.odin
+++ b/tests/core/encoding/json/test_core_json.odin
@@ -3,6 +3,7 @@ package test_core_json
import "core:encoding/json"
import "core:testing"
import "core:fmt"
+import "core:os"
TEST_count := 0
TEST_fail := 0
@@ -20,17 +21,22 @@ when ODIN_TEST {
}
}
log :: proc(t: ^testing.T, v: any, loc := #caller_location) {
- fmt.printf("[%v] LOG:\n\t%v\n", loc, v)
+ fmt.printf("[%v] ", loc)
+ fmt.printf("log: %v\n", v)
}
}
main :: proc() {
t := testing.T{}
-
+
parse_json(&t)
marshal_json(&t)
+ unmarshal_json(&t)
- fmt.printf("\n%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
+ fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
+ if TEST_fail > 0 {
+ os.exit(1)
+ }
}
@test
@@ -65,7 +71,8 @@ parse_json :: proc(t: ^testing.T) {
_, err := json.parse(transmute([]u8)json_data)
- expect(t, err == .None, "expected json error to be none")
+ msg := fmt.tprintf("Expected `json.parse` to return nil, got %v", err)
+ expect(t, err == nil, msg)
}
@test
@@ -82,6 +89,259 @@ marshal_json :: proc(t: ^testing.T) {
}
_, err := json.marshal(my_struct)
-
- expect(t, err == .None, "expected json error to be none")
+ msg := fmt.tprintf("Expected `json.marshal` to return nil, got %v", err)
+ expect(t, err == nil, msg)
}
+
+PRODUCTS := `
+{
+ "cash": "0",
+ "products": [
+ {
+ "name": "Cog\nCola",
+ "cost": "3",
+ "owned": "1",
+
+ "profit": "4",
+ "seconds": 3,
+ "multiplier": 1,
+ "auto_click": false
+ },
+ {
+ "name": "gingerBeer",
+ "cost": "9",
+ "owned": "0",
+
+ "profit": "16",
+ "seconds": 5,
+ "multiplier": 1,
+ "auto_click": false
+ },
+ {
+ "name": "Coffee",
+ "cost": "27",
+ "owned": "0",
+
+ "profit": "64",
+ "seconds": 7,
+ "multiplier": 1,
+ "auto_click": false
+ },
+ {
+ "name": "Haggis",
+ "cost": "81",
+ "owned": "0",
+
+ "profit": "256",
+ "seconds": 11,
+ "multiplier": 1,
+ "auto_click": false
+ },
+ {
+ "name": "Lasagna",
+ "cost": "243",
+ "owned": "0",
+
+ "profit": "1024",
+ "seconds": 13,
+ "multiplier": 1,
+ "auto_click": false
+ },
+ {
+ "name": "Asparagus",
+ "cost": "729",
+ "owned": "0",
+
+ "profit": "4096",
+ "seconds": 17,
+ "multiplier": 1,
+ "auto_click": false
+ },
+ {
+ "name": "Yorkshire Pudding",
+ "cost": "2187",
+ "owned": "0",
+
+ "profit": "16384",
+ "seconds": 19,
+ "multiplier": 1,
+ "auto_click": false
+ },
+ {
+ "name": "Salmon Wrap",
+ "cost": "6561",
+ "owned": "0",
+
+ "profit": "65536",
+ "seconds": 23,
+ "multiplier": 1,
+ "auto_click": false
+ },
+ {
+ "name": "Poke Bowl",
+ "cost": "19683",
+ "owned": "0",
+
+ "profit": "262144",
+ "seconds": 29,
+ "multiplier": 1,
+ "auto_click": false
+ },
+ {
+ "name": "Chili Con Carne",
+ "cost": "59049",
+ "owned": "0",
+
+ "profit": "1048576",
+ "seconds": 59,
+ "multiplier": 1,
+ "auto_click": false
+ },
+ ],
+}
+`
+
+original_data := Game_Marshal{
+ cash = "0",
+ products = {
+ {
+ name = "Cog\nCola",
+ cost = "3",
+ owned = "1",
+ profit = "4",
+ seconds = 3,
+ multiplier = 1,
+ auto_click = false,
+ },
+ {
+ name = "gingerBeer",
+ cost = "9",
+ owned = "0",
+ profit = "16",
+ seconds = 5,
+ multiplier = 1,
+ auto_click = false,
+ },
+ {
+ name = "Coffee",
+ cost = "27",
+ owned = "0",
+ profit = "64",
+ seconds = 7,
+ multiplier = 1,
+ auto_click = false,
+ },
+ {
+ name = "Haggis",
+ cost = "81",
+ owned = "0",
+ profit = "256",
+ seconds = 11,
+ multiplier = 1,
+ auto_click = false,
+ },
+ {
+ name = "Lasagna",
+ cost = "243",
+ owned = "0",
+ profit = "1024",
+ seconds = 13,
+ multiplier = 1,
+ auto_click = false,
+ },
+ {
+ name = "Asparagus",
+ cost = "729",
+ owned = "0",
+ profit = "4096",
+ seconds = 17,
+ multiplier = 1,
+ auto_click = false,
+ },
+ {
+ name = "Yorkshire Pudding",
+ cost = "2187",
+ owned = "0",
+ profit = "16384",
+ seconds = 19,
+ multiplier = 1,
+ auto_click = false,
+ },
+ {
+ name = "Salmon Wrap",
+ cost = "6561",
+ owned = "0",
+ profit = "65536",
+ seconds = 23,
+ multiplier = 1,
+ auto_click = false,
+ },
+ {
+ name = "Poke Bowl",
+ cost = "19683",
+ owned = "0",
+ profit = "262144",
+ seconds = 29,
+ multiplier = 1,
+ auto_click = false,
+ },
+ {
+ name = "Chili Con Carne",
+ cost = "59049",
+ owned = "0",
+ profit = "1048576",
+ seconds = 59,
+ multiplier = 1,
+ auto_click = false,
+ },
+ },
+}
+
+Product_Marshal :: struct {
+ name: cstring,
+ owned: string,
+
+ cost: string,
+
+ profit: string,
+ seconds: int,
+ multiplier: int,
+
+ auto_click: bool,
+}
+
+Game_Marshal :: struct {
+ cash: string,
+ products: []Product_Marshal,
+}
+
+cleanup :: proc(g: Game_Marshal) {
+ for p in g.products {
+ delete(p.name)
+ delete(p.owned)
+ delete(p.cost)
+ delete(p.profit)
+ }
+ delete(g.products)
+ delete(g.cash)
+}
+
+@test
+unmarshal_json :: proc(t: ^testing.T) {
+ g: Game_Marshal
+ err := json.unmarshal(transmute([]u8)PRODUCTS, &g, json.DEFAULT_SPECIFICATION)
+ defer cleanup(g)
+
+ msg := fmt.tprintf("Expected `json.unmarshal` to return nil, got %v", err)
+ expect(t, err == nil, msg)
+
+ msg = fmt.tprintf("Expected %v products to have been unmarshaled, got %v", len(original_data.products), len(g.products))
+ expect(t, len(g.products) == len(original_data.products), msg)
+
+ msg = fmt.tprintf("Expected cash to have been unmarshaled as %v, got %v", original_data.cash, g.cash)
+ expect(t, original_data.cash == g.cash, msg)
+
+ for p, i in g.products {
+ expect(t, p == original_data.products[i], "Producted unmarshaled improperly")
+ }
+} \ No newline at end of file
diff --git a/tests/core/encoding/varint/test_core_varint.odin b/tests/core/encoding/varint/test_core_varint.odin
new file mode 100644
index 000000000..2c3669afa
--- /dev/null
+++ b/tests/core/encoding/varint/test_core_varint.odin
@@ -0,0 +1,156 @@
+package test_core_varint
+
+import "core:encoding/varint"
+import "core:testing"
+import "core:fmt"
+import "core:os"
+import "core:slice"
+import "core:math/rand"
+
+TEST_count := 0
+TEST_fail := 0
+
+RANDOM_TESTS :: 100
+
+when ODIN_TEST {
+ expect :: testing.expect
+ log :: testing.log
+} else {
+ expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) {
+ TEST_count += 1
+ if !condition {
+ TEST_fail += 1
+ fmt.printf("[%v] %v\n", loc, message)
+ return
+ }
+ }
+ log :: proc(t: ^testing.T, v: any, loc := #caller_location) {
+ fmt.printf("[%v] ", loc)
+ fmt.printf("log: %v\n", v)
+ }
+}
+
+main :: proc() {
+ t := testing.T{}
+
+ test_leb128(&t)
+
+ fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
+ if TEST_fail > 0 {
+ os.exit(1)
+ }
+}
+
+@(test)
+test_leb128 :: proc(t: ^testing.T) {
+ buf: [varint.LEB128_MAX_BYTES]u8
+
+ for vector in ULEB_Vectors {
+ val, size, err := varint.decode_uleb128(vector.encoded)
+
+ msg := fmt.tprintf("Expected %02x to decode to %v consuming %v bytes, got %v and %v", vector.encoded, vector.value, vector.size, val, size)
+ expect(t, size == vector.size && val == vector.value, msg)
+
+ msg = fmt.tprintf("Expected decoder to return error %v, got %v for vector %v", vector.error, err, vector)
+ expect(t, err == vector.error, msg)
+
+ if err == .None { // Try to roundtrip
+ size, err = varint.encode_uleb128(buf[:], vector.value)
+
+ msg = fmt.tprintf("Expected %v to encode to %02x, got %02x", vector.value, vector.encoded, buf[:size])
+ expect(t, size == vector.size && slice.simple_equal(vector.encoded, buf[:size]), msg)
+ }
+ }
+
+ for vector in ILEB_Vectors {
+ val, size, err := varint.decode_ileb128(vector.encoded)
+
+ msg := fmt.tprintf("Expected %02x to decode to %v consuming %v bytes, got %v and %v", vector.encoded, vector.value, vector.size, val, size)
+ expect(t, size == vector.size && val == vector.value, msg)
+
+ msg = fmt.tprintf("Expected decoder to return error %v, got %v", vector.error, err)
+ expect(t, err == vector.error, msg)
+
+ if err == .None { // Try to roundtrip
+ size, err = varint.encode_ileb128(buf[:], vector.value)
+
+ msg = fmt.tprintf("Expected %v to encode to %02x, got %02x", vector.value, vector.encoded, buf[:size])
+ expect(t, size == vector.size && slice.simple_equal(vector.encoded, buf[:size]), msg)
+ }
+ }
+
+ for num_bytes in 1..uint(16) {
+ for _ in 0..RANDOM_TESTS {
+ unsigned, signed := get_random(num_bytes)
+
+ {
+ encode_size, encode_err := varint.encode_uleb128(buf[:], unsigned)
+ msg := fmt.tprintf("%v failed to encode as an unsigned LEB128 value, got %v", unsigned, encode_err)
+ expect(t, encode_err == .None, msg)
+
+ decoded, decode_size, decode_err := varint.decode_uleb128(buf[:])
+ msg = fmt.tprintf("Expected %02x to decode as %v, got %v", buf[:encode_size], unsigned, decoded)
+ expect(t, decode_err == .None && decode_size == encode_size && decoded == unsigned, msg)
+ }
+
+ {
+ encode_size, encode_err := varint.encode_ileb128(buf[:], signed)
+ msg := fmt.tprintf("%v failed to encode as a signed LEB128 value, got %v", signed, encode_err)
+ expect(t, encode_err == .None, msg)
+
+ decoded, decode_size, decode_err := varint.decode_ileb128(buf[:])
+ msg = fmt.tprintf("Expected %02x to decode as %v, got %v, err: %v", buf[:encode_size], signed, decoded, decode_err)
+ expect(t, decode_err == .None && decode_size == encode_size && decoded == signed, msg)
+ }
+ }
+ }
+}
+
+get_random :: proc(byte_count: uint) -> (u: u128, i: i128) {
+ assert(byte_count >= 0 && byte_count <= size_of(u128))
+
+ for _ in 1..byte_count {
+ u <<= 8
+ u |= u128(rand.uint32() & 0xff)
+ }
+
+ bias := i128(1 << (byte_count * 7)) - 1
+ i = i128(u) - bias
+
+ return
+}
+
+ULEB_Test_Vector :: struct {
+ encoded: []u8,
+ value: u128,
+ size: int,
+ error: varint.Error,
+}
+
+ULEB_Vectors :: []ULEB_Test_Vector{
+ { []u8{0x00}, 0, 1, .None },
+ { []u8{0x7f}, 127, 1, .None },
+ { []u8{0xE5, 0x8E, 0x26}, 624485, 3, .None },
+ { []u8{0x80}, 0, 0, .Buffer_Too_Small },
+ { []u8{}, 0, 0, .Buffer_Too_Small },
+
+ { []u8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03}, max(u128), 19, .None },
+}
+
+ILEB_Test_Vector :: struct {
+ encoded: []u8,
+ value: i128,
+ size: int,
+ error: varint.Error,
+}
+
+ILEB_Vectors :: []ILEB_Test_Vector{
+ { []u8{0x00}, 0, 1, .None },
+ { []u8{0x3f}, 63, 1, .None },
+ { []u8{0x40}, -64, 1, .None },
+ { []u8{0xC0, 0xBB, 0x78}, -123456, 3, .None },
+ { []u8{}, 0, 0, .Buffer_Too_Small },
+
+ { []u8{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7e}, min(i128), 19, .None },
+ { []u8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}, max(i128), 19, .None },
+} \ No newline at end of file