aboutsummaryrefslogtreecommitdiff
path: root/rsh/e2e_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'rsh/e2e_test.go')
-rw-r--r--rsh/e2e_test.go84
1 files changed, 84 insertions, 0 deletions
diff --git a/rsh/e2e_test.go b/rsh/e2e_test.go
new file mode 100644
index 0000000..1fa80c7
--- /dev/null
+++ b/rsh/e2e_test.go
@@ -0,0 +1,84 @@
+package main
+
+import (
+ "bytes"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strconv"
+ "testing"
+)
+
+// TestEndToEndRealRsync drives the actual rsync binary through the actual rsh
+// transport binary into the in-process SSH server, which runs the remote rsync
+// via /bin/sh. It proves real rsync + the Go transport move files intact.
+func TestEndToEndRealRsync(t *testing.T) {
+ if testing.Short() {
+ t.Skip("short mode")
+ }
+ rsyncBin, err := exec.LookPath("rsync")
+ if err != nil {
+ t.Skip("rsync not installed")
+ }
+
+ // Build the rsh binary so rsync can exec it as its remote shell.
+ rshBin := filepath.Join(t.TempDir(), "rsh")
+ if out, err := exec.Command("go", "build", "-o", rshBin, ".").CombinedOutput(); err != nil {
+ t.Fatalf("build rsh: %v\n%s", err, out)
+ }
+
+ keyPath, pub := genClientKey(t)
+ srv := newTestServer(t, pub, shellExec)
+ kh := writeKnownHosts(t, "127.0.0.1", srv.port(), srv.hostKey.PublicKey())
+
+ src := t.TempDir()
+ dst := t.TempDir()
+ mustWrite(t, filepath.Join(src, "a.txt"), "alpha")
+ mustWrite(t, filepath.Join(src, "sub", "b.bin"), "\x00\x01\x02\x03beta")
+ mustWrite(t, filepath.Join(src, "sub", "c.txt"), "gamma gamma gamma")
+
+ cmd := exec.Command(rsyncBin, "-a", "-e", rshBin, src+"/", "u@127.0.0.1:"+dst+"/")
+ cmd.Env = append(os.Environ(),
+ "RSH_KEY="+keyPath,
+ "RSH_KNOWN_HOSTS="+kh,
+ "RSH_PORT="+strconv.Itoa(srv.port()),
+ )
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Fatalf("rsync: %v\n%s", err, out)
+ }
+
+ checkSame(t, src, dst)
+}
+
+func mustWrite(t *testing.T, path, content string) {
+ t.Helper()
+ if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func checkSame(t *testing.T, src, dst string) {
+ t.Helper()
+ err := filepath.Walk(src, func(p string, info os.FileInfo, err error) error {
+ if err != nil || info.IsDir() {
+ return err
+ }
+ rel, _ := filepath.Rel(src, p)
+ want, _ := os.ReadFile(p)
+ got, err := os.ReadFile(filepath.Join(dst, rel))
+ if err != nil {
+ t.Errorf("missing on dest: %s (%v)", rel, err)
+ return nil
+ }
+ if !bytes.Equal(got, want) {
+ t.Errorf("content mismatch for %s", rel)
+ }
+ return nil
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+}