Add more integration testing for the transfer kitten

This commit is contained in:
Kovid Goyal 2023-07-26 16:24:31 +05:30
parent e24dd7be2c
commit c11d1d3430
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 107 additions and 45 deletions

View File

@ -48,7 +48,9 @@
:code:`/path/to/dir/` on the local computer.
Note that when copying multiple files or directories, the destination
must be an existing directory on the receiving computer.
must be an existing directory on the receiving computer. Relative file
paths are resolved with respect to the current directory on the computer
running the kitten and the home directory on the other computer.
'''

View File

@ -26,6 +26,7 @@ import (
"kitty/tools/utils/humanize"
"kitty/tools/wcswidth"
"golang.org/x/exp/slices"
"golang.org/x/sys/unix"
)
@ -683,6 +684,8 @@ func files_for_receive(opts *Options, dest string, files []*remote_file, remote_
}
spec_paths := make([]string, len(specs))
for i := range specs {
// use the shortest path as the path for the spec
slices.SortStableFunc(spec_map[i], func(a, b *remote_file) bool { return len(a.remote_path) < len(b.remote_path) })
spec_paths[i] = spec_map[i][0].remote_path
}
if opts.Mode == "mirror" {

View File

@ -177,14 +177,14 @@ func process(opts *Options, paths []string, remote_base string, counter *int) (a
func process_mirrored_files(opts *Options, args []string) (ans []*File, err error) {
paths := utils.Map(func(x string) string { return abspath(expand_home(x)) }, args)
common_path := utils.Commonpath(paths...)
home := strings.TrimRight(home_path(), string(filepath.Separator))
if common_path != "" && strings.HasPrefix(common_path, home+string(filepath.Separator)) {
paths = utils.Map(func(x string) string {
r, _ := filepath.Rel(home, x)
home := strings.TrimRight(home_path(), string(filepath.Separator)) + string(filepath.Separator)
paths = utils.Map(func(path string) string {
if strings.HasPrefix(path, home) {
r, _ := filepath.Rel(home, path)
return filepath.Join("~", r)
}, paths)
}
}
return path
}, paths)
counter := 0
return process(opts, paths, "", &counter)
}
@ -232,7 +232,7 @@ func files_for_send(opts *Options, args []string) (files []*File, err error) {
// detect symlinks to other transferred files
for i, f := range files {
if f.file_type == FileType_symlink {
link_dest, err := os.Readlink(f.local_path)
link_dest, err := os.Readlink(f.expanded_local_path)
if err != nil {
remove = append(remove, i)
continue
@ -241,7 +241,7 @@ func files_for_send(opts *Options, args []string) (files []*File, err error) {
is_abs := filepath.IsAbs(link_dest)
q := link_dest
if !is_abs {
q = filepath.Join(filepath.Dir(f.local_path), link_dest)
q = filepath.Join(filepath.Dir(f.expanded_local_path), link_dest)
}
st, err := os.Stat(q)
if err == nil {

View File

@ -447,9 +447,9 @@ class DestFile:
def __init__(self, ftc: FileTransmissionCommand) -> None:
self.name = ftc.name
if not os.path.isabs(self.name):
self.name = os.path.expanduser(self.name)
self.name = expand_home(self.name)
if not os.path.isabs(self.name):
self.name = os.path.join(tempfile.gettempdir(), self.name)
self.name = abspath(self.name, use_home=True)
try:
self.existing_stat: Optional[os.stat_result] = os.stat(self.name, follow_symlinks=False)
except OSError:

View File

@ -181,6 +181,7 @@ class TestFileTransmission(BaseTest):
def setUp(self):
self.direction_receive = False
self.kitty_home = self.kitty_cwd = self.kitten_home = self.kitten_cwd = ''
super().setUp()
self.tdir = os.path.realpath(tempfile.mkdtemp())
self.responses = []
@ -196,8 +197,12 @@ def tearDown(self):
super().tearDown()
def clean_tdir(self):
shutil.rmtree(self.tdir)
self.tdir = os.path.realpath(tempfile.mkdtemp())
for x in os.listdir(self.tdir):
x = os.path.join(self.tdir, x)
if os.path.isdir(x):
shutil.rmtree(x)
else:
os.remove(x)
self.responses = []
def cr(self, a, b):
@ -324,22 +329,18 @@ def test_rsync_hashers(self):
self.assertEqual(h128.hexdigest(), '8d6b60383dfa90c21be79eecd1b1353d')
@contextmanager
def run_kitten(self, cmd, home_dir='', allow=True):
cwd = os.path.realpath(tempfile.mkdtemp(suffix='-cwd', dir=self.tdir))
def run_kitten(self, cmd, home_dir='', allow=True, cwd=''):
cwd = cwd or self.kitten_cwd or self.tdir
cmd = [kitten_exe(), 'transfer'] + (['--direction=receive'] if self.direction_receive else []) + cmd
env = {'PWD': cwd}
if home_dir:
env['HOME'] = home_dir
try:
env['HOME'] = home_dir or self.kitten_home or self.tdir
with set_paths(home=self.kitty_home, cwd=self.kitty_cwd):
pty = TransferPTY(cmd, cwd=cwd, allow=allow, env=env)
i = 10
while i > 0 and not pty.screen_contents().strip():
pty.process_input_from_child()
i -= 1
yield pty
finally:
if os.path.exists(cwd):
shutil.rmtree(cwd)
def basic_transfer_tests(self):
src = os.path.join(self.tdir, 'src')
@ -445,19 +446,62 @@ def de(path):
multiple_files('--transmit-deltas')
multiple_files('--transmit-deltas')
def setup_dirs(self):
self.clean_tdir()
self.kitty_home = os.path.join(self.tdir, 'kitty-home')
self.kitty_cwd = os.path.join(self.tdir, 'kitty-cwd')
self.kitten_home = os.path.join(self.tdir, 'kitten-home')
self.kitten_cwd = os.path.join(self.tdir, 'kitten-cwd')
tuple(map(os.mkdir, (self.kitty_home, self.kitty_cwd, self.kitten_home, self.kitten_cwd)))
def create_src(self, base):
src = os.path.join(base, 'src')
with open(src, 'wb') as s:
s.write(self.src_data)
return src
def mirror_test(self, src, dest, prefix=''):
self.create_src(src)
os.symlink('/', os.path.join(src, 'sym'))
os.mkdir(os.path.join(src, 'sub'))
os.link(os.path.join(src, 'src'), os.path.join(src, 'sub', 'hardlink'))
with self.run_kitten(['--mode=mirror', f'{prefix}src', f'{prefix}sym', f'{prefix}sub']) as pty:
pty.wait_till_child_exits(require_exit_code=0)
os.remove(os.path.join(dest, 'src'))
os.remove(os.path.join(dest, 'sym'))
shutil.rmtree(os.path.join(dest, 'sub'))
def test_transfer_receive(self):
self.direction_receive = True
self.basic_transfer_tests()
src = os.path.join(self.tdir, 'src')
with open(src, 'wb') as s:
s.write(self.src_data)
# home dir expansion
fname = 'tstest-file'
home = os.path.dirname(src)
with set_paths(home=home), self.run_kitten(['~/'+os.path.basename(src), f'~/{fname}'], home_dir=home) as pty:
pty.wait_till_child_exits(require_exit_code=0)
os.remove(os.path.join(home, fname))
self.setup_dirs()
self.create_src(self.kitty_home)
# dir expansion with single transfer
with self.run_kitten(['~/src', '~/src']) as pty:
pty.wait_till_child_exits(require_exit_code=0)
os.remove(os.path.join(self.kitten_home, 'src'))
with self.run_kitten(['src', 'src']) as pty:
pty.wait_till_child_exits(require_exit_code=0)
os.remove(os.path.join(self.kitten_cwd, 'src'))
# dir expansion with multiple transfers
os.symlink('/', os.path.join(self.kitty_home, 'sym'))
with self.run_kitten(['~/src', '~/sym', '~']) as pty:
pty.wait_till_child_exits(require_exit_code=0)
os.remove(os.path.join(self.kitten_home, 'src'))
os.remove(os.path.join(self.kitten_home, 'sym'))
with self.run_kitten(['src', 'sym', '.']) as pty:
pty.wait_till_child_exits(require_exit_code=0)
os.remove(os.path.join(self.kitten_cwd, 'src'))
os.remove(os.path.join(self.kitten_cwd, 'sym'))
# mirroring
self.setup_dirs()
self.mirror_test(self.kitty_home, self.kitten_home)
def test_transfer_send(self):
self.basic_transfer_tests()
@ -465,19 +509,32 @@ def test_transfer_send(self):
with open(src, 'wb') as s:
s.write(self.src_data)
# home dir expansion
fname = 'tstest-file'
home = os.path.dirname(src)
with set_paths(home=home), self.run_kitten(['~/'+os.path.basename(src), '~/'+fname], home_dir=home) as pty:
pty.wait_till_child_exits(require_exit_code=0)
os.remove(os.path.expanduser('~/'+fname))
self.setup_dirs()
self.create_src(self.kitten_home)
# mirror mode
src_home = os.path.join(self.tdir, 'misrc')
os.mkdir(src_home)
open(os.path.join(src_home, fname), 'w').close()
with self.run_kitten(['--mode=mirror', '~/'+fname], home_dir=src_home) as pty:
# dir expansion with single transfer
with self.run_kitten(['~/src', '~/src']) as pty:
pty.wait_till_child_exits(require_exit_code=0)
with open(os.path.expanduser('~/'+fname)) as f:
self.assertEqual('', f.read())
os.remove(f.name)
os.remove(os.path.join(self.kitty_home, 'src'))
self.create_src(self.kitten_cwd)
with self.run_kitten(['src', 'src']) as pty:
pty.wait_till_child_exits(require_exit_code=0)
os.remove(os.path.join(self.kitty_home, 'src'))
# dir expansion with multiple transfers
os.symlink('/', os.path.join(self.kitten_home, 'sym'))
with self.run_kitten(['~/src', '~/sym', '~']) as pty:
pty.wait_till_child_exits(require_exit_code=0)
os.remove(os.path.join(self.kitty_home, 'src'))
os.remove(os.path.join(self.kitty_home, 'sym'))
os.symlink('/', os.path.join(self.kitten_cwd, 'sym'))
with self.run_kitten(['src', 'sym', '.']) as pty:
pty.wait_till_child_exits(require_exit_code=0)
os.remove(os.path.join(self.kitty_home, 'src'))
os.remove(os.path.join(self.kitty_home, 'sym'))
# mirroring
self.setup_dirs()
self.mirror_test(self.kitten_home, self.kitty_home, prefix='~/')