test: Rewrote expect checks to use expect_value where appropriate.

This commit is contained in:
2026-06-25 10:35:00 -04:00
parent 0b5bf4db73
commit ad3de74e35
11 changed files with 126 additions and 179 deletions

View File

@@ -1,6 +1,6 @@
# TODOs
1. Commands are still leaking. (Do 15. first)
1. Commands are still leaking. (Do 13. first)
2. Add color flag and support non colored output.
@@ -8,31 +8,29 @@
4. Generate md and man pages again.
6. Consistently ignore allocator errors
5. Consistently ignore allocator errors
7. Check for prealloc opportunities. i.e. `make([dynamic]string)` -> `make([dynamic]string, 5)`.
6. Check for prealloc opportunities. i.e. `make([dynamic]string)` -> `make([dynamic]string, 5)`.
8. Add a text filter to the multi_select.
7. Add a text filter to the multi_select.
9. Add tests for untested commands.
8. Add tests for untested commands.
10. add --format -f flag to commands that draw tables.
9. add --format -f flag to commands that draw tables.
11. Replace `testing.expect` calls with `testing.expect_value` calls where appropriate.
10. procedures should be ordered by use, main at the top, then in the order they are called from main.
12. procedures should be ordered by use, main at the top, then in the order they are called from main.
11. Shell completion
13. Shell completion
12. Bring back windows support / cross-compilation.
14. Bring back windows support / cross-compilation.
13. Test all cmds / terminal branches.
15. Test all cmds / terminal branches.
14. Fix error messages to use fmt.eprintf (stderr) instead of fmt.printf (stdout)
16. Fix error messages to use fmt.eprintf (stderr) instead of fmt.printf (stdout)
15. Pass allocator to findr?
17. Pass allocator to findr?
18. Update `read_wire_string` to use a slice.
16. Update `read_wire_string` to use a slice.
## Double-check AI output

View File

