diff options
| author | Gabriel Schneider <[email protected]> | 2026-08-02 12:36:54 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-08-02 17:37:58 -0300 |
| commit | e16f78b255bcf46d8c6f9a4b9e76dd7a3817edeb (patch) | |
| tree | de0db0c369522b5bf92ff32a8351de2224c5c9dc /sidecar/store_test.go | |
| parent | 151ea12251ed876aa87bb486da1bc337e25369e9 (diff) | |
| download | notevi-e16f78b255bcf46d8c6f9a4b9e76dd7a3817edeb.tar.gz notevi-e16f78b255bcf46d8c6f9a4b9e76dd7a3817edeb.zip | |
Diffstat (limited to 'sidecar/store_test.go')
| -rw-r--r-- | sidecar/store_test.go | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/sidecar/store_test.go b/sidecar/store_test.go new file mode 100644 index 0000000..85f50e1 --- /dev/null +++ b/sidecar/store_test.go @@ -0,0 +1,164 @@ +package sidecar + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "sync" + "testing" +) + +func TestAppendCreatesPrivateUnrelatedSidecar(t *testing.T) { + repo := testRepo(t) + // Store must be independent of a user's restrictive auto-track setting. + testJJ(t, repo, "config", "set", "--repo", "snapshot.auto-track", `"none()"`) + testJJ(t, repo, "config", "set", "--repo", "git.private-commits", `"description(glob:'secret:*')"`) + before := testJJ(t, repo, "status") + store, err := Open(repo) + if err != nil { + t.Fatal(err) + } + + if err := store.Append(func(current []byte) ([]byte, error) { + if len(current) != 0 { + t.Fatalf("new store contained %q", current) + } + return []byte("one\n"), nil + }); err != nil { + t.Fatal(err) + } + if err := store.Append(func(current []byte) ([]byte, error) { + if string(current) != "one\n" { + t.Fatalf("second append saw %q", current) + } + return []byte("two\n"), nil + }); err != nil { + t.Fatal(err) + } + + got, err := store.Read() + if err != nil { + t.Fatal(err) + } + if string(got) != "one\ntwo\n" { + t.Fatalf("sidecar log = %q", got) + } + if after := testJJ(t, repo, "status"); after != before { + t.Fatalf("working copy changed:\n--- before\n%s--- after\n%s", before, after) + } + if _, err := os.Stat(filepath.Join(repo, LogFile)); !os.IsNotExist(err) { + t.Fatalf("log materialized in the project working copy: %v", err) + } + + alias := strings.TrimSpace(testJJ(t, repo, "config", "get", "revset-aliases."+Alias)) + if alias == "" { + t.Fatal("repo-local sidecar alias was not configured") + } + private := testJJ(t, repo, "config", "get", "git.private-commits") + if !containsRevsetName(private, Alias) { + t.Fatalf("private commits = %q, missing %s", private, Alias) + } + if !strings.Contains(private, "secret:*") { + t.Fatalf("private commits = %q, previous setting was overwritten", private) + } + parent := strings.TrimSpace(testJJ(t, repo, "log", "-G", "-r", "exactly("+Alias+", 1)", + "-T", "parents.map(|p| p.commit_id()).join(\"\")")) + if parent != strings.Repeat("0", 40) { + t.Fatalf("sidecar parent = %q, want virtual root", parent) + } +} + +func TestLegacyLogIsReadThenImportedOnFirstAppend(t *testing.T) { + repo := testRepo(t) + legacy := []byte("legacy\n") + if err := os.WriteFile(filepath.Join(repo, LogFile), legacy, 0o644); err != nil { + t.Fatal(err) + } + store, err := Open(repo) + if err != nil { + t.Fatal(err) + } + if got, err := store.Read(); err != nil || string(got) != string(legacy) { + t.Fatalf("pre-migration read = %q, %v", got, err) + } + if err := store.Append(func(current []byte) ([]byte, error) { + if string(current) != string(legacy) { + t.Fatalf("migration callback saw %q", current) + } + return []byte("sidecar\n"), nil + }); err != nil { + t.Fatal(err) + } + if got, err := store.Read(); err != nil || string(got) != "legacy\nsidecar\n" { + t.Fatalf("migrated log = %q, %v", got, err) + } +} + +func TestConcurrentAppendsAreSerialized(t *testing.T) { + repo := testRepo(t) + store, err := Open(repo) + if err != nil { + t.Fatal(err) + } + const writers = 6 + errCh := make(chan error, writers) + var wg sync.WaitGroup + for range writers { + wg.Add(1) + go func() { + defer wg.Done() + errCh <- store.Append(func(current []byte) ([]byte, error) { + id := len(strings.Fields(string(current))) + 1 + return []byte(fmt.Sprintf("%d\n", id)), nil + }) + }() + } + wg.Wait() + close(errCh) + for err := range errCh { + if err != nil { + t.Fatal(err) + } + } + got, err := store.Read() + if err != nil { + t.Fatal(err) + } + if string(got) != "1\n2\n3\n4\n5\n6\n" { + t.Fatalf("serialized appends = %q", got) + } +} + +func testRepo(t *testing.T) string { + t.Helper() + if _, err := exec.LookPath("jj"); err != nil { + t.Skip("jj not installed") + } + home := t.TempDir() + t.Setenv("HOME", home) + t.Setenv("JJ_USER", "test") + t.Setenv("JJ_EMAIL", "[email protected]") + repo := filepath.Join(home, "repo") + if err := os.Mkdir(repo, 0o755); err != nil { + t.Fatal(err) + } + cmd := exec.Command("jj", "git", "init") + cmd.Dir = repo + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("jj git init: %v\n%s", err, out) + } + return repo +} + +func testJJ(t *testing.T, repo string, args ...string) string { + t.Helper() + cmd := exec.Command("jj", append([]string{"--ignore-working-copy", "--no-pager"}, args...)...) + cmd.Dir = repo + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("jj %s: %v\n%s", strings.Join(args, " "), err, out) + } + return string(out) +} |
