diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-22 16:52:37 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-22 16:52:37 +0200 |
| commit | bcb07f5587c310063b74d280f7e82aa47a132c39 (patch) | |
| tree | 15ec499cf9acdde3b3876f3fd1cf9316a602cf6d /internal/store/index_test.go | |
| parent | bb5ce162f82417191b80c04f69193d1a8af6b3d8 (diff) | |
Address store package review findings (task 352/store)
Fix CommitIndex to respect force=false by checking os.Stat before writing,
mirroring the Data.Commit behaviour and keeping index/data pairs consistent.
Skip .git directory in WalkIndexes via filepath.SkipDir to avoid spurious
errors or false matches inside the git metadata tree.
Make ShredAllExported continue past individual shred errors and return the
last error, matching Ruby's best-effort shredding behaviour.
Accept io.Reader in Store.Remove instead of hardwiring os.Stdin, enabling
deterministic testing via strings.NewReader injection.
Fix runFzf comment to state that any non-zero fzf exit is treated as no
selection (not only exit 130).
Document ImportRecursive divergence from Ruby basename-flattening behaviour.
Add 14 new tests: Search, SearchActionCat, SearchActionCatBinarySkip,
ShredAllExported, SearchActionExport, ImportRecursive, ReimportAfterExport,
RemoveInteractive, RemoveInteractiveDecline, CommitIndexSkipsExisting,
LoadIndexMissingFile, LoadIndexCorrupted, LoadDataMissingFile,
LoadDataCorrupted, DataExportUnwritable, HashPathEdgeCases,
ImportMissingSourceFile, WalkIndexesInvalidRegex.
Improve TestIndexSort to call sort.Sort and assert final order.
Remove orphaned section-header comment from store_test.go.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/store/index_test.go')
| -rw-r--r-- | internal/store/index_test.go | 80 |
1 files changed, 71 insertions, 9 deletions
diff --git a/internal/store/index_test.go b/internal/store/index_test.go index 6bf2cef..a16d757 100644 --- a/internal/store/index_test.go +++ b/internal/store/index_test.go @@ -2,10 +2,30 @@ package store import ( + "context" + "os" + "path/filepath" + "sort" "strings" "testing" + + "codeberg.org/snonux/geheim/internal/crypto" ) +// newTestIndexCipher is a local helper to avoid import cycle via store_test.go. +func newTestIndexCipher(t *testing.T) *crypto.Cipher { + t.Helper() + keyFile := filepath.Join(t.TempDir(), "key") + if err := os.WriteFile(keyFile, []byte("testkey1234567890"), 0o600); err != nil { + t.Fatalf("writing key file: %v", err) + } + c, err := crypto.NewCipher(keyFile, 32, "testpin", "Hello world") + if err != nil { + t.Fatalf("NewCipher: %v", err) + } + return c +} + // --- TestIsBinary ------------------------------------------------------------ // TestIsBinary verifies that IsBinary returns the correct value for every case @@ -82,9 +102,44 @@ func TestIndexString(t *testing.T) { }) } +// --- TestLoadIndexMissingFile ------------------------------------------------ + +// TestLoadIndexMissingFile confirms that loadIndex returns an error when the +// .index file does not exist on disk. +func TestLoadIndexMissingFile(t *testing.T) { + ctx := context.Background() + c := newTestIndexCipher(t) + + _, err := loadIndex(ctx, "/nonexistent/path/to.index", t.TempDir(), c) + if err == nil { + t.Error("loadIndex with missing file: expected error, got nil") + } +} + +// --- TestLoadIndexCorrupted -------------------------------------------------- + +// TestLoadIndexCorrupted confirms that loadIndex returns an error when the file +// contains data that cannot be decrypted (not valid ciphertext). +func TestLoadIndexCorrupted(t *testing.T) { + ctx := context.Background() + c := newTestIndexCipher(t) + + dir := t.TempDir() + badPath := filepath.Join(dir, "bad.index") + if err := os.WriteFile(badPath, []byte("not valid ciphertext"), 0o600); err != nil { + t.Fatalf("writing bad file: %v", err) + } + + _, err := loadIndex(ctx, badPath, dir, c) + if err == nil { + t.Error("loadIndex with corrupted file: expected error, got nil") + } +} + // --- TestIndexSort ----------------------------------------------------------- -// TestIndexSort verifies that IndexSlice sorts by Description alphabetically. +// TestIndexSort verifies that IndexSlice sorts by Description alphabetically +// using sort.Sort, and validates the sort.Interface helper methods directly. func TestIndexSort(t *testing.T) { hash := strings.Repeat("0", 64) indexes := IndexSlice{ @@ -93,21 +148,28 @@ func TestIndexSort(t *testing.T) { {Description: "mango", Hash: hash}, } - // Use sort package via the interface methods directly. - n := indexes.Len() - if n != 3 { + if n := indexes.Len(); n != 3 { t.Fatalf("Len() = %d; want 3", n) } - // apple < mango should hold. - appleIdx, mangoIdx := 1, 2 // after original order: zebra=0, apple=1, mango=2 - if !indexes.Less(appleIdx, mangoIdx) { + // Before sorting: zebra=0, apple=1, mango=2 — Less(1,2) = apple < mango = true. + if !indexes.Less(1, 2) { t.Errorf("Less(apple, mango) = false; want true") } - - // Swap zebra and apple. + // Swap and verify. indexes.Swap(0, 1) if indexes[0].Description != "apple" || indexes[1].Description != "zebra" { t.Errorf("Swap(0,1) did not exchange elements") } + // Restore original order before sort.Sort. + indexes.Swap(0, 1) + + // Verify sort.Sort produces ascending alphabetical order. + sort.Sort(indexes) + want := []string{"apple", "mango", "zebra"} + for i, w := range want { + if indexes[i].Description != w { + t.Errorf("indexes[%d].Description = %q; want %q", i, indexes[i].Description, w) + } + } } |
