184 lines
3.9 KiB
Go
184 lines
3.9 KiB
Go
// run with docker-compose up --build --abort-on-container-exit
|
|
|
|
package e2e_test
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"os/exec"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/creack/pty"
|
|
)
|
|
|
|
const testprivatekey = `-----BEGIN OPENSSH PRIVATE KEY-----
|
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
|
QyNTUxOQAAACDURkx99uaw1KddraZcLpB5kfMrWwvUz2fPOoArLcpz9QAAAJC+j0+Svo9P
|
|
kgAAAAtzc2gtZWQyNTUxOQAAACDURkx99uaw1KddraZcLpB5kfMrWwvUz2fPOoArLcpz9Q
|
|
AAAEDcQgdh2z2r/6blq0ziJ1l6s6IAX8C+9QHfAH931cHNO9RGTH325rDUp12tplwukHmR
|
|
8ytbC9TPZ886gCstynP1AAAADWJvbGlhbkB1YnVudHU=
|
|
-----END OPENSSH PRIVATE KEY-----
|
|
`
|
|
|
|
const testpublickey = `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINRGTH325rDUp12tplwukHmR8ytbC9TPZ886gCstynP1`
|
|
|
|
const waitTimeout = time.Second * 10
|
|
|
|
func waitForEndpointReady(addr string) {
|
|
waitForEndpointReadyWithTimeout(addr, waitTimeout)
|
|
}
|
|
|
|
func waitForEndpointReadyWithTimeout(addr string, timeout time.Duration) {
|
|
now := time.Now()
|
|
timeout = max(timeout, waitTimeout)
|
|
for {
|
|
if time.Since(now) > timeout {
|
|
log.Panic("timeout waiting for endpoint " + addr)
|
|
}
|
|
|
|
conn, err := net.Dial("tcp", addr)
|
|
if err == nil {
|
|
log.Printf("endpoint %s is ready", addr)
|
|
conn.Close()
|
|
break
|
|
}
|
|
time.Sleep(time.Second)
|
|
}
|
|
}
|
|
|
|
func runCmd(cmd string, args ...string) (*exec.Cmd, io.Writer, io.Reader, error) {
|
|
newargs := append([]string{cmd}, args...)
|
|
newargs = append([]string{"-i0", "-o0", "-e0"}, newargs...)
|
|
c := exec.Command("stdbuf", newargs...)
|
|
c.SysProcAttr = sigtermForPdeathsig
|
|
f, err := pty.Start(c)
|
|
if err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
r := io.TeeReader(f, &buf)
|
|
go func() {
|
|
_, _ = io.Copy(os.Stdout, r)
|
|
}()
|
|
|
|
log.Printf("starting %v", c.Args)
|
|
|
|
return c, f, &buf, nil
|
|
}
|
|
|
|
func runCmdAndWait(cmd string, args ...string) error {
|
|
c, _, _, err := runCmd(cmd, args...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return c.Wait()
|
|
}
|
|
|
|
func waitForStdoutContains(stdout io.Reader, text string, cb func(string)) {
|
|
st := time.Now()
|
|
for {
|
|
scanner := bufio.NewScanner(stdout)
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
if strings.Contains(line, text) {
|
|
cb(line)
|
|
return
|
|
}
|
|
}
|
|
|
|
if time.Since(st) > waitTimeout {
|
|
log.Panicf("timeout waiting for [%s] from prompt", text)
|
|
return
|
|
}
|
|
|
|
time.Sleep(time.Second) // stdout has no data yet
|
|
}
|
|
}
|
|
|
|
func enterPassword(stdin io.Writer, stdout io.Reader, password string) {
|
|
waitForStdoutContains(stdout, "'s password", func(_ string) {
|
|
_, _ = fmt.Fprintf(stdin, "%v\n", password)
|
|
log.Printf("got password prompt, sending password")
|
|
})
|
|
}
|
|
|
|
func checkSharedFileContent(t *testing.T, targetfie string, expected string) {
|
|
f, err := os.Open(fmt.Sprintf("/shared/%v", targetfie))
|
|
if err != nil {
|
|
t.Errorf("failed to open shared file, %v", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
b, err := io.ReadAll(f)
|
|
if err != nil {
|
|
t.Errorf("failed to read shared file, %v", err)
|
|
}
|
|
|
|
if string(b) != expected {
|
|
t.Errorf("shared file content mismatch, expected %v, got %v", expected, string(b))
|
|
}
|
|
}
|
|
|
|
func killCmd(c *exec.Cmd) {
|
|
if c.Process != nil {
|
|
if err := c.Process.Kill(); err != nil {
|
|
log.Printf("failed to kill ssh process, %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func runAndGetStdout(cmd string, args ...string) ([]byte, error) {
|
|
c, _, stdout, err := runCmd(cmd, args...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := c.Wait(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return io.ReadAll(stdout)
|
|
}
|
|
|
|
func nextAvaliablePort() int {
|
|
l, err := net.Listen("tcp", ":0")
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
defer l.Close()
|
|
return l.Addr().(*net.TCPAddr).Port
|
|
}
|
|
|
|
func nextAvailablePiperAddress() (string, string) {
|
|
port := strconv.Itoa(nextAvaliablePort())
|
|
return net.JoinHostPort("127.0.0.1", (port)), port
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
if os.Getenv("SSHPIPERD_E2E_TEST") != "1" {
|
|
log.Printf("skipping e2e test")
|
|
os.Exit(0)
|
|
return
|
|
}
|
|
|
|
_ = runCmdAndWait("ssh", "-V")
|
|
|
|
for _, ep := range []string{
|
|
"host-password:2222",
|
|
"host-publickey:2222",
|
|
} {
|
|
waitForEndpointReady(ep)
|
|
}
|
|
|
|
os.Exit(m.Run())
|
|
}
|