summaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/_util.py23
-rw-r--r--tests/configs/match-final14
-rw-r--r--tests/test_config.py16
-rw-r--r--tests/test_sftp_big.py51
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")