// Copyright 2025 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build unix package bufio_test import ( "bufio" "io" "net" "path/filepath" "strings" "sync" "testing" ) // TestCopyUnixpacket tests that we can use bufio when copying // across a unixpacket socket. This used to fail due to an unnecessary // empty Write call that was interpreted as an EOF. func TestCopyUnixpacket(t *testing.T) { tmpDir := t.TempDir() socket := filepath.Join(tmpDir, "unixsock") // Start a unixpacket server. addr := &net.UnixAddr{ Name: socket, Net: "unixpacket", } server, err := net.ListenUnix("unixpacket", addr) if err != nil { t.Skipf("skipping test because opening a unixpacket socket failed: %v", err) } // Start a goroutine for the server to accept one connection // and read all the data sent on the connection, // reporting the number of bytes read on ch. ch := make(chan int, 1) var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() tot := 0 defer func() { ch <- tot }() serverConn, err := server.Accept() if err != nil { t.Error(err) return } buf := make([]byte, 1024) for { n, err := serverConn.Read(buf) tot += n if err == io.EOF { return } if err != nil { t.Error(err) return } } }() clientConn, err := net.DialUnix("unixpacket", nil, addr) if err != nil { // Leaves the server goroutine hanging. Oh well. t.Fatal(err) } defer wg.Wait() defer clientConn.Close() const data = "data" r := bufio.NewReader(strings.NewReader(data)) n, err := io.Copy(clientConn, r) if err != nil { t.Fatal(err) } if n != int64(len(data)) { t.Errorf("io.Copy returned %d, want %d", n, len(data)) } clientConn.Close() tot := <-ch if tot != len(data) { t.Errorf("server read %d, want %d", tot, len(data)) } }