91 lines
2.8 KiB
Go
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)
|
|
}
|