| // Copyright 2012 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 !windows && !solaris && !js && !wasip1 |
| // +build !windows,!solaris,!js,!wasip1 |
| |
| package test |
| |
| // direct-tcpip and direct-streamlocal functional tests |
| |
| import ( |
| "fmt" |
| "io" |
| "net" |
| "strings" |
| "testing" |
| ) |
| |
| type dialTester interface { |
| TestServerConn(t *testing.T, c net.Conn) |
| TestClientConn(t *testing.T, c net.Conn) |
| } |
| |
| func testDial(t *testing.T, n, listenAddr string, x dialTester) { |
| server := newServer(t) |
| defer server.Shutdown() |
| sshConn := server.Dial(clientConfig()) |
| defer sshConn.Close() |
| |
| l, err := net.Listen(n, listenAddr) |
| if err != nil { |
| t.Fatalf("Listen: %v", err) |
| } |
| defer l.Close() |
| |
| testData := fmt.Sprintf("hello from %s, %s", n, listenAddr) |
| go func() { |
| for { |
| c, err := l.Accept() |
| if err != nil { |
| break |
| } |
| x.TestServerConn(t, c) |
| |
| io.WriteString(c, testData) |
| c.Close() |
| } |
| }() |
| |
| conn, err := sshConn.Dial(n, l.Addr().String()) |
| if err != nil { |
| t.Fatalf("Dial: %v", err) |
| } |
| x.TestClientConn(t, conn) |
| defer conn.Close() |
| b, err := io.ReadAll(conn) |
| if err != nil { |
| t.Fatalf("ReadAll: %v", err) |
| } |
| t.Logf("got %q", string(b)) |
| if string(b) != testData { |
| t.Fatalf("expected %q, got %q", testData, string(b)) |
| } |
| } |
| |
| type tcpDialTester struct { |
| listenAddr string |
| } |
| |
| func (x *tcpDialTester) TestServerConn(t *testing.T, c net.Conn) { |
| host := strings.Split(x.listenAddr, ":")[0] |
| prefix := host + ":" |
| if !strings.HasPrefix(c.LocalAddr().String(), prefix) { |
| t.Fatalf("expected to start with %q, got %q", prefix, c.LocalAddr().String()) |
| } |
| if !strings.HasPrefix(c.RemoteAddr().String(), prefix) { |
| t.Fatalf("expected to start with %q, got %q", prefix, c.RemoteAddr().String()) |
| } |
| } |
| |
| func (x *tcpDialTester) TestClientConn(t *testing.T, c net.Conn) { |
| // we use zero addresses. see *Client.Dial. |
| if c.LocalAddr().String() != "0.0.0.0:0" { |
| t.Fatalf("expected \"0.0.0.0:0\", got %q", c.LocalAddr().String()) |
| } |
| if c.RemoteAddr().String() != "0.0.0.0:0" { |
| t.Fatalf("expected \"0.0.0.0:0\", got %q", c.RemoteAddr().String()) |
| } |
| } |
| |
| func TestDialTCP(t *testing.T) { |
| x := &tcpDialTester{ |
| listenAddr: "127.0.0.1:0", |
| } |
| testDial(t, "tcp", x.listenAddr, x) |
| } |
| |
| type unixDialTester struct { |
| listenAddr string |
| } |
| |
| func (x *unixDialTester) TestServerConn(t *testing.T, c net.Conn) { |
| if c.LocalAddr().String() != x.listenAddr { |
| t.Fatalf("expected %q, got %q", x.listenAddr, c.LocalAddr().String()) |
| } |
| if c.RemoteAddr().String() != "@" && c.RemoteAddr().String() != "" { |
| t.Fatalf("expected \"@\" or \"\", got %q", c.RemoteAddr().String()) |
| } |
| } |
| |
| func (x *unixDialTester) TestClientConn(t *testing.T, c net.Conn) { |
| if c.RemoteAddr().String() != x.listenAddr { |
| t.Fatalf("expected %q, got %q", x.listenAddr, c.RemoteAddr().String()) |
| } |
| if c.LocalAddr().String() != "@" { |
| t.Fatalf("expected \"@\", got %q", c.LocalAddr().String()) |
| } |
| } |
| |
| func TestDialUnix(t *testing.T) { |
| addr, cleanup := newTempSocket(t) |
| defer cleanup() |
| x := &unixDialTester{ |
| listenAddr: addr, |
| } |
| testDial(t, "unix", x.listenAddr, x) |
| } |