Insert the blank line wsl_v5 requires above `defer` and `go` statements that share no variables with the statement above them. Applied mechanically via `make lint-fix`; the diff is 60 added blank lines and nothing else.
130 lines
2.8 KiB
Go
130 lines
2.8 KiB
Go
package pidlock_test
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/vaultik/internal/pidlock"
|
|
)
|
|
|
|
func TestAcquireAndRelease(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tmpDir := t.TempDir()
|
|
|
|
// Acquire lock
|
|
lock, err := pidlock.Acquire(tmpDir)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, lock)
|
|
|
|
// Verify PID file exists with our PID
|
|
pidPath := filepath.Join(tmpDir, "vaultik.pid")
|
|
data, err := os.ReadFile(pidPath) //nolint:gosec // G304: test's own temp file
|
|
require.NoError(t, err)
|
|
pid, err := strconv.Atoi(string(data))
|
|
require.NoError(t, err)
|
|
assert.Equal(t, os.Getpid(), pid)
|
|
|
|
// Release lock
|
|
err = lock.Release()
|
|
require.NoError(t, err)
|
|
|
|
// Verify PID file is gone
|
|
_, err = os.Stat(pidPath)
|
|
assert.True(t, os.IsNotExist(err))
|
|
}
|
|
|
|
func TestAcquireBlocksSecondInstance(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tmpDir := t.TempDir()
|
|
|
|
// Acquire first lock
|
|
lock1, err := pidlock.Acquire(tmpDir)
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, lock1)
|
|
|
|
defer func() { _ = lock1.Release() }()
|
|
|
|
// Try to acquire second lock - should fail
|
|
lock2, err := pidlock.Acquire(tmpDir)
|
|
require.ErrorIs(t, err, pidlock.ErrAlreadyRunning)
|
|
assert.Nil(t, lock2)
|
|
}
|
|
|
|
func TestAcquireWithStaleLock(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tmpDir := t.TempDir()
|
|
|
|
// Write a stale PID file (PID that doesn't exist)
|
|
stalePID := 999999999 // Unlikely to be a real process
|
|
pidPath := filepath.Join(tmpDir, "vaultik.pid")
|
|
err := os.WriteFile(pidPath, []byte(strconv.Itoa(stalePID)), 0600)
|
|
require.NoError(t, err)
|
|
|
|
// Should be able to acquire lock (stale lock is cleaned up)
|
|
lock, err := pidlock.Acquire(tmpDir)
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, lock)
|
|
|
|
defer func() { _ = lock.Release() }()
|
|
|
|
// Verify our PID is now in the file
|
|
data, err := os.ReadFile(pidPath) //nolint:gosec // G304: test's own temp file
|
|
require.NoError(t, err)
|
|
pid, err := strconv.Atoi(string(data))
|
|
require.NoError(t, err)
|
|
assert.Equal(t, os.Getpid(), pid)
|
|
}
|
|
|
|
func TestReleaseIsIdempotent(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tmpDir := t.TempDir()
|
|
|
|
lock, err := pidlock.Acquire(tmpDir)
|
|
require.NoError(t, err)
|
|
|
|
// Release multiple times - should not error
|
|
err = lock.Release()
|
|
require.NoError(t, err)
|
|
|
|
err = lock.Release()
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestReleaseNilLock(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var lock *pidlock.Lock
|
|
|
|
err := lock.Release()
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestAcquireCreatesDirectory(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tmpDir := t.TempDir()
|
|
nestedDir := filepath.Join(tmpDir, "nested", "dir")
|
|
|
|
lock, err := pidlock.Acquire(nestedDir)
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, lock)
|
|
|
|
defer func() { _ = lock.Release() }()
|
|
|
|
// Verify directory was created
|
|
info, err := os.Stat(nestedDir)
|
|
require.NoError(t, err)
|
|
assert.True(t, info.IsDir())
|
|
}
|