func TestForwardPortsReturnsErrorWhenAllBindsFailed(t *testing.T) { server := httptest.NewServer(fakePortForwardServer(t, "allBindsFailed", nil, nil)) defer server.Close() url, _ := url.ParseRequestURI(server.URL) c := client.NewRESTClient(url, "x", nil, -1, -1) req := c.Post().Resource("testing") conf := &client.Config{ Host: server.URL, } stopChan1 := make(chan struct{}, 1) defer close(stopChan1) pf1, err := New(req, conf, []string{"5555"}, stopChan1) if err != nil { t.Fatalf("error creating pf1: %v", err) } go pf1.ForwardPorts() <-pf1.Ready stopChan2 := make(chan struct{}, 1) pf2, err := New(&client.Request{}, &client.Config{}, []string{"5555"}, stopChan2) if err != nil { t.Fatalf("error creating pf2: %v", err) } if err := pf2.ForwardPorts(); err == nil { t.Fatal("expected non-nil error for pf2.ForwardPorts") } }
// TODO: this test is largely cut and paste, refactor to share code func TestRequestAttachRemoteCommand(t *testing.T) { testCases := []struct { Stdin string Stdout string Stderr string Error string Tty bool }{ { Error: "bail", }, { Stdin: "a", Stdout: "b", Stderr: "c", }, { Stdin: "a", Stdout: "b", Tty: true, }, } for i, testCase := range testCases { localOut := &bytes.Buffer{} localErr := &bytes.Buffer{} server := httptest.NewServer(fakeExecServer(t, i, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, 1)) url, _ := url.ParseRequestURI(server.URL) c := client.NewRESTClient(url, "", client.ContentConfig{GroupVersion: &unversioned.GroupVersion{Group: "x"}}, -1, -1, nil) req := c.Post().Resource("testing") conf := &client.Config{ Host: server.URL, } e, err := NewExecutor(conf, "POST", req.URL()) if err != nil { t.Errorf("%d: unexpected error: %v", i, err) continue } err = e.Stream(strings.NewReader(testCase.Stdin), localOut, localErr, testCase.Tty) hasErr := err != nil if len(testCase.Error) > 0 { if !hasErr { t.Errorf("%d: expected an error", i) } else { if e, a := testCase.Error, err.Error(); !strings.Contains(a, e) { t.Errorf("%d: expected error stream read '%v', got '%v'", i, e, a) } } // TODO: Uncomment when fix #19254 // server.Close() continue } if hasErr { t.Errorf("%d: unexpected error: %v", i, err) // TODO: Uncomment when fix #19254 // server.Close() continue } if len(testCase.Stdout) > 0 { if e, a := testCase.Stdout, localOut; e != a.String() { t.Errorf("%d: expected stdout data '%s', got '%s'", i, e, a) } } if testCase.Stderr != "" { if e, a := testCase.Stderr, localErr; e != a.String() { t.Errorf("%d: expected stderr data '%s', got '%s'", i, e, a) } } // TODO: Uncomment when fix #19254 // server.Close() } }
func TestRequestExecuteRemoteCommand(t *testing.T) { testCases := []struct { Stdin string Stdout string Stderr string Error string Tty bool MessageCount int }{ { Error: "bail", }, { Stdin: "a", Stdout: "b", Stderr: "c", // TODO bump this to a larger number such as 100 once // https://github.com/docker/spdystream/issues/55 is fixed and the Godep // is bumped. Sending multiple messages over stdin/stdout/stderr results // in more frames being spread across multiple spdystream frame workers. // This makes it more likely that the spdystream bug will be encountered, // where streams are closed as soon as a goaway frame is received, and // any pending frames that haven't been processed yet may not be // delivered (it's a race). MessageCount: 1, }, { Stdin: "a", Stdout: "b", Tty: true, }, } for i, testCase := range testCases { localOut := &bytes.Buffer{} localErr := &bytes.Buffer{} server := httptest.NewServer(fakeExecServer(t, i, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, testCase.MessageCount)) url, _ := url.ParseRequestURI(server.URL) c := client.NewRESTClient(url, "", client.ContentConfig{GroupVersion: &unversioned.GroupVersion{Group: "x"}}, -1, -1, nil) req := c.Post().Resource("testing") req.SetHeader(httpstream.HeaderProtocolVersion, StreamProtocolV2Name) req.Param("command", "ls") req.Param("command", "/") conf := &client.Config{ Host: server.URL, } e, err := NewExecutor(conf, "POST", req.URL()) if err != nil { t.Errorf("%d: unexpected error: %v", i, err) continue } err = e.Stream(strings.NewReader(strings.Repeat(testCase.Stdin, testCase.MessageCount)), localOut, localErr, testCase.Tty) hasErr := err != nil if len(testCase.Error) > 0 { if !hasErr { t.Errorf("%d: expected an error", i) } else { if e, a := testCase.Error, err.Error(); !strings.Contains(a, e) { t.Errorf("%d: expected error stream read '%v', got '%v'", i, e, a) } } // TODO: Uncomment when fix #19254 // server.Close() continue } if hasErr { t.Errorf("%d: unexpected error: %v", i, err) // TODO: Uncomment when fix #19254 // server.Close() continue } if len(testCase.Stdout) > 0 { if e, a := strings.Repeat(testCase.Stdout, testCase.MessageCount), localOut; e != a.String() { t.Errorf("%d: expected stdout data '%s', got '%s'", i, e, a) } } if testCase.Stderr != "" { if e, a := strings.Repeat(testCase.Stderr, testCase.MessageCount), localErr; e != a.String() { t.Errorf("%d: expected stderr data '%s', got '%s'", i, e, a) } } // TODO: Uncomment when fix #19254 // server.Close() } }
func TestForwardPorts(t *testing.T) { tests := map[string]struct { ports []string clientSends map[uint16]string serverSends map[uint16]string }{ "forward 1 port with no data either direction": { ports: []string{"5000"}, }, "forward 2 ports with bidirectional data": { ports: []string{"5001", "6000"}, clientSends: map[uint16]string{ 5001: "abcd", 6000: "ghij", }, serverSends: map[uint16]string{ 5001: "1234", 6000: "5678", }, }, } for testName, test := range tests { server := httptest.NewServer(fakePortForwardServer(t, testName, test.serverSends, test.clientSends)) url, _ := url.ParseRequestURI(server.URL) c := client.NewRESTClient(url, "x", nil, -1, -1) req := c.Post().Resource("testing") conf := &client.Config{ Host: server.URL, } stopChan := make(chan struct{}, 1) pf, err := New(req, conf, test.ports, stopChan) if err != nil { t.Fatalf("%s: unexpected error calling New: %v", testName, err) } doneChan := make(chan error) go func() { doneChan <- pf.ForwardPorts() }() <-pf.Ready for port, data := range test.clientSends { clientConn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port)) if err != nil { t.Errorf("%s: error dialing %d: %s", testName, port, err) server.Close() continue } defer clientConn.Close() n, err := clientConn.Write([]byte(data)) if err != nil && err != io.EOF { t.Errorf("%s: Error sending data '%s': %s", testName, data, err) server.Close() continue } if n == 0 { t.Errorf("%s: unexpected write of 0 bytes", testName) server.Close() continue } b := make([]byte, 4) n, err = clientConn.Read(b) if err != nil && err != io.EOF { t.Errorf("%s: Error reading data: %s", testName, err) server.Close() continue } if !bytes.Equal([]byte(test.serverSends[port]), b) { t.Errorf("%s: expected to read '%s', got '%s'", testName, test.serverSends[port], b) server.Close() continue } } // tell r.ForwardPorts to stop close(stopChan) // wait for r.ForwardPorts to actually return err = <-doneChan if err != nil { t.Errorf("%s: unexpected error: %s", testName, err) } server.Close() } }
// TODO: this test is largely cut and paste, refactor to share code func TestRequestAttachRemoteCommand(t *testing.T) { testCases := []struct { Stdin string Stdout string Stderr string Error string Tty bool }{ { Error: "bail", }, { Stdin: "a", Stdout: "b", Stderr: "c", }, { Stdin: "a", Stdout: "b", Tty: true, }, } for i, testCase := range testCases { localOut := &bytes.Buffer{} localErr := &bytes.Buffer{} server := httptest.NewServer(fakeExecServer(t, i, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, 1)) url, _ := url.ParseRequestURI(server.URL) c := client.NewRESTClient(url, "x", nil, -1, -1) req := c.Post().Resource("testing") conf := &client.Config{ Host: server.URL, } e := NewAttach(req, conf, strings.NewReader(testCase.Stdin), localOut, localErr, testCase.Tty) err := e.Execute() hasErr := err != nil if len(testCase.Error) > 0 { if !hasErr { t.Errorf("%d: expected an error", i) } else { if e, a := testCase.Error, err.Error(); !strings.Contains(a, e) { t.Errorf("%d: expected error stream read '%v', got '%v'", i, e, a) } } server.Close() continue } if hasErr { t.Errorf("%d: unexpected error: %v", i, err) server.Close() continue } if len(testCase.Stdout) > 0 { if e, a := testCase.Stdout, localOut; e != a.String() { t.Errorf("%d: expected stdout data '%s', got '%s'", i, e, a) } } if testCase.Stderr != "" { if e, a := testCase.Stderr, localErr; e != a.String() { t.Errorf("%d: expected stderr data '%s', got '%s'", i, e, a) } } server.Close() } }