Skip to content

Commit 191a553

Browse files
committed
Treat timeouts as nonexistence (fix #86)
1 parent a120f6e commit 191a553

10 files changed

Lines changed: 88 additions & 40 deletions

File tree

fixtures/timeout/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fixtures/timeout/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "timeout"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# smoelius: https://stackoverflow.com/a/56459603
7+
repository = "https://httpstat.us/200?sleep=300000" # 5 minutes
8+
9+
[workspace]

fixtures/timeout/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

src/curl.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
use super::RepoStatus;
22
use anyhow::{anyhow, Result};
33
use curl::easy::Easy;
4+
use std::time::Duration;
5+
6+
const TIMEOUT: u64 = 10; // seconds
47

58
pub(crate) fn existence(url: &str) -> Result<RepoStatus<()>> {
69
let mut handle = Easy::new();
710
handle.url(url)?;
811
handle.follow_location(true)?;
9-
handle.transfer().perform()?;
10-
let response_code = handle.response_code()?;
11-
match response_code {
12-
200 => Ok(RepoStatus::Success(url, ())),
13-
404 => Ok(RepoStatus::Nonexistent(url)),
14-
_ => Err(anyhow!("unexpected response code: {response_code}")),
12+
handle.timeout(Duration::from_secs(TIMEOUT))?;
13+
let result = handle.transfer().perform();
14+
match result.and_then(|()| handle.response_code()) {
15+
Ok(200) => Ok(RepoStatus::Success(url, ())),
16+
Ok(404) => Ok(RepoStatus::Nonexistent(url)),
17+
Err(err) if err.is_operation_timedout() => Ok(RepoStatus::Nonexistent(url)),
18+
Ok(response_code) => Err(anyhow!("unexpected response code: {response_code}")),
19+
Err(err) => Err(err.into()),
1520
}
1621
}

tests/cases/timeout.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
path = "fixtures/timeout"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Scanning 1 packages and their dependencies (pass --verbose for more information)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
timeout (https://httpstat.us/200?sleep=300000 does not exist)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Scanning 1 packages and their dependencies (pass --verbose for more information)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
timeout (https://httpstat.us/200?sleep=300000 does not exist)

tests/snapbox.rs

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,24 @@ use snapbox::{
1111
cmd::{cargo_bin, Command as SnapboxCommand},
1212
};
1313
use std::{
14+
env::var,
1415
ffi::OsStr,
1516
fs::{read_dir, read_to_string},
17+
path::{Path, PathBuf},
1618
process::Command,
1719
};
18-
use tempfile::tempdir;
1920

2021
mod util;
2122
use util::{enabled, tee, token_modifier, Tee};
2223

2324
#[derive(Deserialize)]
2425
#[serde(deny_unknown_fields)]
2526
struct Test {
26-
/// Repo url
27-
url: String,
27+
/// Repo path (cannot be used in conjunction with `url`)
28+
path: Option<String>,
29+
30+
/// Repo url (cannot be used in conjunction with `path`)
31+
url: Option<String>,
2832

2933
/// Repo revision; `None` (the default) means the head of the default branch
3034
#[serde(default)]
@@ -33,16 +37,22 @@ struct Test {
3337

3438
#[test]
3539
fn snapbox() -> Result<()> {
36-
let mut read_dir = read_dir("tests/cases")?;
37-
38-
let test_paths = read_dir.try_fold(Vec::new(), |mut url_paths, entry| {
39-
let entry = entry?;
40-
let path = entry.path();
41-
if path.extension() == Some(OsStr::new("toml")) {
42-
url_paths.push(path);
43-
}
44-
Result::<_>::Ok(url_paths)
45-
})?;
40+
let test_cases = Path::new("tests/cases");
41+
42+
let test_paths = if let Ok(testcase) = var("TESTCASE") {
43+
vec![test_cases.join(testcase).with_extension("toml")]
44+
} else {
45+
let mut read_dir = read_dir(test_cases)?;
46+
47+
read_dir.try_fold(Vec::new(), |mut url_paths, entry| {
48+
let entry = entry?;
49+
let path = entry.path();
50+
if path.extension() == Some(OsStr::new("toml")) {
51+
url_paths.push(path);
52+
}
53+
Result::<_>::Ok(url_paths)
54+
})?
55+
};
4656

4757
test_paths
4858
.into_par_iter()
@@ -55,32 +65,43 @@ fn snapbox() -> Result<()> {
5565

5666
let test: Test = toml::from_str(&raw).unwrap();
5767

58-
let tempdir = tempdir()?;
59-
60-
let mut command = SnapboxCommand::new("git").args([
61-
"clone",
62-
&test.url,
63-
&tempdir.path().to_string_lossy(),
64-
]);
65-
if test.rev.is_none() {
66-
command = command.arg("--depth=1");
67-
}
68-
command.assert().success();
69-
70-
if let Some(rev) = &test.rev {
71-
SnapboxCommand::new("git")
72-
.args(["checkout", rev])
73-
.current_dir(&tempdir)
74-
.assert()
75-
.success();
76-
}
68+
let tempdir;
69+
let dir = match (test.path, test.url) {
70+
(Some(path), None) => PathBuf::from(path),
71+
(None, Some(url)) => {
72+
tempdir = tempfile::tempdir()?;
73+
74+
let mut command = SnapboxCommand::new("git").args([
75+
"clone",
76+
&url,
77+
&tempdir.path().to_string_lossy(),
78+
]);
79+
if test.rev.is_none() {
80+
command = command.arg("--depth=1");
81+
}
82+
command.assert().success();
83+
84+
if let Some(rev) = &test.rev {
85+
SnapboxCommand::new("git")
86+
.args(["checkout", rev])
87+
.current_dir(&tempdir)
88+
.assert()
89+
.success();
90+
}
91+
tempdir.path().to_owned()
92+
}
93+
(_, _) => {
94+
panic!("exactly one of `path` and `url` must be set");
95+
}
96+
};
7797

78-
assert!(tempdir.path().join("Cargo.lock").exists());
98+
let path = dir.join("Cargo.lock");
99+
assert!(path.exists(), "{path:?} does not exist");
79100

80101
let mut command = Command::new(cargo_bin("cargo-unmaintained"));
81102
command
82103
.args(["unmaintained", "--color=never", "--imprecise"])
83-
.current_dir(&tempdir);
104+
.current_dir(dir);
84105

85106
if enabled("VERBOSE") {
86107
// smoelius If `VERBOSE` is enabled, don't bother comparing stderr, because it won't

0 commit comments

Comments
 (0)