feat(privilege): acquire sudo and keep timestamp fresh via goroutine

This commit is contained in:
MDietermann
2026-04-13 20:01:34 +02:00
parent 83cf7f0e72
commit 8f9e34174c
2 changed files with 142 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
package privilege
import (
"context"
"errors"
"sync/atomic"
"testing"
"time"
)
type fakeAcquirer struct {
validateErr error
validates int32
refreshes int32
}
func (f *fakeAcquirer) Validate(ctx context.Context) error {
atomic.AddInt32(&f.validates, 1)
return f.validateErr
}
func (f *fakeAcquirer) ValidateNonInteractive(ctx context.Context) error {
atomic.AddInt32(&f.refreshes, 1)
return nil
}
func TestAcquireFailsIfValidateFails(t *testing.T) {
a := &fakeAcquirer{validateErr: errors.New("wrong password")}
_, err := Acquire(context.Background(), a, 10*time.Millisecond)
if err == nil {
t.Fatal("expected error")
}
if atomic.LoadInt32(&a.refreshes) != 0 {
t.Fatal("keepalive ran despite Validate failure")
}
}
func TestAcquireStartsKeepaliveAndStops(t *testing.T) {
a := &fakeAcquirer{}
k, err := Acquire(context.Background(), a, 5*time.Millisecond)
if err != nil {
t.Fatal(err)
}
time.Sleep(25 * time.Millisecond)
k.Stop()
got := atomic.LoadInt32(&a.refreshes)
if got < 2 {
t.Fatalf("refreshes = %d, want >= 2", got)
}
// After Stop, no additional refreshes should occur.
snap := atomic.LoadInt32(&a.refreshes)
time.Sleep(20 * time.Millisecond)
if after := atomic.LoadInt32(&a.refreshes); after != snap {
t.Fatalf("refreshes continued after Stop: %d → %d", snap, after)
}
}
func TestStopIsIdempotent(t *testing.T) {
k, err := Acquire(context.Background(), &fakeAcquirer{}, 5*time.Millisecond)
if err != nil {
t.Fatal(err)
}
k.Stop()
k.Stop() // must not panic or hang
}