Diffs name their chain; history shows the ruleset's diff
The ruleset's diff names the chain each hunk is in on its @@ line, as
git names the function. A history entry shows what it did to the
ruleset (web page, hc history diff, GET /history/{id}/diff), rebuilt
from the current configuration by stepping back through the later
entries. A changed setting is listed by its own fields
(builtins.drop_invalid) instead of the whole object.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e35236dba
commit
92147c8681
12 files changed
+289
-11
No files matched your search
@@ -0,0 +1,72 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
udiff "github.com/aymanbagabas/go-udiff"
|
||||
|
||||
"housecarl/internal/api"
|
||||
"housecarl/internal/model"
|
||||
)
|
||||
|
||||
// TestBlockHeaders: each hunk says which chain it is in, even when the
|
||||
// chain's own line is far above it.
|
||||
func TestBlockHeaders(t *testing.T) {
|
||||
var b strings.Builder
|
||||
b.WriteString("table inet housecarl {\n\tset lan_v4 { type ipv4_addr; }\n\tchain input {\n")
|
||||
for i := 0; i < 20; i++ {
|
||||
b.WriteString("\t\tcounter comment \"in\"\n")
|
||||
}
|
||||
b.WriteString("\t}\n\tchain forward {\n")
|
||||
for i := 0; i < 20; i++ {
|
||||
b.WriteString("\t\tcounter comment \"fw\"\n")
|
||||
}
|
||||
b.WriteString("\t}\n}\n")
|
||||
now := b.String()
|
||||
then := strings.Replace(now, "\t\tcounter comment \"in\"\n\t}", "\t\tcounter comment \"in\"\n\t\taccept comment \"new in\"\n\t}", 1)
|
||||
then = strings.Replace(then, "\t\tcounter comment \"fw\"\n\t}", "\t\taccept comment \"new fw\"\n\t}", 1)
|
||||
|
||||
diff := blockHeaders(udiff.Unified("a", "b", now, then), now, then)
|
||||
var heads []string
|
||||
for _, l := range strings.Split(diff, "\n") {
|
||||
if strings.HasPrefix(l, "@@") {
|
||||
heads = append(heads, l)
|
||||
}
|
||||
}
|
||||
if len(heads) != 2 || !strings.HasSuffix(heads[0], "@@ chain input") || !strings.HasSuffix(heads[1], "@@ chain forward") {
|
||||
t.Fatalf("hunk headers %q, want chain input then chain forward\n%s", heads, diff)
|
||||
}
|
||||
if blockHeaders("", now, then) != "" {
|
||||
t.Fatal("no diff should stay empty")
|
||||
}
|
||||
}
|
||||
|
||||
// TestHistoryDiff: an entry's diff is its own change, rebuilt from the
|
||||
// current configuration however many entries came after it.
|
||||
func TestHistoryDiff(t *testing.T) {
|
||||
e := newEnv(t)
|
||||
var mr api.MutationResponse
|
||||
e.call(e.token, "POST", "/zones", model.Zone{Name: "lan", Interfaces: []string{"eth1"}}, nil)
|
||||
e.call(e.token, "POST", "/rules", model.Rule{Chain: "input", Match: model.Match{Services: []string{"ssh"}}, Comment: "first"}, &mr)
|
||||
first := mr.HistoryID
|
||||
e.call(e.token, "POST", "/rules", model.Rule{Chain: "forward", Match: model.Match{Services: []string{"http"}}, Comment: "second"}, nil)
|
||||
e.call(e.token, "PATCH", "/settings", map[string]any{"builtins": map[string]any{"drop_invalid": true}}, nil)
|
||||
|
||||
var out struct{ Diff string }
|
||||
if code := e.call(e.token, "GET", "/history/"+itoa(first)+"/diff", nil, &out); code != 200 {
|
||||
t.Fatalf("diff: %d", code)
|
||||
}
|
||||
var added []string
|
||||
for _, l := range strings.Split(out.Diff, "\n") {
|
||||
if strings.HasPrefix(l, "+") && !strings.HasPrefix(l, "+++") {
|
||||
added = append(added, l)
|
||||
}
|
||||
}
|
||||
if len(added) == 0 || !strings.Contains(strings.Join(added, "\n"), ` first"`) || strings.Contains(out.Diff, ` second"`) || !strings.Contains(out.Diff, "@@ chain input") {
|
||||
t.Errorf("entry %d's diff:\n%s", first, out.Diff)
|
||||
}
|
||||
if code := e.call(e.token, "GET", "/history/9999/diff", nil, nil); code != 404 {
|
||||
t.Errorf("unknown entry: %d", code)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user