Merge remote-tracking branch 'upstream/master' into sys-windows-2

# Conflicts:
#	core/sys/windows/kernel32.odin
#	core/sys/windows/types.odin
#	core/sys/windows/user32.odin
#	core/sys/windows/winerror.odin
This commit is contained in:
Thomas la Cour
2024-07-11 21:20:53 +02:00
343 changed files with 36936 additions and 9191 deletions
+2 -5
View File
@@ -20,15 +20,12 @@ test_avl :: proc(t: ^testing.T) {
iter := avl.iterator(&tree, avl.Direction.Forward)
testing.expect(t, avl.iterator_get(&iter) == nil, "empty/iterator: first node should be nil")
r: rand.Rand
rand.init(&r, t.seed)
// Test insertion.
NR_INSERTS :: 32 + 1 // Ensure at least 1 collision.
inserted_map := make(map[int]^avl.Node(int))
defer delete(inserted_map)
for i := 0; i < NR_INSERTS; i += 1 {
v := int(rand.uint32(&r) & 0x1f)
v := int(rand.uint32() & 0x1f)
existing_node, in_map := inserted_map[v]
n, ok, _ := avl.find_or_insert(&tree, v)
@@ -78,7 +75,7 @@ test_avl :: proc(t: ^testing.T) {
testing.expect(t, visited == nrEntries, "iterator/backward: visited")
// Test removal.
rand.shuffle(inserted_values[:], &r)
rand.shuffle(inserted_values[:])
for v, i in inserted_values {
node := avl.find(&tree, v)
testing.expect(t, node != nil, "remove: find (pre)")
+3 -6
View File
@@ -14,9 +14,6 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) {
defer mem.tracking_allocator_destroy(&track)
context.allocator = mem.tracking_allocator(&track)
r: rand.Rand
rand.init(&r, t.seed)
log.infof("Testing Red-Black Tree($Key=%v,$Value=%v) using random seed %v.", type_info_of(Key), type_info_of(Value), t.seed)
tree: rb.Tree(Key, Value)
rb.init(&tree)
@@ -35,9 +32,9 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) {
max_key := min(Key)
for i := 0; i < NR_INSERTS; i += 1 {
k := Key(rand.uint32(&r)) & 0x1f
k := Key(rand.uint32()) & 0x1f
min_key = min(min_key, k); max_key = max(max_key, k)
v := Value(rand.uint32(&r))
v := Value(rand.uint32())
existing_node, in_map := inserted_map[k]
n, inserted, _ := rb.find_or_insert(&tree, k, v)
@@ -92,7 +89,7 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) {
testing.expect(t, visited == entry_count, "iterator/backward: visited")
// Test removal (and on_remove callback)
rand.shuffle(inserted_keys[:], &r)
rand.shuffle(inserted_keys[:])
callback_count := entry_count
tree.user_data = &callback_count
tree.on_remove = proc(key: Key, value: Value, user_data: rawptr) {
+8 -16
View File
@@ -134,14 +134,11 @@ test_write :: proc(t: ^testing.T) {
testing.expectf(t, read_err == read_e, fmt.tprintf("read_err %v != %v", read_err, read_e))
defer hxa.file_destroy(file)
testing.expectf(t, file.magic_number == 0x417848, fmt.tprintf("file.magic_number %v != %v",
file.magic_number, 0x417848))
testing.expectf(t, file.magic_number == 0x417848, fmt.tprintf("file.magic_number %v != %v", file.magic_number, 0x417848))
testing.expectf(t, file.version == 3, fmt.tprintf("file.version %v != %v", file.version, 3))
testing.expectf(t, file.internal_node_count == 1, fmt.tprintf("file.internal_node_count %v != %v",
file.internal_node_count, 1))
testing.expectf(t, file.internal_node_count == 1, fmt.tprintf("file.internal_node_count %v != %v", file.internal_node_count, 1))
testing.expectf(t, len(file.nodes) == len(w_file.nodes), fmt.tprintf("len(file.nodes) %v != %v",
len(file.nodes), len(w_file.nodes)))
testing.expectf(t, len(file.nodes) == len(w_file.nodes), fmt.tprintf("len(file.nodes) %v != %v", len(file.nodes), len(w_file.nodes)))
m := &file.nodes[0].meta_data
w_m := &w_file.nodes[0].meta_data
@@ -150,20 +147,16 @@ test_write :: proc(t: ^testing.T) {
m_v, m_v_ok := m[0].value.([]f64le)
testing.expectf(t, m_v_ok, fmt.tprintf("m_v_ok %v != %v", m_v_ok, true))
testing.expectf(t, len(m_v) == len(n1_m1_value), fmt.tprintf("%v != len(m_v) %v",
len(m_v), len(n1_m1_value)))
testing.expectf(t, len(m_v) == len(n1_m1_value), fmt.tprintf("%v != len(m_v) %v", len(m_v), len(n1_m1_value)))
for i := 0; i < len(m_v); i += 1 {
testing.expectf(t, m_v[i] == n1_m1_value[i], fmt.tprintf("m_v[%d] %v != %v",
i, m_v[i], n1_m1_value[i]))
testing.expectf(t, m_v[i] == n1_m1_value[i], fmt.tprintf("m_v[%d] %v != %v", i, m_v[i], n1_m1_value[i]))
}
v, v_ok := file.nodes[0].content.(hxa.Node_Image)
testing.expectf(t, v_ok, fmt.tprintf("v_ok %v != %v", v_ok, true))
testing.expectf(t, v.type == n1_content.type, fmt.tprintf("v.type %v != %v", v.type, n1_content.type))
testing.expectf(t, len(v.resolution) == 3, fmt.tprintf("len(v.resolution) %v != %v",
len(v.resolution), 3))
testing.expectf(t, len(v.image_stack) == len(n1_content.image_stack), fmt.tprintf("len(v.image_stack) %v != %v",
len(v.image_stack), len(n1_content.image_stack)))
testing.expectf(t, len(v.resolution) == 3, fmt.tprintf("len(v.resolution) %v != %v", len(v.resolution), 3))
testing.expectf(t, len(v.image_stack) == len(n1_content.image_stack), fmt.tprintf("len(v.image_stack) %v != %v", len(v.image_stack), len(n1_content.image_stack)))
for i := 0; i < len(v.image_stack); i += 1 {
testing.expectf(t, v.image_stack[i].name == n1_content.image_stack[i].name,
fmt.tprintf("v.image_stack[%d].name %v != %v",
@@ -182,8 +175,7 @@ test_write :: proc(t: ^testing.T) {
testing.expectf(t, l_ok, fmt.tprintf("l_ok %v != %v", l_ok, true))
testing.expectf(t, len(l) == len(n1_t), fmt.tprintf("len(l) %v != %v", len(l), len(n1_t)))
for j := 0; j < len(l); j += 1 {
testing.expectf(t, l[j] == n1_t[j], fmt.tprintf("l[%d] %v (%h) != %v (%h)",
j, l[j], l[j], n1_t[j], n1_t[j]))
testing.expectf(t, l[j] == n1_t[j], fmt.tprintf("l[%d] %v (%h) != %v (%h)", j, l[j], l[j], n1_t[j], n1_t[j]))
}
case []f64le:
l, l_ok := v.image_stack[i].data.([]f64le)
@@ -0,0 +1,439 @@
package test_core_uuid
import "core:crypto"
import "core:encoding/uuid"
import uuid_legacy "core:encoding/uuid/legacy"
import "core:log"
import "core:slice"
import "core:testing"
import "core:time"
@(test)
test_version_and_variant :: proc(t: ^testing.T) {
context.random_generator = crypto.random_generator()
v1 := uuid.generate_v1(0)
v3 := uuid_legacy.generate_v3(uuid.Namespace_DNS, "")
v4 := uuid.generate_v4()
v5 := uuid_legacy.generate_v5(uuid.Namespace_DNS, "")
v6 := uuid.generate_v6()
v7 := uuid.generate_v7()
_v8_array: [16]u8 = 0xff
v8_int := uuid.stamp_v8(max(u128))
v8_array := uuid.stamp_v8(_v8_array)
v8_slice := uuid.stamp_v8(_v8_array[:])
v8_hash := uuid.generate_v8_hash(uuid.Namespace_DNS, "", .SHA512)
testing.expect_value(t, uuid.version(v1), 1)
testing.expect_value(t, uuid.variant(v1), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v3), 3)
testing.expect_value(t, uuid.variant(v3), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v4), 4)
testing.expect_value(t, uuid.variant(v4), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v5), 5)
testing.expect_value(t, uuid.variant(v5), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v6), 6)
testing.expect_value(t, uuid.variant(v6), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v7), 7)
testing.expect_value(t, uuid.variant(v7), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v8_int), 8)
testing.expect_value(t, uuid.variant(v8_int), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v8_array), 8)
testing.expect_value(t, uuid.variant(v8_array), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v8_slice), 8)
testing.expect_value(t, uuid.variant(v8_slice), uuid.Variant_Type.RFC_4122)
testing.expect_value(t, uuid.version(v8_hash), 8)
testing.expect_value(t, uuid.variant(v8_hash), uuid.Variant_Type.RFC_4122)
}
@(test)
test_timestamps :: proc(t: ^testing.T) {
// This test makes sure that timestamps are recoverable and have not been
// overwritten by neighboring bits, taking into account precision loss.
context.random_generator = crypto.random_generator()
N :: max(i64)
max_time := time.Time { N }
mac: [6]byte
v1 := uuid.generate_v1(0, mac, max_time)
v6 := uuid.generate_v6(0, mac, max_time)
v7 := uuid.generate_v7(max_time)
// The counter version keeps its time in the same place as the basic version,
// this is just for the sake of completeness.
v7_counter := uuid.generate_v7(0, max_time)
v1_time := uuid.time_v1(v1)
v6_time := uuid.time_v6(v6)
v7_time := uuid.time_v7(v7)
v7_counter_time := uuid.time_v7(v7_counter)
// I hope the compiler doesn't ever optimize this out.
max_time_hns_resolution := time.Time { N / 100 * 100 }
max_time_ms_resolution := time.Time { N / 1e6 * 1e6 }
testing.expectf(t,
time.diff(max_time_hns_resolution, v1_time) == 0,
"v1 UUID timestamp is invalid, expected %x, got %x",
max_time_hns_resolution, v1_time)
testing.expectf(t,
time.diff(max_time_hns_resolution, v6_time) == 0,
"v6 UUID timestamp is invalid, expected %x, got %x",
max_time_hns_resolution, v6_time)
testing.expectf(t,
time.diff(max_time_ms_resolution, v7_time) == 0,
"v7 UUID timestamp is invalid, expected %x, got %x",
max_time_ms_resolution, v7_time)
testing.expectf(t,
time.diff(max_time_ms_resolution, v7_counter_time) == 0,
"v7 UUID (with counter) timestamp is invalid, expected %x, got %x",
max_time_ms_resolution, v7_counter_time)
}
@(test)
test_v8_hash_implementation :: proc(t: ^testing.T) {
// This example and its results are derived from RFC 9562.
// https://www.rfc-editor.org/rfc/rfc9562.html#name-example-of-a-uuidv8-value-n
id := uuid.generate_v8_hash(uuid.Namespace_DNS, "www.example.com", .SHA256)
id_str := uuid.to_string(id)
defer delete(id_str)
testing.expect_value(t, id_str, "5c146b14-3c52-8afd-938a-375d0df1fbf6")
}
@(test)
test_legacy_namespaced_uuids :: proc(t: ^testing.T) {
TEST_NAME :: "0123456789ABCDEF0123456789ABCDEF"
Expected_Result :: struct {
namespace: uuid.Identifier,
v3, v5: string,
}
Expected_Results := [?]Expected_Result {
{ uuid.Namespace_DNS, "80147f37-36db-3b82-b78f-810c3c6504ba", "18394c41-13a2-593f-abf2-a63e163c2860" },
{ uuid.Namespace_URL, "8136789b-8e16-3fbd-800b-1587e2f22521", "07337422-eb77-5fd3-99af-c7f59e641e13" },
{ uuid.Namespace_OID, "adbb95bc-ea50-3226-9a75-20c34a6030f8", "24db9b0f-70b8-53c4-a301-f695ce17276d" },
{ uuid.Namespace_X500, "a8965ad1-0e54-3d65-b933-8b7cca8e8313", "3012bf2d-fac4-5187-9825-493e6636b936" },
}
for exp in Expected_Results {
v3 := uuid_legacy.generate_v3(exp.namespace, TEST_NAME)
v5 := uuid_legacy.generate_v5(exp.namespace, TEST_NAME)
v3_str := uuid.to_string(v3)
defer delete(v3_str)
v5_str := uuid.to_string(v5)
defer delete(v5_str)
testing.expect_value(t, v3_str, exp.v3)
testing.expect_value(t, v5_str, exp.v5)
}
}
@(test)
test_v1 :: proc(t: ^testing.T) {
context.random_generator = crypto.random_generator()
point_a := time.unix(1, 0)
point_b := time.unix(3, 0)
point_c := time.unix(5, 0)
CLOCK :: 0x3A1A
mac := [6]u8{0xFF, 0x10, 0xAA, 0x55, 0x01, 0xFF}
v1_a := uuid.generate_v1(CLOCK, mac, point_a)
v1_b := uuid.generate_v1(CLOCK, mac, point_b)
v1_c := uuid.generate_v1(CLOCK, mac, point_c)
testing.expect_value(t, uuid.clock_seq(v1_a), CLOCK)
extracted_mac := uuid.node(v1_a)
for i in 0 ..< len(mac) {
testing.expect(t, mac[i] == extracted_mac[i])
}
time_a := uuid.time_v1(v1_a)
time_b := uuid.time_v1(v1_b)
time_c := uuid.time_v1(v1_c)
log.debugf("A: %02x, %v", v1_a, time_a)
log.debugf("B: %02x, %v", v1_b, time_b)
log.debugf("C: %02x, %v", v1_c, time_c)
testing.expect(t, time.diff(time_a, time_b) > 0, "The time on the later-generated v1 UUID is earlier than its successor.")
testing.expect(t, time.diff(time_b, time_c) > 0, "The time on the later-generated v1 UUID is earlier than its successor.")
testing.expect(t, time.diff(time_a, time_c) > 0, "The time on the later-generated v1 UUID is earlier than its successor.")
}
@(test)
test_v6 :: proc(t: ^testing.T) {
context.random_generator = crypto.random_generator()
point_a := time.unix(1, 0)
point_b := time.unix(3, 0)
point_c := time.unix(5, 0)
CLOCK :: 0x3A1A
mac := [6]u8{0xFF, 0x10, 0xAA, 0x55, 0x01, 0xFF}
v6_a := uuid.generate_v6(CLOCK, mac, point_a)
v6_b := uuid.generate_v6(CLOCK, mac, point_b)
v6_c := uuid.generate_v6(CLOCK, mac, point_c)
testing.expect_value(t, uuid.clock_seq(v6_a), CLOCK)
extracted_mac := uuid.node(v6_a)
for i in 0 ..< len(mac) {
testing.expect(t, mac[i] == extracted_mac[i])
}
time_a := uuid.time_v6(v6_a)
time_b := uuid.time_v6(v6_b)
time_c := uuid.time_v6(v6_c)
log.debugf("A: %02x, %v", v6_a, time_a)
log.debugf("B: %02x, %v", v6_b, time_b)
log.debugf("C: %02x, %v", v6_c, time_c)
testing.expect(t, time.diff(time_a, time_b) > 0, "The time on the later-generated v6 UUID is earlier than its successor.")
testing.expect(t, time.diff(time_b, time_c) > 0, "The time on the later-generated v6 UUID is earlier than its successor.")
testing.expect(t, time.diff(time_a, time_c) > 0, "The time on the later-generated v6 UUID is earlier than its successor.")
}
@(test)
test_v7 :: proc(t: ^testing.T) {
context.random_generator = crypto.random_generator()
point_a := time.unix(1, 0)
point_b := time.unix(3, 0)
point_c := time.unix(5, 0)
v7_a := uuid.generate_v7(point_a)
v7_b := uuid.generate_v7(point_b)
v7_c := uuid.generate_v7(point_c)
time_a := uuid.time_v7(v7_a)
time_b := uuid.time_v7(v7_b)
time_c := uuid.time_v7(v7_c)
log.debugf("A: %02x, %v", v7_a, time_a)
log.debugf("B: %02x, %v", v7_b, time_b)
log.debugf("C: %02x, %v", v7_c, time_c)
testing.expect(t, time.diff(time_a, time_b) > 0, "The time on the later-generated v7 UUID is earlier than its successor.")
testing.expect(t, time.diff(time_b, time_c) > 0, "The time on the later-generated v7 UUID is earlier than its successor.")
testing.expect(t, time.diff(time_a, time_c) > 0, "The time on the later-generated v7 UUID is earlier than its successor.")
v7_with_counter := uuid.generate_v7(0x555)
log.debugf("D: %02x", v7_with_counter)
testing.expect_value(t, uuid.counter_v7(v7_with_counter), 0x555)
}
@(test)
test_sorting_v1 :: proc(t: ^testing.T) {
// This test is to make sure that the v1 UUIDs do _not_ sort.
// They are incapable of sorting properly by the nature their time bit ordering.
//
// Something is very strange if they do sort correctly.
point_a := time.unix(1, 0)
point_b := time.unix(3, 0)
point_c := time.unix(5, 0)
point_d := time.unix(7, 0)
point_e := time.unix(11, 0)
mac: [6]byte
v1_a := uuid.generate_v1(0, mac, point_a)
v1_b := uuid.generate_v1(0, mac, point_b)
v1_c := uuid.generate_v1(0, mac, point_c)
v1_d := uuid.generate_v1(0, mac, point_d)
v1_e := uuid.generate_v1(0, mac, point_e)
sort_test := [5]u128be {
transmute(u128be)v1_e,
transmute(u128be)v1_a,
transmute(u128be)v1_d,
transmute(u128be)v1_b,
transmute(u128be)v1_c,
}
log.debugf("Before: %x", sort_test)
slice.sort(sort_test[:])
log.debugf("After: %x", sort_test)
ERROR :: "v1 UUIDs are sorting by time, despite this not being possible."
testing.expect(t, sort_test[0] != transmute(u128be)v1_a, ERROR)
testing.expect(t, sort_test[1] != transmute(u128be)v1_b, ERROR)
testing.expect(t, sort_test[2] != transmute(u128be)v1_c, ERROR)
testing.expect(t, sort_test[3] != transmute(u128be)v1_d, ERROR)
testing.expect(t, sort_test[4] != transmute(u128be)v1_e, ERROR)
}
@(test)
test_sorting_v6 :: proc(t: ^testing.T) {
context.random_generator = crypto.random_generator()
point_a := time.unix(1, 0)
point_b := time.unix(3, 0)
point_c := time.unix(5, 0)
point_d := time.unix(7, 0)
point_e := time.unix(11, 0)
mac: [6]byte
v6_a := uuid.generate_v6(0, mac, point_a)
v6_b := uuid.generate_v6(0, mac, point_b)
v6_c := uuid.generate_v6(0, mac, point_c)
v6_d := uuid.generate_v6(0, mac, point_d)
v6_e := uuid.generate_v6(0, mac, point_e)
sort_test := [5]u128be {
transmute(u128be)v6_e,
transmute(u128be)v6_a,
transmute(u128be)v6_d,
transmute(u128be)v6_b,
transmute(u128be)v6_c,
}
log.debugf("Before: %x", sort_test)
slice.sort(sort_test[:])
log.debugf("After: %x", sort_test)
ERROR :: "v6 UUIDs are failing to sort properly."
testing.expect(t, sort_test[0] < sort_test[1], ERROR)
testing.expect(t, sort_test[1] < sort_test[2], ERROR)
testing.expect(t, sort_test[2] < sort_test[3], ERROR)
testing.expect(t, sort_test[3] < sort_test[4], ERROR)
testing.expect(t, sort_test[0] == transmute(u128be)v6_a, ERROR)
testing.expect(t, sort_test[1] == transmute(u128be)v6_b, ERROR)
testing.expect(t, sort_test[2] == transmute(u128be)v6_c, ERROR)
testing.expect(t, sort_test[3] == transmute(u128be)v6_d, ERROR)
testing.expect(t, sort_test[4] == transmute(u128be)v6_e, ERROR)
}
@(test)
test_sorting_v7 :: proc(t: ^testing.T) {
context.random_generator = crypto.random_generator()
point_a := time.unix(1, 0)
point_b := time.unix(3, 0)
point_c := time.unix(5, 0)
point_d := time.unix(7, 0)
point_e := time.unix(11, 0)
v7_a := uuid.generate_v7(point_a)
v7_b := uuid.generate_v7(point_b)
v7_c := uuid.generate_v7(point_c)
v7_d := uuid.generate_v7(point_d)
v7_e := uuid.generate_v7(point_e)
sort_test := [5]u128be {
transmute(u128be)v7_e,
transmute(u128be)v7_a,
transmute(u128be)v7_d,
transmute(u128be)v7_b,
transmute(u128be)v7_c,
}
log.debugf("Before: %x", sort_test)
slice.sort(sort_test[:])
log.debugf("After: %x", sort_test)
ERROR :: "v7 UUIDs are failing to sort properly."
testing.expect(t, sort_test[0] < sort_test[1], ERROR)
testing.expect(t, sort_test[1] < sort_test[2], ERROR)
testing.expect(t, sort_test[2] < sort_test[3], ERROR)
testing.expect(t, sort_test[3] < sort_test[4], ERROR)
testing.expect(t, sort_test[0] == transmute(u128be)v7_a, ERROR)
testing.expect(t, sort_test[1] == transmute(u128be)v7_b, ERROR)
testing.expect(t, sort_test[2] == transmute(u128be)v7_c, ERROR)
testing.expect(t, sort_test[3] == transmute(u128be)v7_d, ERROR)
testing.expect(t, sort_test[4] == transmute(u128be)v7_e, ERROR)
}
@(test)
test_writing :: proc(t: ^testing.T) {
id: uuid.Identifier
for &b, i in id {
b = u8(i)
}
buf: [uuid.EXPECTED_LENGTH]u8
s_alloc := uuid.to_string(id)
defer delete(s_alloc)
s_buf := uuid.to_string(id, buf[:])
testing.expect_value(t, s_alloc, "00010203-0405-0607-0809-0a0b0c0d0e0f")
testing.expect_value(t, s_buf, "00010203-0405-0607-0809-0a0b0c0d0e0f")
}
@(test)
test_reading :: proc(t: ^testing.T) {
id, err := uuid.read("00010203-0405-0607-0809-0a0b0c0d0e0f")
testing.expect_value(t, err, nil)
for b, i in id {
testing.expect_value(t, b, u8(i))
}
}
@(test)
test_reading_errors :: proc(t: ^testing.T) {
{
BAD_STRING :: "|.......@....@....@....@............"
_, err := uuid.read(BAD_STRING)
testing.expect_value(t, err, uuid.Read_Error.Invalid_Separator)
}
{
BAD_STRING :: "|.......-....-....-....-............"
_, err := uuid.read(BAD_STRING)
testing.expect_value(t, err, uuid.Read_Error.Invalid_Hexadecimal)
}
{
BAD_STRING :: ".......-....-....-....-............"
_, err := uuid.read(BAD_STRING)
testing.expect_value(t, err, uuid.Read_Error.Invalid_Length)
}
{
BAD_STRING :: "|.......-....-....-....-............|"
_, err := uuid.read(BAD_STRING)
testing.expect_value(t, err, uuid.Read_Error.Invalid_Length)
}
{
BAD_STRING :: "00000000-0000-0000-0000-0000000000001"
_, err := uuid.read(BAD_STRING)
testing.expect_value(t, err, uuid.Read_Error.Invalid_Length)
}
{
BAD_STRING :: "00000000000000000000000000000000"
_, err := uuid.read(BAD_STRING)
testing.expect_value(t, err, uuid.Read_Error.Invalid_Length)
}
{
OK_STRING :: "00000000-0000-0000-0000-000000000000"
_, err := uuid.read(OK_STRING)
testing.expect_value(t, err, nil)
}
}
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -53,9 +53,9 @@ test_xxhash_zero_streamed_random_updates :: proc(t: ^testing.T) {
testing.expect(t, xxh3_128_err == nil, "Problem initializing XXH3_128 state")
// XXH3_128_update
random_seed := rand.create(t.seed)
rand.reset(t.seed)
for len(b) > 0 {
update_size := min(len(b), rand.int_max(8192, &random_seed))
update_size := min(len(b), rand.int_max(8192))
if update_size > 4096 {
update_size %= 73
}
+1 -1
View File
@@ -5,7 +5,7 @@ set TEST_ARGS=-fast-tests
set TEST_ARGS=-no-random
set TEST_ARGS=
set OUT_NAME=math_big_test_library.dll
set COMMON=-build-mode:shared -show-timings -no-bounds-check -define:MATH_BIG_EXE=false -vet -strict-style -define:ODIN_TEST_FANCY=false
set COMMON=-build-mode:shared -show-timings -no-bounds-check -define:MATH_BIG_EXE=false -vet -strict-style
echo ---
echo Running core:math/big tests
echo ---
@@ -0,0 +1,51 @@
package test_core_math_fixed
import "core:math/fixed"
import "core:testing"
@test
test_fixed_4_4_unsigned :: proc(t: ^testing.T) {
I_SHIFT :: 4
F_MASK :: 15
F_ULP :: 0.0625
Fixed :: fixed.Fixed(u8, 4)
for c in 0..<256 {
raw := u8(c)
fv := transmute(Fixed)raw
i := raw >> I_SHIFT
f := raw & F_MASK
expected := f64(i) + F_ULP * f64(f)
testing.expectf(t, fixed.to_f64(fv) == expected, "Expected Fixed(u8, 4)(%v) to equal %.5f, got %.5f", raw, expected, fixed.to_f64(fv))
}
}
@test
test_fixed_4_4_signed :: proc(t: ^testing.T) {
I_SHIFT :: 4
F_MASK :: 15
F_ULP :: 0.0625
Fixed :: fixed.Fixed(i8, 4)
for c in 0..<256 {
raw := i8(c)
fv := transmute(Fixed)raw
f := raw & F_MASK
expected: f64
if c < 128 {
i := raw >> I_SHIFT
expected = f64(i) + F_ULP * f64(f)
} else if c == 128 {
expected = 8.0
} else if c > 128 {
i := i8(-8)
i += (raw & 0b0111_0000) >> I_SHIFT
expected = f64(i) + F_ULP * f64(f)
}
testing.expectf(t, fixed.to_f64(fv) == expected, "Expected Fixed(i8, 4)(%v, %v) to equal %.5f, got %.5f", c, raw, expected, fixed.to_f64(fv))
}
}
@@ -0,0 +1,35 @@
package test_core_math_rand
import "core:math/rand"
import "core:testing"
@test
test_default_rand_determinism :: proc(t: ^testing.T) {
rand.reset(13)
first_value := rand.int127()
rand.reset(13)
second_value := rand.int127()
testing.expect(t, first_value == second_value, "Context default random number generator is non-deterministic.")
}
@test
test_default_rand_determinism_user_set :: proc(t: ^testing.T) {
rng_state_1 := rand.create(13)
rng_state_2 := rand.create(13)
rng_1 := rand.default_random_generator(&rng_state_1)
rng_2 := rand.default_random_generator(&rng_state_2)
first_value, second_value: i128
{
context.random_generator = rng_1
first_value = rand.int127()
}
{
context.random_generator = rng_2
second_value = rand.int127()
}
testing.expect(t, first_value == second_value, "User-set default random number generator is non-deterministic.")
}
+80
View File
@@ -0,0 +1,80 @@
package test_core_mem
import "core:testing"
import "core:mem"
expect_pool_allocation :: proc(t: ^testing.T, expected_used_bytes, num_bytes, alignment: int) {
pool: mem.Dynamic_Pool
mem.dynamic_pool_init(pool = &pool, alignment = alignment)
pool_allocator := mem.dynamic_pool_allocator(&pool)
element, err := mem.alloc(num_bytes, alignment, pool_allocator)
testing.expect(t, err == .None)
testing.expect(t, element != nil)
expected_bytes_left := pool.block_size - expected_used_bytes
testing.expectf(t, pool.bytes_left == expected_bytes_left,
`
Allocated data with size %v bytes, expected %v bytes left, got %v bytes left, off by %v bytes.
Pool:
block_size = %v
out_band_size = %v
alignment = %v
unused_blocks = %v
used_blocks = %v
out_band_allocations = %v
current_block = %v
current_pos = %v
bytes_left = %v
`,
num_bytes, expected_bytes_left, pool.bytes_left, expected_bytes_left - pool.bytes_left,
pool.block_size,
pool.out_band_size,
pool.alignment,
pool.unused_blocks,
pool.used_blocks,
pool.out_band_allocations,
pool.current_block,
pool.current_pos,
pool.bytes_left,
)
mem.dynamic_pool_destroy(&pool)
testing.expect(t, pool.used_blocks == nil)
}
expect_pool_allocation_out_of_band :: proc(t: ^testing.T, num_bytes, out_band_size: int) {
testing.expect(t, num_bytes >= out_band_size, "Sanity check failed, your test call is flawed! Make sure that num_bytes >= out_band_size!")
pool: mem.Dynamic_Pool
mem.dynamic_pool_init(pool = &pool, out_band_size = out_band_size)
pool_allocator := mem.dynamic_pool_allocator(&pool)
element, err := mem.alloc(num_bytes, allocator = pool_allocator)
testing.expect(t, err == .None)
testing.expect(t, element != nil)
testing.expectf(t, pool.out_band_allocations != nil,
"Allocated data with size %v bytes, which is >= out_of_band_size and it should be in pool.out_band_allocations, but isn't!",
)
mem.dynamic_pool_destroy(&pool)
testing.expect(t, pool.out_band_allocations == nil)
}
@(test)
test_dynamic_pool_alloc_aligned :: proc(t: ^testing.T) {
expect_pool_allocation(t, expected_used_bytes = 16, num_bytes = 16, alignment=8)
}
@(test)
test_dynamic_pool_alloc_unaligned :: proc(t: ^testing.T) {
expect_pool_allocation(t, expected_used_bytes = 8, num_bytes=1, alignment=8)
expect_pool_allocation(t, expected_used_bytes = 16, num_bytes=9, alignment=8)
}
@(test)
test_dynamic_pool_alloc_out_of_band :: proc(t: ^testing.T) {
expect_pool_allocation_out_of_band(t, num_bytes = 128, out_band_size = 128)
expect_pool_allocation_out_of_band(t, num_bytes = 129, out_band_size = 128)
}
+101 -2
View File
@@ -18,6 +18,7 @@ import "core:sync"
import "core:time"
import "core:thread"
import "core:fmt"
import "core:log"
@test
address_parsing_test :: proc(t: ^testing.T) {
@@ -216,6 +217,8 @@ IP_Address_Parsing_Test_Vectors :: []IP_Address_Parsing_Test_Vector{
ENDPOINT_TWO_SERVERS := net.Endpoint{net.IP4_Address{127, 0, 0, 1}, 9991}
ENDPOINT_CLOSED_PORT := net.Endpoint{net.IP4_Address{127, 0, 0, 1}, 9992}
ENDPOINT_SERVER_SENDS := net.Endpoint{net.IP4_Address{127, 0, 0, 1}, 9993}
ENDPOINT_UDP_ECHO := net.Endpoint{net.IP4_Address{127, 0, 0, 1}, 9994}
ENDPOINT_NONBLOCK := net.Endpoint{net.IP4_Address{127, 0, 0, 1}, 9995}
@(test)
two_servers_binding_same_endpoint :: proc(t: ^testing.T) {
@@ -256,7 +259,7 @@ client_sends_server_data :: proc(t: ^testing.T) {
}
tcp_client :: proc(thread_data: rawptr) {
r := transmute(^Thread_Data)thread_data
r := cast(^Thread_Data)thread_data
defer sync.wait_group_done(r.wg)
@@ -271,7 +274,7 @@ client_sends_server_data :: proc(t: ^testing.T) {
}
tcp_server :: proc(thread_data: rawptr) {
r := transmute(^Thread_Data)thread_data
r := cast(^Thread_Data)thread_data
defer sync.wait_group_done(r.wg)
@@ -516,6 +519,102 @@ join_url_test :: proc(t: ^testing.T) {
}
}
@test
test_udp_echo :: proc(t: ^testing.T) {
server, make_server_err := net.make_unbound_udp_socket(.IP4)
if !testing.expect_value(t, make_server_err, nil) {
return
}
defer net.close(server)
bind_server_err := net.bind(server, ENDPOINT_UDP_ECHO)
if !testing.expect_value(t, bind_server_err, nil) {
return
}
client, make_client_err := net.make_unbound_udp_socket(.IP4)
if !testing.expect_value(t, make_client_err, nil) {
return
}
defer net.close(client)
msg := "Hellope world!"
buf: [64]u8
bytes_written, send_err := net.send_udp(client, transmute([]u8)msg[:], ENDPOINT_UDP_ECHO)
if !testing.expect_value(t, send_err, nil) {
return
}
if !testing.expect_value(t, bytes_written, len(msg)) {
return
}
bytes_read, _, read_err := net.recv_udp(server, buf[:])
if !testing.expect_value(t, read_err, nil) {
return
}
if !testing.expect_value(t, bytes_read, len(msg)) {
return
}
testing.expect_value(t, msg, transmute(string)buf[:bytes_read])
}
@test
test_dns_resolve :: proc(t: ^testing.T) {
// NOTE: This test depends on external factors, so if it fails, an IP
// address may have changed or become unavailable.
// The net API returns only one address per protocol version, and DNS
// records can store many, so we'll have to check all possibilities.
ep4, ep6, resolve_err := net.resolve("dns.quad9.net")
if !testing.expect_value(t, resolve_err, nil) {
return
}
ip4, ip4_ok := ep4.address.(net.IP4_Address)
if !testing.expect(t, ip4_ok, "Unable to resolve IP4") {
return
}
valid_ip4_a := net.IP4_Address{ 9, 9, 9, 9}
valid_ip4_b := net.IP4_Address{149, 112, 112, 112}
if ip4 != valid_ip4_a && ip4 != valid_ip4_b {
log.errorf("DNS resolved to invalid IP4: %v, expected %v or %v", ip4, valid_ip4_a, valid_ip4_b)
}
ip6, ip6_ok := ep6.address.(net.IP6_Address)
if !testing.expect(t, ip6_ok, "Unable to resolve IP6") {
return
}
valid_ip6_a := net.IP6_Address{0x2620, 0xfe, 0, 0, 0, 0, 0, 9}
valid_ip6_b := net.IP6_Address{0x2620, 0xfe, 0, 0, 0, 0, 0, 0xfe}
if ip6 != valid_ip6_a && ip6 != valid_ip6_b {
log.errorf("DNS resolved to invalid IP6: %v, expected %v or %v", ip6, valid_ip6_a, valid_ip6_b)
}
}
@test
test_nonblocking_option :: proc(t: ^testing.T) {
server, listen_err := net.listen_tcp(ENDPOINT_NONBLOCK)
if !testing.expect_value(t, listen_err, nil) {
return
}
defer net.close(server)
testing.set_fail_timeout(t, 2 * time.Second)
// If the nonblocking option isn't set correctly in the operating system,
// this should block until the timeout hits.
net.set_blocking(server, false)
_, _, accept_err := net.accept_tcp(server)
if !testing.expect_value(t, accept_err, net.Accept_Error.Would_Block) {
return
}
}
@(private)
address_to_binstr :: proc(address: net.Address) -> (binstr: string) {
switch t in address {
+4
View File
@@ -17,13 +17,16 @@ download_assets :: proc() {
@(require) import "encoding/hex"
@(require) import "encoding/hxa"
@(require) import "encoding/json"
@(require) import "encoding/uuid"
@(require) import "encoding/varint"
@(require) import "encoding/xml"
@(require) import "flags"
@(require) import "fmt"
@(require) import "math"
@(require) import "math/big"
@(require) import "math/linalg/glsl"
@(require) import "math/noise"
@(require) import "math/rand"
@(require) import "mem"
@(require) import "net"
@(require) import "odin"
@@ -37,3 +40,4 @@ download_assets :: proc() {
@(require) import "text/match"
@(require) import "thread"
@(require) import "time"
@(require) import "unicode"
@@ -35,12 +35,10 @@ test_split_list_windows :: proc(t: ^testing.T) {
assert(i == d.i, fmt.tprintf("wrong data index: i %d != d.i %d\n", i, d.i))
r := filepath.split_list(d.v)
defer delete_split(r)
testing.expect(t, len(r) == len(d.e), fmt.tprintf("i:%d %s(%s) len(r) %d != len(d.e) %d",
i, #procedure, d.v, len(r), len(d.e)))
testing.expect(t, len(r) == len(d.e), fmt.tprintf("i:%d %s(%s) len(r) %d != len(d.e) %d", i, #procedure, d.v, len(r), len(d.e)))
if len(r) == len(d.e) {
for _, j in r {
testing.expect(t, r[j] == d.e[j], fmt.tprintf("i:%d %s(%v) -> %v[%d] != %v",
i, #procedure, d.v, r[j], j, d.e[j]))
testing.expect(t, r[j] == d.e[j], fmt.tprintf("i:%d %s(%v) -> %v[%d] != %v", i, #procedure, d.v, r[j], j, d.e[j]))
}
}
}
+70 -9
View File
@@ -3,6 +3,7 @@ package test_core_slice
import "core:slice"
import "core:testing"
import "core:math/rand"
import "core:log"
@test
test_sort_with_indices :: proc(t: ^testing.T) {
@@ -10,7 +11,7 @@ test_sort_with_indices :: proc(t: ^testing.T) {
test_sizes :: []int{7, 13, 347, 1031, 10111, 100003}
for test_size in test_sizes {
r := rand.create(t.seed)
rand.reset(t.seed)
vals := make([]u64, test_size)
r_idx := make([]int, test_size) // Reverse index
@@ -21,7 +22,7 @@ test_sort_with_indices :: proc(t: ^testing.T) {
// Set up test values
for _, i in vals {
vals[i] = rand.uint64(&r)
vals[i] = rand.uint64()
}
// Sort
@@ -29,7 +30,7 @@ test_sort_with_indices :: proc(t: ^testing.T) {
defer delete(f_idx)
// Verify sorted test values
rand.init(&r, t.seed)
rand.reset(t.seed)
for v, i in f_idx {
r_idx[v] = i
@@ -45,7 +46,7 @@ test_sort_with_indices :: proc(t: ^testing.T) {
}
}
idx_pass := vals[r_idx[i]] == rand.uint64(&r)
idx_pass := vals[r_idx[i]] == rand.uint64()
testing.expect(t, idx_pass, "Expected index to have been sorted")
if !idx_pass {
break
@@ -61,7 +62,7 @@ test_sort_by_indices :: proc(t: ^testing.T) {
test_sizes :: []int{7, 13, 347, 1031, 10111, 100003}
for test_size in test_sizes {
r := rand.create(t.seed)
rand.reset(t.seed)
vals := make([]u64, test_size)
r_idx := make([]int, test_size) // Reverse index
@@ -72,7 +73,7 @@ test_sort_by_indices :: proc(t: ^testing.T) {
// Set up test values
for _, i in vals {
vals[i] = rand.uint64(&r)
vals[i] = rand.uint64()
}
// Sort
@@ -80,7 +81,7 @@ test_sort_by_indices :: proc(t: ^testing.T) {
defer delete(f_idx)
// Verify sorted test values
rand.init(&r, t.seed)
rand.reset(t.seed)
{
indices := make([]int, test_size)
@@ -200,12 +201,12 @@ test_permutation_iterator :: proc(t: ^testing.T) {
permutations_counted: int
for slice.permute(&iter) {
n := 0
for item, index in s {
for item in s {
n *= 10
n += item
}
if n in seen {
testing.fail_now(t, "Permutation iterator made a duplicate permutation.")
log.error("Permutation iterator made a duplicate permutation.")
return
}
seen[n] = true
@@ -215,3 +216,63 @@ test_permutation_iterator :: proc(t: ^testing.T) {
testing.expect_value(t, len(seen), FAC_5)
testing.expect_value(t, permutations_counted, FAC_5)
}
// Test inputs from #3276 and #3769
UNIQUE_TEST_VECTORS :: [][2][]int{
{{2,2,2}, {2}},
{{1,1,1,2,2,3,3,3,3}, {1,2,3}},
{{1,2,4,4,5}, {1,2,4,5}},
}
@test
test_unique :: proc(t: ^testing.T) {
for v in UNIQUE_TEST_VECTORS {
assorted := v[0]
expected := v[1]
uniq := slice.unique(assorted)
testing.expectf(t, slice.equal(uniq, expected), "Expected slice.uniq(%v) == %v, got %v", v[0], v[1], uniq)
}
for v in UNIQUE_TEST_VECTORS {
assorted := v[0]
expected := v[1]
uniq := slice.unique_proc(assorted, proc(a, b: int) -> bool {
return a == b
})
testing.expectf(t, slice.equal(uniq, expected), "Expected slice.unique_proc(%v, ...) == %v, got %v", v[0], v[1], uniq)
}
r := rand.create(t.seed)
context.random_generator = rand.default_random_generator(&r)
// 10_000 random tests
for _ in 0..<10_000 {
assorted: [dynamic]i64
expected: [dynamic]i64
// Prime with 1 value
old := rand.int63()
append(&assorted, old)
append(&expected, old)
// Add 99 additional random values
for _ in 1..<100 {
new := rand.int63()
append(&assorted, new)
if old != new {
append(&expected, new)
}
old = new
}
original := slice.clone(assorted[:])
uniq := slice.unique(assorted[:])
testing.expectf(t, slice.equal(uniq, expected[:]), "Expected slice.uniq(%v) == %v, got %v", original, expected, uniq)
delete(assorted)
delete(original)
delete(expected)
}
}
+21 -19
View File
@@ -5,6 +5,7 @@ import "core:testing"
import "core:text/i18n"
T :: i18n.get
Tn :: i18n.get_n
Test :: struct {
section: string,
@@ -47,7 +48,8 @@ test_custom_pluralizer :: proc(t: ^testing.T) {
{"", "Message1/plural", "This is message 1", 1},
{"", "Message1/plural", "This is message 1 - plural A", 1_000_000},
{"", "Message1/plural", "This is message 1 - plural B", 42},
// This isn't in the catalog, so should ruturn the key.
// This isn't in the catalog, so should return the key.
{"", "Come visit us on Discord!", "Come visit us on Discord!", 1},
},
})
@@ -61,11 +63,11 @@ test_mixed_context :: proc(t: ^testing.T) {
plural = nil,
tests = {
// These are in the catalog.
{"", "Message1", "This is message 1 without Context", 1},
{"Context", "Message1", "This is message 1 with Context", 1},
{"", "Message1", "This is message 1 without Context",-1},
{"Context", "Message1", "This is message 1 with Context", -1},
// This isn't in the catalog, so should ruturn the key.
{"", "Come visit us on Discord!", "Come visit us on Discord!", 1},
{"", "Come visit us on Discord!", "Come visit us on Discord!", -1},
},
})
}
@@ -90,15 +92,15 @@ test_nl_mo :: proc(t: ^testing.T) {
plural = nil, // Default pluralizer
tests = {
// These are in the catalog.
{"", "There are 69,105 leaves here.", "Er zijn hier 69.105 bladeren.", 1},
{"", "Hellope, World!", "Hallo, Wereld!", 1},
{"", "There are 69,105 leaves here.", "Er zijn hier 69.105 bladeren.", -1},
{"", "Hellope, World!", "Hallo, Wereld!", -1},
{"", "There is %d leaf.\n", "Er is %d blad.\n", 1},
{"", "There are %d leaves.\n", "Er is %d blad.\n", 1},
{"", "There is %d leaf.\n", "Er zijn %d bladeren.\n", 42},
{"", "There are %d leaves.\n", "Er zijn %d bladeren.\n", 42},
// This isn't in the catalog, so should ruturn the key.
{"", "Come visit us on Discord!", "Come visit us on Discord!", 1},
{"", "Come visit us on Discord!", "Come visit us on Discord!", -1},
},
})
}
@@ -111,15 +113,15 @@ test_qt_linguist :: proc(t: ^testing.T) {
plural = nil, // Default pluralizer
tests = {
// These are in the catalog.
{"Page", "Text for translation", "Tekst om te vertalen", 1},
{"Page", "Also text to translate", "Ook tekst om te vertalen", 1},
{"installscript", "99 bottles of beer on the wall", "99 flessen bier op de muur", 1},
{"Page", "Text for translation", "Tekst om te vertalen", -1},
{"Page", "Also text to translate", "Ook tekst om te vertalen", -1},
{"installscript", "99 bottles of beer on the wall", "99 flessen bier op de muur", -1},
{"apple_count", "%d apple(s)", "%d appel", 1},
{"apple_count", "%d apple(s)", "%d appels", 42},
// These aren't in the catalog, so should ruturn the key.
{"", "Come visit us on Discord!", "Come visit us on Discord!", 1},
{"Fake_Section", "Come visit us on Discord!", "Come visit us on Discord!", 1},
{"", "Come visit us on Discord!", "Come visit us on Discord!", -1},
{"Fake_Section", "Come visit us on Discord!", "Come visit us on Discord!", -1},
},
})
}
@@ -133,16 +135,16 @@ test_qt_linguist_merge_sections :: proc(t: ^testing.T) {
options = {merge_sections = true},
tests = {
// All of them are now in section "", lookup with original section should return the key.
{"", "Text for translation", "Tekst om te vertalen", 1},
{"", "Also text to translate", "Ook tekst om te vertalen", 1},
{"", "99 bottles of beer on the wall", "99 flessen bier op de muur", 1},
{"", "Text for translation", "Tekst om te vertalen", -1},
{"", "Also text to translate", "Ook tekst om te vertalen", -1},
{"", "99 bottles of beer on the wall", "99 flessen bier op de muur", -1},
{"", "%d apple(s)", "%d appel", 1},
{"", "%d apple(s)", "%d appels", 42},
// All of them are now in section "", lookup with original section should return the key.
{"Page", "Text for translation", "Text for translation", 1},
{"Page", "Also text to translate", "Also text to translate", 1},
{"installscript", "99 bottles of beer on the wall", "99 bottles of beer on the wall", 1},
{"Page", "Text for translation", "Text for translation", -1},
{"Page", "Also text to translate", "Also text to translate", -1},
{"installscript", "99 bottles of beer on the wall", "99 bottles of beer on the wall", -1},
{"apple_count", "%d apple(s)", "%d apple(s)", 1},
{"apple_count", "%d apple(s)", "%d apple(s)", 42},
},
@@ -175,7 +177,7 @@ test :: proc(t: ^testing.T, suite: Test_Suite, loc := #caller_location) {
if err == .None {
for test in suite.tests {
val := T(test.section, test.key, test.n, cat)
val := test.n > -1 ? Tn(test.section, test.key, test.n, cat): T(test.section, test.key, cat)
testing.expectf(t, val == test.val, "Expected key `%v` from section `%v`'s form for value `%v` to equal `%v`, got `%v`", test.key, test.section, test.n, test.val, val, loc=loc)
}
}
+135
View File
@@ -0,0 +1,135 @@
package test_core_unicode
import "core:log"
import "core:testing"
import "core:unicode/utf8"
Test_Case :: struct {
str: string,
expected_clusters: int,
}
run_test_cases :: proc(t: ^testing.T, test_cases: []Test_Case, loc := #caller_location) {
failed := 0
for c, i in test_cases {
log.debugf("(#% 4i) %q ...", i, c.str)
result, _, _ := utf8.grapheme_count(c.str)
if !testing.expectf(t, result == c.expected_clusters,
"(#% 4i) graphemes: %i != %i, %q %s", i, result, c.expected_clusters, c.str, c.str,
loc = loc)
{
failed += 1
}
}
log.logf(.Error if failed > 0 else .Info, "% 4i/% 4i test cases failed.", failed, len(test_cases), location = loc)
}
@test
test_official_gcb_cases :: proc(t: ^testing.T) {
run_test_cases(t, official_grapheme_break_test_cases)
}
@test
test_official_emoji_cases :: proc(t: ^testing.T) {
run_test_cases(t, official_emoji_test_cases)
}
@test
test_grapheme_byte_index_segmentation :: proc(t: ^testing.T) {
SAMPLE_1 :: "\U0001F600"
SAMPLE_2 :: "\U0001F3F4\U000E0067\U000E0062\U000E0065\U000E006E\U000E0067\U000E007F"
SAMPLE_3 :: "\U0001F468\U0001F3FB\u200D\U0001F9B0"
str := SAMPLE_1 + SAMPLE_2 + SAMPLE_3 + SAMPLE_2 + SAMPLE_1
graphemes, _, _, _ := utf8.decode_grapheme_clusters(str)
defer delete(graphemes)
defer if testing.failed(t) {
log.infof("%#v\n%q\n%v", graphemes, str, transmute([]u8)str)
}
if !testing.expect_value(t, len(graphemes), 5) {
return
}
testing.expect_value(t, graphemes[0].rune_index, 0)
testing.expect_value(t, graphemes[1].rune_index, 1)
testing.expect_value(t, graphemes[2].rune_index, 8)
testing.expect_value(t, graphemes[3].rune_index, 12)
testing.expect_value(t, graphemes[4].rune_index, 19)
grapheme_1 := str[graphemes[0].byte_index:graphemes[1].byte_index]
grapheme_2 := str[graphemes[1].byte_index:graphemes[2].byte_index]
grapheme_3 := str[graphemes[2].byte_index:graphemes[3].byte_index]
grapheme_4 := str[graphemes[3].byte_index:graphemes[4].byte_index]
grapheme_5 := str[graphemes[4].byte_index:]
testing.expectf(t, grapheme_1 == SAMPLE_1, "expected %q, got %q", SAMPLE_1, grapheme_1)
testing.expectf(t, grapheme_2 == SAMPLE_2, "expected %q, got %q", SAMPLE_2, grapheme_2)
testing.expectf(t, grapheme_3 == SAMPLE_3, "expected %q, got %q", SAMPLE_3, grapheme_3)
testing.expectf(t, grapheme_4 == SAMPLE_2, "expected %q, got %q", SAMPLE_2, grapheme_2)
testing.expectf(t, grapheme_5 == SAMPLE_1, "expected %q, got %q", SAMPLE_1, grapheme_1)
}
@test
test_width :: proc(t: ^testing.T) {
{
str := "He\u200dllo"
graphemes, _, width := utf8.grapheme_count(str)
testing.expect_value(t, graphemes, 5)
testing.expect_value(t, width, 5)
}
{
// Note that a zero-width space is still considered a grapheme as far
// as the specification is concerned.
str := "He\u200bllo"
graphemes, _, width := utf8.grapheme_count(str)
testing.expect_value(t, graphemes, 6)
testing.expect_value(t, width, 5)
}
{
str := "\U0001F926\U0001F3FC\u200D\u2642"
graphemes, _, width := utf8.grapheme_count(str)
testing.expect_value(t, graphemes, 1)
testing.expect_value(t, width, 2)
}
{
str := "H̷e̶l̵l̸o̴p̵e̷ ̸w̶o̸r̵l̶d̵!̴"
graphemes, _, width := utf8.grapheme_count(str)
testing.expect_value(t, graphemes, 14)
testing.expect_value(t, width, 14)
}
{
str := "aカ.ヒフ"
graphemes, grapheme_count, _, width := utf8.decode_grapheme_clusters(str)
defer delete(graphemes)
testing.expect_value(t, grapheme_count, 5)
testing.expect_value(t, width, 8)
if grapheme_count == 5 {
testing.expect_value(t, graphemes[0].width, 1)
testing.expect_value(t, graphemes[1].width, 2)
testing.expect_value(t, graphemes[2].width, 1)
testing.expect_value(t, graphemes[3].width, 2)
testing.expect_value(t, graphemes[4].width, 2)
}
}
{
str := "いろはにほへ"
graphemes, _, width := utf8.grapheme_count(str)
testing.expect_value(t, graphemes, 6)
testing.expect_value(t, width, 12)
}
{
str := "舍利弗,是諸法空相,不生不滅,不垢不淨,不增不減。"
graphemes, _, width := utf8.grapheme_count(str)
testing.expect_value(t, graphemes, 25)
testing.expect_value(t, width, 50)
}
}
File diff suppressed because it is too large Load Diff
+41 -34
View File
@@ -16,10 +16,10 @@ map_insert_random_key_value :: proc(t: ^testing.T) {
defer delete(m)
unique_keys := 0
r := rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
for _ in 0..<entries {
k := rand.int63(&r)
v := rand.int63(&r)
k := rand.int63()
v := rand.int63()
if k not_in m {
unique_keys += 1
@@ -36,12 +36,12 @@ map_insert_random_key_value :: proc(t: ^testing.T) {
testing.expectf(t, len(m) == unique_keys, "Expected len(map) to equal %v, got %v", unique_keys, len(m))
// Reset randomizer and verify
r = rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
num_fails := 0
for _ in 0..<entries {
k := rand.int63(&r)
v := rand.int63(&r)
k := rand.int63()
v := rand.int63()
cond := m[k] == v
if !cond {
@@ -66,10 +66,11 @@ map_update_random_key_value :: proc(t: ^testing.T) {
defer delete(m)
unique_keys := 0
r := rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
for _ in 0..<entries {
k := rand.int63(&r)
v := rand.int63(&r)
k := rand.int63()
v := rand.int63()
if k not_in m {
unique_keys += 1
@@ -88,21 +89,22 @@ map_update_random_key_value :: proc(t: ^testing.T) {
half_entries := entries / 2
// Reset randomizer and update half the entries
r = rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
for _ in 0..<half_entries {
k := rand.int63(&r)
v := rand.int63(&r)
k := rand.int63()
v := rand.int63()
m[k] = v + 42
}
// Reset randomizer and verify
r = rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
num_fails := 0
for i in 0..<entries {
k := rand.int63(&r)
v := rand.int63(&r)
k := rand.int63()
v := rand.int63()
diff := i64(42) if i < half_entries else i64(0)
cond := m[k] == (v + diff)
@@ -128,10 +130,11 @@ map_delete_random_key_value :: proc(t: ^testing.T) {
defer delete(m)
unique_keys := 0
r := rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
for _ in 0..<entries {
k := rand.int63(&r)
v := rand.int63(&r)
k := rand.int63()
v := rand.int63()
if k not_in m {
unique_keys += 1
@@ -150,21 +153,22 @@ map_delete_random_key_value :: proc(t: ^testing.T) {
half_entries := entries / 2
// Reset randomizer and delete half the entries
r = rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
for _ in 0..<half_entries {
k := rand.int63(&r)
_ = rand.int63(&r)
k := rand.int63()
_ = rand.int63()
delete_key(&m, k)
}
// Reset randomizer and verify
r = rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
num_fails := 0
for i in 0..<entries {
k := rand.int63(&r)
v := rand.int63(&r)
k := rand.int63()
v := rand.int63()
if i < half_entries {
if k in m {
@@ -206,9 +210,10 @@ set_insert_random_key_value :: proc(t: ^testing.T) {
defer delete(m)
unique_keys := 0
r := rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
for _ in 0..<entries {
k := rand.int63(&r)
k := rand.int63()
if k not_in m {
unique_keys += 1
}
@@ -224,11 +229,11 @@ set_insert_random_key_value :: proc(t: ^testing.T) {
testing.expectf(t, len(m) == unique_keys, "Expected len(map) to equal %v, got %v", unique_keys, len(m))
// Reset randomizer and verify
r = rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
num_fails := 0
for _ in 0..<entries {
k := rand.int63(&r)
k := rand.int63()
cond := k in m
if !cond {
@@ -253,9 +258,10 @@ set_delete_random_key_value :: proc(t: ^testing.T) {
defer delete(m)
unique_keys := 0
r := rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
for _ in 0..<entries {
k := rand.int63(&r)
k := rand.int63()
if k not_in m {
unique_keys += 1
@@ -274,18 +280,19 @@ set_delete_random_key_value :: proc(t: ^testing.T) {
half_entries := entries / 2
// Reset randomizer and delete half the entries
r = rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
for _ in 0..<half_entries {
k := rand.int63(&r)
k := rand.int63()
delete_key(&m, k)
}
// Reset randomizer and verify
r = rand.create(t.seed + seed_incr)
rand.reset(t.seed + seed_incr)
num_fails := 0
for i in 0..<entries {
k := rand.int63(&r)
k := rand.int63()
if i < half_entries {
if k in m {