Browse Source

Add xxhash tests to CI.

Jeroen van Rijn 4 years ago
parent
commit
637685316d
5 changed files with 143 additions and 84 deletions
  1. 1 82
      core/hash/xxhash/common.odin
  2. 2 1
      core/time/perf.odin
  3. 4 1
      tests/core/Makefile
  4. 5 0
      tests/core/build.bat
  5. 131 0
      tests/core/hash/test_core_hash.odin

+ 1 - 82
core/hash/xxhash/common.odin

@@ -79,85 +79,4 @@ XXH64_read64 :: #force_inline proc(buf: []u8, alignment: Alignment) -> (res: u64
 		mem_copy(&b, raw_data(buf[:]), 8)
 		return u64(b)
 	}
-}
-
-
-/*
-	Benchmarks
-*/
-
-setup_xxhash :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
-	assert(options != nil)
-
-	options.input = make([]u8, options.bytes, allocator)
-	return nil if len(options.input) == options.bytes else .Allocation_Error
-}
-
-teardown_xxhash :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
-	assert(options != nil)
-
-	delete(options.input)
-	return nil
-}
-
-benchmark_xxhash32 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
-	buf := options.input
-
-	for _ in 0..=options.rounds {
-		_ = XXH32(buf)
-	}
-	options.count     = options.rounds
-	options.processed = options.rounds * options.bytes
-	return nil
-}
-
-benchmark_xxhash64 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
-	buf := options.input
-
-	for _ in 0..=options.rounds {
-		_ = XXH64(buf)
-	}
-	options.count     = options.rounds
-	options.processed = options.rounds * options.bytes
-	return nil
-}
-
-benchmark_print :: proc(name: string, options: ^time.Benchmark_Options) {
-	fmt.printf("\t[%v] %v rounds, %v bytes procesed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s\n",
-		name,
-		options.rounds,
-		options.processed,
-		time.duration_nanoseconds(options.duration),
-		options.rounds_per_second,
-		options.megabytes_per_second,
-	)
-}
-
-@test
-benchmark_runner :: proc(t: ^testing.T) {
-	fmt.println("Starting benchmarks:")
-
-	options := &time.Benchmark_Options{
-		rounds   = 1_000,
-		bytes    = 100,
-		setup    = setup_xxhash,
-		bench    = benchmark_xxhash32,
-		teardown = teardown_xxhash,
-	}
-	err := time.benchmark(options, context.allocator)
-	benchmark_print("xxhash32 100 bytes", options)
-
-	options.bytes = 1_000_000
-	err = time.benchmark(options, context.allocator)
-	benchmark_print("xxhash32 1_000_000 bytes", options)
-
-	options.bytes  = 100
-	options.bench = benchmark_xxhash64
-	err = time.benchmark(options, context.allocator)
-	benchmark_print("xxhash64 100 bytes", options)
-
-	options.bytes = 1_000_000
-	err = time.benchmark(options, context.allocator)
-	benchmark_print("xxhash64 1_000_000 bytes", options)
-}
-
+}

+ 2 - 1
core/time/perf.odin

