Skip to content

Commit a15435c

Browse files
authored
Merge pull request #2352 from input-output-hk/sfa/fix_flakiness_on_should_delay_between_retries_tests
Remove flakiness on should delay between retries tests
2 parents 971b382 + 4669759 commit a15435c

File tree

5 files changed

+94
-57
lines changed

5 files changed

+94
-57
lines changed

Cargo.lock

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

mithril-aggregator/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-aggregator"
3-
version = "0.7.11"
3+
version = "0.7.12"
44
description = "A Mithril Aggregator server"
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-aggregator/src/file_uploaders/interface.rs

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub trait FileUploader: Sync + Send {
6767

6868
#[cfg(test)]
6969
mod tests {
70-
use std::{path::PathBuf, time::Instant};
70+
use std::{path::PathBuf, sync::Mutex, time::Instant};
7171

7272
use super::*;
7373
use anyhow::anyhow;
@@ -172,39 +172,53 @@ mod tests {
172172

173173
#[tokio::test]
174174
async fn should_delay_between_retries() {
175-
let mut uploader = MockTestFileUploader::new();
175+
struct FileUploaderAssertDelay {
176+
delay_ms: u64,
177+
last_attempt_start_time: Mutex<Option<Instant>>,
178+
}
176179

177-
let delay = Duration::from_millis(50);
178-
uploader
179-
.expect_retry_policy()
180-
.returning(move || FileUploadRetryPolicy {
181-
attempts: 4,
182-
delay_between_attempts: delay,
183-
});
180+
#[async_trait]
181+
impl FileUploader for FileUploaderAssertDelay {
182+
async fn upload_without_retry(&self, _filepath: &Path) -> StdResult<FileUri> {
183+
let mut last_attempt_start_time = self.last_attempt_start_time.lock().unwrap();
184+
if let Some(last_start_attempt) = *last_attempt_start_time {
185+
let duration = last_start_attempt.elapsed();
186+
let expected_delay_greater_than_or_equal = Duration::from_millis(self.delay_ms);
187+
assert!(
188+
duration >= expected_delay_greater_than_or_equal,
189+
"duration should be greater than or equal to {}ms but was {}ms",
190+
expected_delay_greater_than_or_equal.as_millis(),
191+
duration.as_millis()
192+
);
193+
let expected_delay_less_than = Duration::from_millis(2 * self.delay_ms);
194+
assert!(
195+
duration < expected_delay_less_than,
196+
"duration should be less than {}ms but was {}ms",
197+
expected_delay_less_than.as_millis(),
198+
duration.as_millis()
199+
);
200+
}
201+
*last_attempt_start_time = Some(Instant::now());
184202

185-
uploader
186-
.expect_upload_without_retry()
187-
.times(4)
188-
.returning(move |_| Err(anyhow!("Failure while uploading...")));
203+
Err(anyhow::anyhow!("Upload failed"))
204+
}
205+
206+
fn retry_policy(&self) -> FileUploadRetryPolicy {
207+
FileUploadRetryPolicy {
208+
attempts: 4,
209+
delay_between_attempts: Duration::from_millis(self.delay_ms),
210+
}
211+
}
212+
}
213+
214+
let uploader = FileUploaderAssertDelay {
215+
delay_ms: 50,
216+
last_attempt_start_time: Mutex::new(None),
217+
};
189218

190-
let start = Instant::now();
191219
uploader
192220
.upload(&PathBuf::from("file_to_upload"))
193221
.await
194222
.expect_err("An error should be returned when all retries are done");
195-
let duration = start.elapsed();
196-
197-
assert!(
198-
duration >= delay * 3,
199-
"Duration should be at least 3 times the delay ({}ms) but was {}ms",
200-
delay.as_millis() * 3,
201-
duration.as_millis()
202-
);
203-
assert!(
204-
duration < delay * 4,
205-
"Duration should be less than 4 times the delay ({}ms) but was {}ms",
206-
delay.as_millis() * 4,
207-
duration.as_millis()
208-
);
209223
}
210224
}

mithril-client/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-client"
3-
version = "0.11.11"
3+
version = "0.11.12"
44
description = "Mithril client library"
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-client/src/file_downloader/retry.rs

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl FileDownloader for RetryDownloader {
9797
#[cfg(test)]
9898
mod tests {
9999

100-
use std::time::Instant;
100+
use std::{sync::Mutex, time::Instant};
101101

102102
use mithril_common::entities::FileUri;
103103

@@ -227,22 +227,59 @@ mod tests {
227227

228228
#[tokio::test]
229229
async fn should_delay_between_retries() {
230-
let mock_file_downloader = MockFileDownloaderBuilder::default()
231-
.with_file_uri("http://whatever/00001.tar.gz")
232-
.with_compression(None)
233-
.with_failure()
234-
.with_times(4)
235-
.build();
236-
let delay = Duration::from_millis(50);
230+
struct FileDownloaderAssertDelay {
231+
expected_delay_greater_than_or_equal: Duration,
232+
expected_delay_less_than: Duration,
233+
last_attempt_start_time: Mutex<Option<Instant>>,
234+
}
235+
236+
#[async_trait]
237+
impl FileDownloader for FileDownloaderAssertDelay {
238+
async fn download_unpack(
239+
&self,
240+
_location: &FileDownloaderUri,
241+
_file_size: u64,
242+
_target_dir: &Path,
243+
_compression_algorithm: Option<CompressionAlgorithm>,
244+
_download_event_type: DownloadEvent,
245+
) -> StdResult<()> {
246+
let mut last_attempt_start_time = self.last_attempt_start_time.lock().unwrap();
247+
if let Some(last_start_attempt) = *last_attempt_start_time {
248+
let duration = last_start_attempt.elapsed();
249+
assert!(
250+
duration >= self.expected_delay_greater_than_or_equal,
251+
"duration should be greater than or equal to {}ms but was {}ms",
252+
self.expected_delay_greater_than_or_equal.as_millis(),
253+
duration.as_millis()
254+
);
255+
assert!(
256+
duration < self.expected_delay_less_than,
257+
"duration should be less than {}ms but was {}ms",
258+
self.expected_delay_less_than.as_millis(),
259+
duration.as_millis()
260+
);
261+
}
262+
*last_attempt_start_time = Some(Instant::now());
263+
264+
Err(anyhow::anyhow!("Download failed"))
265+
}
266+
}
267+
268+
let delay_ms = 50;
269+
let mock_file_downloader = Arc::new(FileDownloaderAssertDelay {
270+
expected_delay_greater_than_or_equal: Duration::from_millis(delay_ms),
271+
expected_delay_less_than: Duration::from_millis(2 * delay_ms),
272+
last_attempt_start_time: Mutex::new(None),
273+
});
274+
237275
let retry_downloader = RetryDownloader::new(
238-
Arc::new(mock_file_downloader),
276+
mock_file_downloader.clone(),
239277
FileDownloadRetryPolicy {
240278
attempts: 4,
241-
delay_between_attempts: delay,
279+
delay_between_attempts: Duration::from_millis(delay_ms),
242280
},
243281
);
244282

245-
let start = Instant::now();
246283
retry_downloader
247284
.download_unpack(
248285
&FileDownloaderUri::FileUri(FileUri("http://whatever/00001.tar.gz".to_string())),
@@ -256,19 +293,5 @@ mod tests {
256293
)
257294
.await
258295
.expect_err("An error should be returned when all download attempts fail");
259-
let duration = start.elapsed();
260-
261-
assert!(
262-
duration >= delay * 3,
263-
"Duration should be at least 3 times the delay ({}ms) but was {}ms",
264-
delay.as_millis() * 3,
265-
duration.as_millis()
266-
);
267-
assert!(
268-
duration < delay * 4,
269-
"Duration should be less than 4 times the delay ({}ms) but was {}ms",
270-
delay.as_millis() * 4,
271-
duration.as_millis()
272-
);
273296
}
274297
}

0 commit comments

Comments
 (0)