mirror of
https://github.com/herdrdev/herdr.git
synced 2026-09-21 16:01:04 +00:00
test: deflake recent CI failures (#4139)
This commit is contained in:
@@ -14,8 +14,11 @@ const fixtureTimeoutMs = process.platform === 'win32' ? 120_000 : 30_000;
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
temporaryDirectories.splice(0).map((path) => rm(path, { recursive: true, force: true })),
|
||||
temporaryDirectories.map((path) =>
|
||||
rm(path, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }),
|
||||
),
|
||||
);
|
||||
temporaryDirectories.length = 0;
|
||||
});
|
||||
|
||||
describe('preview documentation snapshots', () => {
|
||||
|
||||
@@ -7,6 +7,8 @@ import json
|
||||
import shutil
|
||||
import struct
|
||||
import tempfile
|
||||
import time
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
import xml.etree.ElementTree as ET
|
||||
import zipfile
|
||||
@@ -74,10 +76,18 @@ def validate_nuspec(archive: zipfile.ZipFile, package: dict[str, Any]) -> None:
|
||||
def acquire_package(package: dict[str, Any], package_path: Path) -> None:
|
||||
package_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
if not package_path.exists():
|
||||
with urllib.request.urlopen(
|
||||
package["url"], timeout=DOWNLOAD_TIMEOUT_SECONDS
|
||||
) as response, package_path.open("wb") as output:
|
||||
shutil.copyfileobj(response, output)
|
||||
for attempt in range(3):
|
||||
try:
|
||||
with urllib.request.urlopen(
|
||||
package["url"], timeout=DOWNLOAD_TIMEOUT_SECONDS
|
||||
) as response, package_path.open("wb") as output:
|
||||
shutil.copyfileobj(response, output)
|
||||
break
|
||||
except urllib.error.HTTPError as error:
|
||||
if error.code < 500 or attempt == 2:
|
||||
raise
|
||||
error.close()
|
||||
time.sleep(2**attempt)
|
||||
actual = sha256_file(package_path)
|
||||
if actual != package["sha256"]:
|
||||
raise ValueError(
|
||||
|
||||
@@ -6,6 +6,7 @@ import json
|
||||
import struct
|
||||
import tempfile
|
||||
import unittest
|
||||
import urllib.error
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
@@ -52,7 +53,7 @@ class WindowsConptyPackageTests(unittest.TestCase):
|
||||
self.assertIn('conpty\\conpty.dll', wrapper)
|
||||
self.assertIn('"*Microsoft Corporation*"', wrapper)
|
||||
|
||||
def test_package_download_has_a_finite_timeout(self) -> None:
|
||||
def test_package_download_retries_server_errors_with_a_finite_timeout(self) -> None:
|
||||
payload = b"package"
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
destination = Path(temporary) / "conpty.nupkg"
|
||||
@@ -60,14 +61,31 @@ class WindowsConptyPackageTests(unittest.TestCase):
|
||||
"url": "https://example.invalid/conpty.nupkg",
|
||||
"sha256": hashlib.sha256(payload).hexdigest(),
|
||||
}
|
||||
with mock.patch.object(
|
||||
package.urllib.request, "urlopen", return_value=io.BytesIO(payload)
|
||||
) as urlopen:
|
||||
server_error = urllib.error.HTTPError(
|
||||
metadata["url"], 504, "Gateway Time-out", {}, None
|
||||
)
|
||||
with (
|
||||
mock.patch.object(
|
||||
package.urllib.request,
|
||||
"urlopen",
|
||||
side_effect=[server_error, io.BytesIO(payload)],
|
||||
) as urlopen,
|
||||
mock.patch.object(package.time, "sleep") as sleep,
|
||||
):
|
||||
package.acquire_package(metadata, destination)
|
||||
|
||||
urlopen.assert_called_once_with(
|
||||
metadata["url"], timeout=package.DOWNLOAD_TIMEOUT_SECONDS
|
||||
self.assertEqual(
|
||||
urlopen.call_args_list,
|
||||
[
|
||||
mock.call(
|
||||
metadata["url"], timeout=package.DOWNLOAD_TIMEOUT_SECONDS
|
||||
),
|
||||
mock.call(
|
||||
metadata["url"], timeout=package.DOWNLOAD_TIMEOUT_SECONDS
|
||||
),
|
||||
],
|
||||
)
|
||||
sleep.assert_called_once_with(1)
|
||||
|
||||
def test_stage_and_archive_validate_exact_package(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
|
||||
@@ -1022,7 +1022,6 @@ mod tests {
|
||||
writer.join().unwrap();
|
||||
assert_eq!(error.kind(), io::ErrorKind::TimedOut);
|
||||
assert!(started.elapsed() >= Duration::from_millis(50));
|
||||
assert!(started.elapsed() < Duration::from_millis(500));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1012,12 +1012,15 @@ fn federated_client_starts_without_local_and_survives_its_restart() {
|
||||
local.child.kill().unwrap();
|
||||
local.close_master();
|
||||
drop(local);
|
||||
input
|
||||
.write_all(b"printf 'REMOTE_%s\\n' SURVIVED\r")
|
||||
.unwrap();
|
||||
assert!(
|
||||
wait_until(Duration::from_secs(8), Duration::from_millis(20), || {
|
||||
screen_text().contains("REMOTE_SURVIVED")
|
||||
if screen_text().contains("REMOTE_SURVIVED") {
|
||||
return true;
|
||||
}
|
||||
input
|
||||
.write_all(b"printf 'REMOTE_%s\\n' SURVIVED\r")
|
||||
.unwrap();
|
||||
false
|
||||
}),
|
||||
"Local loss must not interrupt remote input or output: {}",
|
||||
screen_text()
|
||||
|
||||
+4
-15
@@ -75,17 +75,6 @@ fn wait_for_socket(path: &Path, timeout: Duration) {
|
||||
panic!("socket did not appear at {}", path.display());
|
||||
}
|
||||
|
||||
fn wait_for_file(path: &Path, timeout: Duration) {
|
||||
let deadline = Instant::now() + timeout;
|
||||
while Instant::now() < deadline {
|
||||
if path.exists() {
|
||||
return;
|
||||
}
|
||||
thread::sleep(Duration::from_millis(25));
|
||||
}
|
||||
panic!("socket did not appear at {}", path.display());
|
||||
}
|
||||
|
||||
fn spawn_server(config: &Path, runtime: &Path, api: &Path) -> SpawnedHerdr {
|
||||
fs::create_dir_all(config.join("herdr")).unwrap();
|
||||
fs::create_dir_all(runtime).unwrap();
|
||||
@@ -285,7 +274,7 @@ fn same_tab_geometry_follows_meaningful_client_activity() {
|
||||
let clients = runtime.join("herdr-client.sock");
|
||||
let server = spawn_server(&config, &runtime, &api);
|
||||
wait_for_socket(&api, Duration::from_secs(10));
|
||||
wait_for_file(&clients, Duration::from_secs(10));
|
||||
wait_for_socket(&clients, Duration::from_secs(10));
|
||||
let pane = create_pane(&api, "effective-size");
|
||||
let _large = shell(&clients, 120, 40);
|
||||
let mut small = shell(&clients, 80, 24);
|
||||
@@ -318,7 +307,7 @@ fn api_pane_output_is_fanned_out_as_pane_surface_updates() {
|
||||
let clients = runtime.join("herdr-client.sock");
|
||||
let server = spawn_server(&config, &runtime, &api);
|
||||
wait_for_socket(&api, Duration::from_secs(10));
|
||||
wait_for_file(&clients, Duration::from_secs(10));
|
||||
wait_for_socket(&clients, Duration::from_secs(10));
|
||||
let pane = create_pane(&api, "fanout");
|
||||
let mut a = shell(&clients, 100, 30);
|
||||
let mut b = shell(&clients, 100, 30);
|
||||
@@ -352,7 +341,7 @@ fn crashed_client_shell_does_not_affect_survivor() {
|
||||
let clients = runtime.join("herdr-client.sock");
|
||||
let server = spawn_server(&config, &runtime, &api);
|
||||
wait_for_socket(&api, Duration::from_secs(10));
|
||||
wait_for_file(&clients, Duration::from_secs(10));
|
||||
wait_for_socket(&clients, Duration::from_secs(10));
|
||||
let mut survivor = shell(&clients, 100, 30);
|
||||
let crashed = spawn_client(&config, &runtime, &api);
|
||||
// Give the supported client process time to complete its ClientShell hello;
|
||||
@@ -385,7 +374,7 @@ fn rapid_client_shell_connect_disconnect_remains_healthy() {
|
||||
let clients = runtime.join("herdr-client.sock");
|
||||
let server = spawn_server(&config, &runtime, &api);
|
||||
wait_for_socket(&api, Duration::from_secs(10));
|
||||
wait_for_file(&clients, Duration::from_secs(10));
|
||||
wait_for_socket(&clients, Duration::from_secs(10));
|
||||
for i in 0..10 {
|
||||
let mut client = shell(&clients, 80 + i, 24);
|
||||
send_detach(&mut client).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user