1// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package unix
6
7import (
8	"reflect"
9	"testing"
10	"unsafe"
11)
12
13func Test_anyToSockaddr_darwin(t *testing.T) {
14	tests := []struct {
15		name string
16		rsa  *RawSockaddrAny
17		sa   Sockaddr
18		err  error
19	}{
20		{
21			name: "AF_SYSTEM emtpy",
22			rsa:  sockaddrCtlToAny(RawSockaddrCtl{}),
23			err:  EAFNOSUPPORT,
24		},
25		{
26			name: "AF_SYSTEM no sysaddr",
27			rsa: sockaddrCtlToAny(RawSockaddrCtl{
28				Sc_family: AF_SYSTEM,
29			}),
30			err: EAFNOSUPPORT,
31		},
32		{
33			name: "AF_SYSTEM/AF_SYS_CONTROL empty ",
34			rsa: sockaddrCtlToAny(RawSockaddrCtl{
35				Sc_family:  AF_SYSTEM,
36				Ss_sysaddr: AF_SYS_CONTROL,
37			}),
38			sa: &SockaddrCtl{},
39		},
40		{
41			name: "AF_SYSTEM ID and unit",
42			rsa: sockaddrCtlToAny(RawSockaddrCtl{
43				Sc_family:  AF_SYSTEM,
44				Ss_sysaddr: AF_SYS_CONTROL,
45				Sc_id:      0x42,
46				Sc_unit:    0xC71,
47			}),
48			sa: &SockaddrCtl{
49				ID:   0x42,
50				Unit: 0xC71,
51			},
52		},
53		{
54			name: "AF_VSOCK emtpy",
55			rsa:  sockaddrVMToAny(RawSockaddrVM{}),
56			err:  EAFNOSUPPORT,
57		},
58		{
59			name: "AF_VSOCK Cid and Port",
60			rsa: sockaddrVMToAny(RawSockaddrVM{
61				Family: AF_VSOCK,
62				Cid:    VMADDR_CID_HOST,
63				Port:   VMADDR_PORT_ANY,
64			}),
65			sa: &SockaddrVM{
66				CID:  VMADDR_CID_HOST,
67				Port: VMADDR_PORT_ANY,
68			},
69		},
70	}
71
72	for _, tt := range tests {
73		t.Run(tt.name, func(t *testing.T) {
74			fd := int(0)
75			sa, err := anyToSockaddr(fd, tt.rsa)
76			if err != tt.err {
77				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
78			}
79
80			if !reflect.DeepEqual(sa, tt.sa) {
81				t.Fatalf("unexpected Sockaddr:\n got: %#v\nwant: %#v", sa, tt.sa)
82			}
83		})
84	}
85}
86
87func TestSockaddrCtl_sockaddr(t *testing.T) {
88	tests := []struct {
89		name string
90		sa   *SockaddrCtl
91		raw  *RawSockaddrCtl
92		err  error
93	}{
94		{
95			name: "empty",
96			sa:   &SockaddrCtl{},
97			raw: &RawSockaddrCtl{
98				Sc_len:     SizeofSockaddrCtl,
99				Sc_family:  AF_SYSTEM,
100				Ss_sysaddr: AF_SYS_CONTROL,
101			},
102		},
103		{
104			name: "with ID and unit",
105			sa: &SockaddrCtl{
106				ID:   0x42,
107				Unit: 0xff,
108			},
109			raw: &RawSockaddrCtl{
110				Sc_len:     SizeofSockaddrCtl,
111				Sc_family:  AF_SYSTEM,
112				Ss_sysaddr: AF_SYS_CONTROL,
113				Sc_id:      0x42,
114				Sc_unit:    0xff,
115			},
116		},
117	}
118
119	for _, tt := range tests {
120		t.Run(tt.name, func(t *testing.T) {
121			out, l, err := tt.sa.sockaddr()
122			if err != tt.err {
123				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
124			}
125
126			// Must be 0 on error or a fixed size otherwise.
127			if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrCtl) {
128				t.Fatalf("unexpected Socklen: %d", l)
129			}
130
131			if out != nil {
132				raw := (*RawSockaddrCtl)(out)
133				if !reflect.DeepEqual(raw, tt.raw) {
134					t.Fatalf("unexpected RawSockaddrCtl:\n got: %#v\nwant: %#v", raw, tt.raw)
135				}
136			}
137		})
138	}
139}
140
141func TestSockaddrVM_sockaddr(t *testing.T) {
142	tests := []struct {
143		name string
144		sa   *SockaddrVM
145		raw  *RawSockaddrVM
146		err  error
147	}{
148		{
149			name: "empty",
150			sa:   &SockaddrVM{},
151			raw: &RawSockaddrVM{
152				Len:    SizeofSockaddrVM,
153				Family: AF_VSOCK,
154			},
155		},
156		{
157			name: "with CID and port",
158			sa: &SockaddrVM{
159				CID:  VMADDR_CID_HOST,
160				Port: VMADDR_PORT_ANY,
161			},
162			raw: &RawSockaddrVM{
163				Len:    SizeofSockaddrVM,
164				Family: AF_VSOCK,
165				Port:   VMADDR_PORT_ANY,
166				Cid:    VMADDR_CID_HOST,
167			},
168		},
169	}
170
171	for _, tt := range tests {
172		t.Run(tt.name, func(t *testing.T) {
173			out, l, err := tt.sa.sockaddr()
174			if err != tt.err {
175				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
176			}
177
178			// Must be 0 on error or a fixed size otherwise.
179			if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrVM) {
180				t.Fatalf("unexpected Socklen: %d", l)
181			}
182
183			if out != nil {
184				raw := (*RawSockaddrVM)(out)
185				if !reflect.DeepEqual(raw, tt.raw) {
186					t.Fatalf("unexpected RawSockaddrVM:\n got: %#v\nwant: %#v", raw, tt.raw)
187				}
188			}
189		})
190	}
191}
192
193func sockaddrCtlToAny(in RawSockaddrCtl) *RawSockaddrAny {
194	var out RawSockaddrAny
195	copy(
196		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
197		(*(*[SizeofSockaddrCtl]byte)(unsafe.Pointer(&in)))[:],
198	)
199	return &out
200}
201
202func sockaddrVMToAny(in RawSockaddrVM) *RawSockaddrAny {
203	var out RawSockaddrAny
204	copy(
205		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
206		(*(*[SizeofSockaddrVM]byte)(unsafe.Pointer(&in)))[:],
207	)
208	return &out
209}
210