use super::super::fixture::{Fixture, NOW, Result};
use super::StartIssue;
use crate::link::LinkAction;
use std::sync::atomic::Ordering;
fn issued(issue: std::thread::JoinHandle<()>) -> Result {
issue.join().map_err(|_| "the pass issue panicked")?;
Ok(())
}
#[test]
fn the_start_issue_holds_the_pass_and_the_first_open_asks_nothing() -> Result {
let fixture = Fixture::unissued(false)?;
issued(StartIssue::new(fixture.authority.clone(), NOW).begin()?)?;
assert_eq!(fixture.calls.load(Ordering::Relaxed), 1);
let opened = fixture
.session()?
.open_link(&Fixture::link(), LinkAction::Export, NOW);
assert!(opened.is_ok(), "the open after the issue was refused");
assert_eq!(
fixture.calls.load(Ordering::Relaxed),
1,
"the open asked for a pass already held"
);
fixture.finish()
}
#[test]
fn an_open_during_the_start_issue_waits_for_it_and_is_served_by_it() -> Result {
let (fixture, hold) = Fixture::unissued_held()?;
let issue = StartIssue::new(fixture.authority.clone(), NOW).begin()?;
hold.entered.recv()?;
let session = fixture.session()?;
let open = std::thread::spawn(move || {
session
.open_link(&Fixture::link(), LinkAction::Export, NOW)
.is_ok()
});
hold.release.send(())?;
issued(issue)?;
assert!(
open.join().map_err(|_| "the open panicked")?,
"the open that came during the issue was refused"
);
assert_eq!(
fixture.calls.load(Ordering::Relaxed),
1,
"the waiting open asked again"
);
fixture.finish()
}
#[test]
fn a_refused_start_issue_holds_nothing_and_the_next_open_asks_again() -> Result {
let fixture = Fixture::unissued(true)?;
issued(StartIssue::new(fixture.authority.clone(), NOW).begin()?)?;
assert!(
fixture.authority.pass.current()?.is_empty(),
"a refused issue left a pass held"
);
let opened = fixture
.authority
.open(&Fixture::link(), LinkAction::Export, NOW);
assert!(opened.is_err(), "an open with no pass was admitted");
assert_eq!(fixture.calls.load(Ordering::Relaxed), 2);
fixture.finish()
}