1// Copyright 2019 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 5// +build linux 6 7package unix 8 9import ( 10 "reflect" 11 "testing" 12 "unsafe" 13) 14 15func Test_anyToSockaddr(t *testing.T) { 16 tests := []struct { 17 name string 18 rsa *RawSockaddrAny 19 sa Sockaddr 20 err error 21 }{ 22 { 23 name: "AF_TIPC bad addrtype", 24 rsa: &RawSockaddrAny{ 25 Addr: RawSockaddr{ 26 Family: AF_TIPC, 27 }, 28 }, 29 err: EINVAL, 30 }, 31 { 32 name: "AF_TIPC NameSeq", 33 rsa: sockaddrTIPCToAny(RawSockaddrTIPC{ 34 Family: AF_TIPC, 35 Addrtype: TIPC_SERVICE_RANGE, 36 Scope: 1, 37 Addr: (&TIPCServiceRange{ 38 Type: 1, 39 Lower: 2, 40 Upper: 3, 41 }).tipcAddr(), 42 }), 43 sa: &SockaddrTIPC{ 44 Scope: 1, 45 Addr: &TIPCServiceRange{ 46 Type: 1, 47 Lower: 2, 48 Upper: 3, 49 }, 50 }, 51 }, 52 { 53 name: "AF_TIPC Name", 54 rsa: sockaddrTIPCToAny(RawSockaddrTIPC{ 55 Family: AF_TIPC, 56 Addrtype: TIPC_SERVICE_ADDR, 57 Scope: 2, 58 Addr: (&TIPCServiceName{ 59 Type: 1, 60 Instance: 2, 61 Domain: 3, 62 }).tipcAddr(), 63 }), 64 sa: &SockaddrTIPC{ 65 Scope: 2, 66 Addr: &TIPCServiceName{ 67 Type: 1, 68 Instance: 2, 69 Domain: 3, 70 }, 71 }, 72 }, 73 { 74 name: "AF_TIPC ID", 75 rsa: sockaddrTIPCToAny(RawSockaddrTIPC{ 76 Family: AF_TIPC, 77 Addrtype: TIPC_SOCKET_ADDR, 78 Scope: 3, 79 Addr: (&TIPCSocketAddr{ 80 Ref: 1, 81 Node: 2, 82 }).tipcAddr(), 83 }), 84 sa: &SockaddrTIPC{ 85 Scope: 3, 86 Addr: &TIPCSocketAddr{ 87 Ref: 1, 88 Node: 2, 89 }, 90 }, 91 }, 92 { 93 name: "AF_MAX EAFNOSUPPORT", 94 rsa: &RawSockaddrAny{ 95 Addr: RawSockaddr{ 96 Family: AF_MAX, 97 }, 98 }, 99 err: EAFNOSUPPORT, 100 }, 101 // TODO: expand to support other families. 102 } 103 104 for _, tt := range tests { 105 t.Run(tt.name, func(t *testing.T) { 106 // TODO: parameterize fd (and its setup) when needed. 107 sa, err := anyToSockaddr(0, tt.rsa) 108 if err != tt.err { 109 t.Fatalf("unexpected error: %v, want: %v", err, tt.err) 110 } 111 112 if !reflect.DeepEqual(sa, tt.sa) { 113 t.Fatalf("unexpected Sockaddr:\n got: %#v\nwant: %#v", sa, tt.sa) 114 } 115 }) 116 } 117} 118 119func TestSockaddrTIPC_sockaddr(t *testing.T) { 120 tests := []struct { 121 name string 122 sa *SockaddrTIPC 123 raw *RawSockaddrTIPC 124 err error 125 }{ 126 { 127 name: "no fields set", 128 sa: &SockaddrTIPC{}, 129 err: EINVAL, 130 }, 131 { 132 name: "ID", 133 sa: &SockaddrTIPC{ 134 Scope: 1, 135 Addr: &TIPCSocketAddr{ 136 Ref: 1, 137 Node: 2, 138 }, 139 }, 140 raw: &RawSockaddrTIPC{ 141 Family: AF_TIPC, 142 Addrtype: TIPC_SOCKET_ADDR, 143 Scope: 1, 144 Addr: (&TIPCSocketAddr{ 145 Ref: 1, 146 Node: 2, 147 }).tipcAddr(), 148 }, 149 }, 150 { 151 name: "NameSeq", 152 sa: &SockaddrTIPC{ 153 Scope: 2, 154 Addr: &TIPCServiceRange{ 155 Type: 1, 156 Lower: 2, 157 Upper: 3, 158 }, 159 }, 160 raw: &RawSockaddrTIPC{ 161 Family: AF_TIPC, 162 Addrtype: TIPC_SERVICE_RANGE, 163 Scope: 2, 164 Addr: (&TIPCServiceRange{ 165 Type: 1, 166 Lower: 2, 167 Upper: 3, 168 }).tipcAddr(), 169 }, 170 }, 171 { 172 name: "Name", 173 sa: &SockaddrTIPC{ 174 Scope: 3, 175 Addr: &TIPCServiceName{ 176 Type: 1, 177 Instance: 2, 178 Domain: 3, 179 }, 180 }, 181 raw: &RawSockaddrTIPC{ 182 Family: AF_TIPC, 183 Addrtype: TIPC_SERVICE_ADDR, 184 Scope: 3, 185 Addr: (&TIPCServiceName{ 186 Type: 1, 187 Instance: 2, 188 Domain: 3, 189 }).tipcAddr(), 190 }, 191 }, 192 } 193 194 for _, tt := range tests { 195 t.Run(tt.name, func(t *testing.T) { 196 out, l, err := tt.sa.sockaddr() 197 if err != tt.err { 198 t.Fatalf("unexpected error: %v, want: %v", err, tt.err) 199 } 200 201 // Must be 0 on error or a fixed size otherwise. 202 if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrTIPC) { 203 t.Fatalf("unexpected Socklen: %d", l) 204 } 205 if out == nil { 206 // No pointer to cast, return early. 207 return 208 } 209 210 raw := (*RawSockaddrTIPC)(out) 211 if !reflect.DeepEqual(raw, tt.raw) { 212 t.Fatalf("unexpected RawSockaddrTIPC:\n got: %#v\nwant: %#v", raw, tt.raw) 213 } 214 }) 215 } 216} 217 218func sockaddrTIPCToAny(in RawSockaddrTIPC) *RawSockaddrAny { 219 var out RawSockaddrAny 220 221 // Explicitly copy the contents of in into out to produce the correct 222 // sockaddr structure, without relying on unsafe casting to a type of a 223 // larger size. 224 copy( 225 (*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:], 226 (*(*[SizeofSockaddrTIPC]byte)(unsafe.Pointer(&in)))[:], 227 ) 228 229 return &out 230} 231