use ::cache::disk::DiskCache;
use ::client::{
connect_to_server,
};
use ::commands::{
do_compile,
request_shutdown,
request_stats,
};
use env_logger;
use mio::Sender;
use ::mock_command::*;
use ::server::{
ServerMessage,
create_server,
run_server,
};
use std::boxed::Box;
use std::fs::File;
use std::io::{
Cursor,
Write,
};
use std::path::Path;
use std::sync::{Arc,Mutex,mpsc};
use std::thread;
use test::utils::*;
#[derive(Default)]
struct ServerOptions {
idle_timeout: Option<u64>,
}
fn run_server_thread<T: Into<Option<ServerOptions>> + Send + 'static>(cache_dir: &Path, options: T) -> (u16, Sender<ServerMessage>, Arc<Mutex<MockCommandCreator>>, thread::JoinHandle<()>) {
let (tx, rx) = mpsc::channel();
let storage = Box::new(DiskCache::new(&cache_dir));
let handle = thread::spawn(move || {
let (mut server, event_loop) = create_server::<Arc<Mutex<MockCommandCreator>>>(0, storage).unwrap();
assert!(server.port() > 0);
let options = options.into();
if let Some(options) = options {
if let Some(timeout) = options.idle_timeout {
server.set_idle_timeout(timeout);
}
}
let port = server.port();
let sender = event_loop.channel();
let creator = server.command_creator();
tx.send((port, sender, creator)).unwrap();
run_server(server, event_loop).unwrap()
});
let (port, sender, creator) = rx.recv().unwrap();
(port, sender, creator, handle)
}
#[test]
fn test_server_shutdown() {
let f = TestFixture::new();
let (port, _, _, child) = run_server_thread(&f.tempdir.path(), None);
let conn = connect_to_server(port).unwrap();
request_shutdown(conn).unwrap();
child.join().unwrap();
}
#[test]
fn test_server_idle_timeout() {
let f = TestFixture::new();
let (_, _, _, child) = run_server_thread(&f.tempdir.path(), ServerOptions { idle_timeout: Some(1)});
child.join().unwrap();
}
#[test]
fn test_server_stats() {
let f = TestFixture::new();
let (port, sender, _, child) = run_server_thread(&f.tempdir.path(), None);
let conn = connect_to_server(port).unwrap();
let stats = cache_stats_map(request_stats(conn).unwrap());
assert_eq!(&CacheStat::Count(0), stats.get("Compile requests").unwrap());
sender.send(ServerMessage::Shutdown).unwrap();
child.join().unwrap();
}
#[test]
fn test_server_unsupported_compiler() {
let f = TestFixture::new();
let (port, sender, server_creator, child) = run_server_thread(&f.tempdir.path(), None);
let conn = connect_to_server(port).unwrap();
{
let mut c = server_creator.lock().unwrap();
c.next_command_spawns(Ok(MockChild::new(exit_status(0), "hello", "error")));
}
let exe = &f.bins[0];
let cmdline = vec!["-c", "file.c", "-o", "file.o"];
let cwd = f.tempdir.path();
let client_creator = Arc::new(Mutex::new(MockCommandCreator::new()));
const COMPILER_STDOUT: &'static [u8] = b"some stdout";
const COMPILER_STDERR: &'static [u8] = b"some stderr";
{
let mut c = client_creator.lock().unwrap();
c.next_command_spawns(Ok(MockChild::new(exit_status(0), COMPILER_STDOUT, COMPILER_STDERR)));
}
let mut stdout = Cursor::new(Vec::new());
let mut stderr = Cursor::new(Vec::new());
let path = Some(f.paths);
assert_eq!(0, do_compile(client_creator.clone(), conn, exe, cmdline, cwd, path, &mut stdout, &mut stderr).unwrap());
assert_eq!(0, server_creator.lock().unwrap().children.len());
assert_eq!(0, client_creator.lock().unwrap().children.len());
assert_eq!(COMPILER_STDOUT, &stdout.into_inner()[..]);
assert_eq!(COMPILER_STDERR, &stderr.into_inner()[..]);
sender.send(ServerMessage::Shutdown).unwrap();
child.join().unwrap();
}
#[test]
fn test_server_compile() {
match env_logger::init() {
Ok(_) => {},
Err(_) => {},
}
let f = TestFixture::new();
let (port, sender, server_creator, child) = run_server_thread(&f.tempdir.path(), None);
const PREPROCESSOR_STDOUT : &'static [u8] = b"preprocessor stdout";
const PREPROCESSOR_STDERR : &'static [u8] = b"preprocessor stderr";
const STDOUT : &'static [u8] = b"some stdout";
const STDERR : &'static [u8] = b"some stderr";
let conn = connect_to_server(port).unwrap();
{
let mut c = server_creator.lock().unwrap();
c.next_command_spawns(Ok(MockChild::new(exit_status(0), "gcc", "")));
c.next_command_spawns(Ok(MockChild::new(exit_status(0), PREPROCESSOR_STDOUT, PREPROCESSOR_STDERR)));
let obj = f.tempdir.path().join("file.o");
c.next_command_calls(move || {
match File::create(&obj)
.and_then(|mut f| f.write_all(b"file contents")) {
Ok(_) => Ok(MockChild::new(exit_status(0), STDOUT, STDERR)),
Err(e) => Err(e),
}
});
}
let exe = &f.bins[0];
let cmdline = vec!["-c", "file.c", "-o", "file.o"];
let cwd = f.tempdir.path();
let client_creator = Arc::new(Mutex::new(MockCommandCreator::new()));
let mut stdout = Cursor::new(Vec::new());
let mut stderr = Cursor::new(Vec::new());
let path = Some(f.paths);
assert_eq!(0, do_compile(client_creator.clone(), conn, exe, cmdline, cwd, path, &mut stdout, &mut stderr).unwrap());
assert_eq!(0, server_creator.lock().unwrap().children.len());
assert_eq!(STDOUT, stdout.into_inner().as_slice());
assert_eq!(STDERR, stderr.into_inner().as_slice());
sender.send(ServerMessage::Shutdown).unwrap();
child.join().unwrap();
}