116 lines
3.2 KiB
Go
116 lines
3.2 KiB
Go
// SPDX-License-Identifier: MIT
|
|||
|
|
|
||
|
|
package iprule
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"prx/internal/execx"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestParseRules(t *testing.T) {
|
||
|
|
out := `0: from all lookup local
|
||
|
|
50: from all to 198.51.100.0/24 lookup 102
|
||
|
|
100: from all fwmark 0x100 lookup 100
|
||
|
|
32766: from all lookup main
|
||
|
|
32767: from all lookup default
|
||
|
|
`
|
||
|
|
entries := parseRules(out)
|
||
|
|
if len(entries) != 5 {
|
||
|
|
t.Fatalf("expected 5 entries, got %d", len(entries))
|
||
|
|
}
|
||
|
|
if !entries[2].HasMark || entries[2].Mark != 0x100 || entries[2].Table != 100 || entries[2].Priority != 100 {
|
||
|
|
t.Errorf("mark entry parsed wrong: %+v", entries[2])
|
||
|
|
}
|
||
|
|
if !entries[1].HasTo || entries[1].To != "198.51.100.0/24" || entries[1].Table != 102 {
|
||
|
|
t.Errorf("bypass entry parsed wrong: %+v", entries[1])
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func ruleRunner(out string) (*execx.Fake, *[]execx.Call) {
|
||
|
|
f := &execx.Fake{Handler: func(name string, args []string, _ []byte) (execx.Result, error) {
|
||
|
|
if len(args) >= 2 && args[len(args)-2] == "rule" && args[len(args)-1] == "show" {
|
||
|
|
return execx.Result{Stdout: []byte(out)}, nil
|
||
|
|
}
|
||
|
|
return execx.Result{}, nil
|
||
|
|
}}
|
||
|
|
return f, &f.Calls
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRuleExists(t *testing.T) {
|
||
|
|
f, _ := ruleRunner("100:\tfrom all fwmark 0x100 lookup 100\n")
|
||
|
|
ok, err := RuleExists(context.Background(), f, Spec{Family: 4, Mark: 0x100, Table: 100, Priority: 100})
|
||
|
|
if err != nil || !ok {
|
||
|
|
t.Fatalf("RuleExists = %v, %v", ok, err)
|
||
|
|
}
|
||
|
|
ok, err = RuleExists(context.Background(), f, Spec{Family: 4, Mark: 0x100, Table: 100, Priority: 200})
|
||
|
|
if err != nil || ok {
|
||
|
|
t.Fatalf("expected absent, got %v, %v", ok, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestEnsureRuleAddsWhenMissing(t *testing.T) {
|
||
|
|
f, calls := ruleRunner("")
|
||
|
|
changed, err := EnsureRule(context.Background(), f, Spec{Family: 4, Mark: 0x100, Table: 100, Priority: 100})
|
||
|
|
if err != nil || !changed {
|
||
|
|
t.Fatalf("EnsureRule = %v, %v", changed, err)
|
||
|
|
}
|
||
|
|
if !hasCall(*calls, "ip", "rule", "add", "fwmark", "0x100", "lookup", "100", "priority", "100") {
|
||
|
|
t.Fatalf("expected add call, got %+v", *calls)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestEnsureRuleNoopWhenPresent(t *testing.T) {
|
||
|
|
f, calls := ruleRunner("100:\tfrom all fwmark 0x100 lookup 100\n")
|
||
|
|
changed, err := EnsureRule(context.Background(), f, Spec{Family: 4, Mark: 0x100, Table: 100, Priority: 100})
|
||
|
|
if err != nil || changed {
|
||
|
|
t.Fatalf("expected no-op, got %v, %v", changed, err)
|
||
|
|
}
|
||
|
|
for _, c := range *calls {
|
||
|
|
if len(c.Args) >= 2 && c.Args[1] == "add" {
|
||
|
|
t.Fatalf("unexpected add call: %+v", c)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRemoveRulesByTable(t *testing.T) {
|
||
|
|
out := `50: from all to 198.51.100.0/24 lookup 102
|
||
|
|
100: from all fwmark 0x100 lookup 100
|
||
|
|
110: from all fwmark 0x100 lookup 100
|
||
|
|
`
|
||
|
|
f, calls := ruleRunner(out)
|
||
|
|
n, err := RemoveRulesByTable(context.Background(), f, 4, 100)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("RemoveRulesByTable: %v", err)
|
||
|
|
}
|
||
|
|
if n != 2 {
|
||
|
|
t.Fatalf("removed %d, want 2", n)
|
||
|
|
}
|
||
|
|
for _, c := range *calls {
|
||
|
|
if len(c.Args) >= 2 && c.Args[1] == "del" && !strings.Contains(strings.Join(c.Args, " "), "lookup 100") {
|
||
|
|
t.Fatalf("deleted wrong rule: %+v", c)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func hasCall(calls []execx.Call, name string, args ...string) bool {
|
||
|
|
for _, c := range calls {
|
||
|
|
if c.Name != name || len(c.Args) != len(args) {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
match := true
|
||
|
|
for i := range args {
|
||
|
|
if c.Args[i] != args[i] {
|
||
|
|
match = false
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if match {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|