123456789module tests1011import compress.zlib12import crypto.blake313import crypto.hmac14import crypto.sha25615import net16import net.http17import time1819202122fn test_blake3_vectors() {23 assert blake3.sum256(''.bytes()).hex() == 'af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262'24 assert blake3.sum256('abc'.bytes()).hex() == '6437b3ac38465133ffb63b75273a8db548c558465d79db03fd359c6cd5bd9d85'25 assert blake3.sum256('The quick brown fox jumps over the lazy dog'.bytes()).hex() == '2f1514181aadccd913abd94cfa592701a5686ab23f8df1dff1b74710febc6d4a'26}2728fn test_blake3_streaming_matches_one_shot() {29 mut d := blake3.Digest.new_hash()!30 d.write('The quick brown '.bytes())!31 d.write('fox jumps over the lazy dog'.bytes())!32 assert d.checksum(32) == blake3.sum256('The quick brown fox jumps over the lazy dog'.bytes())33}3435fn test_zlib_round_trip() {36 37 38 mut all_bytes := []u8{len: 256}39 for i in 0 .. 256 {40 all_bytes[i] = u8(i)41 }42 mut payloads := [[]u8{}, 'hello koh'.bytes()]43 payloads << all_bytes44 for payload in payloads {45 packed := zlib.compress(payload)!46 assert zlib.decompress(packed)! == payload47 }48}4950fn test_sha256_and_hmac_vectors() {51 assert sha256.sum256('abc'.bytes()).hex() == 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'52 assert sha256.hexhash('abc') == 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'53 54 mac := hmac.new('key'.bytes(), 'The quick brown fox jumps over the lazy dog'.bytes(),55 sha256.sum256, 64)56 assert mac.hex() == 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8'57}5859struct EtagHandler {60mut:61 seen_if_none_match string62}6364fn (mut h EtagHandler) handle(req http.Request) http.Response {65 h.seen_if_none_match = req.header.get_custom('If-None-Match', http.HeaderQueryConfig{}) or {66 ''67 }68 mut resp := http.Response{69 body: 'payload'70 }71 if h.seen_if_none_match == '*' {72 resp.status_code = 41273 resp.status_msg = 'Precondition Failed'74 } else {75 resp.status_code = 20076 resp.status_msg = 'OK'77 }78 resp.header.add_custom('ETag', '"3b1f"') or {}79 return resp80}81828384fn start_probe_server() !(int, &http.Server) {85 for port in [19301, 19302, 19303, 19304, 19305] {86 listener := net.listen_tcp(.ip, '127.0.0.1:${port}') or { continue }87 mut server := &http.Server{88 listener: listener89 handler: EtagHandler{}90 show_startup_message: false91 }92 spawn server.listen_and_serve()93 server.wait_till_running()!94 return port, server95 }96 return error('no free port for the probe server')97}9899100101102fn test_http_client_sends_headers_and_reads_status_and_etag() {103 port, mut server := start_probe_server()!104 defer {105 server.stop()106 }107 url := 'http://127.0.0.1:${port}/probe'108 mut hdr := http.new_header()109 hdr.add_custom('If-None-Match', '*')!110111 resp := http.fetch(112 url: url113 method: .get114 header: hdr115 )!116 assert resp.status_code == 412117 assert resp.header.get_custom('ETag', http.HeaderQueryConfig{}) or { '' } == '"3b1f"'118119 plain := http.fetch(url: url, method: .get)!120 assert plain.status_code == 200121 assert plain.body == 'payload'122123 124 125 if _ := http.fetch(126 url: 'http://127.0.0.1:19399/gone'127 method: .get128 read_timeout: 2 * time.second129 )130 {131 assert false, 'a request to a closed port should fail'132 }133}