package zitcli
import (
"os"
"path/filepath"
"testing"
"time"
"craftdesign.group/quarry/internal/events"
"craftdesign.group/quarry/internal/lease"
)
// #245: a store write runs under its lease. A zit that would go on
// writing is killed the moment another node takes the lease, rather than
// left committing while that node writes too.
func TestAWriteIsKilledWhenItsLeaseIsLost(t *testing.T) {
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, "zit"), []byte("#!/bin/sh\nexec sleep 30\n"), 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("PATH", dir+string(os.PathListSeparator)+os.Getenv("PATH"))
ev, err := events.Start(t.TempDir())
if err != nil {
t.Fatal(err)
}
t.Cleanup(ev.Close)
ttl := 300 * time.Millisecond
m, err := lease.New(ev.JS(), "node-a", ttl)
if err != nil {
t.Fatal(err)
}
t.Cleanup(m.Close)
kv, err := ev.JS().KeyValue(lease.Bucket)
if err != nil {
t.Fatal(err)
}
c := New(t.TempDir())
start := time.Now()
var werr error
err = m.Guard("repo", func(tok lease.Token) error {
go func() {
time.Sleep(ttl)
kv.Put("repo", []byte("node-b"))
}()
_, werr = c.WikiCommit(tok, "Page", "dan", "", []byte("body"))
return nil
})
if err != nil {
t.Fatal(err)
}
if werr == nil {
t.Fatal("FAIL: a write whose lease was lost reported success")
}
if took := time.Since(start); took > 10*time.Second {
t.Fatalf("FAIL: the write ran %s after its lease was lost; want it killed", took)
}
}