//! Unit tests for `koh update`: ordering versions, decoding a release //! document, and the two checks that stand between a download and the binary. module update import crypto.blake3 import json2 import os fn scratch(name string) !string { dir := os.join_path(os.temp_dir(), 'koh3_update_${os.getpid()}_${name}') os.rmdir_all(dir) or {} os.mkdir_all(dir, os.MkdirParams{})! return dir } fn test_versions_compare_as_numbers_component_by_component() { assert compare_versions('2.10.0', '2.9.9') == 1 assert compare_versions('2.9.9', '2.10.0') == -1 assert compare_versions('3.0.82', '3.0.82') == 0 assert compare_versions('1.0', '1.0.0') == 0 assert compare_versions('1.01', '1.1') == 0 assert compare_versions('1.0.1', '1.0') == 1 assert compare_versions('10.0.0', '9.9.9') == 1 assert compare_versions('0.9', '1.0') == -1 } fn test_a_release_document_is_read_with_and_without_notes() { body := '{"version":"3.0.84","platforms":{"macos-aarch64":{"url":"https://x/koh","blake3":"ab"}}}' document := json2.decode[Document](body)! assert document.version == '3.0.84' assert document.notes or { 'absent' } == 'absent' assert document.platforms['macos-aarch64'] or { PlatformFile{} }.url == 'https://x/koh' with_notes := '{"version":"3.0.84","notes":"hello","platforms":{}}' assert json2.decode[Document](with_notes)!.notes or { '' } == 'hello' } fn test_a_download_that_is_not_the_published_file_is_refused() { body := 'the new binary'.bytes() // The Blake3 of this exact text, computed elsewhere: a real check, not the // implementation checking itself. good := '0e86a96ebd4c3d861a2e85c07544478573af7ab3745c1d4e7b5750fdbe7cc397' assert blake3.sum256(body).hex() == good verify(body, good)! if _ := verify(body, 'ff'.repeat(32)) { assert false, 'a download that does not match its checksum must be refused' } else { assert err.msg().contains('not the published file') } if _ := verify([]u8{}, good) { assert false, 'an empty download must be refused' } if _ := verify(body, '') { assert false, 'a document without a checksum must be refused' } } fn test_staging_writes_beside_the_target_and_refuses_a_locked_folder() { dir := scratch('stage')! defer { os.rmdir_all(dir) or {} } staged := stage(dir, 'binary'.bytes())! assert os.dir(staged) == dir assert os.read_file(staged)! == 'binary' // 0755: the file is about to become the koh binary. assert (os.stat(staged) or { panic(err) }).mode & 0o777 == 0o755 locked := os.join_path(dir, 'locked') os.mkdir_all(locked, os.MkdirParams{})! os.chmod(locked, 0o500)! defer { os.chmod(locked, 0o700) or {} } if _ := stage(locked, 'binary'.bytes()) { assert false, 'a folder that cannot be written must be refused' } else { assert err.msg().contains('cannot write beside') } } fn test_the_source_can_be_named_by_the_environment() { os.setenv(source_env, 'http://127.0.0.1:8080/koh/releases/latest.json', true) assert source() == 'http://127.0.0.1:8080/koh/releases/latest.json' os.unsetenv(source_env) assert source() == default_source }