Skip to content
quarry Artifact [d455933459]
Login

Artifact [d455933459]

Artifact d455933459bd37b0ca3a9b12ac6757340c3c859031c6997ff40be1c0c3e6d014:


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)
	}
}