Merge branch 'master' into xml

This commit is contained in:
Jeroen van Rijn
2022-04-27 14:37:15 +02:00
482 changed files with 63710 additions and 19741 deletions

75
tests/common/common.odin Normal file
View File

@@ -0,0 +1,75 @@
// Boilerplate for tests
package common
import "core:testing"
import "core:fmt"
import "core:os"
import "core:strings"
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) {
TEST_count += 1
if !condition {
TEST_fail += 1
fmt.printf("[%v] FAIL %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)
}
}
report :: proc(t: ^testing.T) {
if TEST_fail > 0 {
if TEST_fail > 1 {
fmt.printf("%v/%v tests successful, %v tests failed.\n", TEST_count - TEST_fail, TEST_count, TEST_fail)
} else {
fmt.printf("%v/%v tests successful, 1 test failed.\n", TEST_count - TEST_fail, TEST_count)
}
os.exit(1)
} else {
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
}

View File

@@ -1,29 +1,46 @@
ODIN=../../odin
PYTHON=$(shell which python3)
all: download_test_assets image_test compress_test strings_test hash_test crypto_test encoding_test
all: download_test_assets image_test compress_test strings_test hash_test crypto_test noise_test encoding_test \
math_test linalg_glsl_math_test filepath_test reflect_test os_exit_test
download_test_assets:
$(PYTHON) download_assets.py
image_test:
$(ODIN) run image/test_core_image.odin -out=test_image -o:speed -no-bounds-check
$(ODIN) run image/test_core_image.odin -file -out:test_core_image
compress_test:
$(ODIN) run compress/test_core_compress.odin -out=test_compress -o:speed -no-bounds-check
$(ODIN) run compress/test_core_compress.odin -file -out:test_core_compress
strings_test:
$(ODIN) run strings/test_core_strings.odin -out=test_strings -o:speed -no-bounds-check
odin_test:
$(ODIN) run odin -out=test_odin -o:speed -no-bounds-check
$(ODIN) run strings/test_core_strings.odin -file -out:test_core_strings
hash_test:
$(ODIN) run hash -out=test_hash -o:speed -no-bounds-check
$(ODIN) run hash -o:speed -no-bounds-check -out:test_hash
crypto_test:
$(ODIN) run crypto -out=crypto_hash -o:speed -no-bounds-check
$(ODIN) run crypto -o:speed -no-bounds-check -out:test_crypto_hash
noise_test:
$(ODIN) run math/noise -out:test_noise
encoding_test:
$(ODIN) run encoding/json -out=test_encoding_json -o:speed -no-bounds-check
$(ODIN) run encoding/xml -out=test_encoding_xml -o:speed -no-bounds-check
$(ODIN) run encoding/hxa -collection:tests=.. -out:test_hxa
$(ODIN) run encoding/json -out:test_json
$(ODIN) run encoding/varint -out:test_varint
math_test:
$(ODIN) run math/test_core_math.odin -file -collection:tests=.. -out:test_core_math
linalg_glsl_math_test:
$(ODIN) run math/linalg/glsl/test_linalg_glsl_math.odin -file -collection:tests=.. -out:test_linalg_glsl_math
filepath_test:
$(ODIN) run path/filepath/test_core_filepath.odin -file -collection:tests=.. -out:test_core_filepath
reflect_test:
$(ODIN) run reflect/test_core_reflect.odin -file -collection:tests=.. -out:test_core_reflect
os_exit_test:
$(ODIN) run os/test_core_os_exit.odin -file -out:test_core_os_exit && exit 1 || exit 0

Binary file not shown.

View File

@@ -0,0 +1,26 @@
Copyright (c) 2016-2021 Ginger Bill. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Binary file not shown.

View File

@@ -0,0 +1,95 @@
<p align="center">
<img src="misc/logo-slim.png" alt="Odin logo" style="width:65%">
<br/>
The Data-Oriented Language for Sane Software Development.
<br/>
<br/>
<a href="https://github.com/odin-lang/odin/releases/latest">
<img src="https://img.shields.io/github/release/odin-lang/odin.svg">
</a>
<a href="https://github.com/odin-lang/odin/releases/latest">
<img src="https://img.shields.io/badge/platforms-Windows%20|%20Linux%20|%20macOS-green.svg">
</a>
<br>
<a href="https://discord.gg/odinlang">
<img src="https://img.shields.io/discord/568138951836172421?logo=discord">
</a>
<a href="https://github.com/odin-lang/odin/actions">
<img src="https://github.com/odin-lang/odin/workflows/CI/badge.svg?branch=master&event=push">
</a>
</p>
# The Odin Programming Language
Odin is a general-purpose programming language with distinct typing, built for high performance, modern systems, and built-in data-oriented data types. The Odin Programming Language, the C alternative for the joy of programming.
Website: [https://odin-lang.org/](https://odin-lang.org/)
```odin
package main
import "core:fmt"
main :: proc() {
program := "+ + * 😃 - /"
accumulator := 0
for token in program {
switch token {
case '+': accumulator += 1
case '-': accumulator -= 1
case '*': accumulator *= 2
case '/': accumulator /= 2
case '😃': accumulator *= accumulator
case: // Ignore everything else
}
}
fmt.printf("The program \"%s\" calculates the value %d\n",
program, accumulator)
}
```
## Documentation
#### [Getting Started](https://odin-lang.org/docs/install)
Instructions for downloading and installing the Odin compiler and libraries.
#### [Nightly Builds](https://odin-lang.org/docs/nightly/)
Get the latest nightly builds of Odin.
### Learning Odin
#### [Overview of Odin](https://odin-lang.org/docs/overview)
An overview of the Odin programming language.
#### [Frequently Asked Questions (FAQ)](https://odin-lang.org/docs/faq)
Answers to common questions about Odin.
#### [Packages](https://pkg.odin-lang.org/)
Documentation for all the official packages part of the [core](https://pkg.odin-lang.org/core/) and [vendor](https://pkg.odin-lang.org/vendor/) library collections.
#### [The Odin Wiki](https://github.com/odin-lang/Odin/wiki)
A wiki maintained by the Odin community.
#### [Odin Discord](https://discord.gg/sVBPHEv)
Get live support and talk with other odiners on the Odin Discord.
### Articles
#### [The Odin Blog](https://odin-lang.org/news/)
The official blog of the Odin programming language, featuring announcements, news, and in-depth articles by the Odin team and guests.
## Warnings
* The Odin compiler is still in development.

Binary file not shown.

View File

@@ -1,39 +1,65 @@
@echo off
set COMMON=-show-timings -no-bounds-check -vet -strict-style
set COMMON=-show-timings -no-bounds-check -vet -strict-style -collection:tests=..
set PATH_TO_ODIN==..\..\odin
python3 download_assets.py
echo ---
echo Running core:image tests
echo ---
%PATH_TO_ODIN% run image %COMMON% -out:test_image.exe
%PATH_TO_ODIN% run image %COMMON% -out:test_core_image.exe
echo ---
echo Running core:compress tests
echo ---
%PATH_TO_ODIN% run compress %COMMON% -out:test_compress.exe
%PATH_TO_ODIN% run compress %COMMON% -out:test_core_compress.exe
echo ---
echo Running core:strings tests
echo ---
%PATH_TO_ODIN% run strings %COMMON% -out:test_strings.exe
%PATH_TO_ODIN% run strings %COMMON% -out:test_core_strings.exe
echo ---
echo Running core:hash tests
echo ---
%PATH_TO_ODIN% run hash %COMMON% -o:size -out:test_hash.exe
%PATH_TO_ODIN% run hash %COMMON% -o:size -out:test_core_hash.exe
echo ---
echo Running core:odin tests
echo ---
%PATH_TO_ODIN% run odin %COMMON% -o:size -out:test_odin.exe
%PATH_TO_ODIN% run odin %COMMON% -o:size -out:test_core_odin.exe
echo ---
echo Running core:crypto hash tests
echo ---
%PATH_TO_ODIN% run crypto %COMMON% -o:speed -out:test_crypto.exe
%PATH_TO_ODIN% run crypto %COMMON% -out:test_crypto_hash.exe
echo ---
echo Running core:encoding tests
echo ---
%PATH_TO_ODIN% run encoding\json %COMMON% -out:test_json.exe
%PATH_TO_ODIN% run encoding\xml %COMMON% -out:test_xml.exe
%PATH_TO_ODIN% run encoding/hxa %COMMON% -out:test_hxa.exe
%PATH_TO_ODIN% run encoding/json %COMMON% -out:test_json.exe
%PATH_TO_ODIN% run encoding/varint %COMMON% -out:test_varint.exe
echo ---
echo Running core:math/noise tests
echo ---
%PATH_TO_ODIN% run math/noise %COMMON% -out:test_noise.exe
echo ---
echo Running core:math tests
echo ---
%PATH_TO_ODIN% run math %COMMON% -out:test_core_math.exe
echo ---
echo Running core:math/linalg/glsl tests
echo ---
%PATH_TO_ODIN% run math/linalg/glsl %COMMON% -out:test_linalg_glsl.exe
echo ---
echo Running core:path/filepath tests
echo ---
%PATH_TO_ODIN% run path/filepath %COMMON% -out:test_core_filepath.exe
echo ---
echo Running core:reflect tests
echo ---
%PATH_TO_ODIN% run reflect %COMMON% -out:test_core_reflect.exe

View File

@@ -7,13 +7,14 @@ package test_core_compress
List of contributors:
Jeroen van Rijn: Initial implementation.
A test suite for ZLIB, GZIP.
A test suite for ZLIB, GZIP and Shoco.
*/
import "core:testing"
import "core:compress/zlib"
import "core:compress/gzip"
import "core:compress/shoco"
import "core:bytes"
import "core:fmt"
@@ -38,7 +39,8 @@ 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)
}
}
@@ -47,8 +49,12 @@ main :: proc() {
t := testing.T{w=w}
zlib_test(&t)
gzip_test(&t)
shoco_test(&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
@@ -130,3 +136,56 @@ gzip_test :: proc(t: ^testing.T) {
expect(t, false, error)
}
}
@test
shoco_test :: proc(t: ^testing.T) {
Shoco_Tests :: []struct{
compressed: []u8,
raw: []u8,
short_pack: int,
short_sentinel: int,
}{
{ #load("../assets/Shoco/README.md.shoco"), #load("../assets/Shoco/README.md"), 10, 1006 },
{ #load("../assets/Shoco/LICENSE.shoco"), #load("../assets/Shoco/LICENSE"), 25, 68 },
}
for v in Shoco_Tests {
expected_raw := len(v.raw)
expected_compressed := len(v.compressed)
biggest_unpacked := shoco.decompress_bound(expected_compressed)
biggest_packed := shoco.compress_bound(expected_raw)
buffer := make([]u8, max(biggest_packed, biggest_unpacked))
defer delete(buffer)
size, err := shoco.decompress(v.compressed, buffer[:])
msg := fmt.tprintf("Expected `decompress` to return `nil`, got %v", err)
expect(t, err == nil, msg)
msg = fmt.tprintf("Decompressed %v bytes into %v. Expected to decompress into %v bytes.", len(v.compressed), size, expected_raw)
expect(t, size == expected_raw, msg)
expect(t, string(buffer[:size]) == string(v.raw), "Decompressed contents don't match.")
size, err = shoco.compress(string(v.raw), buffer[:])
expect(t, err == nil, "Expected `compress` to return `nil`.")
msg = fmt.tprintf("Compressed %v bytes into %v. Expected to compress into %v bytes.", expected_raw, size, expected_compressed)
expect(t, size == expected_compressed, msg)
size, err = shoco.decompress(v.compressed, buffer[:expected_raw - 10])
msg = fmt.tprintf("Decompressing into too small a buffer returned %v, expected `.Output_Too_Short`", err)
expect(t, err == .Output_Too_Short, msg)
size, err = shoco.compress(string(v.raw), buffer[:expected_compressed - 10])
msg = fmt.tprintf("Compressing into too small a buffer returned %v, expected `.Output_Too_Short`", err)
expect(t, err == .Output_Too_Short, msg)
size, err = shoco.decompress(v.compressed[:v.short_pack], buffer[:])
expect(t, err == .Stream_Too_Short, "Expected `decompress` to return `Stream_Too_Short` because there was no more data after selecting a pack.")
size, err = shoco.decompress(v.compressed[:v.short_sentinel], buffer[:])
expect(t, err == .Stream_Too_Short, "Expected `decompress` to return `Stream_Too_Short` because there was no more data after non-ASCII sentinel.")
}
}

View File

@@ -36,6 +36,8 @@ import "core:crypto/sm3"
import "core:crypto/jh"
import "core:crypto/groestl"
import "core:crypto/haval"
import "core:crypto/siphash"
import "core:os"
TEST_count := 0
TEST_fail := 0
@@ -52,8 +54,9 @@ when ODIN_TEST {
return
}
}
log :: proc(t: ^testing.T, v: any, loc := #caller_location) {
fmt.printf("[%v] LOG:\n\t%v\n", loc, v)
log :: proc(t: ^testing.T, v: any, loc := #caller_location) {
fmt.printf("[%v] ", loc)
fmt.printf("log: %v\n", v)
}
}
@@ -111,6 +114,7 @@ main :: proc() {
test_haval_192(&t)
test_haval_224(&t)
test_haval_256(&t)
test_siphash_2_4(&t)
// "modern" crypto tests
test_chacha20(&t)
@@ -121,7 +125,10 @@ main :: proc() {
bench_modern(&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)
}
}
TestHash :: struct {
@@ -198,7 +205,7 @@ test_md5 :: proc(t: ^testing.T) {
@(test)
test_sha1 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -220,7 +227,7 @@ test_sha1 :: proc(t: ^testing.T) {
@(test)
test_sha224 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -238,7 +245,7 @@ test_sha224 :: proc(t: ^testing.T) {
@(test)
test_sha256 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -256,7 +263,7 @@ test_sha256 :: proc(t: ^testing.T) {
@(test)
test_sha384 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -274,7 +281,7 @@ test_sha384 :: proc(t: ^testing.T) {
@(test)
test_sha512 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -292,7 +299,7 @@ test_sha512 :: proc(t: ^testing.T) {
@(test)
test_sha3_224 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -314,7 +321,7 @@ test_sha3_224 :: proc(t: ^testing.T) {
@(test)
test_sha3_256 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -336,7 +343,7 @@ test_sha3_256 :: proc(t: ^testing.T) {
@(test)
test_sha3_384 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -358,7 +365,7 @@ test_sha3_384 :: proc(t: ^testing.T) {
@(test)
test_sha3_512 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -408,7 +415,7 @@ test_shake_256 :: proc(t: ^testing.T) {
@(test)
test_keccak_224 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -424,7 +431,7 @@ test_keccak_224 :: proc(t: ^testing.T) {
@(test)
test_keccak_256 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -440,7 +447,7 @@ test_keccak_256 :: proc(t: ^testing.T) {
@(test)
test_keccak_384 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -456,7 +463,7 @@ test_keccak_384 :: proc(t: ^testing.T) {
@(test)
test_keccak_512 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
// https://www.di-mgt.com.au/sha_testvectors.html
test_vectors := [?]TestHash {
@@ -472,7 +479,7 @@ test_keccak_512 :: proc(t: ^testing.T) {
@(test)
test_whirlpool :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://web.archive.org/web/20171129084214/http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html
test_vectors := [?]TestHash {
TestHash{"19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3", ""},
@@ -628,7 +635,7 @@ test_blake2s :: proc(t: ^testing.T) {
@(test)
test_ripemd_128 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
test_vectors := [?]TestHash {
TestHash{"cdf26213a150dc3ecb610f18f6b38b46", ""},
@@ -648,7 +655,7 @@ test_ripemd_128 :: proc(t: ^testing.T) {
@(test)
test_ripemd_160 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
test_vectors := [?]TestHash {
TestHash{"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""},
@@ -668,7 +675,7 @@ test_ripemd_160 :: proc(t: ^testing.T) {
@(test)
test_ripemd_256 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
test_vectors := [?]TestHash {
TestHash{"02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d", ""},
@@ -677,7 +684,7 @@ test_ripemd_256 :: proc(t: ^testing.T) {
TestHash{"87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e", "message digest"},
TestHash{"649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133", "abcdefghijklmnopqrstuvwxyz"},
TestHash{"3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
TestHash{"5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
TestHash{"5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
}
for v, _ in test_vectors {
computed := ripemd.hash_256(v.str)
@@ -688,7 +695,7 @@ test_ripemd_256 :: proc(t: ^testing.T) {
@(test)
test_ripemd_320 :: proc(t: ^testing.T) {
// Test vectors from
// Test vectors from
// https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
test_vectors := [?]TestHash {
TestHash{"22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8", ""},
@@ -813,7 +820,7 @@ test_sm3 :: proc(t: ^testing.T) {
test_vectors := [?]TestHash {
TestHash{"1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b", ""},
TestHash{"66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0", "abc"},
TestHash{"debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732", "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"},
TestHash{"debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732", "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"},
TestHash{"5fdfe814b8573ca021983970fc79b2218c9570369b4859684e2e4c3fc76cb8ea", "The quick brown fox jumps over the lazy dog"},
TestHash{"ca27d14a42fc04c1e5ecf574a95a8c2d70ecb5805e9b429026ccac8f28b20098", "The quick brown fox jumps over the lazy cog"},
}
@@ -945,7 +952,7 @@ test_haval_128 :: proc(t: ^testing.T) {
TestHash{"3caf4a79e81adcd6d1716bcc1cef4573", "message digest"},
TestHash{"dc502247fb3eb8376109eda32d361d82", "abcdefghijklmnopqrstuvwxyz"},
TestHash{"44068770868768964d1f2c3bff4aa3d8", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
TestHash{"de5eb3f7d9eb08fae7a07d68e3047ec6", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
TestHash{"de5eb3f7d9eb08fae7a07d68e3047ec6", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
}
for v, _ in test_vectors_3 {
computed := haval.hash_128_3(v.str)
@@ -981,7 +988,7 @@ test_haval_160 :: proc(t: ^testing.T) {
TestHash{"43a47f6f1c016207f08be8115c0977bf155346da", "message digest"},
TestHash{"eba9fa6050f24c07c29d1834a60900ea4e32e61b", "abcdefghijklmnopqrstuvwxyz"},
TestHash{"c30bce448cf8cfe957c141e90c0a063497cdfeeb", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
TestHash{"97dc988d97caae757be7523c4e8d4ea63007a4b9", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
TestHash{"97dc988d97caae757be7523c4e8d4ea63007a4b9", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
}
for v, _ in test_vectors_3 {
computed := haval.hash_160_3(v.str)
@@ -1100,3 +1107,44 @@ test_haval_256 :: proc(t: ^testing.T) {
expect(t, computed_str == v.hash, fmt.tprintf("Expected: %s for input of %s, but got %s instead", v.hash, v.str, computed_str))
}
}
@(test)
test_siphash_2_4 :: proc(t: ^testing.T) {
// Test vectors from
// https://github.com/veorq/SipHash/blob/master/vectors.h
test_vectors := [?]u64 {
0x726fdb47dd0e0e31, 0x74f839c593dc67fd, 0x0d6c8009d9a94f5a, 0x85676696d7fb7e2d,
0xcf2794e0277187b7, 0x18765564cd99a68d, 0xcbc9466e58fee3ce, 0xab0200f58b01d137,
0x93f5f5799a932462, 0x9e0082df0ba9e4b0, 0x7a5dbbc594ddb9f3, 0xf4b32f46226bada7,
0x751e8fbc860ee5fb, 0x14ea5627c0843d90, 0xf723ca908e7af2ee, 0xa129ca6149be45e5,
0x3f2acc7f57c29bdb, 0x699ae9f52cbe4794, 0x4bc1b3f0968dd39c, 0xbb6dc91da77961bd,
0xbed65cf21aa2ee98, 0xd0f2cbb02e3b67c7, 0x93536795e3a33e88, 0xa80c038ccd5ccec8,
0xb8ad50c6f649af94, 0xbce192de8a85b8ea, 0x17d835b85bbb15f3, 0x2f2e6163076bcfad,
0xde4daaaca71dc9a5, 0xa6a2506687956571, 0xad87a3535c49ef28, 0x32d892fad841c342,
0x7127512f72f27cce, 0xa7f32346f95978e3, 0x12e0b01abb051238, 0x15e034d40fa197ae,
0x314dffbe0815a3b4, 0x027990f029623981, 0xcadcd4e59ef40c4d, 0x9abfd8766a33735c,
0x0e3ea96b5304a7d0, 0xad0c42d6fc585992, 0x187306c89bc215a9, 0xd4a60abcf3792b95,
0xf935451de4f21df2, 0xa9538f0419755787, 0xdb9acddff56ca510, 0xd06c98cd5c0975eb,
0xe612a3cb9ecba951, 0xc766e62cfcadaf96, 0xee64435a9752fe72, 0xa192d576b245165a,
0x0a8787bf8ecb74b2, 0x81b3e73d20b49b6f, 0x7fa8220ba3b2ecea, 0x245731c13ca42499,
0xb78dbfaf3a8d83bd, 0xea1ad565322a1a0b, 0x60e61c23a3795013, 0x6606d7e446282b93,
0x6ca4ecb15c5f91e1, 0x9f626da15c9625f3, 0xe51b38608ef25f57, 0x958a324ceb064572,
}
key: [16]byte
for i in 0..<16 {
key[i] = byte(i)
}
for i in 0..<len(test_vectors) {
data := make([]byte, i)
for j in 0..<i {
data[j] = byte(j)
}
vector := test_vectors[i]
computed := siphash.sum_2_4(data[:], key[:])
expect(t, computed == vector, fmt.tprintf("Expected: 0x%x for input of %v, but got 0x%x instead", vector, data, computed))
}
}

View File

@@ -308,7 +308,7 @@ test_x25519 :: proc(t: ^testing.T) {
test_rand_bytes :: proc(t: ^testing.T) {
log(t, "Testing rand_bytes")
if ODIN_OS != "linux" {
if ODIN_OS != .Linux {
log(t, "rand_bytes not supported - skipping")
return
}

View File

@@ -50,7 +50,10 @@ def try_download_file(url, out_file):
print("Could not download", url)
return 1
def try_download_and_unpack_zip(url, out_file, extract_path):
def try_download_and_unpack_zip(suite):
url = ASSETS_BASE_URL.format(suite, "{}.zip".format(suite))
out_file = DOWNLOAD_BASE_PATH.format(suite) + "/{}.zip".format(suite)
print("\tDownloading {} to {}.".format(url, out_file))
if try_download_file(url, out_file) is not None:
@@ -62,6 +65,7 @@ def try_download_and_unpack_zip(url, out_file, extract_path):
with zipfile.ZipFile(out_file) as z:
for file in z.filelist:
filename = file.filename
extract_path = DOWNLOAD_BASE_PATH.format(suite)
print("\t\tExtracting: {}".format(filename))
z.extract(file, extract_path)
@@ -69,56 +73,25 @@ def try_download_and_unpack_zip(url, out_file, extract_path):
print("Could not extract ZIP file")
return 2
def download_png_assets():
suite = "PNG"
url = ASSETS_BASE_URL.format(suite, "{}.zip".format(suite))
out_file = DOWNLOAD_BASE_PATH.format(suite) + "/{}.zip".format(suite)
extract_path = DOWNLOAD_BASE_PATH.format(suite)
def main():
print("Downloading PNG assets")
# Make PNG assets path
try:
path = DOWNLOAD_BASE_PATH.format(suite)
path = DOWNLOAD_BASE_PATH.format("PNG")
os.makedirs(path)
except FileExistsError:
pass
# Try downloading and unpacking the PNG assets
r = try_download_and_unpack_zip(url, out_file, extract_path)
r = try_download_and_unpack_zip("PNG")
if r is not None:
return r
# We could fall back on downloading the PNG files individually, but it's slow
print("Done downloading PNG assets")
def download_unicode_assets():
suite = "XML"
url = "https://www.w3.org/2003/entities/2007xml/unicode.xml.zip"
out_file = DOWNLOAD_BASE_PATH.format(suite) + "/{}.zip".format(suite)
extract_path = DOWNLOAD_BASE_PATH.format(suite)
print("Downloading {}.".format(url))
# Make XML assets path
try:
path = DOWNLOAD_BASE_PATH.format(suite)
os.makedirs(path)
except FileExistsError:
pass
# Try downloading and unpacking the assets
r = try_download_and_unpack_zip(url, out_file, extract_path)
if r is not None:
return r
print("Done downloading Unicode/XML assets")
def main():
download_png_assets()
download_unicode_assets()
return 0
if __name__ == '__main__':

View File

@@ -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]))
}
}
}
}

View File

@@ -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")
}
}

View File

@@ -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 },
}

View File

@@ -5,6 +5,7 @@ import "core:hash"
import "core:time"
import "core:testing"
import "core:fmt"
import "core:os"
TEST_count := 0
TEST_fail := 0
@@ -17,12 +18,13 @@ when ODIN_TEST {
TEST_count += 1
if !condition {
TEST_fail += 1
fmt.printf("[%v] %v", loc, message)
fmt.printf("[%v] %v\n", loc, message)
return
}
}
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)
}
}
@@ -31,7 +33,10 @@ main :: proc() {
test_benchmark_runner(&t)
test_xxhash_vectors(&t)
test_crc64_vectors(&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)
}
}
/*

View File

@@ -5,7 +5,7 @@
List of contributors:
Jeroen van Rijn: Initial implementation.
A test suite for PNG.
A test suite for PNG + QOI.
*/
package test_core_image
@@ -14,6 +14,7 @@ import "core:testing"
import "core:compress"
import "core:image"
import "core:image/png"
import "core:image/qoi"
import "core:bytes"
import "core:hash"
@@ -25,8 +26,8 @@ import "core:time"
import "core:runtime"
WRITE_PPM_ON_FAIL :: #config(WRITE_PPM_ON_FAIL, false)
TEST_FILE_PATH_PREFIX :: "tests/core/assets/PNG"
WRITE_PPM_ON_FAIL :: #config(WRITE_PPM_ON_FAIL, false)
TEST_SUITE_PATH :: "assets/PNG"
TEST_count := 0
TEST_fail := 0
@@ -44,30 +45,20 @@ 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)
}
}
I_Error :: image.Error
main :: proc() {
t := testing.T{}
png_test(&t)
fmt.printf("\n%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
}
test_file_path :: proc(filename: string, extension := "png") -> (path: string) {
path = fmt.tprintf("%v%v/%v.%v", ODIN_ROOT, TEST_FILE_PATH_PREFIX, filename, extension)
temp := transmute([]u8)path
for r, i in path {
if r == '\\' {
temp[i] = '/'
}
fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
if TEST_fail > 0 {
os.exit(1)
}
return path
}
PNG_Test :: struct {
@@ -1472,7 +1463,7 @@ run_png_suite :: proc(t: ^testing.T, suite: []PNG_Test) -> (subtotal: int) {
context = runtime.default_context()
for file in suite {
test_file := test_file_path(file.file)
test_file := fmt.tprintf("%v/%v.png", TEST_SUITE_PATH, file.file)
img: ^png.Image
err: png.Error
@@ -1509,11 +1500,34 @@ run_png_suite :: proc(t: ^testing.T, suite: []PNG_Test) -> (subtotal: int) {
passed &= dims_pass
hash := hash.crc32(pixels)
error = fmt.tprintf("%v test %v hash is %08x, expected %08x.", file.file, count, hash, test.hash)
expect(t, test.hash == hash, error)
png_hash := hash.crc32(pixels)
error = fmt.tprintf("%v test %v hash is %08x, expected %08x with %v.", file.file, count, png_hash, test.hash, test.options)
expect(t, test.hash == png_hash, error)
passed &= test.hash == png_hash
// Roundtrip through QOI to test the QOI encoder and decoder.
if passed && img.depth == 8 && (img.channels == 3 || img.channels == 4) {
qoi_buffer: bytes.Buffer
defer bytes.buffer_destroy(&qoi_buffer)
qoi_save_err := qoi.save(&qoi_buffer, img)
error = fmt.tprintf("%v test %v QOI save failed with %v.", file.file, count, qoi_save_err)
expect(t, qoi_save_err == nil, error)
if qoi_save_err == nil {
qoi_img, qoi_load_err := qoi.load(qoi_buffer.buf[:])
defer qoi.destroy(qoi_img)
error = fmt.tprintf("%v test %v QOI load failed with %v.", file.file, count, qoi_load_err)
expect(t, qoi_load_err == nil, error)
qoi_hash := hash.crc32(qoi_img.pixels.buf[:])
error = fmt.tprintf("%v test %v QOI load hash is %08x, expected it match PNG's %08x with %v.", file.file, count, qoi_hash, png_hash, test.options)
expect(t, qoi_hash == png_hash, error)
}
}
passed &= test.hash == hash
if .return_metadata in test.options {
if v, ok := img.metadata.(^image.PNG_Info); ok {
@@ -1778,7 +1792,7 @@ write_image_as_ppm :: proc(filename: string, image: ^image.Image) -> (success: b
img := image
// PBM 16-bit images are big endian
when ODIN_ENDIAN == "little" {
when ODIN_ENDIAN == .Little {
if img.depth == 16 {
// The pixel components are in Big Endian. Let's byteswap back.
input := mem.slice_data_cast([]u16, img.pixels.buf[:])
@@ -1796,7 +1810,7 @@ write_image_as_ppm :: proc(filename: string, image: ^image.Image) -> (success: b
}
mode: int = 0
when ODIN_OS == "linux" || ODIN_OS == "darwin" {
when ODIN_OS == .Linux || ODIN_OS == .Darwin {
// NOTE(justasd): 644 (owner read, write; group read; others read)
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
}

View File

@@ -4,14 +4,11 @@ set PATH_TO_ODIN==..\..\..\..\odin
set TEST_ARGS=-fast-tests
set TEST_ARGS=-no-random
set TEST_ARGS=
set OUT_NAME=math_big_test_library
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
echo ---
echo Running core:math/big tests
echo ---
rem Fails
:%PATH_TO_ODIN% build . %COMMON% -o:speed -out:%OUT_NAME%
rem Passes
%PATH_TO_ODIN% build . %COMMON% -o:size -out:%OUT_NAME%
%PATH_TO_ODIN% build . %COMMON% -o:speed -out:%OUT_NAME%
python3 test.py %TEST_ARGS%

View File

@@ -32,9 +32,9 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring {
@export test_initialize_constants :: proc "c" () -> (res: u64) {
context = runtime.default_context()
res = u64(big.initialize_constants())
//assert(MUL_KARATSUBA_CUTOFF >= 40);
return res
_ = big.initialize_constants()
return u64(big._DIGIT_NAILS)
}
@export test_error_string :: proc "c" (err: big.Error) -> (res: cstring) {
@@ -208,7 +208,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring {
/*
dest = shr_digit(src, digits)
*/
@export test_shr_digit :: proc "c" (source: cstring, digits: int) -> (res: PyRes) {
@export test_shr_leg :: proc "c" (source: cstring, digits: int) -> (res: PyRes) {
context = runtime.default_context()
err: big.Error
@@ -216,7 +216,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring {
defer big.internal_destroy(src)
if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_digit:atoi(src):", err=err} }
if err = #force_inline big.internal_shr_digit(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err} }
if err = #force_inline big._private_int_shr_leg(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err} }
r := print_to_buffer(src)
return PyRes{res = r, err = nil}
@@ -225,7 +225,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring {
/*
dest = shl_digit(src, digits)
*/
@export test_shl_digit :: proc "c" (source: cstring, digits: int) -> (res: PyRes) {
@export test_shl_leg :: proc "c" (source: cstring, digits: int) -> (res: PyRes) {
context = runtime.default_context()
err: big.Error
@@ -233,7 +233,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring {
defer big.internal_destroy(src)
if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shl_digit:atoi(src):", err=err} }
if err = #force_inline big.internal_shl_digit(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err} }
if err = #force_inline big._private_int_shl_leg(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err} }
r := print_to_buffer(src)
return PyRes{res = r, err = nil}

View File

@@ -17,7 +17,6 @@ import gc
from enum import Enum
import argparse
parser = argparse.ArgumentParser(
description = "Odin core:math/big test suite",
epilog = "By default we run regression and random tests with preset parameters.",
@@ -127,17 +126,22 @@ def we_iterate():
# Error enum values
#
class Error(Enum):
Okay = 0
Out_Of_Memory = 1
Invalid_Pointer = 2
Invalid_Argument = 3
Unknown_Error = 4
Max_Iterations_Reached = 5
Buffer_Overflow = 6
Integer_Overflow = 7
Division_by_Zero = 8
Math_Domain_Error = 9
Unimplemented = 127
Okay = 0
Out_Of_Memory = 1
Invalid_Pointer = 2
Invalid_Argument = 3
Unknown_Error = 4
Assignment_To_Immutable = 10
Max_Iterations_Reached = 11
Buffer_Overflow = 12
Integer_Overflow = 13
Integer_Underflow = 14
Division_by_Zero = 30
Math_Domain_Error = 31
Cannot_Open_File = 50
Cannot_Read_File = 51
Cannot_Write_File = 52
Unimplemented = 127
#
# Disable garbage collection
@@ -158,6 +162,8 @@ def load(export_name, args, res):
export_name.restype = res
return export_name
#
# Result values will be passed in a struct { res: cstring, err: Error }
#
@@ -165,7 +171,11 @@ class Res(Structure):
_fields_ = [("res", c_char_p), ("err", c_uint64)]
initialize_constants = load(l.test_initialize_constants, [], c_uint64)
print("initialize_constants: ", initialize_constants())
NAILS = initialize_constants()
LEG_BITS = 64 - NAILS
print("LEG BITS: ", LEG_BITS)
error_string = load(l.test_error_string, [c_byte], c_char_p)
@@ -182,8 +192,8 @@ int_sqrt = load(l.test_sqrt, [c_char_p ], Res)
int_root_n = load(l.test_root_n, [c_char_p, c_longlong], Res)
# Logical operations
int_shl_digit = load(l.test_shl_digit, [c_char_p, c_longlong], Res)
int_shr_digit = load(l.test_shr_digit, [c_char_p, c_longlong], Res)
int_shl_leg = load(l.test_shl_leg, [c_char_p, c_longlong], Res)
int_shr_leg = load(l.test_shr_leg, [c_char_p, c_longlong], Res)
int_shl = load(l.test_shl, [c_char_p, c_longlong], Res)
int_shr = load(l.test_shr, [c_char_p, c_longlong], Res)
int_shr_signed = load(l.test_shr_signed, [c_char_p, c_longlong], Res)
@@ -397,26 +407,26 @@ def test_root_n(number = 0, root = 0, expected_error = Error.Okay):
return test("test_root_n", res, [number, root], expected_error, expected_result)
def test_shl_digit(a = 0, digits = 0, expected_error = Error.Okay):
def test_shl_leg(a = 0, digits = 0, expected_error = Error.Okay):
args = [arg_to_odin(a), digits]
res = int_shl_digit(*args)
res = int_shl_leg(*args)
expected_result = None
if expected_error == Error.Okay:
expected_result = a << (digits * 60)
return test("test_shl_digit", res, [a, digits], expected_error, expected_result)
expected_result = a << (digits * LEG_BITS)
return test("test_shl_leg", res, [a, digits], expected_error, expected_result)
def test_shr_digit(a = 0, digits = 0, expected_error = Error.Okay):
def test_shr_leg(a = 0, digits = 0, expected_error = Error.Okay):
args = [arg_to_odin(a), digits]
res = int_shr_digit(*args)
res = int_shr_leg(*args)
expected_result = None
if expected_error == Error.Okay:
if a < 0:
# Don't pass negative numbers. We have a shr_signed.
return False
else:
expected_result = a >> (digits * 60)
expected_result = a >> (digits * LEG_BITS)
return test("test_shr_digit", res, [a, digits], expected_error, expected_result)
return test("test_shr_leg", res, [a, digits], expected_error, expected_result)
def test_shl(a = 0, bits = 0, expected_error = Error.Okay):
args = [arg_to_odin(a), bits]
@@ -551,12 +561,12 @@ TESTS = {
test_root_n: [
[ 1298074214633706907132624082305024, 2, Error.Okay, ],
],
test_shl_digit: [
test_shl_leg: [
[ 3192, 1 ],
[ 1298074214633706907132624082305024, 2 ],
[ 1024, 3 ],
],
test_shr_digit: [
test_shr_leg: [
[ 3680125442705055547392, 1 ],
[ 1725436586697640946858688965569256363112777243042596638790631055949824, 2 ],
[ 219504133884436710204395031992179571, 2 ],
@@ -614,10 +624,10 @@ total_failures = 0
# test_shr_signed also tests shr, so we're not going to test shr randomly.
#
RANDOM_TESTS = [
test_add, test_sub, test_mul, test_sqr, test_div,
test_log, test_pow, test_sqrt, test_root_n,
test_shl_digit, test_shr_digit, test_shl, test_shr_signed,
test_gcd, test_lcm, test_is_square,
test_add, test_sub, test_mul, test_sqr,
test_log, test_pow, test_sqrt, test_root_n,
test_shl_leg, test_shr_leg, test_shl, test_shr_signed,
test_gcd, test_lcm, test_is_square, test_div,
]
SKIP_LARGE = [
test_pow, test_root_n, # test_gcd,
@@ -714,9 +724,9 @@ if __name__ == '__main__':
a = randint(1, 1 << BITS)
b = TEST_ROOT_N_PARAMS[index]
index = (index + 1) % len(TEST_ROOT_N_PARAMS)
elif test_proc == test_shl_digit:
elif test_proc == test_shl_leg:
b = randint(0, 10);
elif test_proc == test_shr_digit:
elif test_proc == test_shr_leg:
a = abs(a)
b = randint(0, 10);
elif test_proc == test_shl:

View File

@@ -0,0 +1,85 @@
// Tests "linalg_glsl_math.odin" in "core:math/linalg/glsl".
// Must be run with `-collection:tests=` flag, e.g.
// ./odin run tests/core/math/linalg/glsl/test_linalg_glsl_math.odin -collection:tests=./tests
package test_core_math_linalg_glsl_math
import glsl "core:math/linalg/glsl"
import "core:fmt"
import "core:math"
import "core:testing"
import tc "tests:common"
main :: proc() {
t := testing.T{}
test_fract_f32(&t)
test_fract_f64(&t)
tc.report(&t)
}
@test
test_fract_f32 :: proc(t: ^testing.T) {
using math
r: f32
Datum :: struct {
i: int,
v: f32,
e: f32,
}
@static data := []Datum{
{ 0, 10.5, 0.5 }, // Issue #1574 fract in linalg/glm is broken
{ 1, -10.5, -0.5 },
{ 2, F32_MIN, F32_MIN }, // 0x1p-126
{ 3, -F32_MIN, -F32_MIN },
{ 4, 0.0, 0.0 },
{ 5, -0.0, -0.0 },
{ 6, 1, 0.0 },
{ 7, -1, -0.0 },
{ 8, 0h3F80_0001, 0h3400_0000 }, // 0x1.000002p+0, 0x1p-23
{ 9, -0h3F80_0001, -0h3400_0000 },
}
for d, i in data {
assert(i == d.i)
r = glsl.fract(d.v)
tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%v (%h)) -> %v (%h) != %v", i, #procedure, d.v, d.v, r, r, d.e))
}
}
@test
test_fract_f64 :: proc(t: ^testing.T) {
using math
r: f64
Datum :: struct {
i: int,
v: f64,
e: f64,
}
@static data := []Datum{
{ 0, 10.5, 0.5 }, // Issue #1574 fract in linalg/glm is broken
{ 1, -10.5, -0.5 },
{ 2, F64_MIN, F64_MIN }, // 0x1p-1022
{ 3, -F64_MIN, -F64_MIN },
{ 4, 0.0, 0.0 },
{ 5, -0.0, -0.0 },
{ 6, 1, 0.0 },
{ 7, -1, -0.0 },
{ 8, 0h3FF0_0000_0000_0001, 0h3CB0_0000_0000_0000 }, // 0x1.0000000000001p+0, 0x1p-52
{ 9, -0h3FF0_0000_0000_0001, -0h3CB0_0000_0000_0000 },
}
for d, i in data {
assert(i == d.i)
r = glsl.fract(d.v)
tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%v (%h)) -> %v (%h) != %v", i, #procedure, d.v, d.v, r, r, d.e))
}
}

View File

@@ -0,0 +1,151 @@
package test_core_math_noise
import "core:testing"
import "core:math/noise"
import "core:fmt"
import "core:os"
TEST_count := 0
TEST_fail := 0
V2 :: noise.Vec2
V3 :: noise.Vec3
V4 :: noise.Vec4
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{}
noise_test(&t)
fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
if TEST_fail > 0 {
os.exit(1)
}
}
Test_Vector :: struct {
seed: i64,
coord: union {V2, V3, V4},
expected: f32,
test_proc: union {
proc(_: i64, _: V2) -> f32,
proc(_: i64, _: V3) -> f32,
proc(_: i64, _: V4) -> f32,
},
}
SEED_1 :: 2324223232
SEED_2 :: 932466901
SEED_3 :: 9321
COORD_1 :: V4{ 242.0, 3433.0, 920.0, 222312.0}
COORD_2 :: V4{ 590.0, 9411.0, 5201.0, 942124256.0}
COORD_3 :: V4{12090.0, 19411.0, 81950901.0, 4224219.0}
Noise_Tests := []Test_Vector{
/*
`noise_2d` tests.
*/
{SEED_1, COORD_1.xy, 0.25010583, noise.noise_2d},
{SEED_2, COORD_2.xy, -0.92513955, noise.noise_2d},
{SEED_3, COORD_3.xy, 0.67327416, noise.noise_2d},
/*
`noise_2d_improve_x` tests.
*/
{SEED_1, COORD_1.xy, 0.17074019, noise.noise_2d_improve_x},
{SEED_2, COORD_2.xy, 0.72330487, noise.noise_2d_improve_x},
{SEED_3, COORD_3.xy, -0.032076947, noise.noise_2d_improve_x},
/*
`noise_3d_improve_xy` tests.
*/
{SEED_1, COORD_1.xyz, 0.14819577, noise.noise_3d_improve_xy},
{SEED_2, COORD_2.xyz, -0.065345764, noise.noise_3d_improve_xy},
{SEED_3, COORD_3.xyz, -0.37761918, noise.noise_3d_improve_xy},
/*
`noise_3d_improve_xz` tests.
*/
{SEED_1, COORD_1.xyz, -0.50075006, noise.noise_3d_improve_xz},
{SEED_2, COORD_2.xyz, -0.36039603, noise.noise_3d_improve_xz},
{SEED_3, COORD_3.xyz, -0.3479203, noise.noise_3d_improve_xz},
/*
`noise_3d_fallback` tests.
*/
{SEED_1, COORD_1.xyz, 0.6557345, noise.noise_3d_fallback},
{SEED_2, COORD_2.xyz, 0.55452216, noise.noise_3d_fallback},
{SEED_3, COORD_3.xyz, -0.26408964, noise.noise_3d_fallback},
/*
`noise_3d_fallback` tests.
*/
{SEED_1, COORD_1.xyz, 0.6557345, noise.noise_3d_fallback},
{SEED_2, COORD_2.xyz, 0.55452216, noise.noise_3d_fallback},
{SEED_3, COORD_3.xyz, -0.26408964, noise.noise_3d_fallback},
/*
`noise_4d_improve_xyz_improve_xy` tests.
*/
{SEED_1, COORD_1, 0.44929826, noise.noise_4d_improve_xyz_improve_xy},
{SEED_2, COORD_2, -0.13270882, noise.noise_4d_improve_xyz_improve_xy},
{SEED_3, COORD_3, 0.10298563, noise.noise_4d_improve_xyz_improve_xy},
/*
`noise_4d_improve_xyz_improve_xz` tests.
*/
{SEED_1, COORD_1, -0.078514606, noise.noise_4d_improve_xyz_improve_xz},
{SEED_2, COORD_2, -0.032157656, noise.noise_4d_improve_xyz_improve_xz},
{SEED_3, COORD_3, -0.38607058, noise.noise_4d_improve_xyz_improve_xz},
/*
`noise_4d_improve_xyz` tests.
*/
{SEED_1, COORD_1, -0.4442258, noise.noise_4d_improve_xyz},
{SEED_2, COORD_2, 0.36822623, noise.noise_4d_improve_xyz},
{SEED_3, COORD_3, 0.22628775, noise.noise_4d_improve_xyz},
/*
`noise_4d_fallback` tests.
*/
{SEED_1, COORD_1, -0.14233987, noise.noise_4d_fallback},
{SEED_2, COORD_2, 0.1354035, noise.noise_4d_fallback},
{SEED_3, COORD_3, 0.14565045, noise.noise_4d_fallback},
}
noise_test :: proc(t: ^testing.T) {
for test in Noise_Tests {
output: f32
switch coord in test.coord {
case V2:
output = test.test_proc.(proc(_: i64, _: V2) -> f32)(test.seed, test.coord.(V2))
case V3:
output = test.test_proc.(proc(_: i64, _: V3) -> f32)(test.seed, test.coord.(V3))
case V4:
output = test.test_proc.(proc(_: i64, _: V4) -> f32)(test.seed, test.coord.(V4))
}
error := fmt.tprintf("Seed %v, Coord: %v, Expected: %3.8f. Got %3.8f", test.seed, test.coord, test.expected, output)
expect(t, test.expected == output, error)
}
}

View File

@@ -0,0 +1,310 @@
// Tests "math.odin" in "core:math".
// Must be run with `-collection:tests=` flag, e.g.
// ./odin run tests/core/math/test_core_math.odin -collection:tests=./tests
package test_core_math
import "core:fmt"
import "core:math"
import "core:testing"
import tc "tests:common"
main :: proc() {
t := testing.T{}
test_classify_f16(&t)
test_classify_f32(&t)
test_classify_f64(&t)
test_trunc_f16(&t)
test_trunc_f32(&t)
test_trunc_f64(&t)
tc.report(&t)
}
@test
test_classify_f16 :: proc(t: ^testing.T) {
using math
using Float_Class
r: Float_Class
Datum :: struct {
i: int,
v: f16,
e: math.Float_Class,
}
@static data := []Datum{
{ 0, 1.2, Normal },
{ 1, 0h0001, Subnormal },
{ 2, 0.0, Zero },
{ 3, -0.0, Neg_Zero },
{ 4, SNAN_F16, NaN },
{ 5, QNAN_F16, NaN },
{ 6, INF_F16, Inf },
{ 7, NEG_INF_F16, Neg_Inf },
}
for d, i in data {
assert(i == d.i)
r = classify_f16(d.v)
tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, d.v, r, d.e))
}
/* Check all subnormals (exponent 0, 10-bit significand non-zero) */
for i :u16 = 1; i < 0x400; i += 1 {
v :f16 = transmute(f16)i
r = classify_f16(v)
e :Float_Class: Subnormal
tc.expect(t, r == e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, v, r, e))
}
}
@test
test_classify_f32 :: proc(t: ^testing.T) {
using math
using Float_Class
r: Float_Class
Datum :: struct {
i: int,
v: f32,
e: math.Float_Class,
}
@static data := []Datum{
{ 0, 1.2, Normal },
{ 1, 0h0000_0001, Subnormal },
{ 2, 0.0, Zero },
{ 3, -0.0, Neg_Zero },
{ 4, SNAN_F32, NaN },
{ 5, QNAN_F32, NaN },
{ 6, INF_F32, Inf },
{ 7, NEG_INF_F32, Neg_Inf },
}
for d, i in data {
assert(i == d.i)
r = classify_f32(d.v)
tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, d.v, r, d.e))
}
}
@test
test_classify_f64 :: proc(t: ^testing.T) {
using math
using Float_Class
r: Float_Class
Datum :: struct {
i: int,
v: f64,
e: math.Float_Class,
}
@static data := []Datum{
{ 0, 1.2, Normal },
{ 1, 0h0000_0000_0000_0001, Subnormal },
{ 2, 0.0, Zero },
{ 3, -0.0, Neg_Zero },
{ 4, SNAN_F64, NaN },
{ 5, QNAN_F64, NaN },
{ 6, INF_F64, Inf },
{ 7, NEG_INF_F64, Neg_Inf },
}
for d, i in data {
assert(i == d.i)
r = classify_f64(d.v)
tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, d.v, r, d.e))
}
}
@test
test_trunc_f16 :: proc(t: ^testing.T) {
using math
r, v: f16
Datum :: struct {
i: int,
v: f16,
e: f16,
}
@static data := []Datum{
{ 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken
{ 1, -10.5, -10 },
{ 2, F16_MAX, F16_MAX },
{ 3, -F16_MAX, -F16_MAX },
{ 4, F16_MIN, 0.0 },
{ 5, -F16_MIN, -0.0 },
{ 6, 0.0, 0.0 },
{ 7, -0.0, -0.0 },
{ 8, 1, 1 },
{ 9, -1, -1 },
{ 10, INF_F16, INF_F16 },
{ 11, NEG_INF_F16, NEG_INF_F16 },
/* From https://en.wikipedia.org/wiki/Half-precision_floating-point_format */
{ 12, 0h3C01, 1 }, // 0x1.004p+0 (smallest > 1)
{ 13, -0h3C01, -1 },
{ 14, 0h3BFF, 0.0 }, // 0x1.ffcp-1 (largest < 1)
{ 15, -0h3BFF, -0.0 },
{ 16, 0h0001, 0.0 }, // 0x0.004p-14 (smallest subnormal)
{ 17, -0h0001, -0.0 },
{ 18, 0h03FF, 0.0 }, // 0x0.ffcp-14 (largest subnormal)
{ 19, -0h03FF, -0.0 },
{ 20, 0hC809, -8 }, // -0x1.024p+3
{ 21, 0h4458, 4 }, // 0x1.16p+2
}
for d, i in data {
assert(i == d.i)
r = trunc_f16(d.v)
tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %h != %h", i, #procedure, d.v, r, d.e))
}
v = SNAN_F16
r = trunc_f16(v)
tc.expect(t, is_nan_f16(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
v = QNAN_F16
r = trunc_f16(v)
tc.expect(t, is_nan_f16(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
}
@test
test_trunc_f32 :: proc(t: ^testing.T) {
using math
r, v: f32
Datum :: struct {
i: int,
v: f32,
e: f32,
}
@static data := []Datum{
{ 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken
{ 1, -10.5, -10 },
{ 2, F32_MAX, F32_MAX },
{ 3, -F32_MAX, -F32_MAX },
{ 4, F32_MIN, 0.0 },
{ 5, -F32_MIN, -0.0 },
{ 6, 0.0, 0.0 },
{ 7, -0.0, -0.0 },
{ 8, 1, 1 },
{ 9, -1, -1 },
{ 10, INF_F32, INF_F32 },
{ 11, NEG_INF_F32, NEG_INF_F32 },
/* From https://en.wikipedia.org/wiki/Single-precision_floating-point_format */
{ 12, 0h3F80_0001, 1 }, // 0x1.000002p+0 (smallest > 1)
{ 13, -0h3F80_0001, -1 },
{ 14, 0h3F7F_FFFF, 0.0 }, // 0x1.fffffep-1 (largest < 1)
{ 15, -0h3F7F_FFFF, -0.0 },
{ 16, 0h0000_0001, 0.0 }, // 0x0.000002p-126 (smallest subnormal)
{ 17, -0h0000_0001, -0.0 },
{ 18, 0h007F_FFFF, 0.0 }, // 0x0.fffffep-126 (largest subnormal)
{ 19, -0h007F_FFFF, -0.0 },
/* From libc-test src/math/sanity/truncf.h */
{ 20, 0hC101_11D0, -8 }, // -0x1.0223ap+3
{ 21, 0h408B_0C34, 4 }, // 0x1.161868p+2
{ 22, 0hC106_1A5A, -8 }, // -0x1.0c34b4p+3
{ 23, 0hC0D1_0378, -6 }, // -0x1.a206fp+2
{ 24, 0h4114_45DE, 9 }, // 0x1.288bbcp+3
{ 25, 0h3F29_77E8, 0.0 }, // 0x1.52efdp-1
{ 26, 0hBED0_2E64, -0.0 }, // -0x1.a05cc8p-2
{ 27, 0h3F0F_CF7D, 0.0 }, // 0x1.1f9efap-1
{ 28, 0h3F46_2ED8, 0.0 }, // 0x1.8c5dbp-1
{ 29, 0hBF2D_C375, -0.0 }, // -0x1.5b86eap-1
}
for d, i in data {
assert(i == d.i)
r = trunc_f32(d.v)
tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %h != %h", i, #procedure, d.v, r, d.e))
}
v = SNAN_F32
r = trunc_f32(v)
tc.expect(t, is_nan_f32(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
v = QNAN_F32
r = trunc_f32(v)
tc.expect(t, is_nan_f32(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
}
@test
test_trunc_f64 :: proc(t: ^testing.T) {
using math
r, v: f64
Datum :: struct {
i: int,
v: f64,
e: f64,
}
data := []Datum{
{ 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken
{ 1, -10.5, -10 },
{ 2, F64_MAX, F64_MAX },
{ 3, -F64_MAX, -F64_MAX },
{ 4, F64_MIN, 0.0 },
{ 5, -F64_MIN, -0.0 },
{ 6, 0.0, 0.0 },
{ 7, -0.0, -0.0 },
{ 8, 1, 1 },
{ 9, -1, -1 },
{ 10, INF_F64, INF_F64 },
{ 11, NEG_INF_F64, NEG_INF_F64 },
/* From https://en.wikipedia.org/wiki/Double-precision_floating-point_format */
{ 12, 0h3FF0_0000_0000_0001, 1 }, // 0x1.0000000000001p+0 (smallest > 1)
{ 13, -0h3FF0_0000_0000_0001, -1 },
{ 14, 0h3FEF_FFFF_FFFF_FFFF, 0.0 }, // 0x1.fffffffffffffp-1 (largest < 1)
{ 15, -0h3FEF_FFFF_FFFF_FFFF, -0.0 },
{ 16, 0h0000_0000_0000_0001, 0.0 }, // 0x0.0000000000001p-1022 (smallest subnormal)
{ 17, -0h0000_0000_0000_0001, -0.0 },
{ 18, 0h000F_FFFF_FFFF_FFFF, 0.0 }, // 0x0.fffffffffffffp-1022 (largest subnormal)
{ 19, -0h000F_FFFF_FFFF_FFFF, -0.0 },
/* From libc-test src/math/sanity/trunc.h */
{ 20, 0hC020_2239_F3C6_A8F1, -8 }, // -0x1.02239f3c6a8f1p+3
{ 21, 0h4011_6186_8E18_BC67, 4 }, // 0x1.161868e18bc67p+2
{ 22, 0hC020_C34B_3E01_E6E7, -8 }, // -0x1.0c34b3e01e6e7p+3
{ 23, 0hC01A_206F_0A19_DCC4, -6 }, // -0x1.a206f0a19dcc4p+2
{ 24, 0h4022_88BB_B0D6_A1E6, 9 }, // 0x1.288bbb0d6a1e6p+3
{ 25, 0h3FE5_2EFD_0CD8_0497, 0.0 }, // 0x1.52efd0cd80497p-1
{ 26, 0hBFDA_05CC_7544_81D1, -0.0 }, // -0x1.a05cc754481d1p-2
{ 27, 0h3FE1_F9EF_9347_45CB, 0.0 }, // 0x1.1f9ef934745cbp-1
{ 28, 0h3FE8_C5DB_097F_7442, 0.0 }, // 0x1.8c5db097f7442p-1
{ 29, 0hBFE5_B86E_A811_8A0E, -0.0 }, // -0x1.5b86ea8118a0ep-1
}
for d, i in data {
assert(i == d.i)
r = trunc_f64(d.v)
tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %h != %h", i, #procedure, d.v, r, d.e))
}
v = SNAN_F64
r = trunc_f64(v)
tc.expect(t, is_nan_f64(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
v = QNAN_F64
r = trunc_f64(v)
tc.expect(t, is_nan_f64(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
}

View File

@@ -2,7 +2,7 @@ package test_core_odin_parser
import "core:testing"
import "core:fmt"
import "core:os"
import "core:odin/parser"
@@ -22,7 +22,8 @@ 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)
}
}
@@ -30,9 +31,13 @@ main :: proc() {
t := testing.T{}
test_parse_demo(&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
test_parse_demo :: proc(t: ^testing.T) {
pkg, ok := parser.parse_package_from_path("examples/demo")
@@ -42,4 +47,4 @@ test_parse_demo :: proc(t: ^testing.T) {
for key, value in pkg.files {
expect(t, value.syntax_error_count == 0, fmt.tprintf("%v should contain zero errors", key))
}
}
}

View File

@@ -0,0 +1,10 @@
// Tests that Odin run returns exit code of built executable on Unix
// Needs exit status to be inverted to return 0 on success, e.g.
// $(./odin run tests/core/os/test_core_os_exit.odin && exit 1 || exit 0)
package test_core_os_exit
import "core:os"
main :: proc() {
os.exit(1)
}

View File

@@ -0,0 +1,123 @@
// Tests "path.odin" in "core:path/filepath".
// Must be run with `-collection:tests=` flag, e.g.
// ./odin run tests/core/path/filepath/test_core_filepath.odin -collection:tests=tests
package test_core_filepath
import "core:fmt"
import "core:path/filepath"
import "core:testing"
import tc "tests:common"
main :: proc() {
t := testing.T{}
when ODIN_OS == .Windows {
test_split_list_windows(&t)
} else {
test_split_list_unix(&t)
}
tc.report(&t)
}
@test
test_split_list_windows :: proc(t: ^testing.T) {
using filepath
Datum :: struct {
i: int,
v: string,
e: [3]string,
}
@static data := []Datum{
{ 0, "C:\\Odin;C:\\Visual Studio;\"C:\\Some Other\"",
[3]string{"C:\\Odin", "C:\\Visual Studio", "C:\\Some Other"} }, // Issue #1537
{ 1, "a;;b", [3]string{"a", "", "b"} },
{ 2, "a;b;", [3]string{"a", "b", ""} },
{ 3, ";a;b", [3]string{"", "a", "b"} },
{ 4, ";;", [3]string{"", "", ""} },
{ 5, "\"a;b\"c;d;\"f\"", [3]string{"a;bc", "d", "f"} },
{ 6, "\"a;b;c\";d\";e\";f", [3]string{"a;b;c", "d;e", "f"} },
}
for d, i in data {
assert(i == d.i, fmt.tprintf("wrong data index: i %d != d.i %d\n", i, d.i))
r := split_list(d.v)
defer delete(r)
tc.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 {
tc.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]))
}
}
}
{
v := ""
r := split_list(v)
tc.expect(t, r == nil, fmt.tprintf("%s(%s) -> %v != nil", #procedure, v, r))
}
{
v := "a"
r := split_list(v)
defer delete(r)
tc.expect(t, len(r) == 1, fmt.tprintf("%s(%s) len(r) %d != 1", #procedure, v, len(r)))
if len(r) == 1 {
tc.expect(t, r[0] == "a", fmt.tprintf("%s(%v) -> %v[0] != a", #procedure, v, r[0]))
}
}
}
@test
test_split_list_unix :: proc(t: ^testing.T) {
using filepath
Datum :: struct {
i: int,
v: string,
e: [3]string,
}
@static data := []Datum{
{ 0, "/opt/butler:/home/fancykillerpanda/Projects/Odin/Odin:/usr/local/sbin",
[3]string{"/opt/butler", "/home/fancykillerpanda/Projects/Odin/Odin", "/usr/local/sbin"} }, // Issue #1537
{ 1, "a::b", [3]string{"a", "", "b"} },
{ 2, "a:b:", [3]string{"a", "b", ""} },
{ 3, ":a:b", [3]string{"", "a", "b"} },
{ 4, "::", [3]string{"", "", ""} },
{ 5, "\"a:b\"c:d:\"f\"", [3]string{"a:bc", "d", "f"} },
{ 6, "\"a:b:c\":d\":e\":f", [3]string{"a:b:c", "d:e", "f"} },
}
for d, i in data {
assert(i == d.i, fmt.tprintf("wrong data index: i %d != d.i %d\n", i, d.i))
r := split_list(d.v)
defer delete(r)
tc.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 {
tc.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]))
}
}
}
{
v := ""
r := split_list(v)
tc.expect(t, r == nil, fmt.tprintf("%s(%s) -> %v != nil", #procedure, v, r))
}
{
v := "a"
r := split_list(v)
defer delete(r)
tc.expect(t, len(r) == 1, fmt.tprintf("%s(%s) len(r) %d != 1", #procedure, v, len(r)))
if len(r) == 1 {
tc.expect(t, r[0] == "a", fmt.tprintf("%s(%v) -> %v[0] != a", #procedure, v, r[0]))
}
}
}

View File

@@ -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))
}
}
}

View File

@@ -1,8 +1,9 @@
package test_core_image
package test_core_strings
import "core:strings"
import "core:testing"
import "core:fmt"
import "core:os"
TEST_count := 0
TEST_fail := 0
@@ -20,7 +21,8 @@ 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)
}
}
@@ -30,14 +32,17 @@ main :: proc() {
test_index_any_larger_string_not_found(&t)
test_index_any_small_string_found(&t)
test_index_any_larger_string_found(&t)
test_cut(&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
test_index_any_small_string_not_found :: proc(t: ^testing.T) {
index := strings.index_any(".", "/:\"")
log(t, index)
expect(t, index == -1, "index_any should be negative")
}
@@ -58,3 +63,30 @@ test_index_any_larger_string_found :: proc(t: ^testing.T) {
index := strings.index_any("aaaaaaaa:aaaaaaaa", "/:\"")
expect(t, index == 8, "index_any should be 8")
}
Cut_Test :: struct {
input: string,
offset: int,
length: int,
output: string,
}
cut_tests :: []Cut_Test{
{"some example text", 0, 4, "some" },
{"some example text", 2, 2, "me" },
{"some example text", 5, 7, "example" },
{"some example text", 5, 0, "example text"},
{"恥ずべきフクロウ", 4, 0, "フクロウ" },
}
@test
test_cut :: proc(t: ^testing.T) {
for test in cut_tests {
res := strings.cut(test.input, test.offset, test.length)
defer delete(res)
msg := fmt.tprintf("cut(\"%v\", %v, %v) expected to return \"%v\", got \"%v\"",
test.input, test.offset, test.length, test.output, res)
expect(t, res == test.output, msg)
}
}

17
tests/issues/run.bat Normal file
View File

@@ -0,0 +1,17 @@
@echo off
if not exist "build\" mkdir build
set COMMON=-collection:tests=.. -out:build\test_issue.exe
@echo on
..\..\odin build test_issue_829.odin %COMMON% -file
build\test_issue
..\..\odin build test_issue_1592.odin %COMMON% -file
build\test_issue
@echo off
rmdir /S /Q build

18
tests/issues/run.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
set -eu
mkdir -p build
ODIN=../../odin
COMMON="-collection:tests=.. -out:build/test_issue"
set -x
$ODIN build test_issue_829.odin $COMMON -file
./build/test_issue
$ODIN build test_issue_1592.odin $COMMON -file
./build/test_issue
set +x
rm -rf build

View File

@@ -0,0 +1,489 @@
// Tests issue #1592 https://github.com/odin-lang/Odin/issues/1592
package test_issues
import "core:fmt"
import "core:testing"
import tc "tests:common"
main :: proc() {
t := testing.T{}
/* This won't short-circuit */
test_orig()
/* These will short-circuit */
test_simple_const_false(&t)
test_simple_const_true(&t)
/* These won't short-circuit */
test_simple_proc_false(&t)
test_simple_proc_true(&t)
/* These won't short-circuit */
test_const_false_const_false(&t)
test_const_false_const_true(&t)
test_const_true_const_false(&t)
test_const_true_const_true(&t)
/* These won't short-circuit */
test_proc_false_const_false(&t)
test_proc_false_const_true(&t)
test_proc_true_const_false(&t)
test_proc_true_const_true(&t)
tc.report(&t)
}
/* Original issue #1592 example */
// I get a LLVM code gen error when this constant is false, but it works when it is true
CONSTANT_BOOL :: false
bool_result :: proc() -> bool {
return false
}
@test
test_orig :: proc() {
if bool_result() || CONSTANT_BOOL {
}
}
CONSTANT_FALSE :: false
CONSTANT_TRUE :: true
false_result :: proc() -> bool {
return false
}
true_result :: proc() -> bool {
return true
}
@test
test_simple_const_false :: proc(t: ^testing.T) {
if CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if (CONSTANT_FALSE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if (!CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !!CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_FALSE == true {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_FALSE == false {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(CONSTANT_FALSE == true) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(CONSTANT_FALSE == false) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
}
@test
test_simple_const_true :: proc(t: ^testing.T) {
if CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if (CONSTANT_TRUE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if (!CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if (!CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !!CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE == true {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE == false {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE == true) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE == false) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_simple_proc_false :: proc(t: ^testing.T) {
if false_result() {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !false_result() {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_simple_proc_true :: proc(t: ^testing.T) {
if true_result() {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !true_result() {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
}
@test
test_const_false_const_false :: proc(t: ^testing.T) {
if CONSTANT_FALSE || CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_FALSE && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !CONSTANT_FALSE || CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !CONSTANT_FALSE && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_FALSE || !CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_FALSE && !CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_FALSE || CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(CONSTANT_FALSE && CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_const_false_const_true :: proc(t: ^testing.T) {
if CONSTANT_FALSE || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_FALSE && CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !CONSTANT_FALSE || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !CONSTANT_FALSE && CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_FALSE || !CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_FALSE && !CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_FALSE || CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_FALSE && CONSTANT_TRUE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_const_true_const_false :: proc(t: ^testing.T) {
if CONSTANT_TRUE || CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !CONSTANT_TRUE || CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !CONSTANT_TRUE && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_TRUE || !CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE && !CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(CONSTANT_TRUE || CONSTANT_FALSE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE && CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_const_true_const_true :: proc(t: ^testing.T) {
if CONSTANT_TRUE || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE && CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !CONSTANT_TRUE || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !CONSTANT_TRUE && CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_TRUE || !CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE && !CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE || CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE && CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
}
@test
test_proc_false_const_false :: proc(t: ^testing.T) {
if false_result() || CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if false_result() && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(false_result() || CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(false_result() && CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_proc_false_const_true :: proc(t: ^testing.T) {
if false_result() || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if false_result() && CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(false_result() || CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(false_result() && CONSTANT_TRUE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_proc_true_const_false :: proc(t: ^testing.T) {
if true_result() || CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if true_result() && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(true_result() || CONSTANT_FALSE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(true_result() && CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_proc_true_const_true :: proc(t: ^testing.T) {
if true_result() || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if true_result() && CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(true_result() || CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(true_result() && CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
}

View File

@@ -0,0 +1,33 @@
// Tests issue #829 https://github.com/odin-lang/Odin/issues/829
package test_issues
import "core:fmt"
import "core:testing"
import tc "tests:common"
/* Original issue #829 example */
env : map[string]proc(a, b : int) -> int = {
"+" = proc(a, b : int) -> int {
return a + b
},
}
test_orig :: proc() {
fmt.println(env["+"](1, 2))
}
main :: proc() {
t := testing.T{}
test_orig()
test_orig_ret(&t)
tc.report(&t)
}
test_orig_ret :: proc(t: ^testing.T) {
r := fmt.tprint(env["+"](1, 2))
tc.expect(t, r == "3", fmt.tprintf("%s: \"%s\" != \"3\"\n", #procedure, r))
}

View File

@@ -1,6 +1,13 @@
ODIN=../../odin
ODINFLAGS=
OS=$(shell uname)
ifeq ($(OS), OpenBSD)
ODINFLAGS:=$(ODINFLAGS) -extra-linker-flags:-L/usr/local/lib
endif
all: botan_test
botan_test:
$(ODIN) run botan -out=botan_hash -o:speed -no-bounds-check
$(ODIN) run botan -o:speed -no-bounds-check $(ODINFLAGS) -out=vendor_botan

View File

@@ -14,6 +14,7 @@ package test_vendor_botan
import "core:testing"
import "core:fmt"
import "core:os"
import "vendor:botan/md4"
import "vendor:botan/md5"
@@ -30,6 +31,7 @@ import "vendor:botan/gost"
import "vendor:botan/streebog"
import "vendor:botan/sm3"
import "vendor:botan/skein512"
import "vendor:botan/siphash"
TEST_count := 0
TEST_fail := 0
@@ -82,8 +84,12 @@ main :: proc() {
test_sm3(&t)
test_skein512_256(&t)
test_skein512_512(&t)
test_siphash_2_4(&t)
fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
if TEST_fail > 0 {
os.exit(1)
}
}
TestHash :: struct {
@@ -575,3 +581,44 @@ test_skein512_512 :: proc(t: ^testing.T) {
expect(t, computed_str == v.hash, fmt.tprintf("Expected: %s for input of %s, but got %s instead", v.hash, v.str, computed_str))
}
}
@(test)
test_siphash_2_4 :: proc(t: ^testing.T) {
// Test vectors from
// https://github.com/veorq/SipHash/blob/master/vectors.h
test_vectors := [?]u64 {
0x726fdb47dd0e0e31, 0x74f839c593dc67fd, 0x0d6c8009d9a94f5a, 0x85676696d7fb7e2d,
0xcf2794e0277187b7, 0x18765564cd99a68d, 0xcbc9466e58fee3ce, 0xab0200f58b01d137,
0x93f5f5799a932462, 0x9e0082df0ba9e4b0, 0x7a5dbbc594ddb9f3, 0xf4b32f46226bada7,
0x751e8fbc860ee5fb, 0x14ea5627c0843d90, 0xf723ca908e7af2ee, 0xa129ca6149be45e5,
0x3f2acc7f57c29bdb, 0x699ae9f52cbe4794, 0x4bc1b3f0968dd39c, 0xbb6dc91da77961bd,
0xbed65cf21aa2ee98, 0xd0f2cbb02e3b67c7, 0x93536795e3a33e88, 0xa80c038ccd5ccec8,
0xb8ad50c6f649af94, 0xbce192de8a85b8ea, 0x17d835b85bbb15f3, 0x2f2e6163076bcfad,
0xde4daaaca71dc9a5, 0xa6a2506687956571, 0xad87a3535c49ef28, 0x32d892fad841c342,
0x7127512f72f27cce, 0xa7f32346f95978e3, 0x12e0b01abb051238, 0x15e034d40fa197ae,
0x314dffbe0815a3b4, 0x027990f029623981, 0xcadcd4e59ef40c4d, 0x9abfd8766a33735c,
0x0e3ea96b5304a7d0, 0xad0c42d6fc585992, 0x187306c89bc215a9, 0xd4a60abcf3792b95,
0xf935451de4f21df2, 0xa9538f0419755787, 0xdb9acddff56ca510, 0xd06c98cd5c0975eb,
0xe612a3cb9ecba951, 0xc766e62cfcadaf96, 0xee64435a9752fe72, 0xa192d576b245165a,
0x0a8787bf8ecb74b2, 0x81b3e73d20b49b6f, 0x7fa8220ba3b2ecea, 0x245731c13ca42499,
0xb78dbfaf3a8d83bd, 0xea1ad565322a1a0b, 0x60e61c23a3795013, 0x6606d7e446282b93,
0x6ca4ecb15c5f91e1, 0x9f626da15c9625f3, 0xe51b38608ef25f57, 0x958a324ceb064572,
}
key: [16]byte
for i in 0..<16 {
key[i] = byte(i)
}
for i in 0..<len(test_vectors) {
data := make([]byte, i)
for j in 0..<i {
data[j] = byte(j)
}
vector := test_vectors[i]
computed := siphash.sum_2_4(data[:], key[:])
expect(t, computed == vector, fmt.tprintf("Expected: 0x%x for input of %v, but got 0x%x instead", vector, data, computed))
}
}

View File

@@ -5,9 +5,9 @@ set PATH_TO_ODIN==..\..\odin
echo ---
echo Running vendor:botan tests
echo ---
%PATH_TO_ODIN% run botan %COMMON%
%PATH_TO_ODIN% run botan %COMMON% -out:vendor_botan.exe
echo ---
echo Running vendor:glfw tests
echo ---
%PATH_TO_ODIN% run glfw %COMMON%
%PATH_TO_ODIN% run glfw %COMMON% -out:vendor_glfw.exe

View File

@@ -3,6 +3,7 @@ package test_vendor_glfw
import "core:testing"
import "core:fmt"
import "vendor:glfw"
import "core:os"
GLFW_MAJOR :: 3
GLFW_MINOR :: 3
@@ -36,6 +37,9 @@ main :: proc() {
test_glfw(&t)
fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
if TEST_fail > 0 {
os.exit(1)
}
}
@(test)