|
|
@ -1,12 +1,12 @@
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::io;
|
|
|
|
use std::io;
|
|
|
|
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
|
|
|
|
use async_trait::async_trait;
|
|
|
|
use async_trait::async_trait;
|
|
|
|
use log::*;
|
|
|
|
use log::*;
|
|
|
|
|
|
|
|
|
|
|
|
use super::super::HeapSecretKey;
|
|
|
|
use crate::authenticator::Authenticator;
|
|
|
|
use super::msg::*;
|
|
|
|
use crate::msg::*;
|
|
|
|
use super::Authenticator;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mod none;
|
|
|
|
mod none;
|
|
|
|
mod static_key;
|
|
|
|
mod static_key;
|
|
|
@ -48,7 +48,10 @@ impl Verifier {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Creates a verifier that uses the [`StaticKeyAuthenticationMethod`] exclusively.
|
|
|
|
/// Creates a verifier that uses the [`StaticKeyAuthenticationMethod`] exclusively.
|
|
|
|
pub fn static_key(key: impl Into<HeapSecretKey>) -> Self {
|
|
|
|
pub fn static_key<K>(key: K) -> Self
|
|
|
|
|
|
|
|
where
|
|
|
|
|
|
|
|
K: FromStr + PartialEq + Send + Sync + 'static,
|
|
|
|
|
|
|
|
{
|
|
|
|
Self::new(vec![
|
|
|
|
Self::new(vec![
|
|
|
|
Box::new(StaticKeyAuthenticationMethod::new(key)) as Box<dyn AuthenticationMethod>
|
|
|
|
Box::new(StaticKeyAuthenticationMethod::new(key)) as Box<dyn AuthenticationMethod>
|
|
|
|
])
|
|
|
|
])
|
|
|
@ -117,10 +120,12 @@ pub trait AuthenticationMethod: Send + Sync {
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
mod tests {
|
|
|
|
|
|
|
|
use std::sync::mpsc;
|
|
|
|
use test_log::test;
|
|
|
|
use test_log::test;
|
|
|
|
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
use super::*;
|
|
|
|
use crate::common::FramedTransport;
|
|
|
|
|
|
|
|
|
|
|
|
use crate::authenticator::TestAuthenticator;
|
|
|
|
|
|
|
|
|
|
|
|
struct SuccessAuthenticationMethod;
|
|
|
|
struct SuccessAuthenticationMethod;
|
|
|
|
|
|
|
|
|
|
|
@ -150,147 +155,131 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[test(tokio::test)]
|
|
|
|
#[test(tokio::test)]
|
|
|
|
async fn verifier_should_fail_to_verify_if_initialization_fails() {
|
|
|
|
async fn verifier_should_fail_to_verify_if_initialization_fails() {
|
|
|
|
let (mut t1, mut t2) = FramedTransport::test_pair(100);
|
|
|
|
let mut authenticator = TestAuthenticator {
|
|
|
|
|
|
|
|
initialize: Box::new(|_| Err(io::Error::from(io::ErrorKind::Other))),
|
|
|
|
// Queue up a response to the initialization request
|
|
|
|
..Default::default()
|
|
|
|
t2.write_frame(b"invalid initialization response")
|
|
|
|
};
|
|
|
|
.await
|
|
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> =
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> =
|
|
|
|
vec![Box::new(SuccessAuthenticationMethod)];
|
|
|
|
vec![Box::new(SuccessAuthenticationMethod)];
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
verifier.verify(&mut t1).await.unwrap_err();
|
|
|
|
verifier.verify(&mut authenticator).await.unwrap_err();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test(tokio::test)]
|
|
|
|
#[test(tokio::test)]
|
|
|
|
async fn verifier_should_fail_to_verify_if_fails_to_send_finished_indicator_after_success() {
|
|
|
|
async fn verifier_should_fail_to_verify_if_fails_to_send_finished_indicator_after_success() {
|
|
|
|
let (mut t1, mut t2) = FramedTransport::test_pair(100);
|
|
|
|
let mut authenticator = TestAuthenticator {
|
|
|
|
|
|
|
|
initialize: Box::new(|_| {
|
|
|
|
// Queue up a response to the initialization request
|
|
|
|
Ok(InitializationResponse {
|
|
|
|
t2.write_frame_for(&AuthenticationResponse::Initialization(
|
|
|
|
methods: vec![SuccessAuthenticationMethod.id().to_string()]
|
|
|
|
InitializationResponse {
|
|
|
|
.into_iter()
|
|
|
|
methods: vec![SuccessAuthenticationMethod.id().to_string()]
|
|
|
|
.collect(),
|
|
|
|
.into_iter()
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
finished: Box::new(|| Err(io::Error::new(io::ErrorKind::Other, "test error"))),
|
|
|
|
))
|
|
|
|
..Default::default()
|
|
|
|
.await
|
|
|
|
};
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Then drop the transport so it cannot receive anything else
|
|
|
|
|
|
|
|
drop(t2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> =
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> =
|
|
|
|
vec![Box::new(SuccessAuthenticationMethod)];
|
|
|
|
vec![Box::new(SuccessAuthenticationMethod)];
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
assert_eq!(
|
|
|
|
|
|
|
|
verifier.verify(&mut t1).await.unwrap_err().kind(),
|
|
|
|
let err = verifier.verify(&mut authenticator).await.unwrap_err();
|
|
|
|
io::ErrorKind::WriteZero
|
|
|
|
assert_eq!(err.kind(), io::ErrorKind::Other);
|
|
|
|
);
|
|
|
|
assert_eq!(err.to_string(), "test error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test(tokio::test)]
|
|
|
|
#[test(tokio::test)]
|
|
|
|
async fn verifier_should_fail_to_verify_if_has_no_authentication_methods() {
|
|
|
|
async fn verifier_should_fail_to_verify_if_has_no_authentication_methods() {
|
|
|
|
let (mut t1, mut t2) = FramedTransport::test_pair(100);
|
|
|
|
let mut authenticator = TestAuthenticator {
|
|
|
|
|
|
|
|
initialize: Box::new(|_| {
|
|
|
|
// Queue up a response to the initialization request
|
|
|
|
Ok(InitializationResponse {
|
|
|
|
t2.write_frame_for(&AuthenticationResponse::Initialization(
|
|
|
|
methods: vec![SuccessAuthenticationMethod.id().to_string()]
|
|
|
|
InitializationResponse {
|
|
|
|
.into_iter()
|
|
|
|
methods: vec![SuccessAuthenticationMethod.id().to_string()]
|
|
|
|
.collect(),
|
|
|
|
.into_iter()
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
))
|
|
|
|
};
|
|
|
|
.await
|
|
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> = vec![];
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> = vec![];
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
verifier.verify(&mut t1).await.unwrap_err();
|
|
|
|
verifier.verify(&mut authenticator).await.unwrap_err();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test(tokio::test)]
|
|
|
|
#[test(tokio::test)]
|
|
|
|
async fn verifier_should_fail_to_verify_if_initialization_yields_no_valid_authentication_methods(
|
|
|
|
async fn verifier_should_fail_to_verify_if_initialization_yields_no_valid_authentication_methods(
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
let (mut t1, mut t2) = FramedTransport::test_pair(100);
|
|
|
|
let mut authenticator = TestAuthenticator {
|
|
|
|
|
|
|
|
initialize: Box::new(|_| {
|
|
|
|
// Queue up a response to the initialization request
|
|
|
|
Ok(InitializationResponse {
|
|
|
|
t2.write_frame_for(&AuthenticationResponse::Initialization(
|
|
|
|
methods: vec!["other".to_string()].into_iter().collect(),
|
|
|
|
InitializationResponse {
|
|
|
|
})
|
|
|
|
methods: vec!["other".to_string()].into_iter().collect(),
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
))
|
|
|
|
};
|
|
|
|
.await
|
|
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> =
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> =
|
|
|
|
vec![Box::new(SuccessAuthenticationMethod)];
|
|
|
|
vec![Box::new(SuccessAuthenticationMethod)];
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
verifier.verify(&mut t1).await.unwrap_err();
|
|
|
|
verifier.verify(&mut authenticator).await.unwrap_err();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test(tokio::test)]
|
|
|
|
#[test(tokio::test)]
|
|
|
|
async fn verifier_should_fail_to_verify_if_no_authentication_method_succeeds() {
|
|
|
|
async fn verifier_should_fail_to_verify_if_no_authentication_method_succeeds() {
|
|
|
|
let (mut t1, mut t2) = FramedTransport::test_pair(100);
|
|
|
|
let mut authenticator = TestAuthenticator {
|
|
|
|
|
|
|
|
initialize: Box::new(|_| {
|
|
|
|
// Queue up a response to the initialization request
|
|
|
|
Ok(InitializationResponse {
|
|
|
|
t2.write_frame_for(&AuthenticationResponse::Initialization(
|
|
|
|
methods: vec![FailAuthenticationMethod.id().to_string()]
|
|
|
|
InitializationResponse {
|
|
|
|
.into_iter()
|
|
|
|
methods: vec![FailAuthenticationMethod.id().to_string()]
|
|
|
|
.collect(),
|
|
|
|
.into_iter()
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
))
|
|
|
|
};
|
|
|
|
.await
|
|
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> = vec![Box::new(FailAuthenticationMethod)];
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> = vec![Box::new(FailAuthenticationMethod)];
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
verifier.verify(&mut t1).await.unwrap_err();
|
|
|
|
verifier.verify(&mut authenticator).await.unwrap_err();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test(tokio::test)]
|
|
|
|
#[test(tokio::test)]
|
|
|
|
async fn verifier_should_return_id_of_authentication_method_upon_success() {
|
|
|
|
async fn verifier_should_return_id_of_authentication_method_upon_success() {
|
|
|
|
let (mut t1, mut t2) = FramedTransport::test_pair(100);
|
|
|
|
let mut authenticator = TestAuthenticator {
|
|
|
|
|
|
|
|
initialize: Box::new(|_| {
|
|
|
|
// Queue up a response to the initialization request
|
|
|
|
Ok(InitializationResponse {
|
|
|
|
t2.write_frame_for(&AuthenticationResponse::Initialization(
|
|
|
|
methods: vec![SuccessAuthenticationMethod.id().to_string()]
|
|
|
|
InitializationResponse {
|
|
|
|
.into_iter()
|
|
|
|
methods: vec![SuccessAuthenticationMethod.id().to_string()]
|
|
|
|
.collect(),
|
|
|
|
.into_iter()
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
))
|
|
|
|
};
|
|
|
|
.await
|
|
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> =
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> =
|
|
|
|
vec![Box::new(SuccessAuthenticationMethod)];
|
|
|
|
vec![Box::new(SuccessAuthenticationMethod)];
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
assert_eq!(
|
|
|
|
assert_eq!(
|
|
|
|
verifier.verify(&mut t1).await.unwrap(),
|
|
|
|
verifier.verify(&mut authenticator).await.unwrap(),
|
|
|
|
SuccessAuthenticationMethod.id()
|
|
|
|
SuccessAuthenticationMethod.id()
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test(tokio::test)]
|
|
|
|
#[test(tokio::test)]
|
|
|
|
async fn verifier_should_try_authentication_methods_in_order_until_one_succeeds() {
|
|
|
|
async fn verifier_should_try_authentication_methods_in_order_until_one_succeeds() {
|
|
|
|
let (mut t1, mut t2) = FramedTransport::test_pair(100);
|
|
|
|
let mut authenticator = TestAuthenticator {
|
|
|
|
|
|
|
|
initialize: Box::new(|_| {
|
|
|
|
// Queue up a response to the initialization request
|
|
|
|
Ok(InitializationResponse {
|
|
|
|
t2.write_frame_for(&AuthenticationResponse::Initialization(
|
|
|
|
methods: vec![
|
|
|
|
InitializationResponse {
|
|
|
|
FailAuthenticationMethod.id().to_string(),
|
|
|
|
methods: vec![
|
|
|
|
SuccessAuthenticationMethod.id().to_string(),
|
|
|
|
FailAuthenticationMethod.id().to_string(),
|
|
|
|
]
|
|
|
|
SuccessAuthenticationMethod.id().to_string(),
|
|
|
|
.into_iter()
|
|
|
|
]
|
|
|
|
.collect(),
|
|
|
|
.into_iter()
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
))
|
|
|
|
};
|
|
|
|
.await
|
|
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> = vec![
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> = vec![
|
|
|
|
Box::new(FailAuthenticationMethod),
|
|
|
|
Box::new(FailAuthenticationMethod),
|
|
|
@ -298,84 +287,79 @@ mod tests {
|
|
|
|
];
|
|
|
|
];
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
let verifier = Verifier::from(methods);
|
|
|
|
assert_eq!(
|
|
|
|
assert_eq!(
|
|
|
|
verifier.verify(&mut t1).await.unwrap(),
|
|
|
|
verifier.verify(&mut authenticator).await.unwrap(),
|
|
|
|
SuccessAuthenticationMethod.id()
|
|
|
|
SuccessAuthenticationMethod.id()
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test(tokio::test)]
|
|
|
|
#[test(tokio::test)]
|
|
|
|
async fn verifier_should_send_start_method_before_attempting_each_method() {
|
|
|
|
async fn verifier_should_send_start_method_before_attempting_each_method() {
|
|
|
|
let (mut t1, mut t2) = FramedTransport::test_pair(100);
|
|
|
|
let (tx, rx) = mpsc::channel();
|
|
|
|
|
|
|
|
|
|
|
|
// Queue up a response to the initialization request
|
|
|
|
let mut authenticator = TestAuthenticator {
|
|
|
|
t2.write_frame_for(&AuthenticationResponse::Initialization(
|
|
|
|
initialize: Box::new(|_| {
|
|
|
|
InitializationResponse {
|
|
|
|
Ok(InitializationResponse {
|
|
|
|
methods: vec![
|
|
|
|
methods: vec![
|
|
|
|
FailAuthenticationMethod.id().to_string(),
|
|
|
|
FailAuthenticationMethod.id().to_string(),
|
|
|
|
SuccessAuthenticationMethod.id().to_string(),
|
|
|
|
SuccessAuthenticationMethod.id().to_string(),
|
|
|
|
]
|
|
|
|
]
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
.collect(),
|
|
|
|
.collect(),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
))
|
|
|
|
}),
|
|
|
|
.await
|
|
|
|
start_method: Box::new(move |method| {
|
|
|
|
.unwrap();
|
|
|
|
tx.send(method.method).unwrap();
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
..Default::default()
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> = vec![
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> = vec![
|
|
|
|
Box::new(FailAuthenticationMethod),
|
|
|
|
Box::new(FailAuthenticationMethod),
|
|
|
|
Box::new(SuccessAuthenticationMethod),
|
|
|
|
Box::new(SuccessAuthenticationMethod),
|
|
|
|
];
|
|
|
|
];
|
|
|
|
Verifier::from(methods).verify(&mut t1).await.unwrap();
|
|
|
|
Verifier::from(methods)
|
|
|
|
|
|
|
|
.verify(&mut authenticator)
|
|
|
|
|
|
|
|
.await
|
|
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
// Check that we get a start method for each of the attempted methods
|
|
|
|
assert_eq!(rx.try_recv().unwrap(), FailAuthenticationMethod.id());
|
|
|
|
match t2.read_frame_as::<Authentication>().await.unwrap().unwrap() {
|
|
|
|
assert_eq!(rx.try_recv().unwrap(), SuccessAuthenticationMethod.id());
|
|
|
|
Authentication::Initialization(_) => (),
|
|
|
|
assert_eq!(rx.try_recv().unwrap_err(), mpsc::TryRecvError::Empty);
|
|
|
|
x => panic!("Unexpected response: {x:?}"),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
match t2.read_frame_as::<Authentication>().await.unwrap().unwrap() {
|
|
|
|
|
|
|
|
Authentication::StartMethod(x) => assert_eq!(x.method, FailAuthenticationMethod.id()),
|
|
|
|
|
|
|
|
x => panic!("Unexpected response: {x:?}"),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
match t2.read_frame_as::<Authentication>().await.unwrap().unwrap() {
|
|
|
|
|
|
|
|
Authentication::StartMethod(x) => {
|
|
|
|
|
|
|
|
assert_eq!(x.method, SuccessAuthenticationMethod.id())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
x => panic!("Unexpected response: {x:?}"),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test(tokio::test)]
|
|
|
|
#[test(tokio::test)]
|
|
|
|
async fn verifier_should_send_finished_when_a_method_succeeds() {
|
|
|
|
async fn verifier_should_send_finished_when_a_method_succeeds() {
|
|
|
|
let (mut t1, mut t2) = FramedTransport::test_pair(100);
|
|
|
|
let (tx, rx) = mpsc::channel();
|
|
|
|
|
|
|
|
|
|
|
|
// Queue up a response to the initialization request
|
|
|
|
let mut authenticator = TestAuthenticator {
|
|
|
|
t2.write_frame_for(&AuthenticationResponse::Initialization(
|
|
|
|
initialize: Box::new(|_| {
|
|
|
|
InitializationResponse {
|
|
|
|
Ok(InitializationResponse {
|
|
|
|
methods: vec![
|
|
|
|
methods: vec![
|
|
|
|
FailAuthenticationMethod.id().to_string(),
|
|
|
|
FailAuthenticationMethod.id().to_string(),
|
|
|
|
SuccessAuthenticationMethod.id().to_string(),
|
|
|
|
SuccessAuthenticationMethod.id().to_string(),
|
|
|
|
]
|
|
|
|
]
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
.collect(),
|
|
|
|
.collect(),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
))
|
|
|
|
}),
|
|
|
|
.await
|
|
|
|
finished: Box::new(move || {
|
|
|
|
.unwrap();
|
|
|
|
tx.send(()).unwrap();
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
..Default::default()
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> = vec![
|
|
|
|
let methods: Vec<Box<dyn AuthenticationMethod>> = vec![
|
|
|
|
Box::new(FailAuthenticationMethod),
|
|
|
|
Box::new(FailAuthenticationMethod),
|
|
|
|
Box::new(SuccessAuthenticationMethod),
|
|
|
|
Box::new(SuccessAuthenticationMethod),
|
|
|
|
];
|
|
|
|
];
|
|
|
|
Verifier::from(methods).verify(&mut t1).await.unwrap();
|
|
|
|
Verifier::from(methods)
|
|
|
|
|
|
|
|
.verify(&mut authenticator)
|
|
|
|
// Clear out the initialization and start methods
|
|
|
|
.await
|
|
|
|
t2.read_frame_as::<Authentication>().await.unwrap().unwrap();
|
|
|
|
.unwrap();
|
|
|
|
t2.read_frame_as::<Authentication>().await.unwrap().unwrap();
|
|
|
|
|
|
|
|
t2.read_frame_as::<Authentication>().await.unwrap().unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match t2.read_frame_as::<Authentication>().await.unwrap().unwrap() {
|
|
|
|
rx.try_recv().unwrap();
|
|
|
|
Authentication::Finished => (),
|
|
|
|
assert_eq!(rx.try_recv().unwrap_err(), mpsc::TryRecvError::Empty);
|
|
|
|
x => panic!("Unexpected response: {x:?}"),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|