mirror of https://github.com/chipsenkbeil/distant
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
5.2 KiB
Rust
170 lines
5.2 KiB
Rust
use distant_net::{
|
|
AuthClient, AuthErrorKind, AuthQuestion, AuthRequest, AuthServer, AuthVerifyKind, Client,
|
|
IntoSplit, MpscListener, MpscTransport, ServerExt,
|
|
};
|
|
use std::collections::HashMap;
|
|
use tokio::sync::mpsc;
|
|
|
|
/// Spawns a server and client connected together, returning the client
|
|
fn setup() -> (AuthClient, mpsc::Receiver<AuthRequest>) {
|
|
// Make a pair of inmemory transports that we can use to test client and server connected
|
|
let (t1, t2) = MpscTransport::pair(100);
|
|
|
|
// Create the client
|
|
let (writer, reader) = t1.into_split();
|
|
let client = AuthClient::from(Client::new(writer, reader).unwrap());
|
|
|
|
// Prepare a channel where we can pass back out whatever request we get
|
|
let (tx, rx) = mpsc::channel(100);
|
|
|
|
let tx_2 = tx.clone();
|
|
let tx_3 = tx.clone();
|
|
let tx_4 = tx.clone();
|
|
|
|
// Make a server that echos questions back as answers and only verifies the text "yes"
|
|
let server = AuthServer {
|
|
on_challenge: move |questions, options| {
|
|
let questions_2 = questions.clone();
|
|
tx.try_send(AuthRequest::Challenge { questions, options })
|
|
.unwrap();
|
|
questions_2.into_iter().map(|x| x.text).collect()
|
|
},
|
|
on_verify: move |kind, text| {
|
|
let valid = text == "yes";
|
|
tx_2.try_send(AuthRequest::Verify { kind, text }).unwrap();
|
|
valid
|
|
},
|
|
on_info: move |text| {
|
|
tx_3.try_send(AuthRequest::Info { text }).unwrap();
|
|
},
|
|
on_error: move |kind, text| {
|
|
tx_4.try_send(AuthRequest::Error { kind, text }).unwrap();
|
|
},
|
|
};
|
|
|
|
// Spawn the server to listen for our client to connect
|
|
tokio::spawn(async move {
|
|
let (writer, reader) = t2.into_split();
|
|
let (tx, listener) = MpscListener::channel(1);
|
|
tx.send((writer, reader)).await.unwrap();
|
|
let _server = server.start(listener).unwrap();
|
|
});
|
|
|
|
(client, rx)
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn client_should_be_able_to_challenge_against_server() {
|
|
let (mut client, mut rx) = setup();
|
|
|
|
// Gotta start with the handshake first
|
|
client.handshake().await.unwrap();
|
|
|
|
// Now do the challenge
|
|
assert_eq!(
|
|
client
|
|
.challenge(
|
|
vec![AuthQuestion::new("hello".to_string())],
|
|
Default::default()
|
|
)
|
|
.await
|
|
.unwrap(),
|
|
vec!["hello".to_string()]
|
|
);
|
|
|
|
// Verify that the server received the request
|
|
let request = rx.recv().await.unwrap();
|
|
match request {
|
|
AuthRequest::Challenge { questions, options } => {
|
|
assert_eq!(questions.len(), 1);
|
|
assert_eq!(questions[0].text, "hello");
|
|
assert_eq!(questions[0].options, HashMap::new());
|
|
|
|
assert_eq!(options, HashMap::new());
|
|
}
|
|
x => panic!("Unexpected request received by server: {:?}", x),
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn client_should_be_able_to_verify_against_server() {
|
|
let (mut client, mut rx) = setup();
|
|
|
|
// Gotta start with the handshake first
|
|
client.handshake().await.unwrap();
|
|
|
|
// "no" will yield false
|
|
assert!(!client
|
|
.verify(AuthVerifyKind::Host, "no".to_string())
|
|
.await
|
|
.unwrap());
|
|
|
|
// Verify that the server received the request
|
|
let request = rx.recv().await.unwrap();
|
|
match request {
|
|
AuthRequest::Verify { kind, text } => {
|
|
assert_eq!(kind, AuthVerifyKind::Host);
|
|
assert_eq!(text, "no");
|
|
}
|
|
x => panic!("Unexpected request received by server: {:?}", x),
|
|
}
|
|
|
|
// "yes" will yield true
|
|
assert!(client
|
|
.verify(AuthVerifyKind::Host, "yes".to_string())
|
|
.await
|
|
.unwrap());
|
|
|
|
// Verify that the server received the request
|
|
let request = rx.recv().await.unwrap();
|
|
match request {
|
|
AuthRequest::Verify { kind, text } => {
|
|
assert_eq!(kind, AuthVerifyKind::Host);
|
|
assert_eq!(text, "yes");
|
|
}
|
|
x => panic!("Unexpected request received by server: {:?}", x),
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn client_should_be_able_to_send_info_to_server() {
|
|
let (mut client, mut rx) = setup();
|
|
|
|
// Gotta start with the handshake first
|
|
client.handshake().await.unwrap();
|
|
|
|
// Send some information
|
|
client.info(String::from("hello, world")).await.unwrap();
|
|
|
|
// Verify that the server received the request
|
|
let request = rx.recv().await.unwrap();
|
|
match request {
|
|
AuthRequest::Info { text } => assert_eq!(text, "hello, world"),
|
|
x => panic!("Unexpected request received by server: {:?}", x),
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn client_should_be_able_to_send_error_to_server() {
|
|
let (mut client, mut rx) = setup();
|
|
|
|
// Gotta start with the handshake first
|
|
client.handshake().await.unwrap();
|
|
|
|
// Send some error
|
|
client
|
|
.error(AuthErrorKind::Unknown, String::from("hello, world"))
|
|
.await
|
|
.unwrap();
|
|
|
|
// Verify that the server received the request
|
|
let request = rx.recv().await.unwrap();
|
|
match request {
|
|
AuthRequest::Error { kind, text } => {
|
|
assert_eq!(kind, AuthErrorKind::Unknown);
|
|
assert_eq!(text, "hello, world");
|
|
}
|
|
x => panic!("Unexpected request received by server: {:?}", x),
|
|
}
|
|
}
|