@@ -123,7 +123,7 @@ test_command_help_unknown :: proc(t: ^testing.T) {
text := strings.to_string(b)
testing.expect_value(t, len(text), 0)
}
}
@(test)
test_command_help_version :: proc(t: ^testing.T) {
@@ -236,9 +236,9 @@ test_parse_args_positional :: proc(t: ^testing.T) {
testing.expect(t, ok, "should succeed")
testing.expect_value(t, cmd.name, "backup")
testing.expect(t, len(cmd.args) == 1)
testing.expect(t, cmd.args[0] == "/project/.env")
}
testing.expect_value(t, len(cmd.args), 1)
testing.expect_value(t, cmd.args[0], "/project/.env")
}
@(test)
test_parse_args_long_flag_with_value :: proc(t: ^testing.T) {
@@ -248,7 +248,7 @@ test_parse_args_long_flag_with_value :: proc(t: ^testing.T) {
defer delete_command(&cmd)
testing.expect_value(t, cmd.flags["config"], "x.json")
}
}
@(test)
test_parse_args_short_flag_with_value :: proc(t: ^testing.T) {
@@ -258,7 +258,7 @@ test_parse_args_short_flag_with_value :: proc(t: ^testing.T) {
defer delete_command(&cmd)
testing.expect_value(t, cmd.flags["c"], "x.json")
}
}
@(test)
test_parse_args_long_bool_flag :: proc(t: ^testing.T) {
@@ -268,7 +268,7 @@ test_parse_args_long_bool_flag :: proc(t: ^testing.T) {
defer delete_command(&cmd)
testing.expect_value(t, cmd.bool_set["force"], true)
}
}
@(test)
test_parse_args_short_bool_flag :: proc(t: ^testing.T) {
@@ -278,7 +278,7 @@ test_parse_args_short_bool_flag :: proc(t: ^testing.T) {
defer delete_command(&cmd)
testing.expect_value(t, cmd.bool_set["l"], true)
}
}
@(test)
test_parse_args_multiple_positionals :: proc(t: ^testing.T) {
@@ -288,9 +288,9 @@ test_parse_args_multiple_positionals :: proc(t: ^testing.T) {
defer delete_command(&cmd)
testing.expect_value(t, len(cmd.args), 2)
testing.expect(t, cmd.args[0] == "a")
testing.expect(t, cmd.args[1] == "b")
}
testing.expect_value(t, cmd.args[0], "a")
testing.expect_value(t, cmd.args[1], "b")
}
@(test)
test_parse_args_mixed_flags_and_positionals :: proc(t: ^testing.T) {
@@ -300,9 +300,9 @@ test_parse_args_mixed_flags_and_positionals :: proc(t: ^testing.T) {
defer delete_command(&cmd)
testing.expect_value(t, cmd.bool_set["force"], true)
testing.expect(t, len(cmd.args) == 1)
testing.expect(t, cmd.args[0] == "/project/.env")
}
testing.expect_value(t, len(cmd.args), 1)
testing.expect_value(t, cmd.args[0], "/project/.env")
}
@(test)
test_parse_args_no_args :: proc(t: ^testing.T) {
@@ -318,10 +318,10 @@ test_parse_args_flag_then_positional_then_flag :: proc(t: ^testing.T) {
testing.expect(t, ok, "should succeed")
testing.expect_value(t, cmd.bool_set["force"], true)
testing.expect(t, cmd.bool_set["verbose"] == true)
testing.expect(t, len(cmd.args) == 1)
testing.expect(t, cmd.args[0] == "a.env")
}
testing.expect_value(t, cmd.bool_set["verbose"], true)
testing.expect_value(t, len(cmd.args), 1)
testing.expect_value(t, cmd.args[0], "a.env")
}
@(test)
test_parse_args_config_file_long_flag :: proc(t: ^testing.T) {
@@ -333,11 +333,7 @@ test_parse_args_config_file_long_flag :: proc(t: ^testing.T) {
defer delete_command(&cmd)
testing.expect_value(t, cmd.config_path, "/custom/config.json")
t,
cmd.config_path == "/custom/config.json",
"config_path should be set from --config-file",
)
}
}
@(test)
test_parse_args_config_file_short_flag :: proc(t: ^testing.T) {
@@ -347,11 +343,7 @@ test_parse_args_config_file_short_flag :: proc(t: ^testing.T) {
defer delete_command(&cmd)
testing.expect_value(t, cmd.config_path, "/custom/config.json")
t,
cmd.config_path == "/custom/config.json",
"config_path should be set from -c",
)
}
}
@(test)
test_parse_args_config_file_defaults :: proc(t: ^testing.T) {

View File

@@ -1,7 +1,6 @@
#+test
package main
import "core:fmt"
import "core:testing"
@(test)
@@ -10,13 +9,9 @@ test_find_unbacked_finds_missing :: proc(t: ^testing.T) {
db := []EnvFile{{path = "/a/.env"}, {path = "/b/.env"}}
result := find_unbacked(local, db[:])
testing.expect(t, len(result) == 1, fmt.tprintf("expected 1 unbacked, got %d", len(result)))
testing.expect_value(t, len(result), 1)
if len(result) > 0 {
testing.expect(
t,
result[0] == "/c/.env",
fmt.tprintf("expected /c/.env, got %s", result[0]),
)
testing.expect_value(t, result[0], "/c/.env")
}
}
@@ -26,7 +21,7 @@ test_find_unbacked_all_backed :: proc(t: ^testing.T) {
db := []EnvFile{{path = "/a/.env"}, {path = "/b/.env"}}
result := find_unbacked(local, db[:])
testing.expect(t, len(result) == 0, fmt.tprintf("expected 0 unbacked, got %d", len(result)))
testing.expect_value(t, len(result), 0)
}
@(test)
@@ -35,7 +30,7 @@ test_find_unbacked_no_local :: proc(t: ^testing.T) {
db := []EnvFile{{path = "/a/.env"}}
result := find_unbacked(local, db[:])
testing.expect(t, len(result) == 0, fmt.tprintf("expected 0 unbacked, got %d", len(result)))
testing.expect_value(t, len(result), 0)
}
@(test)
@@ -44,6 +39,6 @@ test_find_unbacked_none_backed :: proc(t: ^testing.T) {
db: []EnvFile
result := find_unbacked(local, db[:])
testing.expect(t, len(result) == 2, fmt.tprintf("expected 2 unbacked, got %d", len(result)))
testing.expect_value(t, len(result), 2)
}

View File

@@ -11,9 +11,9 @@ test_filepath_base_equals_rel :: proc(t: ^testing.T) {
for path in cases {
dir := filepath.dir(path)
rel, rel_err := filepath.rel(dir, path, context.temp_allocator)
testing.expect(t, rel_err == nil, "filepath.rel returned an error")
testing.expect_value(t, rel_err, nil)
base := filepath.base(path)
testing.expect(t, rel == base, "filepath.rel(dir, path) should equal filepath.base(path)")
testing.expect_value(t, rel, base)
}
}

View File

@@ -16,13 +16,9 @@ test_new_config_single_key :: proc(t: ^testing.T) {
cfg := new_config(paths)
defer delete_config(&cfg)
testing.expect(t, len(cfg.keys) == 1, "should have 1 key")
testing.expect(t, cfg.keys[0].private == "/home/user/.ssh/id_ed25519", "Private path mismatch")
testing.expect(
t,
cfg.keys[0].public == "/home/user/.ssh/id_ed25519.pub",
"Public path mismatch",
)
testing.expect_value(t, len(cfg.keys), 1)
testing.expect_value(t, cfg.keys[0].private, "/home/user/.ssh/id_ed25519")
testing.expect_value(t, cfg.keys[0].public, "/home/user/.ssh/id_ed25519.pub")
}
@(test)
@@ -31,9 +27,9 @@ test_new_config_multiple_keys :: proc(t: ^testing.T) {
cfg := new_config(paths)
defer delete_config(&cfg)
testing.expect(t, len(cfg.keys) == 2, "should have 2 keys")
testing.expect(t, cfg.keys[0].private == "/home/user/.ssh/id_ed25519")
testing.expect(t, cfg.keys[1].private == "/home/user/.ssh/id_rsa")
testing.expect_value(t, len(cfg.keys), 2)
testing.expect_value(t, cfg.keys[0].private, "/home/user/.ssh/id_ed25519")
testing.expect_value(t, cfg.keys[1].private, "/home/user/.ssh/id_rsa")
}
@(test)
@@ -42,7 +38,7 @@ test_new_config_empty_keys :: proc(t: ^testing.T) {
cfg := new_config(paths)
defer delete_config(&cfg)
testing.expect(t, len(cfg.keys) == 0, "should have 0 keys")
testing.expect_value(t, len(cfg.keys), 0)
}
@(test)
@@ -51,10 +47,10 @@ test_new_config_scan_defaults :: proc(t: ^testing.T) {
cfg := new_config(paths)
defer delete_config(&cfg)
testing.expect(t, cfg.scan_config.matcher == "\\.env", "matcher should be \\.env")
testing.expect(t, len(cfg.scan_config.exclude) == 4, "should have 4 exclude patterns")
testing.expect(t, len(cfg.scan_config.include) == 1, "should have 1 include path")
testing.expect(t, cfg.scan_config.include[0] == "~", "include should be ~")
testing.expect_value(t, cfg.scan_config.matcher, "\\.env")
testing.expect_value(t, len(cfg.scan_config.exclude), 4)
testing.expect_value(t, len(cfg.scan_config.include), 1)
testing.expect_value(t, cfg.scan_config.include[0], "~")
}
@(test)
@@ -65,7 +61,7 @@ test_new_config_exclude_patterns :: proc(t: ^testing.T) {
expected := []string{"*\\.envrc", "\\.local/", "node_modules", "vendor"}
for i in 0 ..< len(expected) {
testing.expect(t, cfg.scan_config.exclude[i] == expected[i])
testing.expect_value(t, cfg.scan_config.exclude[i], expected[i])
}
}
@@ -75,7 +71,7 @@ test_save_load_config_roundtrip :: proc(t: ^testing.T) {
defer os.remove_all(base)
cfgPath, err := filepath.join([]string{base, "config.json"}, context.temp_allocator)
testing.expect(t, err == nil, "cfgPath should build successfully")
testing.expect_value(t, err, nil)
cfg := new_config([]string{"/home/user/.ssh/id_ed25519"}, cfgPath)
defer delete_config(&cfg)
@@ -87,13 +83,13 @@ test_save_load_config_roundtrip :: proc(t: ^testing.T) {
if !ok do return
defer delete_config(&loaded)
testing.expect(t, len(loaded.keys) == 1, "should have 1 key")
testing.expect(t, loaded.keys[0].private == "/home/user/.ssh/id_ed25519")
testing.expect(t, loaded.keys[0].public == "/home/user/.ssh/id_ed25519.pub")
testing.expect(t, loaded.scan_config.matcher == "\\.env")
testing.expect(t, len(loaded.scan_config.exclude) == 4)
testing.expect(t, len(loaded.scan_config.include) == 1)
testing.expect(t, loaded.scan_config.include[0] == "~")
testing.expect_value(t, len(loaded.keys), 1)
testing.expect_value(t, loaded.keys[0].private, "/home/user/.ssh/id_ed25519")
testing.expect_value(t, loaded.keys[0].public, "/home/user/.ssh/id_ed25519.pub")
testing.expect_value(t, loaded.scan_config.matcher, "\\.env")
testing.expect_value(t, len(loaded.scan_config.exclude), 4)
testing.expect_value(t, len(loaded.scan_config.include), 1)
testing.expect_value(t, loaded.scan_config.include[0], "~")
}
@(test)
@@ -108,7 +104,7 @@ test_save_config_no_clobber :: proc(t: ^testing.T) {
defer os.remove_all(base)
cfgPath, err := filepath.join([]string{base, "config.json"}, context.temp_allocator)
testing.expect(t, err == nil, "cfgPath should build successfully")
testing.expect_value(t, err, nil)
cfg := new_config([]string{"/home/user/.ssh/key1"}, cfgPath)
defer delete_config(&cfg)
@@ -125,7 +121,7 @@ test_save_config_force_overwrites :: proc(t: ^testing.T) {
defer os.remove_all(base)
cfgPath, err := filepath.join([]string{base, "config.json"}, context.temp_allocator)
testing.expect(t, err == nil, "cfgPath should build successfully")
testing.expect_value(t, err, nil)
cfg := new_config([]string{"/home/user/.ssh/key1"}, cfgPath)
defer delete_config(&cfg)
@@ -140,12 +136,8 @@ test_save_config_force_overwrites :: proc(t: ^testing.T) {
if !ok do return
defer delete_config(&loaded)
testing.expect(t, len(loaded.keys) == 1, "should have 1 key")
testing.expect(
t,
loaded.keys[0].private == "/home/user/.ssh/key2",
"should be the overwritten key",
)
testing.expect_value(t, len(loaded.keys), 1)
testing.expect_value(t, loaded.keys[0].private, "/home/user/.ssh/key2")
}
@(test)
@@ -190,7 +182,7 @@ test_search_paths_expands_tilde :: proc(t: ^testing.T) {
paths := search_paths(cfg, context.temp_allocator)
testing.expect(t, len(paths) == 1, "should have 1 path")
testing.expect_value(t, len(paths), 1)
if len(paths) > 0 {
testing.expectf(
t,

View File

@@ -27,13 +27,10 @@ test_encrypt_decrypt_roundtrip :: proc(t: ^testing.T) {
testing.expect(t, dec_ok, "decryption should succeed")
defer delete(decrypted)
testing.expect(
t,
len(decrypted) == len(original),
fmt.tprintf("expected %d bytes, got %d", len(original), len(decrypted)),
)
testing.expect_value(t, len(decrypted), len(original))
// TODO: Should this be a loop?
for i in 0 ..< len(original) {
testing.expect(t, decrypted[i] == original[i], fmt.tprintf("byte mismatch at index %d", i))
testing.expect_value(t, decrypted[i], original[i])
}
}
@@ -56,16 +53,8 @@ test_encrypt_decrypt_multi_recipient :: proc(t: ^testing.T) {
defer delete(decrypted2)
for i in 0 ..< len(original) {
testing.expect(
t,
decrypted1[i] == original[i],
fmt.tprintf("key1: byte mismatch at %d", i),
)
testing.expect(
t,
decrypted2[i] == original[i],
fmt.tprintf("key2: byte mismatch at %d", i),
)
testing.expect_value(t, decrypted1[i], original[i])
testing.expect_value(t, decrypted2[i], original[i])
}
}
@@ -96,7 +85,7 @@ test_encrypt_empty_plaintext :: proc(t: ^testing.T) {
testing.expect(t, dec_ok, "decryption should succeed")
defer delete(decrypted)
testing.expect(t, len(decrypted) == 0, "decrypted empty data should be empty")
testing.expect_value(t, len(decrypted), 0)
}
@(test)
@@ -113,8 +102,9 @@ test_recipient_can_decrypt_senders_data :: proc(t: ^testing.T) {
testing.expect(t, dec_ok, "second recipient should decrypt without the sender key present")
defer delete(decrypted)
// TODO: Should this be a loop?
for i in 0 ..< len(original) {
testing.expect(t, decrypted[i] == original[i], fmt.tprintf("byte mismatch at %d", i))
testing.expect_value(t, decrypted[i], original[i])
}
}
@@ -128,9 +118,9 @@ test_ciphertext_has_magic :: proc(t: ^testing.T) {
defer delete(encrypted)
testing.expect(t, len(encrypted) >= 4, "ciphertext should have at least 4 bytes")
testing.expect(t, encrypted[0] == u8('E'), "magic byte 0")
testing.expect(t, encrypted[1] == u8('N'), "magic byte 1")
testing.expect(t, encrypted[2] == u8('V'), "magic byte 2")
testing.expect(t, encrypted[3] == u8('R'), "magic byte 3")
testing.expect_value(t, encrypted[0], u8('E'))
testing.expect_value(t, encrypted[1], u8('N'))
testing.expect_value(t, encrypted[2], u8('V'))
testing.expect_value(t, encrypted[3], u8('R'))
}

View File

@@ -67,10 +67,10 @@ test_encrypt_decrypt_sqlite_roundtrip :: proc(t: ^testing.T) {
defer delete(encrypted)
testing.expect(t, len(encrypted) >= HEADER_SIZE, "ciphertext should have header")
testing.expect(t, encrypted[0] == u8('E'), "magic byte 0")
testing.expect(t, encrypted[1] == u8('N'), "magic byte 1")
testing.expect(t, encrypted[2] == u8('V'), "magic byte 2")
testing.expect(t, encrypted[3] == u8('R'), "magic byte 3")
testing.expect_value(t, encrypted[0], u8('E'))
testing.expect_value(t, encrypted[1], u8('N'))
testing.expect_value(t, encrypted[2], u8('V'))
testing.expect_value(t, encrypted[3], u8('R'))
plaintext, dec_ok := decrypt(encrypted, cfg.keys[:])
testing.expect(t, dec_ok, "decryption should succeed")
@@ -142,7 +142,7 @@ test_encrypt_write_read_decrypt :: proc(t: ^testing.T) {
}
defer delete(plaintext)
testing.expect(t, len(plaintext) == len(sqlite_data), "size mismatch after file round-trip")
testing.expect_value(t, len(plaintext), len(sqlite_data))
}
@(test)
@@ -189,7 +189,7 @@ test_decrypt_then_deserialize_sqlite :: proc(t: ^testing.T) {
copy(buf[:len(plaintext)], plaintext)
rc = sqlite.deserialize(mem_db, "main", buf, n, n, {.FREEONCLOSE, .RESIZEABLE})
testing.expect(t, rc == sqlite.OK, "deserialize should succeed")
testing.expect_value(t, rc, sqlite.OK)
if rc != sqlite.OK {
sqlite.free(buf)
return
@@ -198,14 +198,14 @@ test_decrypt_then_deserialize_sqlite :: proc(t: ^testing.T) {
sql: cstring = "SELECT path FROM envr_env_files"
stmt: sqlite.Stmt
rc = sqlite.prepare_v2(mem_db, sql, -1, &stmt, nil)
testing.expect(t, rc == sqlite.OK, "prepare failed")
testing.expect_value(t, rc, sqlite.OK)
if rc != sqlite.OK {
return
}
defer sqlite.finalize(stmt)
rc = sqlite.step(stmt)
testing.expect(t, rc == sqlite.ROW, "expected at least one row")
testing.expect_value(t, rc, sqlite.ROW)
if rc == sqlite.ROW {
path := string(sqlite.column_text(stmt, 0))
testing.expect(t, len(path) > 0, "path should not be empty")
@@ -275,15 +275,7 @@ test_full_db_cycle :: proc(t: ^testing.T) {
}
defer delete(plaintext2)
testing.expect(
t,
len(plaintext2) == len(original_data),
fmt.tprintf(
"double round-trip size mismatch: expected %d, got %d",
len(original_data),
len(plaintext2),
),
)
testing.expect_value(t, len(plaintext2), len(original_data))
os.remove(data_path)
os.remove(envr_dir_path)
@@ -317,7 +309,7 @@ test_ssh_key_parse_from_fixtures :: proc(t: ^testing.T) {
return
}
testing.expect(t, len(x25519_pairs) == 1, "should have 1 x25519 keypair")
testing.expect_value(t, len(x25519_pairs), 1)
}
@(test)
@@ -327,7 +319,7 @@ test_config_load_with_fixture_key :: proc(t: ^testing.T) {
delete(cfg.keys)
}
testing.expect(t, len(cfg.keys) == 1, "should have 1 key")
testing.expect_value(t, len(cfg.keys), 1)
key := cfg.keys[0]

View File

@@ -81,7 +81,7 @@ test_db_insert_or_replace :: proc(t: ^testing.T) {
results, list_ok := db_list(&db)
testing.expect(t, list_ok, "list should succeed")
testing.expect(t, len(results) == 1, "should have 1 row, not 2")
testing.expect_value(t, len(results), 1)
fetched, fetch_ok := db_fetch(&db, "/project/.env")
testing.expect(t, fetch_ok, "fetch should succeed")
@@ -149,7 +149,7 @@ test_db_list_empty :: proc(t: ^testing.T) {
results, list_ok := db_list(&db)
testing.expect(t, list_ok, "list should succeed on empty db")
testing.expect(t, len(results) == 0, "should have 0 rows")
testing.expect_value(t, len(results), 0)
}
@(test)
@@ -276,11 +276,11 @@ test_get_git_remotes_single :: proc(t: ^testing.T) {
config_content := "[core]\n\trepositoryformatversion = 0\n[remote \"origin\"]\n\turl = git@github.com:user/repo.git\n\tfetch = +refs/heads/*:refs/remotes/origin/*\n"
config_path := fmt.tprintf("%s/config", git_dir)
err := os.write_entire_file(config_path, transmute([]u8)config_content)
testing.expect(t, err == nil, "should write .git/config")
testing.expect_value(t, err, nil)
remotes := get_git_remotes(base, context.temp_allocator)
testing.expect(t, len(remotes) == 1, "should find 1 remote")
testing.expect_value(t, len(remotes), 1)
if len(remotes) != 1 do return
testing.expect_value(t, remotes[0], "git@github.com:user/repo.git")
}
@@ -296,11 +296,11 @@ test_get_git_remotes_multiple :: proc(t: ^testing.T) {
config_content := "[remote \"origin\"]\n\turl = git@github.com:user/repo.git\n[remote \"upstream\"]\n\turl = https://gitlab.com/upstream/repo.git\n"
config_path := fmt.tprintf("%s/config", git_dir)
err := os.write_entire_file(config_path, transmute([]u8)config_content)
testing.expect(t, err == nil, "should write .git/config")
testing.expect_value(t, err, nil)
remotes := get_git_remotes(base, context.temp_allocator)
testing.expect(t, len(remotes) == 2, "should find 2 remotes")
testing.expect_value(t, len(remotes), 2)
}
@(test)
@@ -310,7 +310,7 @@ test_get_git_remotes_no_config :: proc(t: ^testing.T) {
remotes := get_git_remotes(base, context.temp_allocator)
testing.expect(t, len(remotes) == 0, "should return empty when no .git/config")
testing.expect_value(t, len(remotes), 0)
}
@(test)
@@ -324,11 +324,11 @@ test_get_git_remotes_no_remotes :: proc(t: ^testing.T) {
config_content := "[core]\n\trepositoryformatversion = 0\n\tbare = false\n"
config_path := fmt.tprintf("%s/config", git_dir)
err := os.write_entire_file(config_path, transmute([]u8)config_content)
testing.expect(t, err == nil, "should write .git/config")
testing.expect_value(t, err, nil)
remotes := get_git_remotes(base, context.temp_allocator)
testing.expect(t, len(remotes) == 0, "should return empty when no remote sections")
testing.expect_value(t, len(remotes), 0)
}
@(test)
@@ -338,7 +338,7 @@ test_new_env_file :: proc(t: ^testing.T) {
env_path := fmt.tprintf("%s/.env", base)
err := os.write_entire_file(env_path, "SECRET=value\n")
testing.expect(t, err == nil, ".env file should exists")
testing.expect_value(t, err, nil)
file, ok := new_env_file(env_path)
testing.expect(t, ok, "new_env_file should succeed")
@@ -350,8 +350,8 @@ test_new_env_file :: proc(t: ^testing.T) {
testing.expect(t, filepath.is_abs(file.path), "path should be absolute")
testing.expect(t, strings.has_suffix(file.path, "/.env"), "path should end with /.env")
testing.expect(t, file.contents == "SECRET=value\n", "contents mismatch")
testing.expect(t, len(file.sha256) == 64, "sha256 should be 64 hex chars")
testing.expect_value(t, file.contents, "SECRET=value\n")
testing.expect_value(t, len(file.sha256), 64)
}
@(test)
@@ -366,7 +366,7 @@ test_closing_db_has_no_leaks :: proc(t: ^testing.T) {
defer os.remove_all(base)
cfg_path, err := filepath.join([]string{base, "config.json"}, context.temp_allocator)
testing.expect(t, err == nil, "cfgPath should build successfully")
testing.expect_value(t, err, nil)
{
cfg := new_config([]string{"fixtures/keys/insecure-test-key"}, cfg_path)
@@ -385,7 +385,7 @@ test_open_existing_db_has_no_leaks :: proc(t: ^testing.T) {
defer os.remove_all(base)
cfg_path, err := filepath.join([]string{base, "config.json"}, context.temp_allocator)
testing.expect(t, err == nil, "cfgPath should build successfully")
testing.expect_value(t, err, nil)
{
cfg := new_config([]string{"fixtures/keys/insecure-test-key"}, cfg_path)
@@ -422,7 +422,7 @@ test_db_sync_noop :: proc(t: ^testing.T) {
env_path := fmt.tprintf("%s/.env", base)
content := "KEY=value\n"
write_err := os.write_entire_file(env_path, transmute([]u8)content)
testing.expect(t, write_err == nil, "should write .env file")
testing.expect_value(t, write_err, nil)
digest := hash.hash_bytes(
hash.Algorithm.SHA256,
@@ -441,8 +441,8 @@ test_db_sync_noop :: proc(t: ^testing.T) {
db_insert(&db, f)
result, sync_err := db_sync(&db, &f)
testing.expect(t, sync_err == .None, "sync should not error")
testing.expect(t, result == {}, "should be noop")
testing.expect_value(t, sync_err, SyncError.None)
testing.expect_value(t, result, nil)
}
@(test)
@@ -453,7 +453,7 @@ test_db_sync_backed_up :: proc(t: ^testing.T) {
env_path := fmt.tprintf("%s/.env", base)
changed_content := "KEY=changed\n"
write_err := os.write_entire_file(env_path, transmute([]u8)changed_content)
testing.expect(t, write_err == nil, "should write .env file")
testing.expect_value(t, write_err, nil)
db, ok := db_init()
testing.expect(t, ok, "failed to create test db")
@@ -464,7 +464,7 @@ test_db_sync_backed_up :: proc(t: ^testing.T) {
db_insert(&db, f)
result, sync_err := db_sync(&db, &f)
testing.expect(t, sync_err == .None, "sync should not error")
testing.expect_value(t, sync_err, SyncError.None)
testing.expect(t, .BackedUp in result, "should be backed up")
}
@@ -485,11 +485,11 @@ test_db_sync_restored :: proc(t: ^testing.T) {
db_insert(&db, f)
result, err := db_sync(&db, &f)
testing.expect(t, err == .None, "sync should not error")
testing.expect_value(t, err, SyncError.None)
testing.expect(t, .Restored in result, "should be restored")
data, read_err := os.read_entire_file_from_path(env_path, context.temp_allocator)
testing.expect(t, read_err == nil, "file should exist after restore")
testing.expect_value(t, read_err, nil)
if read_err == nil {
testing.expect_value(t, string(data), "SECRET=value")
}
@@ -522,7 +522,7 @@ test_db_sync_moved :: proc(t: ^testing.T) {
config_content := "[remote \"origin\"]\n\turl = git@github.com:user/repo.git\n"
config_path := fmt.tprintf("%s/config", git_dir)
write_err := os.write_entire_file(config_path, transmute([]u8)config_content)
testing.expect(t, write_err == nil, "should write .git/config")
testing.expect_value(t, write_err, nil)
db, ok := db_init()
testing.expect(t, ok, "failed to create test db")
@@ -540,7 +540,7 @@ test_db_sync_moved :: proc(t: ^testing.T) {
testing.expect(t, db_insert(&db, f), "insert should succeed")
result, err := db_sync(&db, &f)
testing.expect(t, err == .None, "sync should not error")
testing.expect_value(t, err, SyncError.None)
if err != .None do return
testing.expect(t, .DirUpdated in result, "should have DirUpdated flag")
testing.expect(t, .Restored in result, "should have Restored flag")

View File

@@ -83,6 +83,6 @@ test_scan_path_empty_dir :: proc(t: ^testing.T) {
results, ok := scan_path(base, cfg)
defer delete(results)
testing.expect(t, ok, "scan_path should succeed")
testing.expect(t, len(results) == 0, fmt.tprintf("expected 0 results, got %d", len(results)))
testing.expect_value(t, len(results), 0)
}

View File

@@ -46,15 +46,7 @@ test_private_key_pub_matches_public_key :: proc(t: ^testing.T) {
kp, priv_ok := parse_ssh_private_key(TEST_KEY_DIR + "/test_ed25519")
testing.expect(t, priv_ok, "expected private key to parse")
testing.expect(
t,
pub_from_pub == kp.Public,
fmt.tprintf(
"public key mismatch:\n from .pub: %v\n from priv: %v",
pub_from_pub,
kp.Public,
),
)
testing.expect_value(t, pub_from_pub, kp.Public)
}
@(test)
@@ -64,12 +56,11 @@ test_read_wire_string :: proc(t: ^testing.T) {
s, ok := read_wire_string(data, &offset)
testing.expect(t, ok, "expected read_wire_string to succeed")
testing.expect(t, s == "hello", fmt.tprintf("expected 'hello', got %q", s))
testing.expect(t, offset == 9, fmt.tprintf("expected offset 9, got %d", offset))
testing.expect_value(t, s, "hello")
testing.expect_value(t, offset, 9)
s2, ok2 := read_wire_string(data, &offset)
testing.expect(t, ok2, "expected second read to succeed")
testing.expect(t, s2 == "", "expected empty string")
testing.expect_value(t, s2, "")
}

View File

@@ -18,11 +18,9 @@ decorations := table.Decorations {
"─",
}
ansi_aware_width :: proc(str: string) -> int {
#no_bounds_check {
ansi_aware_width :: proc(str: string) -> int #no_bounds_check {
width := 0
i := 0
for i < len(str) {
for i := 0; i < len(str); {
if i + 1 < len(str) && str[i] == 0x1b && str[i + 1] == '[' {
i += 2
for i < len(str) {c := str[i]; i += 1; if c >= 0x40 && c <= 0x7E {break}}
@@ -33,7 +31,6 @@ ansi_aware_width :: proc(str: string) -> int {
}
return width
}
}
write_borderless_table :: proc(w: io.Writer, t: ^table.Table) {
table.build(t, ansi_aware_width)