diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/_util.py | 23 | ||||
-rw-r--r-- | tests/configs/match-final | 14 | ||||
-rw-r--r-- | tests/test_config.py | 16 | ||||
-rw-r--r-- | tests/test_sftp_big.py | 51 |
4 files changed, 101 insertions, 3 deletions
diff --git a/tests/_util.py b/tests/_util.py index aeee96ea..acc06852 100644 --- a/tests/_util.py +++ b/tests/_util.py @@ -7,7 +7,7 @@ import socket import struct import sys import unittest -from time import sleep +import time import threading import pytest @@ -303,7 +303,7 @@ class TestServer(ServerInterface): if username == "bad-server": raise Exception("Ack!") if username == "unresponsive-server": - sleep(5) + time.sleep(5) return AUTH_SUCCESSFUL return AUTH_FAILED @@ -442,3 +442,22 @@ def server( ts.close() socks.close() sockc.close() + + +def wait_until(condition, *, timeout=2): + """ + Wait until `condition()` no longer raises an `AssertionError` or until + `timeout` seconds have passed, which causes a `TimeoutError` to be raised. + """ + deadline = time.time() + timeout + + while True: + try: + condition() + except AssertionError as e: + if time.time() > deadline: + timeout_message = f"Condition not reached after {timeout}s" + raise TimeoutError(timeout_message) from e + else: + return + time.sleep(0.01) diff --git a/tests/configs/match-final b/tests/configs/match-final new file mode 100644 index 00000000..21e927fc --- /dev/null +++ b/tests/configs/match-final @@ -0,0 +1,14 @@ +Host jump + HostName jump.example.org + Port 1003 + +Host finally + HostName finally.example.org + Port 1001 + +Host default-port + HostName default-port.example.org + +Match final host "*.example.org" !host jump.example.org + ProxyJump jump + Port 1002 diff --git a/tests/test_config.py b/tests/test_config.py index d2395965..1e623e0a 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1030,3 +1030,19 @@ class TestComplexMatching: # !canonical in a config that is canonicalized - does NOT match result = load_config("match-canonical-yes").lookup("www") assert result["user"] == "hidden" + + +class TestFinalMatching(object): + def test_finally(self): + result = load_config("match-final").lookup("finally") + assert result["proxyjump"] == "jump" + assert result["port"] == "1001" + + def test_default_port(self): + result = load_config("match-final").lookup("default-port") + assert result["proxyjump"] == "jump" + assert result["port"] == "1002" + + def test_negated(self): + result = load_config("match-final").lookup("jump") + assert result["port"] == "1003" diff --git a/tests/test_sftp_big.py b/tests/test_sftp_big.py index acfe71e3..7d1110c3 100644 --- a/tests/test_sftp_big.py +++ b/tests/test_sftp_big.py @@ -30,7 +30,7 @@ import time from paramiko.common import o660 -from ._util import slow +from ._util import slow, wait_until @slow @@ -365,3 +365,52 @@ class TestBigSFTP: finally: sftp.remove(f"{sftp.FOLDER}/hongry.txt") t.packetizer.REKEY_BYTES = pow(2, 30) + + def test_prefetch_limit(self, sftp): + """ + write a 1MB file and prefetch with a limit + """ + kblob = 1024 * b"x" + start = time.time() + + def expect_prefetch_extents(file, expected_extents): + with file._prefetch_lock: + assert len(file._prefetch_extents) == expected_extents + + try: + with sftp.open(f"{sftp.FOLDER}/hongry.txt", "w") as f: + for n in range(1024): + f.write(kblob) + if n % 128 == 0: + sys.stderr.write(".") + sys.stderr.write(" ") + + assert ( + sftp.stat(f"{sftp.FOLDER}/hongry.txt").st_size == 1024 * 1024 + ) + end = time.time() + sys.stderr.write(f"{round(end - start)}s") + + # read with prefetch, no limit + # expecting 32 requests (32k * 32 == 1M) + with sftp.open(f"{sftp.FOLDER}/hongry.txt", "rb") as f: + file_size = f.stat().st_size + f.prefetch(file_size) + wait_until(lambda: expect_prefetch_extents(f, 32)) + + # read with prefetch, limiting to 5 simultaneous requests + with sftp.open(f"{sftp.FOLDER}/hongry.txt", "rb") as f: + file_size = f.stat().st_size + f.prefetch(file_size, 5) + wait_until(lambda: expect_prefetch_extents(f, 5)) + for n in range(1024): + with f._prefetch_lock: + assert len(f._prefetch_extents) <= 5 + data = f.read(1024) + assert data == kblob + + if n % 128 == 0: + sys.stderr.write(".") + + finally: + sftp.remove(f"{sftp.FOLDER}/hongry.txt") |