123456789module tests1011import compress.zlib12import crypto.blake313import crypto.hmac14import crypto.sha25615import net16import net.http17import os18import time1920212223fn test_built_with_the_pinned_v() {24 assert @VCURRENTHASH == 'b9a2d87'25}2627fn test_koh_refuses_a_build_without_garbage_collection() {28 output := os.join_path(os.temp_dir(), 'koh-no-gc-${os.getpid()}')29 result := os.execute('v -gc none -o "${output}" "${@VMODROOT}/src/koh.v"')30 assert result.exit_code != 031 assert result.output.contains('Koh requires garbage collection')32}3334fn test_linux_release_script_builds_without_zig() {35 dir := os.join_path(os.temp_dir(), 'koh-release-script-${time.now().unix_nano()}')36 tools := os.join_path(dir, 'tools')37 os.mkdir_all(tools)!38 for name in ['dirname', 'mkdir', 'cc'] {39 os.symlink(os.find_abs_path_of_executable(name)!, os.join_path(tools, name))!40 }41 os.cp('${@VMODROOT}/build.sh', os.join_path(dir, 'build.sh'))!42 v := os.join_path(tools, 'v')43 os.write_file(v, '#!/bin/sh44if [ "$1" = version ]; then echo "V 0.5.2 b9a2d87"; exit 0; fi45printf "%s\\n" "$@" > args46while [ "$#" -gt 0 ]; do47 if [ "$1" = -o ]; then : > "$2"; exit 0; fi48 shift49done50exit 151')!52 os.chmod(v, 0o755)!53 for cpu in ['aarch64', 'x86_64'] {54 uname := os.join_path(tools, 'uname')55 os.write_file(uname, '#!/bin/sh\ncase "$1" in -s) echo Linux ;; -m) echo ${cpu} ;; esac\n')!56 os.chmod(uname, 0o755)!57 result := os.execute('PATH="${tools}" KOH_TARGET=linux-${cpu} /bin/sh "${dir}/build.sh"')58 assert result.exit_code == 0, result.output59 assert os.is_file(os.join_path(dir, 'build/releases/koh-linux-${cpu}'))60 args := os.read_file(os.join_path(dir, 'args'))!61 assert args.contains('-gc\nboehm\n')62 assert args.contains('-d\nuse_bundled_libgc\n')63 assert args.contains('-ldflags\n-static -s\n')64 }65}6667686970fn test_blake3_vectors() {71 assert blake3.sum256(''.bytes()).hex() == 'af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262'72 assert blake3.sum256('abc'.bytes()).hex() == '6437b3ac38465133ffb63b75273a8db548c558465d79db03fd359c6cd5bd9d85'73 assert blake3.sum256('The quick brown fox jumps over the lazy dog'.bytes()).hex() == '2f1514181aadccd913abd94cfa592701a5686ab23f8df1dff1b74710febc6d4a'74}7576fn test_blake3_streaming_matches_one_shot() {77 mut d := blake3.Digest.new_hash()!78 d.write('The quick brown '.bytes())!79 d.write('fox jumps over the lazy dog'.bytes())!80 assert d.checksum(32) == blake3.sum256('The quick brown fox jumps over the lazy dog'.bytes())81}8283fn test_zlib_round_trip() {84 85 86 mut all_bytes := []u8{len: 256}87 for i in 0 .. 256 {88 all_bytes[i] = u8(i)89 }90 mut payloads := [[]u8{}, 'hello koh'.bytes()]91 payloads << all_bytes92 for payload in payloads {93 packed := zlib.compress(payload)!94 assert zlib.decompress(packed)! == payload95 }96}9798fn test_sha256_and_hmac_vectors() {99 assert sha256.sum256('abc'.bytes()).hex() == 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'100 assert sha256.hexhash('abc') == 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'101 102 mac := hmac.new('key'.bytes(), 'The quick brown fox jumps over the lazy dog'.bytes(),103 sha256.sum256, 64)104 assert mac.hex() == 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8'105}106107struct EtagHandler {108mut:109 seen_if_none_match string110}111112fn (mut h EtagHandler) handle(req http.Request) http.Response {113 h.seen_if_none_match = req.header.get_custom('If-None-Match', http.HeaderQueryConfig{}) or {114 ''115 }116 mut resp := http.Response{117 body: 'payload'118 }119 if h.seen_if_none_match == '*' {120 resp.status_code = 412121 resp.status_msg = 'Precondition Failed'122 } else {123 resp.status_code = 200124 resp.status_msg = 'OK'125 }126 resp.header.add_custom('ETag', '"3b1f"') or {}127 return resp128}129130131132fn start_probe_server() !(int, &http.Server) {133 for port in [19301, 19302, 19303, 19304, 19305] {134 listener := net.listen_tcp(.ip, '127.0.0.1:${port}') or { continue }135 mut server := &http.Server{136 listener: listener137 handler: EtagHandler{}138 show_startup_message: false139 }140 spawn server.listen_and_serve()141 server.wait_till_running()!142 return port, server143 }144 return error('no free port for the probe server')145}146147148149150fn test_http_client_sends_headers_and_reads_status_and_etag() {151 port, mut server := start_probe_server()!152 defer {153 server.stop()154 }155 url := 'http://127.0.0.1:${port}/probe'156 mut hdr := http.new_header()157 hdr.add_custom('If-None-Match', '*')!158159 resp := http.fetch(160 url: url161 method: .get162 header: hdr163 )!164 assert resp.status_code == 412165 assert resp.header.get_custom('ETag', http.HeaderQueryConfig{}) or { '' } == '"3b1f"'166167 plain := http.fetch(url: url, method: .get)!168 assert plain.status_code == 200169 assert plain.body == 'payload'170171 172 173 if _ := http.fetch(174 url: 'http://127.0.0.1:19399/gone'175 method: .get176 read_timeout: 2 * time.second177 )178 {179 assert false, 'a request to a closed port should fail'180 }181}