diff options
Diffstat (limited to 'libgo/go/exp/ssh/session_test.go')
-rw-r--r-- | libgo/go/exp/ssh/session_test.go | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/libgo/go/exp/ssh/session_test.go b/libgo/go/exp/ssh/session_test.go new file mode 100644 index 00000000000..4be7746d17e --- /dev/null +++ b/libgo/go/exp/ssh/session_test.go @@ -0,0 +1,149 @@ +// Copyright 2011 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. + +package ssh + +// Session tests. + +import ( + "bytes" + "io" + "testing" +) + +// dial constructs a new test server and returns a *ClientConn. +func dial(t *testing.T) *ClientConn { + pw := password("tiger") + serverConfig.PasswordCallback = func(user, pass string) bool { + return user == "testuser" && pass == string(pw) + } + serverConfig.PubKeyCallback = nil + + l, err := Listen("tcp", "127.0.0.1:0", serverConfig) + if err != nil { + t.Fatalf("unable to listen: %s", err) + } + go func() { + defer l.Close() + conn, err := l.Accept() + if err != nil { + t.Errorf("Unable to accept: %v", err) + return + } + defer conn.Close() + if err := conn.Handshake(); err != nil { + t.Errorf("Unable to handshake: %v", err) + return + } + for { + ch, err := conn.Accept() + if err == io.EOF { + return + } + if err != nil { + t.Errorf("Unable to accept incoming channel request: %v", err) + return + } + if ch.ChannelType() != "session" { + ch.Reject(UnknownChannelType, "unknown channel type") + continue + } + ch.Accept() + go func() { + defer ch.Close() + // this string is returned to stdout + shell := NewServerShell(ch, "golang") + shell.ReadLine() + type exitMsg struct { + PeersId uint32 + Request string + WantReply bool + Status uint32 + } + // TODO(dfc) casting to the concrete type should not be + // necessary to send a packet. + msg := exitMsg{ + PeersId: ch.(*channel).theirId, + Request: "exit-status", + WantReply: false, + Status: 0, + } + ch.(*channel).serverConn.writePacket(marshal(msgChannelRequest, msg)) + }() + } + t.Log("done") + }() + + config := &ClientConfig{ + User: "testuser", + Auth: []ClientAuth{ + ClientAuthPassword(pw), + }, + } + + c, err := Dial("tcp", l.Addr().String(), config) + if err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } + return c +} + +// Test a simple string is returned to session.Stdout. +func TestSessionShell(t *testing.T) { + conn := dial(t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %s", err) + } + defer session.Close() + stdout := new(bytes.Buffer) + session.Stdout = stdout + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %s", err) + } + if err := session.Wait(); err != nil { + t.Fatalf("Remote command did not exit cleanly: %s", err) + } + actual := stdout.String() + if actual != "golang" { + t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) + } +} + +// TODO(dfc) add support for Std{in,err}Pipe when the Server supports it. + +// Test a simple string is returned via StdoutPipe. +func TestSessionStdoutPipe(t *testing.T) { + conn := dial(t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %s", err) + } + defer session.Close() + stdout, err := session.StdoutPipe() + if err != nil { + t.Fatalf("Unable to request StdoutPipe(): %v", err) + } + var buf bytes.Buffer + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %s", err) + } + done := make(chan bool, 1) + go func() { + if _, err := io.Copy(&buf, stdout); err != nil { + t.Errorf("Copy of stdout failed: %v", err) + } + done <- true + }() + if err := session.Wait(); err != nil { + t.Fatalf("Remote command did not exit cleanly: %s", err) + } + <-done + actual := buf.String() + if actual != "golang" { + t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) + } +} |