123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- // License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
- package ssh
- import (
- "encoding/binary"
- "encoding/json"
- "fmt"
- "io/fs"
- "kitty"
- "kitty/tools/utils/shm"
- "os"
- "os/exec"
- "path"
- "path/filepath"
- "strings"
- "testing"
- "github.com/google/go-cmp/cmp"
- "golang.org/x/sys/unix"
- )
- var _ = fmt.Print
- func TestCloneEnv(t *testing.T) {
- env := map[string]string{"a": "1", "b": "2"}
- data, err := json.Marshal(env)
- if err != nil {
- t.Fatal(err)
- }
- mmap, err := shm.CreateTemp("", 128)
- if err != nil {
- t.Fatal(err)
- }
- defer mmap.Unlink()
- copy(mmap.Slice()[4:], data)
- binary.BigEndian.PutUint32(mmap.Slice(), uint32(len(data)))
- mmap.Close()
- x, err := add_cloned_env(mmap.Name())
- if err != nil {
- t.Fatal(err)
- }
- diff := cmp.Diff(env, x)
- if diff != "" {
- t.Fatalf("Failed to deserialize env\n%s", diff)
- }
- }
- func basic_connection_data(overrides ...string) *connection_data {
- ans := &connection_data{
- script_type: "sh", request_id: "123-123", remote_args: []string{},
- username: "testuser", hostname_for_match: "host.test",
- dont_create_shm: true,
- }
- opts, bad_lines, err := load_config(ans.hostname_for_match, ans.username, overrides)
- if err != nil {
- panic(err)
- }
- if len(bad_lines) != 0 {
- panic(fmt.Sprintf("Bad config lines: %s with error: %s", bad_lines[0].Line, bad_lines[0].Err))
- }
- ans.host_opts = opts
- return ans
- }
- func TestSSHBootstrapScriptLimit(t *testing.T) {
- cd := basic_connection_data()
- err := get_remote_command(cd)
- if err != nil {
- t.Fatal(err)
- }
- total := 0
- for _, x := range cd.rcmd {
- total += len(x)
- }
- if total > 9000 {
- t.Fatalf("Bootstrap script too large: %d bytes", total)
- }
- }
- func TestSSHTarfile(t *testing.T) {
- tdir := t.TempDir()
- cd := basic_connection_data()
- data, err := make_tarfile(cd, func(key string) (val string, found bool) { return })
- if err != nil {
- t.Fatal(err)
- }
- cmd := exec.Command("tar", "xpzf", "-", "-C", tdir)
- cmd.Stderr = os.Stderr
- inp, err := cmd.StdinPipe()
- if err != nil {
- t.Fatal(err)
- }
- err = cmd.Start()
- if err != nil {
- t.Fatal(err)
- }
- _, err = inp.Write(data)
- if err != nil {
- t.Fatal(err)
- }
- inp.Close()
- err = cmd.Wait()
- if err != nil {
- t.Fatal(err)
- }
- seen := map[string]bool{}
- err = filepath.WalkDir(tdir, func(name string, d fs.DirEntry, werr error) error {
- if werr != nil {
- return werr
- }
- rname, werr := filepath.Rel(tdir, name)
- if werr != nil {
- return werr
- }
- rname = strings.ReplaceAll(rname, "\\", "/")
- if rname == "." {
- return nil
- }
- fi, werr := d.Info()
- if werr != nil {
- return werr
- }
- if fi.Mode().Perm()&0o600 == 0 {
- return fmt.Errorf("%s is not rw for its owner. Actual permissions: %s", rname, fi.Mode().String())
- }
- seen[rname] = true
- return nil
- })
- if err != nil {
- t.Fatal(err)
- }
- if !seen["data.sh"] {
- t.Fatalf("data.sh missing")
- }
- for _, x := range []string{".terminfo/kitty.terminfo", ".terminfo/x/" + kitty.DefaultTermName} {
- if !seen["home/"+x] {
- t.Fatalf("%s missing", x)
- }
- }
- for _, x := range []string{"shell-integration/bash/kitty.bash", "shell-integration/fish/vendor_completions.d/kitty.fish"} {
- if !seen[path.Join("home", cd.host_opts.Remote_dir, x)] {
- t.Fatalf("%s missing", x)
- }
- }
- for _, x := range []string{"kitty", "kitten"} {
- p := filepath.Join(tdir, "home", cd.host_opts.Remote_dir, "kitty", "bin", x)
- if err = unix.Access(p, unix.X_OK); err != nil {
- t.Fatalf("Cannot execute %s with error: %s", x, err)
- }
- }
- if seen[path.Join("home", cd.host_opts.Remote_dir, "shell-integration", "ssh", "kitten")] {
- t.Fatalf("Contents of shell-integration/ssh not excluded")
- }
- }
|