@@ -60,7 +60,8 @@ Benchmark_Options :: struct {
 
 	count:     int,
 	processed: int,
-	output:    []u8,
+	output:    []u8, // Unused for hash benchmarks
+	hash:      u128,
 
 	/*
 		Performance

+ 4 - 1
tests/core/Makefile

@@ -1,7 +1,7 @@
 ODIN=../../odin
 PYTHON=$(shell which python3)
 
-all: download_test_assets image_test compress_test strings_test
+all: download_test_assets image_test compress_test strings_test hash_test
 
 download_test_assets:
 	$(PYTHON) download_assets.py
@@ -14,3 +14,6 @@ compress_test:
 
 strings_test:
 	$(ODIN) run strings/test_core_strings.odin
+
+hash_test:
+	$(ODIN) run hash/test_core_hash.odin -o:size -no-bounds-check

+ 5 - 0
tests/core/build.bat

@@ -16,3 +16,8 @@ echo ---
 echo Running core:strings tests
 echo ---
 %PATH_TO_ODIN% run strings %COMMON%
+
+echo ---
+echo Running core:hash tests
+echo ---
+%PATH_TO_ODIN% run hash %COMMON% -o:size

+ 131 - 0
tests/core/hash/test_core_hash.odin

@@ -0,0 +1,131 @@
+package test_core_image
+
+import "core:hash/xxhash"
+import "core:time"
+import "core:testing"
+import "core:fmt"
+
+TEST_count := 0
+TEST_fail  := 0
+
+when ODIN_TEST {
+    expect  :: testing.expect
+    log     :: testing.log
+} else {
+    expect  :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) {
+        fmt.printf("[%v] ", loc)
+        TEST_count += 1
+        if !condition {
+            TEST_fail += 1
+            fmt.println(" FAIL:", message)
+            return
+        }
+        fmt.println(" PASS")
+    }
+    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_benchmark_runner(&t)
+    fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
+}
+
+/*
+    Benchmarks
+*/
+
+setup_xxhash :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
+    assert(options != nil)
+
+    options.input = make([]u8, options.bytes, allocator)
+    return nil if len(options.input) == options.bytes else .Allocation_Error
+}
+
+teardown_xxhash :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
+    assert(options != nil)
+
+    delete(options.input)
+    return nil
+}
+
+benchmark_xxhash32 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
+    buf := options.input
+
+    h: u32
+    for _ in 0..=options.rounds {
+        h = xxhash.XXH32(buf)
+    }
+    options.count     = options.rounds
+    options.processed = options.rounds * options.bytes
+    options.hash      = u128(h)
+    return nil
+}
+
+benchmark_xxhash64 :: proc(options: ^time.Benchmark_Options, allocator := context.allocator) -> (err: time.Benchmark_Error) {
+    buf := options.input
+
+    h: u64
+    for _ in 0..=options.rounds {
+        h = xxhash.XXH64(buf)
+    }
+    options.count     = options.rounds
+    options.processed = options.rounds * options.bytes
+    options.hash      = u128(h)
+    return nil
+}
+
+benchmark_print :: proc(name: string, options: ^time.Benchmark_Options) {
+    fmt.printf("\t[%v] %v rounds, %v bytes procesed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s\n",
+        name,
+        options.rounds,
+        options.processed,
+        time.duration_nanoseconds(options.duration),
+        options.rounds_per_second,
+        options.megabytes_per_second,
+    )
+}
+
+@test
+test_benchmark_runner :: proc(t: ^testing.T) {
+    fmt.println("Starting benchmarks:")
+
+    name    := "xxhash32 100 zero bytes"
+    options := &time.Benchmark_Options{
+        rounds   = 1_000,
+        bytes    = 100,
+        setup    = setup_xxhash,
+        bench    = benchmark_xxhash32,
+        teardown = teardown_xxhash,
+    }
+
+    err  := time.benchmark(options, context.allocator)
+    expect(t, err == nil, name)
+    expect(t, options.hash == 0x85f6413c, name)
+    benchmark_print(name, options)
+
+    name = "xxhash32 1 MiB zero bytes"
+    options.bytes = 1_048_576
+    err = time.benchmark(options, context.allocator)
+    expect(t, err == nil, name)
+    expect(t, options.hash == 0x9430f97f, name)
+    benchmark_print(name, options)
+
+    name = "xxhash64 100 zero bytes"
+    options.bytes  = 100
+    options.bench = benchmark_xxhash64
+    err = time.benchmark(options, context.allocator)
+    expect(t, err == nil, name)
+    expect(t, options.hash == 0x17bb1103c92c502f, name)
+    benchmark_print(name, options)
+
+    name = "xxhash64 1 MiB zero bytes"
+    options.bytes = 1_048_576
+    err = time.benchmark(options, context.allocator)
+    expect(t, err == nil, name)
+    expect(t, options.hash == 0x87d2a1b6e1163ef1, name)
+    benchmark_print(name, options)
+}