]> Cypherpunks.ru repositories - gostls13.git/blob - src/net/unixsock_test.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / net / unixsock_test.go
1 // Copyright 2013 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 //go:build !plan9 && !windows
6
7 package net
8
9 import (
10         "bytes"
11         "internal/testenv"
12         "os"
13         "reflect"
14         "runtime"
15         "syscall"
16         "testing"
17         "time"
18 )
19
20 func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
21         if !testableNetwork("unixgram") {
22                 t.Skip("unixgram test")
23         }
24         switch runtime.GOOS {
25         case "js", "wasip1":
26                 t.Skipf("skipping: syscall.Socket not implemented on %s", runtime.GOOS)
27         }
28         if runtime.GOOS == "openbsd" {
29                 testenv.SkipFlaky(t, 15157)
30         }
31
32         addr := testUnixAddr(t)
33         la, err := ResolveUnixAddr("unixgram", addr)
34         if err != nil {
35                 t.Fatal(err)
36         }
37         c, err := ListenUnixgram("unixgram", la)
38         if err != nil {
39                 t.Fatal(err)
40         }
41         defer func() {
42                 c.Close()
43                 os.Remove(addr)
44         }()
45
46         off := make(chan bool)
47         data := [5]byte{1, 2, 3, 4, 5}
48         go func() {
49                 defer func() { off <- true }()
50                 s, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
51                 if err != nil {
52                         t.Error(err)
53                         return
54                 }
55                 defer syscall.Close(s)
56                 rsa := &syscall.SockaddrUnix{Name: addr}
57                 if err := syscall.Sendto(s, data[:], 0, rsa); err != nil {
58                         t.Error(err)
59                         return
60                 }
61         }()
62
63         <-off
64         b := make([]byte, 64)
65         c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
66         n, from, err := c.ReadFrom(b)
67         if err != nil {
68                 t.Fatal(err)
69         }
70         if from != nil {
71                 t.Fatalf("unexpected peer address: %v", from)
72         }
73         if !bytes.Equal(b[:n], data[:]) {
74                 t.Fatalf("got %v; want %v", b[:n], data[:])
75         }
76 }
77
78 func TestUnixgramZeroBytePayload(t *testing.T) {
79         if !testableNetwork("unixgram") {
80                 t.Skip("unixgram test")
81         }
82
83         c1 := newLocalPacketListener(t, "unixgram")
84         defer os.Remove(c1.LocalAddr().String())
85         defer c1.Close()
86
87         c2, err := Dial("unixgram", c1.LocalAddr().String())
88         if err != nil {
89                 t.Fatal(err)
90         }
91         defer os.Remove(c2.LocalAddr().String())
92         defer c2.Close()
93
94         for _, genericRead := range []bool{false, true} {
95                 n, err := c2.Write(nil)
96                 if err != nil {
97                         t.Fatal(err)
98                 }
99                 if n != 0 {
100                         t.Errorf("got %d; want 0", n)
101                 }
102                 c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
103                 var b [1]byte
104                 var peer Addr
105                 if genericRead {
106                         _, err = c1.(Conn).Read(b[:])
107                 } else {
108                         _, peer, err = c1.ReadFrom(b[:])
109                 }
110                 switch err {
111                 case nil: // ReadFrom succeeds
112                         if peer != nil { // peer is connected-mode
113                                 t.Fatalf("unexpected peer address: %v", peer)
114                         }
115                 default: // Read may timeout, it depends on the platform
116                         if !isDeadlineExceeded(err) {
117                                 t.Fatal(err)
118                         }
119                 }
120         }
121 }
122
123 func TestUnixgramZeroByteBuffer(t *testing.T) {
124         if !testableNetwork("unixgram") {
125                 t.Skip("unixgram test")
126         }
127         // issue 4352: Recvfrom failed with "address family not
128         // supported by protocol family" if zero-length buffer provided
129
130         c1 := newLocalPacketListener(t, "unixgram")
131         defer os.Remove(c1.LocalAddr().String())
132         defer c1.Close()
133
134         c2, err := Dial("unixgram", c1.LocalAddr().String())
135         if err != nil {
136                 t.Fatal(err)
137         }
138         defer os.Remove(c2.LocalAddr().String())
139         defer c2.Close()
140
141         b := []byte("UNIXGRAM ZERO BYTE BUFFER TEST")
142         for _, genericRead := range []bool{false, true} {
143                 n, err := c2.Write(b)
144                 if err != nil {
145                         t.Fatal(err)
146                 }
147                 if n != len(b) {
148                         t.Errorf("got %d; want %d", n, len(b))
149                 }
150                 c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
151                 var peer Addr
152                 if genericRead {
153                         _, err = c1.(Conn).Read(nil)
154                 } else {
155                         _, peer, err = c1.ReadFrom(nil)
156                 }
157                 switch err {
158                 case nil: // ReadFrom succeeds
159                         if peer != nil { // peer is connected-mode
160                                 t.Fatalf("unexpected peer address: %v", peer)
161                         }
162                 default: // Read may timeout, it depends on the platform
163                         if !isDeadlineExceeded(err) {
164                                 t.Fatal(err)
165                         }
166                 }
167         }
168 }
169
170 func TestUnixgramWrite(t *testing.T) {
171         if !testableNetwork("unixgram") {
172                 t.Skip("unixgram test")
173         }
174
175         addr := testUnixAddr(t)
176         laddr, err := ResolveUnixAddr("unixgram", addr)
177         if err != nil {
178                 t.Fatal(err)
179         }
180         c, err := ListenPacket("unixgram", addr)
181         if err != nil {
182                 t.Fatal(err)
183         }
184         defer os.Remove(addr)
185         defer c.Close()
186
187         testUnixgramWriteConn(t, laddr)
188         testUnixgramWritePacketConn(t, laddr)
189 }
190
191 func testUnixgramWriteConn(t *testing.T, raddr *UnixAddr) {
192         c, err := Dial("unixgram", raddr.String())
193         if err != nil {
194                 t.Fatal(err)
195         }
196         defer c.Close()
197
198         b := []byte("CONNECTED-MODE SOCKET")
199         if _, err := c.(*UnixConn).WriteToUnix(b, raddr); err == nil {
200                 t.Fatal("should fail")
201         } else if err.(*OpError).Err != ErrWriteToConnected {
202                 t.Fatalf("should fail as ErrWriteToConnected: %v", err)
203         }
204         if _, err = c.(*UnixConn).WriteTo(b, raddr); err == nil {
205                 t.Fatal("should fail")
206         } else if err.(*OpError).Err != ErrWriteToConnected {
207                 t.Fatalf("should fail as ErrWriteToConnected: %v", err)
208         }
209         if _, _, err = c.(*UnixConn).WriteMsgUnix(b, nil, raddr); err == nil {
210                 t.Fatal("should fail")
211         } else if err.(*OpError).Err != ErrWriteToConnected {
212                 t.Fatalf("should fail as ErrWriteToConnected: %v", err)
213         }
214         if _, err := c.Write(b); err != nil {
215                 t.Fatal(err)
216         }
217 }
218
219 func testUnixgramWritePacketConn(t *testing.T, raddr *UnixAddr) {
220         addr := testUnixAddr(t)
221         c, err := ListenPacket("unixgram", addr)
222         if err != nil {
223                 t.Fatal(err)
224         }
225         defer os.Remove(addr)
226         defer c.Close()
227
228         b := []byte("UNCONNECTED-MODE SOCKET")
229         if _, err := c.(*UnixConn).WriteToUnix(b, raddr); err != nil {
230                 t.Fatal(err)
231         }
232         if _, err := c.WriteTo(b, raddr); err != nil {
233                 t.Fatal(err)
234         }
235         if _, _, err := c.(*UnixConn).WriteMsgUnix(b, nil, raddr); err != nil {
236                 t.Fatal(err)
237         }
238         if _, err := c.(*UnixConn).Write(b); err == nil {
239                 t.Fatal("should fail")
240         }
241 }
242
243 func TestUnixConnLocalAndRemoteNames(t *testing.T) {
244         if !testableNetwork("unix") {
245                 t.Skip("unix test")
246         }
247
248         handler := func(ls *localServer, ln Listener) {}
249         for _, laddr := range []string{"", testUnixAddr(t)} {
250                 laddr := laddr
251                 taddr := testUnixAddr(t)
252                 ta, err := ResolveUnixAddr("unix", taddr)
253                 if err != nil {
254                         t.Fatal(err)
255                 }
256                 ln, err := ListenUnix("unix", ta)
257                 if err != nil {
258                         t.Fatal(err)
259                 }
260                 ls := (&streamListener{Listener: ln}).newLocalServer()
261                 defer ls.teardown()
262                 if err := ls.buildup(handler); err != nil {
263                         t.Fatal(err)
264                 }
265
266                 la, err := ResolveUnixAddr("unix", laddr)
267                 if err != nil {
268                         t.Fatal(err)
269                 }
270                 c, err := DialUnix("unix", la, ta)
271                 if err != nil {
272                         t.Fatal(err)
273                 }
274                 defer func() {
275                         c.Close()
276                         if la != nil {
277                                 defer os.Remove(laddr)
278                         }
279                 }()
280                 if _, err := c.Write([]byte("UNIXCONN LOCAL AND REMOTE NAME TEST")); err != nil {
281                         t.Fatal(err)
282                 }
283
284                 switch runtime.GOOS {
285                 case "android", "linux":
286                         if laddr == "" {
287                                 laddr = "@" // autobind feature
288                         }
289                 }
290                 var connAddrs = [3]struct{ got, want Addr }{
291                         {ln.Addr(), ta},
292                         {c.LocalAddr(), &UnixAddr{Name: laddr, Net: "unix"}},
293                         {c.RemoteAddr(), ta},
294                 }
295                 for _, ca := range connAddrs {
296                         if !reflect.DeepEqual(ca.got, ca.want) {
297                                 t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
298                         }
299                 }
300         }
301 }
302
303 func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
304         if !testableNetwork("unixgram") {
305                 t.Skip("unixgram test")
306         }
307
308         for _, laddr := range []string{"", testUnixAddr(t)} {
309                 laddr := laddr
310                 taddr := testUnixAddr(t)
311                 ta, err := ResolveUnixAddr("unixgram", taddr)
312                 if err != nil {
313                         t.Fatal(err)
314                 }
315                 c1, err := ListenUnixgram("unixgram", ta)
316                 if err != nil {
317                         t.Fatal(err)
318                 }
319                 defer func() {
320                         c1.Close()
321                         os.Remove(taddr)
322                 }()
323
324                 var la *UnixAddr
325                 if laddr != "" {
326                         if la, err = ResolveUnixAddr("unixgram", laddr); err != nil {
327                                 t.Fatal(err)
328                         }
329                 }
330                 c2, err := DialUnix("unixgram", la, ta)
331                 if err != nil {
332                         t.Fatal(err)
333                 }
334                 defer func() {
335                         c2.Close()
336                         if la != nil {
337                                 defer os.Remove(laddr)
338                         }
339                 }()
340
341                 switch runtime.GOOS {
342                 case "android", "linux":
343                         if laddr == "" {
344                                 laddr = "@" // autobind feature
345                         }
346                 }
347
348                 var connAddrs = [4]struct{ got, want Addr }{
349                         {c1.LocalAddr(), ta},
350                         {c1.RemoteAddr(), nil},
351                         {c2.LocalAddr(), &UnixAddr{Name: laddr, Net: "unixgram"}},
352                         {c2.RemoteAddr(), ta},
353                 }
354                 for _, ca := range connAddrs {
355                         if !reflect.DeepEqual(ca.got, ca.want) {
356                                 t.Fatalf("got %#v; want %#v", ca.got, ca.want)
357                         }
358                 }
359         }
360 }
361
362 func TestUnixUnlink(t *testing.T) {
363         if !testableNetwork("unix") {
364                 t.Skip("unix test")
365         }
366         switch runtime.GOOS {
367         case "js", "wasip1":
368                 t.Skipf("skipping: %s does not support Unlink", runtime.GOOS)
369         }
370
371         name := testUnixAddr(t)
372
373         listen := func(t *testing.T) *UnixListener {
374                 l, err := Listen("unix", name)
375                 if err != nil {
376                         t.Fatal(err)
377                 }
378                 return l.(*UnixListener)
379         }
380         checkExists := func(t *testing.T, desc string) {
381                 if _, err := os.Stat(name); err != nil {
382                         t.Fatalf("unix socket does not exist %s: %v", desc, err)
383                 }
384         }
385         checkNotExists := func(t *testing.T, desc string) {
386                 if _, err := os.Stat(name); err == nil {
387                         t.Fatalf("unix socket does exist %s: %v", desc, err)
388                 }
389         }
390
391         // Listener should remove on close.
392         t.Run("Listen", func(t *testing.T) {
393                 l := listen(t)
394                 checkExists(t, "after Listen")
395                 l.Close()
396                 checkNotExists(t, "after Listener close")
397         })
398
399         // FileListener should not.
400         t.Run("FileListener", func(t *testing.T) {
401                 l := listen(t)
402                 f, _ := l.File()
403                 l1, _ := FileListener(f)
404                 checkExists(t, "after FileListener")
405                 f.Close()
406                 checkExists(t, "after File close")
407                 l1.Close()
408                 checkExists(t, "after FileListener close")
409                 l.Close()
410                 checkNotExists(t, "after Listener close")
411         })
412
413         // Only first call to l.Close should remove.
414         t.Run("SecondClose", func(t *testing.T) {
415                 l := listen(t)
416                 checkExists(t, "after Listen")
417                 l.Close()
418                 checkNotExists(t, "after Listener close")
419                 if err := os.WriteFile(name, []byte("hello world"), 0666); err != nil {
420                         t.Fatalf("cannot recreate socket file: %v", err)
421                 }
422                 checkExists(t, "after writing temp file")
423                 l.Close()
424                 checkExists(t, "after second Listener close")
425                 os.Remove(name)
426         })
427
428         // SetUnlinkOnClose should do what it says.
429
430         t.Run("Listen/SetUnlinkOnClose(true)", func(t *testing.T) {
431                 l := listen(t)
432                 checkExists(t, "after Listen")
433                 l.SetUnlinkOnClose(true)
434                 l.Close()
435                 checkNotExists(t, "after Listener close")
436         })
437
438         t.Run("Listen/SetUnlinkOnClose(false)", func(t *testing.T) {
439                 l := listen(t)
440                 checkExists(t, "after Listen")
441                 l.SetUnlinkOnClose(false)
442                 l.Close()
443                 checkExists(t, "after Listener close")
444                 os.Remove(name)
445         })
446
447         t.Run("FileListener/SetUnlinkOnClose(true)", func(t *testing.T) {
448                 l := listen(t)
449                 f, _ := l.File()
450                 l1, _ := FileListener(f)
451                 checkExists(t, "after FileListener")
452                 l1.(*UnixListener).SetUnlinkOnClose(true)
453                 f.Close()
454                 checkExists(t, "after File close")
455                 l1.Close()
456                 checkNotExists(t, "after FileListener close")
457                 l.Close()
458         })
459
460         t.Run("FileListener/SetUnlinkOnClose(false)", func(t *testing.T) {
461                 l := listen(t)
462                 f, _ := l.File()
463                 l1, _ := FileListener(f)
464                 checkExists(t, "after FileListener")
465                 l1.(*UnixListener).SetUnlinkOnClose(false)
466                 f.Close()
467                 checkExists(t, "after File close")
468                 l1.Close()
469                 checkExists(t, "after FileListener close")
470                 l.Close()
471         })
472 }