d55c590c5a
gates / gates (push) Successful in 5m25s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
60 lines
1.6 KiB
Go
60 lines
1.6 KiB
Go
package mailhold
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestHold_MarkerDecidesAndReleaseRemovesIt(t *testing.T) {
|
|
dir := t.TempDir()
|
|
buf := &bytes.Buffer{}
|
|
h := New(dir, log.New(buf, "", 0))
|
|
if h.Held() {
|
|
t.Fatal("no marker: must not hold")
|
|
}
|
|
if err := h.Check("kernel notice", "c1"); err != nil {
|
|
t.Fatalf("no marker: Check = %v", err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(dir, FileName), nil, 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := h.Check("kernel notice", "c1"); !errors.Is(err, ErrHeld) {
|
|
t.Fatalf("marker present: Check = %v, want ErrHeld", err)
|
|
}
|
|
if got := buf.String(); !strings.Contains(got, "[WARN] MAIL-HOLD: not sending kernel notice to c1") {
|
|
t.Fatalf("held mail log line missing: %q", got)
|
|
}
|
|
if err := h.Release(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := os.Stat(filepath.Join(dir, FileName)); !os.IsNotExist(err) {
|
|
t.Fatalf("Release left the marker: %v", err)
|
|
}
|
|
if err := h.Release(); err != nil {
|
|
t.Fatalf("a second Release must be a no-op, got %v", err)
|
|
}
|
|
}
|
|
|
|
// Fail-closed: a marker state that cannot be read (here: the data dir is a FILE, so stat says ENOTDIR) holds mail.
|
|
func TestHold_UnreadableStateHolds(t *testing.T) {
|
|
f := filepath.Join(t.TempDir(), "not-a-dir")
|
|
if err := os.WriteFile(f, nil, 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !New(f, nil).Held() {
|
|
t.Fatal("an unreadable marker state must count as HELD")
|
|
}
|
|
}
|
|
|
|
func TestHold_NilNeverHolds(t *testing.T) {
|
|
var h *Hold
|
|
if h.Held() || h.Check("x", "y") != nil || h.Release() != nil {
|
|
t.Fatal("a nil hold must never hold and never fail")
|
|
}
|
|
}
|