26f897c1ec
release / release-please (push) Failing after 1m49s
docs / build (push) Failing after 6m34s
release / build-and-upload (arm64, linux) (push) Has been cancelled
release / build-and-upload (arm64, windows) (push) Has been cancelled
release / build-darwin (amd64, darwin) (push) Has been cancelled
release / checksums (push) Has been cancelled
release / finalize (push) Has been cancelled
release / build-darwin (arm64, darwin) (push) Has been cancelled
release / build-and-upload (amd64, linux) (push) Has been cancelled
release / build-and-upload (amd64, windows) (push) Has been cancelled
docs / deploy (push) Has been cancelled
98 lines
2.2 KiB
Go
98 lines
2.2 KiB
Go
package daemon
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/kunchenguid/no-mistakes/internal/paths"
|
|
)
|
|
|
|
func TestAcquireSingletonLock_SecondAcquireFails(t *testing.T) {
|
|
p := paths.WithRoot(t.TempDir())
|
|
if err := p.EnsureDirs(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
lock1, err := acquireSingletonLock(p)
|
|
if err != nil {
|
|
t.Fatalf("first acquire: %v", err)
|
|
}
|
|
defer lock1.Release()
|
|
|
|
_, err = acquireSingletonLock(p)
|
|
if err == nil {
|
|
t.Fatal("expected second acquire to fail while first lock is held")
|
|
}
|
|
if !errors.Is(err, ErrSingletonLockHeld) {
|
|
t.Fatalf("expected ErrSingletonLockHeld, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestAcquireSingletonLock_ReleaseAllowsReacquire(t *testing.T) {
|
|
p := paths.WithRoot(t.TempDir())
|
|
if err := p.EnsureDirs(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
lock1, err := acquireSingletonLock(p)
|
|
if err != nil {
|
|
t.Fatalf("first acquire: %v", err)
|
|
}
|
|
lock1.Release()
|
|
|
|
lock2, err := acquireSingletonLock(p)
|
|
if err != nil {
|
|
t.Fatalf("second acquire after release: %v", err)
|
|
}
|
|
defer lock2.Release()
|
|
}
|
|
|
|
func TestAcquireSingletonLock_ReportsExistingHolder(t *testing.T) {
|
|
p := paths.WithRoot(t.TempDir())
|
|
if err := p.EnsureDirs(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
lock1, err := acquireSingletonLock(p)
|
|
if err != nil {
|
|
t.Fatalf("first acquire: %v", err)
|
|
}
|
|
defer lock1.Release()
|
|
|
|
_, err = acquireSingletonLock(p)
|
|
if err == nil {
|
|
t.Fatal("expected second acquire to fail")
|
|
}
|
|
if !strings.Contains(err.Error(), "pid") {
|
|
t.Fatalf("expected error to include holder diagnostics (pid), got: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestSingletonLock_ReleaseNilSafe verifies Release is a safe no-op on a nil
|
|
// receiver, matching the pattern used for a failed-acquire defer.
|
|
func TestSingletonLock_ReleaseNilSafe(t *testing.T) {
|
|
var lock *singletonLock
|
|
lock.Release() // must not panic
|
|
}
|
|
|
|
func TestAcquireSingletonLock_CreatesLockFileUnderRoot(t *testing.T) {
|
|
root := t.TempDir()
|
|
p := paths.WithRoot(root)
|
|
if err := p.EnsureDirs(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
lock, err := acquireSingletonLock(p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer lock.Release()
|
|
|
|
if _, err := os.Stat(filepath.Join(root, "daemon.lock")); err != nil {
|
|
t.Fatalf("expected daemon.lock to exist: %v", err)
|
|
}
|
|
}
|