#[macro_use]
extern crate diesel_migrations;
#[macro_use]
extern crate log;
extern crate raspberry_web;
use actix::SyncArbiter;
use actix_web::http;
use actix_web::test::TestServer;
use diesel::prelude::*;
use diesel::{r2d2::ConnectionManager, r2d2::Pool, SqliteConnection};
use diesel_migrations::RunMigrationsError;
use dotenv::dotenv;
use std::sync::{Once, ONCE_INIT};
use raspberry_web::app::{gpio_status_route, set_gpio_level_route, AppState};
use raspberry_web::handlers::DbExecutor;
use raspberry_web::rpi::create_gpio_arc_mutex;
use raspberry_web::schema;
embed_migrations!("migrations");
static INIT: Once = ONCE_INIT;
fn init_logging_once() {
INIT.call_once(|| {
dotenv().ok();
env_logger::init();
});
}
fn get_pool_after_migrations(
) -> Result<Pool<ConnectionManager<SqliteConnection>>, RunMigrationsError> {
let manager = ConnectionManager::<SqliteConnection>::new(":memory:");
let pool = r2d2::Pool::builder()
.build(manager)
.expect("Failed to create r2d2 pool.");
let connection = pool.get().expect("Failed to acquire connection");
embedded_migrations::run(&connection)?;
Ok(pool)
}
fn setup_db_for_tests(connection: &SqliteConnection) -> Result<(), diesel::result::Error> {
use crate::schema::gpio_state::dsl::*;
diesel::update(gpio_state)
.set((in_use.eq(1), gpio_mode.eq("output"), gpio_level.eq("low")))
.filter(gpio_id.eq(1))
.execute(connection)?;
diesel::update(gpio_state)
.set(in_use.eq(0))
.filter(gpio_id.eq(2))
.execute(connection)?;
diesel::update(gpio_state)
.set((in_use.eq(1), gpio_mode.eq("input")))
.filter(gpio_id.eq(3))
.execute(connection)?;
Ok(())
}
fn get_testserver_with_state() -> TestServer {
init_logging_once();
let test_server = TestServer::build_with_state(|| {
let gpio_arc_mutex = create_gpio_arc_mutex().expect("Could not acquire GPIO");
let addr = SyncArbiter::start(3, || {
DbExecutor({
let pool = get_pool_after_migrations().expect("Could not run migrations");
let connection = pool.get().expect("Failed to acquire connection");
setup_db_for_tests(&connection).expect("Error setting up test database");
pool.clone()
})
});
AppState {
db: addr.clone(),
gpio_arc_mutex: gpio_arc_mutex.clone(),
}
})
.start(|app| {
app.resource("/status/{id}", |r| {
r.method(http::Method::GET).with(gpio_status_route)
})
.resource("/set_level/{id}/{level}", |r| {
r.method(http::Method::GET).with(set_gpio_level_route)
});
});
test_server
}
#[test]
fn test_migrations() {
let pool = get_pool_after_migrations();
assert_eq!(pool.is_ok(), true)
}
#[test]
fn check_status_succes() {
let mut test_server = get_testserver_with_state();
let request = test_server
.client(http::Method::GET, "/status/1")
.finish()
.unwrap();
let response = test_server.execute(request.send()).unwrap();
info!("{:?}", response);
assert!(response.status().is_success())
}
#[test]
fn check_status_gpio_nonexistant_failure() {
let mut test_server = get_testserver_with_state();
let request = test_server
.client(http::Method::GET, "/status/18")
.finish()
.unwrap();
let response = test_server.execute(request.send()).unwrap();
info!("{:?}", response);
assert_eq!(response.status().is_success(), false)
}
#[test]
fn set_gpio_level_success() {
let mut test_server = get_testserver_with_state();
let request = test_server
.client(http::Method::GET, "/set_level/1/high")
.finish()
.unwrap();
let response = test_server.execute(request.send()).unwrap();
info!("{:?}", response);
assert!(response.status().is_success())
}
#[test]
fn set_gpio_level_gpio_nonexistant_failure() {
let mut test_server = get_testserver_with_state();
let request = test_server
.client(http::Method::GET, "/set_level/18/high")
.finish()
.unwrap();
let response = test_server.execute(request.send()).unwrap();
info!("{:?}", response);
assert_eq!(response.status().is_success(), false)
}
#[test]
fn set_gpio_level_gpio_not_in_use_failure() {
let mut test_server = get_testserver_with_state();
let request = test_server
.client(http::Method::GET, "/set_level/2/high")
.finish()
.unwrap();
let response = test_server.execute(request.send()).unwrap();
info!("{:?}", response);
assert_eq!(response.status().is_success(), false)
}
#[test]
fn set_gpio_level_gpio_mode_not_output_failure() {
let mut test_server = get_testserver_with_state();
let request = test_server
.client(http::Method::GET, "/set_level/3/high")
.finish()
.unwrap();
let response = test_server.execute(request.send()).unwrap();
info!("{:?}", response);
assert_eq!(response.status().is_success(), false)
}
#[test]
fn set_gpio_level_unknown_level_failure() {
let mut test_server = get_testserver_with_state();
let request = test_server
.client(http::Method::GET, "/set_level/1/something_random")
.finish()
.unwrap();
let response = test_server.execute(request.send()).unwrap();
info!("{:?}", response);
assert_eq!(response.status().is_success(), false)
}