check / check (push) Successful in 4m1s
smallwebwaf watches SWWAF_STATE_DIR with fsnotify and takes in a saved edit of a state file in place of what it held. It knows its own writes by the SHA-256 of what it last read or wrote; each write first takes in an edit made since. An edit that does not parse is renamed to <name>.bad at the next write. Each edit taken in or set aside is logged and counted. Every ban on a netblock is checked, and the next ban is worked out from the one that ended last. README.md says how to add and lift a ban. Judgement call: a broken edit is set aside at the next write, since an editor's file can be read half written. Model: opus-5-5
36 lines
775 B
Go
36 lines
775 B
Go
package state
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// The test is on write itself: a state file is read before it is
|
|
// written, and a directory in its place fails that read first.
|
|
func TestFailedRenameLeavesNoTemporaryFile(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dir := t.TempDir()
|
|
|
|
// A directory named bans.json cannot be renamed over.
|
|
err := os.Mkdir(filepath.Join(dir, bansJSON), 0o700)
|
|
if err != nil {
|
|
t.Fatalf("mkdir: %v", err)
|
|
}
|
|
|
|
err = write(dir, bansJSON, []byte("{}\n"))
|
|
if err == nil {
|
|
t.Error("writing over a directory did not fail")
|
|
}
|
|
|
|
entries, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
t.Fatalf("read %s: %v", dir, err)
|
|
}
|
|
|
|
if len(entries) != 1 || entries[0].Name() != bansJSON {
|
|
t.Errorf("%s holds %v, want only bans.json", dir, entries)
|
|
}
|
|
}
|