1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
//go:build linux
// +build linux
package netlink_test
import (
"encoding/binary"
"os"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/josharian/native"
"github.com/mdlayher/netlink"
"github.com/mdlayher/netlink/nltest"
"golang.org/x/sys/unix"
)
func TestConnReceiveErrorLinux(t *testing.T) {
skipBigEndian(t)
// Note: using *Conn instead of Linux-only *conn, to test
// error handling logic in *Conn.Receive.
//
// This test also verifies the contractual behavior of OpError wrapping
// errors from system calls in os.SyscallError, but NOT wrapping netlink
// error codes.
tests := []struct {
name string
msgs []netlink.Message
in error
want error
}{
{
name: "netlink message ENOENT",
msgs: []netlink.Message{{
Header: netlink.Header{
Length: 20,
Type: netlink.Error,
Sequence: 1,
PID: 1,
},
// -2, little endian (ENOENT)
Data: []byte{0xfe, 0xff, 0xff, 0xff},
}},
want: &netlink.OpError{
Op: "receive",
Err: unix.ENOENT,
},
},
{
name: "syscall error ENOENT",
in: unix.ENOENT,
want: &netlink.OpError{
Op: "receive",
Err: os.NewSyscallError("recvmsg", unix.ENOENT),
},
},
{
name: "multipart done without error",
msgs: []netlink.Message{
{
Header: netlink.Header{
Flags: netlink.Multi,
},
},
{
Header: netlink.Header{
Type: netlink.Done,
Flags: netlink.Multi,
},
},
},
},
{
name: "multipart done with error",
msgs: []netlink.Message{
{
Header: netlink.Header{
Flags: netlink.Multi,
},
},
{
Header: netlink.Header{
Type: netlink.Done,
Flags: netlink.Multi,
},
// -2, little endian (ENOENT)
Data: []byte{0xfe, 0xff, 0xff, 0xff},
},
},
want: &netlink.OpError{
Op: "receive",
Err: unix.ENOENT,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := nltest.Dial(func(_ []netlink.Message) ([]netlink.Message, error) {
return tt.msgs, tt.in
})
defer c.Close()
// Need to prepopulate nltest's internal buffers by invoking the
// function once.
_, _ = c.Send(netlink.Message{})
_, got := c.Receive()
if diff := cmp.Diff(tt.want, got); diff != "" {
t.Fatalf("unexpected error (-want +got):\n%s", diff)
}
})
}
}
func skipBigEndian(t *testing.T) {
if binary.ByteOrder(native.Endian) == binary.BigEndian {
t.Skip("skipping test on big-endian system")
}
}
|