2020-12-05 08:07:04 +01:00
|
|
|
use std::net::TcpStream;
|
|
|
|
use std::sync::atomic::{AtomicU16, Ordering};
|
2020-04-30 16:54:46 +02:00
|
|
|
use std::thread;
|
|
|
|
|
2020-06-18 02:30:42 +02:00
|
|
|
use kanidm::audit::LogLevel;
|
2020-04-30 16:54:46 +02:00
|
|
|
use kanidm::config::{Configuration, IntegrationTestConfig};
|
|
|
|
use kanidm::core::create_server_core;
|
|
|
|
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
use async_std::task;
|
|
|
|
use tokio::sync::mpsc;
|
2020-04-30 16:54:46 +02:00
|
|
|
|
|
|
|
pub const ADMIN_TEST_PASSWORD: &str = "integration test admin password";
|
2020-12-08 02:06:13 +01:00
|
|
|
static PORT_ALLOC: AtomicU16 = AtomicU16::new(18080);
|
2020-12-05 08:07:04 +01:00
|
|
|
|
|
|
|
fn is_free_port(port: u16) -> bool {
|
|
|
|
match TcpStream::connect(("0.0.0.0", port)) {
|
|
|
|
Ok(_) => false,
|
|
|
|
Err(_) => true,
|
|
|
|
}
|
|
|
|
}
|
2020-04-30 16:54:46 +02:00
|
|
|
|
|
|
|
// Test external behaviours of the service.
|
|
|
|
|
|
|
|
pub fn run_test(test_fn: fn(KanidmClient) -> ()) {
|
2020-12-02 02:12:07 +01:00
|
|
|
// ::std::env::set_var("RUST_LOG", "tide=debug,kanidm=debug");
|
2020-06-05 06:01:20 +02:00
|
|
|
let _ = env_logger::builder()
|
|
|
|
.format_timestamp(None)
|
|
|
|
.format_level(false)
|
|
|
|
.is_test(true)
|
|
|
|
.try_init();
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
let (mut ready_tx, mut ready_rx) = mpsc::channel(1);
|
|
|
|
let (mut finish_tx, mut finish_rx) = mpsc::channel(1);
|
|
|
|
|
2020-12-08 02:06:13 +01:00
|
|
|
let mut counter = 0;
|
2020-12-05 08:07:04 +01:00
|
|
|
let port = loop {
|
|
|
|
let possible_port = PORT_ALLOC.fetch_add(1, Ordering::SeqCst);
|
|
|
|
if is_free_port(possible_port) {
|
|
|
|
break possible_port;
|
|
|
|
}
|
2020-12-08 02:06:13 +01:00
|
|
|
counter += 1;
|
|
|
|
if counter >= 5 {
|
|
|
|
eprintln!("Unable to allocate port!");
|
|
|
|
assert!(false);
|
|
|
|
}
|
2020-12-05 08:07:04 +01:00
|
|
|
};
|
2020-04-30 16:54:46 +02:00
|
|
|
|
|
|
|
let int_config = Box::new(IntegrationTestConfig {
|
|
|
|
admin_password: ADMIN_TEST_PASSWORD.to_string(),
|
|
|
|
});
|
|
|
|
|
2020-06-10 04:07:43 +02:00
|
|
|
// Setup the config ...
|
2020-04-30 16:54:46 +02:00
|
|
|
let mut config = Configuration::new();
|
|
|
|
config.address = format!("127.0.0.1:{}", port);
|
|
|
|
config.secure_cookies = false;
|
|
|
|
config.integration_test_config = Some(int_config);
|
2020-06-18 02:30:42 +02:00
|
|
|
config.log_level = Some(LogLevel::Quiet as u32);
|
2020-12-02 02:12:07 +01:00
|
|
|
// config.log_level = Some(LogLevel::Verbose as u32);
|
2020-09-06 00:44:35 +02:00
|
|
|
config.threads = 1;
|
|
|
|
|
2020-06-24 13:17:46 +02:00
|
|
|
// config.log_level = Some(LogLevel::FullTrace as u32);
|
2020-09-06 00:44:35 +02:00
|
|
|
let t_handle = thread::spawn(move || {
|
2020-04-30 16:54:46 +02:00
|
|
|
// Spawn a thread for the test runner, this should have a unique
|
|
|
|
// port....
|
2020-09-06 00:44:35 +02:00
|
|
|
let mut rt = tokio::runtime::Builder::new()
|
|
|
|
.basic_scheduler()
|
|
|
|
.enable_all()
|
|
|
|
.build()
|
|
|
|
.expect("failed to start tokio");
|
|
|
|
rt.block_on(async {
|
|
|
|
create_server_core(config)
|
|
|
|
.await
|
|
|
|
.expect("failed to start server core");
|
|
|
|
// We have to yield now to guarantee that the tide elements are setup.
|
|
|
|
task::yield_now().await;
|
|
|
|
ready_tx
|
|
|
|
.send(())
|
|
|
|
.await
|
|
|
|
.expect("failed in indicate readiness");
|
|
|
|
finish_rx.recv().await;
|
|
|
|
});
|
2020-04-30 16:54:46 +02:00
|
|
|
});
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
let _ = task::block_on(ready_rx.recv()).expect("failed to start ctx");
|
2020-04-30 16:54:46 +02:00
|
|
|
// Do we need any fixtures?
|
|
|
|
// Yes probably, but they'll need to be futures as well ...
|
|
|
|
// later we could accept fixture as it's own future for re-use
|
|
|
|
|
|
|
|
// Setup the client, and the address we selected.
|
|
|
|
let addr = format!("http://127.0.0.1:{}", port);
|
|
|
|
let rsclient = KanidmClientBuilder::new()
|
|
|
|
.address(addr)
|
|
|
|
.build()
|
|
|
|
.expect("Failed to build client");
|
|
|
|
|
|
|
|
test_fn(rsclient);
|
|
|
|
|
|
|
|
// We DO NOT need teardown, as sqlite is in mem
|
|
|
|
// let the tables hit the floor
|
2020-09-06 00:44:35 +02:00
|
|
|
|
|
|
|
// At this point, when the channel drops, it drops the thread too.
|
|
|
|
task::block_on(finish_tx.send(())).expect("unable to send to ctx");
|
|
|
|
t_handle.join().expect("failed to join thread");
|
2020-04-30 16:54:46 +02:00
|
|
|
}
|