Add partialeq and partialcmp allowing tests to work

This commit is contained in:
William Brown 2018-11-11 13:39:11 +13:00
parent 3c03594e51
commit 56e4809c28
8 changed files with 272 additions and 63 deletions

View file

@ -84,7 +84,8 @@ impl Backend {
) )
", ",
NO_PARAMS, NO_PARAMS,
).unwrap(); )
.unwrap();
// Create a version table for migration indication // Create a version table for migration indication
@ -98,7 +99,7 @@ impl Backend {
} }
} }
pub fn create(&mut self, entries: Vec<Entry>) -> Result<BackendAuditEvent, BackendError> { pub fn create(&mut self, entries: &Vec<Entry>) -> Result<BackendAuditEvent, BackendError> {
log_event!(self.log, "Begin create"); log_event!(self.log, "Begin create");
let be_audit = BackendAuditEvent::new(); let be_audit = BackendAuditEvent::new();
@ -119,7 +120,8 @@ impl Backend {
.map(|val| { .map(|val| {
// TODO: Should we do better than unwrap? // TODO: Should we do better than unwrap?
serde_json::to_string(&val).unwrap() serde_json::to_string(&val).unwrap()
}).collect(); })
.collect();
log_event!(self.log, "serialising: {:?}", ser_entries); log_event!(self.log, "serialising: {:?}", ser_entries);
@ -134,7 +136,8 @@ impl Backend {
conn.execute( conn.execute(
"INSERT INTO id2entry (data) VALUES (?1)", "INSERT INTO id2entry (data) VALUES (?1)",
&[&ser_entry as &ToSql], &[&ser_entry as &ToSql],
).unwrap(); )
.unwrap();
} }
// TODO: update indexes (as needed) // TODO: update indexes (as needed)
@ -148,7 +151,7 @@ impl Backend {
} }
// Take filter, and AuditEvent ref? // Take filter, and AuditEvent ref?
pub fn search(&self, filt: Filter) -> Vec<Entry> { pub fn search(&self, filt: &Filter) -> Result<Vec<Entry>, ()> {
// Do things // Do things
// Alloc a vec for the entries. // Alloc a vec for the entries.
// FIXME: Make this actually a good size for the result set ... // FIXME: Make this actually a good size for the result set ...
@ -172,7 +175,8 @@ impl Backend {
.query_map(NO_PARAMS, |row| IdEntry { .query_map(NO_PARAMS, |row| IdEntry {
id: row.get(0), id: row.get(0),
data: row.get(1), data: row.get(1),
}).unwrap(); })
.unwrap();
for row in id2entry_iter { for row in id2entry_iter {
println!("{:?}", row); println!("{:?}", row);
// FIXME: Handle this properly. // FIXME: Handle this properly.
@ -193,9 +197,10 @@ impl Backend {
} else { } else {
None None
} }
}).collect(); })
.collect();
entries Ok(entries)
} }
pub fn modify() {} pub fn modify() {}
@ -222,14 +227,13 @@ mod tests {
extern crate futures; extern crate futures;
use futures::future; use futures::future;
use futures::future::lazy;
use futures::future::Future; use futures::future::Future;
extern crate tokio; extern crate tokio;
use super::super::entry::Entry; use super::super::entry::Entry;
use super::super::filter::Filter; use super::super::filter::Filter;
use super::super::log::{self, EventLog, LogEvent}; use super::super::log::{self, EventLog};
use super::{Backend, BackendError}; use super::{Backend, BackendError};
macro_rules! run_test { macro_rules! run_test {
@ -237,7 +241,7 @@ mod tests {
System::run(|| { System::run(|| {
let test_log = log::start(); let test_log = log::start();
let mut be = Backend::new(test_log.clone(), ""); let be = Backend::new(test_log.clone(), "");
// Could wrap another future here for the future::ok bit... // Could wrap another future here for the future::ok bit...
let fut = $test_fn(test_log, be); let fut = $test_fn(test_log, be);
@ -257,7 +261,7 @@ mod tests {
run_test!(|log: actix::Addr<EventLog>, mut be: Backend| { run_test!(|log: actix::Addr<EventLog>, mut be: Backend| {
log_event!(log, "Simple Create"); log_event!(log, "Simple Create");
let empty_result = be.create(Vec::new()); let empty_result = be.create(&Vec::new());
log_event!(log, "{:?}", empty_result); log_event!(log, "{:?}", empty_result);
assert_eq!(empty_result, Err(BackendError::EmptyRequest)); assert_eq!(empty_result, Err(BackendError::EmptyRequest));
@ -266,13 +270,13 @@ mod tests {
.unwrap(); .unwrap();
assert!(e.validate()); assert!(e.validate());
let single_result = be.create(vec![e]); let single_result = be.create(&vec![e]);
assert!(single_result.is_ok()); assert!(single_result.is_ok());
// Construct a filter // Construct a filter
let filt = Filter::Pres(String::from("userid")); let filt = Filter::Pres(String::from("userid"));
let entries = be.search(filt); let entries = be.search(&filt).unwrap();
println!("{:?}", entries); println!("{:?}", entries);
// There should only be one entry so is this enough? // There should only be one entry so is this enough?

View file

@ -1,4 +1,4 @@
use serde_json::{Error, Value}; // use serde_json::{Error, Value};
use std::collections::BTreeMap; use std::collections::BTreeMap;
// make a trait entry for everything to adhere to? // make a trait entry for everything to adhere to?
@ -62,6 +62,22 @@ impl Entry {
} }
} }
impl Clone for Entry {
fn clone(&self) -> Entry {
Entry {
attrs: self.attrs.clone(),
}
}
}
impl PartialEq for Entry {
fn eq(&self, rhs: &Entry) -> bool {
// FIXME: This is naive. Later it should be schema
// aware checking.
self.attrs == rhs.attrs
}
}
// pub trait Entry { // pub trait Entry {
//fn to_json_str(&self) -> String; //fn to_json_str(&self) -> String;
// fn to_index_diff -> ??? // fn to_index_diff -> ???

View file

@ -1,3 +1,4 @@
use super::filter::Filter;
use actix::prelude::*; use actix::prelude::*;
use entry::Entry; use entry::Entry;
@ -10,12 +11,15 @@ pub enum EventResult {
Create, Create,
} }
#[derive(Debug)]
pub struct RawSearchEvent {}
// At the top we get "event types" and they contain the needed // At the top we get "event types" and they contain the needed
// actions, and a generic event component. // actions, and a generic event component.
#[derive(Debug)] #[derive(Debug)]
pub struct SearchEvent { pub struct SearchEvent {
filter: (), pub filter: Filter,
class: (), // String class: (), // String
// It could be better to box this later ... // It could be better to box this later ...
event: AuditEvent, event: AuditEvent,
@ -26,9 +30,9 @@ impl Message for SearchEvent {
} }
impl SearchEvent { impl SearchEvent {
pub fn new() -> Self { pub fn new(filter: Filter) -> Self {
SearchEvent { SearchEvent {
filter: (), filter: filter,
class: (), class: (),
event: AuditEvent { event: AuditEvent {
time_start: (), time_start: (),
@ -44,7 +48,7 @@ impl SearchEvent {
pub struct CreateEvent { pub struct CreateEvent {
// This may still actually change to handle the *raw* nature of the // This may still actually change to handle the *raw* nature of the
// input that we plan to parse. // input that we plan to parse.
entries: Vec<Entry>, pub entries: Vec<Entry>,
// It could be better to box this later ... // It could be better to box this later ...
event: AuditEvent, event: AuditEvent,
} }
@ -54,9 +58,9 @@ impl Message for CreateEvent {
} }
impl CreateEvent { impl CreateEvent {
pub fn new() -> Self { pub fn new(entries: Vec<Entry>) -> Self {
CreateEvent { CreateEvent {
entries: Vec::new(), entries: entries,
event: AuditEvent { event: AuditEvent {
time_start: (), time_start: (),
time_end: (), time_end: (),

View file

@ -3,6 +3,7 @@
// entry to assert it matches. // entry to assert it matches.
use super::entry::Entry; use super::entry::Entry;
use std::cmp::{Ordering, PartialOrd};
// Perhaps make these json serialisable. Certainly would make parsing // Perhaps make these json serialisable. Certainly would make parsing
// simpler ... // simpler ...
@ -21,11 +22,22 @@ pub enum Filter {
impl Filter { impl Filter {
fn optimise(mut self) -> Self { fn optimise(mut self) -> Self {
// Apply optimisations to the filter // Apply optimisations to the filter
// An easy way would be imple partialOrd
// then do sort on the or/and/not
// as the general conditions we want
// to optimise on are in those ...
//
// The other big one is folding redundant
// terms down.
//
// If an or/not/and condition has no items, remove it
//
// If its the root item?
self self
} }
// In the future this will probably be used with schema ... // In the future this will probably be used with schema ...
fn validate(mut self) -> Result<(), ()> { fn validate(&self) -> Result<(), ()> {
Ok(()) Ok(())
} }
@ -38,6 +50,9 @@ impl Filter {
// What other parse types do we need? // What other parse types do we need?
// FIXME: This check should be in ENTRY not here, because it's up to others
// to interpret filter meaning and application!!!
// Assert if this filter matches the entry (no index) // Assert if this filter matches the entry (no index)
pub fn entry_match_no_index(&self, e: &Entry) -> bool { pub fn entry_match_no_index(&self, e: &Entry) -> bool {
// Go through the filter components and check them in the entry. // Go through the filter components and check them in the entry.
@ -56,10 +71,68 @@ impl Filter {
} }
} }
impl Clone for Filter {
fn clone(&self) -> Self {
// I think we only need to match self then new + clone?
match self {
Filter::Eq(a, v) => Filter::Eq(a.clone(), v.clone()),
Filter::Sub(a, v) => Filter::Sub(a.clone(), v.clone()),
Filter::Pres(a) => Filter::Pres(a.clone()),
Filter::Or(l) => Filter::Or(l.clone()),
Filter::And(l) => Filter::And(l.clone()),
Filter::Not(l) => Filter::Not(l.clone()),
}
}
}
impl PartialEq for Filter {
fn eq(&self, rhs: &Filter) -> bool {
match (self, rhs) {
(Filter::Eq(a1, v1), Filter::Eq(a2, v2)) => a1 == a2 && v1 == v2,
(Filter::Sub(a1, v1), Filter::Sub(a2, v2)) => a1 == a2 && v1 == v2,
(Filter::Pres(a1), Filter::Pres(a2)) => a1 == a2,
(Filter::Or(l1), Filter::Or(l2)) => l1 == l2,
(Filter::And(l1), Filter::And(l2)) => l1 == l2,
(Filter::Not(l1), Filter::Not(l2)) => l1 == l2,
(_, _) => false,
}
}
}
// remember, this isn't ordering by alphanumeric, this is ordering of
// optimisation preference!
//
impl PartialOrd for Filter {
fn partial_cmp(&self, rhs: &Filter) -> Option<Ordering> {
match (self, rhs) {
(Filter::Eq(a1, _), Filter::Eq(a2, _)) => {
// Order attr name, then value
// Later me may add rules to put certain attrs ahead due
// to optimisation rules
a1.partial_cmp(a2)
}
(Filter::Sub(a1, _), Filter::Sub(a2, _)) => a1.partial_cmp(a2),
(Filter::Pres(a1), Filter::Pres(a2)) => a1.partial_cmp(a2),
(Filter::Eq(_, _), _) => {
// Always higher prefer Eq over all else, as these will have
// the best indexes and return smallest candidates.
Some(Ordering::Less)
}
(_, Filter::Eq(_, _)) => Some(Ordering::Greater),
(Filter::Pres(_), _) => Some(Ordering::Less),
(_, Filter::Pres(_)) => Some(Ordering::Greater),
(Filter::Sub(_, _), _) => Some(Ordering::Greater),
(_, Filter::Sub(_, _)) => Some(Ordering::Less),
(_, _) => Some(Ordering::Equal),
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::Filter; use super::Filter;
use serde_json; use serde_json;
use std::cmp::{Ordering, PartialOrd};
#[test] #[test]
fn test_filter_simple() { fn test_filter_simple() {
@ -82,4 +155,73 @@ mod tests {
fn test_filter_optimise() { fn test_filter_optimise() {
// Given sets of "optimisable" filters, optimise them. // Given sets of "optimisable" filters, optimise them.
} }
#[test]
fn test_filter_eq() {
let f_t1a = Filter::Pres(String::from("userid"));
let f_t1b = Filter::Pres(String::from("userid"));
let f_t1c = Filter::Pres(String::from("zzzz"));
assert_eq!(f_t1a == f_t1b, true);
assert_eq!(f_t1a == f_t1c, false);
assert_eq!(f_t1b == f_t1c, false);
let f_t2a = Filter::And(vec![f_t1a]);
let f_t2b = Filter::And(vec![f_t1b]);
let f_t2c = Filter::And(vec![f_t1c]);
assert_eq!(f_t2a == f_t2b, true);
assert_eq!(f_t2a == f_t2c, false);
assert_eq!(f_t2b == f_t2c, false);
assert_eq!(f_t2c == Filter::Pres(String::from("test")), false);
}
#[test]
fn test_filter_ord() {
// Test that we uphold the rules of partialOrd
// Basic equality
// Test the two major paths here (str vs list)
let f_t1a = Filter::Pres(String::from("userid"));
let f_t1b = Filter::Pres(String::from("userid"));
assert_eq!(f_t1a.partial_cmp(&f_t1b), Some(Ordering::Equal));
assert_eq!(f_t1b.partial_cmp(&f_t1a), Some(Ordering::Equal));
let f_t2a = Filter::And(vec![]);
let f_t2b = Filter::And(vec![]);
assert_eq!(f_t2a.partial_cmp(&f_t2b), Some(Ordering::Equal));
assert_eq!(f_t2b.partial_cmp(&f_t2a), Some(Ordering::Equal));
// antisymmetry: if a < b then !(a > b), as well as a > b implying !(a < b); and
let f_t3b = Filter::Eq(String::from("userid"), String::from(""));
assert_eq!(f_t1a.partial_cmp(&f_t3b), Some(Ordering::Greater));
assert_eq!(f_t3b.partial_cmp(&f_t1a), Some(Ordering::Less));
// transitivity: a < b and b < c implies a < c. The same must hold for both == and >.
let f_t4b = Filter::Sub(String::from("userid"), String::from(""));
assert_eq!(f_t1a.partial_cmp(&f_t4b), Some(Ordering::Less));
assert_eq!(f_t3b.partial_cmp(&f_t4b), Some(Ordering::Less));
assert_eq!(f_t4b.partial_cmp(&f_t1a), Some(Ordering::Greater));
assert_eq!(f_t4b.partial_cmp(&f_t3b), Some(Ordering::Greater));
}
#[test]
fn test_filter_clone() {
// Test that cloning filters yields the same result regardless of
// complexity.
let f_t1a = Filter::Pres(String::from("userid"));
let f_t1b = f_t1a.clone();
let f_t1c = Filter::Pres(String::from("zzzz"));
assert_eq!(f_t1a == f_t1b, true);
assert_eq!(f_t1a == f_t1c, false);
let f_t2a = Filter::And(vec![f_t1a]);
let f_t2b = f_t2a.clone();
let f_t2c = Filter::And(vec![f_t1c]);
assert_eq!(f_t2a == f_t2b, true);
assert_eq!(f_t2a == f_t2c, false);
}
} }

View file

@ -10,12 +10,12 @@ extern crate r2d2_sqlite;
extern crate rusqlite; extern crate rusqlite;
extern crate uuid; extern crate uuid;
use actix::prelude::*; // use actix::prelude::*;
use actix_web::{ // use actix_web::{
http, middleware, App, AsyncResponder, FutureResponse, HttpRequest, HttpResponse, Path, State, // http, middleware, App, AsyncResponder, FutureResponse, HttpRequest, HttpResponse, Path, State,
}; // };
use futures::Future; // use futures::Future;
// This has to be before be so the import order works // This has to be before be so the import order works
#[macro_use] #[macro_use]

View file

@ -1,24 +1,24 @@
extern crate serde; extern crate serde;
extern crate serde_json; extern crate serde_json;
#[macro_use] // #[macro_use]
extern crate serde_derive;
extern crate actix; extern crate actix;
extern crate actix_web; extern crate actix_web;
extern crate futures; extern crate futures;
extern crate serde_derive;
extern crate uuid; extern crate uuid;
use actix::prelude::*; // use actix::prelude::*;
use actix_web::{ use actix_web::{
http, middleware, App, AsyncResponder, FutureResponse, HttpRequest, HttpResponse, Path, State, http, App, AsyncResponder, FutureResponse, HttpRequest, HttpResponse, Path, State,
}; };
use futures::Future; use futures::Future;
#[macro_use] #[macro_use]
extern crate rsidm; extern crate rsidm;
use rsidm::be;
use rsidm::event; use rsidm::event;
use rsidm::log::{self, EventLog}; use rsidm::filter::Filter;
use rsidm::log;
use rsidm::server; use rsidm::server;
struct AppState { struct AppState {
@ -34,8 +34,10 @@ fn index(req: &HttpRequest<AppState>) -> HttpResponse {
HttpResponse::Ok().body("Hello\n") HttpResponse::Ok().body("Hello\n")
} }
fn class_list((name, state): (Path<String>, State<AppState>)) -> FutureResponse<HttpResponse> { fn class_list((_name, state): (Path<String>, State<AppState>)) -> FutureResponse<HttpResponse> {
// println!("request to class_list"); // println!("request to class_list");
let filt = Filter::Pres(String::from("objectclass"));
state state
.qe .qe
.send( .send(
@ -43,14 +45,17 @@ fn class_list((name, state): (Path<String>, State<AppState>)) -> FutureResponse<
// LONG TERM // LONG TERM
// Make a search REQUEST, and create the audit struct here, then // Make a search REQUEST, and create the audit struct here, then
// pass it to the server // pass it to the server
event::SearchEvent::new() //
// FIXME: Don't use SEARCHEVENT here!!!!
//
event::SearchEvent::new(filt),
) )
// TODO: How to time this part of the code? // TODO: How to time this part of the code?
// What does this do? // What does this do?
.from_err() .from_err()
.and_then(|res| match res { .and_then(|res| match res {
// What type is entry? // What type is entry?
Ok(event::EventResult::Search{ entries }) => Ok(HttpResponse::Ok().json(entries)), Ok(event::EventResult::Search { entries }) => Ok(HttpResponse::Ok().json(entries)),
Ok(_) => Ok(HttpResponse::Ok().into()), Ok(_) => Ok(HttpResponse::Ok().into()),
// Can we properly report this? // Can we properly report this?
Err(_) => Ok(HttpResponse::InternalServerError().into()), Err(_) => Ok(HttpResponse::InternalServerError().into()),
@ -84,9 +89,14 @@ fn main() {
// Connect all our end points here. // Connect all our end points here.
// .middleware(middleware::Logger::default()) // .middleware(middleware::Logger::default())
.resource("/", |r| r.f(index)) .resource("/", |r| r.f(index))
.resource("/{class_list}", |r| r.method(http::Method::GET).with(class_list)) .resource("/{class_list}", |r| {
.resource("/{class_list}/", |r| r.method(http::Method::GET).with(class_list)) r.method(http::Method::GET).with(class_list)
}).bind("127.0.0.1:8080") })
.resource("/{class_list}/", |r| {
r.method(http::Method::GET).with(class_list)
})
})
.bind("127.0.0.1:8080")
.unwrap() .unwrap()
.start(); .start();

View file

@ -46,15 +46,26 @@ impl QueryServer {
// Actually conduct a search request // Actually conduct a search request
// This is the core of the server, as it processes the entire event // This is the core of the server, as it processes the entire event
// applies all parts required in order and more. // applies all parts required in order and more.
pub fn search(&mut self) -> Result<Vec<Entry>, ()> { pub fn search(&mut self, se: &SearchEvent) -> Result<Vec<Entry>, ()> {
Ok(Vec::new()) match self.be.search(&se.filter) {
Ok(r) => Ok(r),
Err(_) => Err(()),
}
} }
// What should this take? // What should this take?
// This should probably take raw encoded entries? Or sohuld they // This should probably take raw encoded entries? Or sohuld they
// be handled by fe? // be handled by fe?
pub fn create(&mut self) -> Result<(), ()> { pub fn create(&mut self, ce: &CreateEvent) -> Result<(), ()> {
Ok(()) // Start a txn
// Run any pre checks
// We may change from ce.entries later to something else?
match self.be.create(&ce.entries) {
Ok(_) => Ok(()),
Err(_) => Err(()),
}
// Run and post checks
// Commit/Abort the txn
} }
} }
@ -75,8 +86,10 @@ impl Handler<SearchEvent> for QueryServer {
// Parse what we need from the event? // Parse what we need from the event?
// What kind of event is it? // What kind of event is it?
// In the future we'll likely change search event ...
// was this ok? // was this ok?
let res = match self.search() { let res = match self.search(&msg) {
Ok(entries) => Ok(EventResult::Search { entries: entries }), Ok(entries) => Ok(EventResult::Search { entries: entries }),
Err(e) => Err(e), Err(e) => Err(e),
}; };
@ -92,13 +105,20 @@ impl Handler<CreateEvent> for QueryServer {
fn handle(&mut self, msg: CreateEvent, _: &mut Self::Context) -> Self::Result { fn handle(&mut self, msg: CreateEvent, _: &mut Self::Context) -> Self::Result {
log_event!(self.log, "Begin event {:?}", msg); log_event!(self.log, "Begin event {:?}", msg);
Err(())
let res = match self.create(&msg) {
Ok(()) => Ok(EventResult::Create),
Err(e) => Err(e),
};
log_event!(self.log, "End event {:?}", msg);
// At the end of the event we send it for logging.
res
} }
} }
// Auth requests? How do we structure these ... // Auth requests? How do we structure these ...
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
extern crate actix; extern crate actix;
@ -106,26 +126,28 @@ mod tests {
extern crate futures; extern crate futures;
use futures::future; use futures::future;
use futures::future::lazy;
use futures::future::Future; use futures::future::Future;
extern crate tokio; extern crate tokio;
use super::super::server::QueryServer;
use super::super::be::Backend; use super::super::be::Backend;
use super::super::log::{self, EventLog, LogEvent}; use super::super::entry::Entry;
use super::super::event::{CreateEvent, SearchEvent};
use super::super::filter::Filter;
use super::super::log;
use super::super::server::QueryServer;
macro_rules! run_test { macro_rules! run_test {
($test_fn:expr) => {{ ($test_fn:expr) => {{
System::run(|| { System::run(|| {
let test_log = log::start(); let test_log = log::start();
let mut be = Backend::new(test_log.clone(), ""); let be = Backend::new(test_log.clone(), "");
let mut test_server = QueryServer::new(test_log.clone(), be); let test_server = QueryServer::new(test_log.clone(), be);
// Could wrap another future here for the future::ok bit... // Could wrap another future here for the future::ok bit...
let fut = $test_fn(test_log, test_server); let fut = $test_fn(test_log, test_server);
let comp_fut = fut.map_err(|()| ()).and_then(|r| { let comp_fut = fut.map_err(|()| ()).and_then(|_r| {
println!("Stopping actix ..."); println!("Stopping actix ...");
actix::System::current().stop(); actix::System::current().stop();
future::result(Ok(())) future::result(Ok(()))
@ -136,19 +158,33 @@ mod tests {
}}; }};
} }
#[test] #[test]
fn test_be_create_user() { fn test_be_create_user() {
run_test!(|log, mut server: QueryServer| { run_test!(|_log, mut server: QueryServer| {
let r1 = server.search().unwrap(); let filt = Filter::Pres(String::from("userid"));
let se1 = SearchEvent::new(filt.clone());
let se2 = SearchEvent::new(filt);
let mut e: Entry = Entry::new();
e.add_ava(String::from("userid"), String::from("william"))
.unwrap();
let expected = vec![e];
let ce = CreateEvent::new(expected.clone());
let r1 = server.search(&se1).unwrap();
assert!(r1.len() == 0); assert!(r1.len() == 0);
let cr = server.create(); let cr = server.create(&ce);
assert!(cr.is_ok()); assert!(cr.is_ok());
let r2 = server.search().unwrap(); let r2 = server.search(&se2).unwrap();
assert!(r2.len() == 1); assert!(r2.len() == 1);
assert_eq!(r2, expected);
future::ok(()) future::ok(())
}); });
} }

View file

@ -1,8 +1,6 @@
extern crate actix; extern crate actix;
use actix::prelude::*; use actix::prelude::*;
use std::panic;
extern crate rsidm; extern crate rsidm;
use rsidm::log::{self, EventLog, LogEvent}; use rsidm::log::{self, EventLog, LogEvent};
use rsidm::server::{self, QueryServer}; use rsidm::server::{self, QueryServer};
@ -10,11 +8,10 @@ use rsidm::server::{self, QueryServer};
extern crate futures; extern crate futures;
use futures::future; use futures::future;
use futures::future::lazy;
use futures::future::Future; use futures::future::Future;
extern crate tokio; extern crate tokio;
use tokio::executor::current_thread::CurrentThread; // use tokio::executor::current_thread::CurrentThread;
// Test external behaviorus of the service. // Test external behaviorus of the service.
@ -41,7 +38,7 @@ macro_rules! run_test {
// Now chain them ... // Now chain them ...
// Now append the server shutdown. // Now append the server shutdown.
let comp_fut = fut.map_err(|_| ()).and_then(|r| { let comp_fut = fut.map_err(|_| ()).and_then(|_r| {
println!("Stopping actix ..."); println!("Stopping actix ...");
actix::System::current().stop(); actix::System::current().stop();
future::result(Ok(())) future::result(Ok(()))
@ -58,7 +55,7 @@ macro_rules! run_test {
#[test] #[test]
fn test_schema() { fn test_schema() {
run_test!( run_test!(
|log: actix::Addr<EventLog>, server: actix::Addr<QueryServer>| log.send(LogEvent { |log: actix::Addr<EventLog>, _server: actix::Addr<QueryServer>| log.send(LogEvent {
msg: String::from("Test log event") msg: String::from("Test log event")
}) })
); );