use std::sync::Mutex;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
use std::time::Instant;
use tempfile::tempdir;
use super::ID;
use super::SHA;
use super::config;
use super::hub;
use super::server::Server;
use crate::hub::download::fetch;
use crate::registry::WeightsFormat;
#[test]
fn a_second_fetch_waits_for_the_first_and_downloads_nothing() {
let (open, gate) = mpsc::channel::<()>();
let gate = Mutex::new(gate);
let weights = format!("GET /{ID}/resolve/{SHA}/model.safetensors");
let held = weights.clone();
let server = Server::start(move |method, path| {
if format!("{method} {path}") == held {
let _ = gate.lock().unwrap().recv();
}
hub(method, path)
});
let cache = tempdir().unwrap();
let config = config(cache.path(), &server.url);
let fetch = || fetch(&config, ID, "main", WeightsFormat::Safetensors).unwrap();
thread::scope(|scope| {
let first = scope.spawn(fetch);
let deadline = Instant::now() + Duration::from_secs(20);
while !server.requests().contains(&weights) {
assert!(Instant::now() < deadline, "{:?}", server.requests());
thread::sleep(Duration::from_millis(10));
}
let seen = server.requests().len();
let second = scope.spawn(fetch);
thread::sleep(Duration::from_millis(500));
assert_eq!(server.requests().len(), seen, "the second fetch went ahead");
drop(open);
assert_eq!(first.join().unwrap(), second.join().unwrap());
});
let gets = server.requests().iter().filter(|r| **r == weights).count();
assert_eq!(gets, 1, "{:?}", server.requests());
}