go-firewalld/errors_test.go
2026-07-02 14:08:37 -05:00

91 lines
2.8 KiB
Go

package firewalld
import (
"errors"
"testing"
"github.com/godbus/dbus/v5"
"github.com/stretchr/testify/assert"
)
// makeException builds a dbus.Error shaped like a firewalld exception with the
// given message body.
func makeException(msg string) dbus.Error {
return dbus.Error{Name: exceptionName, Body: []any{msg}}
}
func TestMapErrorSentinels(t *testing.T) {
cases := []struct {
msg string
want error
}{
{"ALREADY_ENABLED", ErrAlreadyEnabled},
{"NOT_ENABLED", ErrNotEnabled},
{"INVALID_ZONE: 'bogus'", ErrInvalidZone},
{"INVALID_PORT: '99999'", ErrInvalidPort},
{"INVALID_ICMPTYPE: 'nope'", ErrInvalidICMPType},
{"NAME_CONFLICT: 'dup'", ErrNameConflict},
{"INVALID_IPSET: 'x'", ErrInvalidIPSet},
}
for _, tc := range cases {
err := mapError(makeException(tc.msg))
assert.ErrorIs(t, err, tc.want, "message %q", tc.msg)
var fe *Error
if assert.ErrorAs(t, err, &fe) {
assert.Equal(t, tc.msg, fe.Message)
}
}
}
// TestMapErrorPassthrough leaves non-firewalld errors untouched.
func TestMapErrorPassthrough(t *testing.T) {
assert.Nil(t, mapError(nil))
plain := errors.New("connection reset")
assert.Equal(t, plain, mapError(plain))
// A D-Bus error that is not a firewalld exception passes through unchanged.
other := dbus.Error{Name: "org.freedesktop.DBus.Error.NoReply", Body: []any{"timeout"}}
assert.Equal(t, other, mapError(other))
}
// TestMapErrorUnknownCode maps an unrecognised firewalld code to a typed *Error
// with no sentinel, so errors.Is against a known sentinel is false but the code
// and message are preserved.
func TestMapErrorUnknownCode(t *testing.T) {
err := mapError(makeException("SOMETHING_NEW: detail"))
var fe *Error
assert.ErrorAs(t, err, &fe)
assert.Equal(t, "SOMETHING_NEW", fe.Code)
assert.False(t, errors.Is(err, ErrInvalidZone))
}
func TestLeadingToken(t *testing.T) {
assert.Equal(t, "INVALID_ZONE", leadingToken("INVALID_ZONE: 'x'"))
assert.Equal(t, "ALREADY_ENABLED", leadingToken("ALREADY_ENABLED"))
assert.Equal(t, "", leadingToken("Firewall is not running"))
assert.Equal(t, "", leadingToken(""))
}
func TestPolicyDictSignature(t *testing.T) {
s := PolicySettings{
IngressZones: []string{"public"},
EgressZones: []string{"HOST"},
Ports: []Port{{Port: "80", Protocol: "tcp"}},
ForwardPorts: []ForwardPort{{Port: "22", Protocol: "tcp"}},
Priority: -1,
}
d := s.toDict()
assert.Equal(t, "a{sv}", sigOf(d))
assert.Equal(t, "a(ss)", d["ports"].Signature().String())
assert.Equal(t, "a(ssss)", d["forward_ports"].Signature().String())
assert.Equal(t, "i", d["priority"].Signature().String())
// Round-trip the dict back through the decoder.
out := policySettingsFromDict(d)
assert.Equal(t, s.IngressZones, out.IngressZones)
assert.Equal(t, s.EgressZones, out.EgressZones)
assert.Equal(t, s.Ports, out.Ports)
assert.Equal(t, int32(-1), out.Priority)
}