func TestGrep(t *testing.T) { assert := assrt.NewAssert(t) cmd := exec.Command("grep", "--color=auto", "bar") host := siphon.NewHost(cmd, siphon.NewInternalAddr()) host.Start() go func() { stdin := host.StdinPipe() stdin.Write([]byte("foo\nbar\nbaz\n")) stdin.Write([]byte{4}) // EOT }() outBuffer := new(bytes.Buffer) io.Copy(outBuffer, host.StdoutPipe()) out := string(outBuffer.Bytes()) expected := // I have no idea where the CR characters come from. "foo\r\n" + "bar\r\n" + "baz\r\n" + "[01;31m[Kbar[m[K\r\n" assert.Equal( expected, out, ) }
func TestDoubleClient(t *testing.T) { assert := assrt.NewAssert(t) addr := siphon.NewAddr("test", "unix", "test.sock") cmd := exec.Command("cat", "-") host := siphon.NewHost(cmd, addr) host.Serve() defer host.UnServe() client1 := siphon.NewClient(addr) client1.Connect() client2 := siphon.NewClient(addr) client2.Connect() host.Start() go func() { // timed pauses are a hack required to make sure the host side flushes the echos in an order we can test. client1.Stdin().Write([]byte("foo\n")) time.Sleep(50 * time.Millisecond) client2.Stdin().Write([]byte("bar\n")) time.Sleep(50 * time.Millisecond) client1.Stdin().Write([]byte("baz\n")) time.Sleep(50 * time.Millisecond) client2.Stdin().Write([]byte{4}) // EOT }() outBuffer1 := new(bytes.Buffer) io.Copy(outBuffer1, client1.Stdout()) out1 := string(outBuffer1.Bytes()) outBuffer2 := new(bytes.Buffer) io.Copy(outBuffer2, client2.Stdout()) out2 := string(outBuffer2.Bytes()) expected := "foo\r\nfoo\r\n" + "bar\r\nbar\r\n" + "baz\r\nbaz\r\n" assert.Equal( expected, out1, ) assert.Equal( expected, out2, ) }
/** Getting any answer from the tty command at all is pretty good news, since `go test` doesn't let the shell's tty come through. */ func TestActuallyNewTty(t *testing.T) { assert := assrt.NewAssert(t) cmd := exec.Command("tty") host := siphon.NewHost(cmd, siphon.NewInternalAddr()) outBuffer := new(bytes.Buffer) hostOut := host.StdoutPipe() host.Start() io.Copy(outBuffer, hostOut) innerTty := string(outBuffer.Bytes()) assert.NotEqual( "", // what exactly you get varies on the current state of your machine, but something like /dev/pts/12 is reasonable. innerTty, ) }
func TestUnixSocket(t *testing.T) { assert := assrt.NewAssert(t) addr := siphon.NewAddr("test", "unix", "test.sock") cmd := exec.Command("cat", "-") host := siphon.NewHost(cmd, addr) host.Serve() defer host.UnServe() client := siphon.NewClient(addr) client.Connect() //client.Attach() // you can't do this in a test. there's no tty. //FIXME: there's really no guarantee that the host finished processing the client connect request by now host.Start() go func() { stdin := client.Stdin() stdin.Write([]byte("foo\nbar\nbaz\n")) stdin.Write([]byte{4}) // EOT }() outBuffer := new(bytes.Buffer) io.Copy(outBuffer, client.Stdout()) out := string(outBuffer.Bytes()) expected := "foo\r\n" + "bar\r\n" + "baz\r\n" expected = expected + expected assert.Equal( expected, out, ) }
func (opts *hostOpts) Execute(args []string) error { addr, err := ParseNewAddr(opts.Address) if err != nil { fmt.Fprintf(os.Stderr, "siphon: %s\n", err) os.Exit(EXIT_BADARGS) } cmd := exec.Command(opts.Command) shutdownCh := HandleShutdown() //handle control-c gracefully host := siphon.NewHost(cmd, addr) //Give the shutdown handler a callback to close the host shutdownCh <- func() { host.UnServe() } fmt.Printf("Hosting %s at %s\n", opts.Command, addr.Label) serveErr := host.Serve() defer host.UnServe() if serveErr != nil { if serveOpError, ok := serveErr.(*net.OpError); ok && serveOpError.Err == syscall.EADDRINUSE { fmt.Fprintf(os.Stderr, "%s\n", serveErr) os.Exit(EXIT_BIND_IN_USE) } else { panic(serveErr) } } host.Start() exitCode := host.Wait() fmt.Printf("siphon: %s exited %d\r\n", opts.Command, exitCode) return nil }