use std::collections::HashMap; use backend::{Device, Room, init_logger, server_main}; use reqwest::{Client, Response, StatusCode}; use serde_json::json; use tokio::spawn; use tracing::info; type RqResult = Result; #[tokio::test(flavor = "current_thread")] async fn smoke() -> RqResult<()> { init_logger(); spawn(server_main()); let client = Client::new(); verify_rooms_state0(&client).await?; init_rooms(&client).await?; verify_rooms_state1(&client).await?; delete_room0(&client).await?; verify_rooms_state2(&client).await?; put_room(&client).await?; verify_rooms_state3(&client).await?; verify_room1_state0(&client).await?; verify_room1_devices_state0(&client).await?; verify_room1_device_psock_state0(&client).await?; delete_psock(&client).await?; verify_room1_device_psock_state1(&client).await?; put_device(&client).await?; verify_new_device_in_place(&client).await?; print_house_report(&client).await?; Ok(()) } async fn print_resp(resp: Response) -> RqResult<()> { info!( "\n<<< StatusCode: {}\n<<< BODY: {}", resp.status(), resp.text().await? ); Ok(()) } async fn verify_rooms_state0(client: &Client) -> RqResult<()> { let resp = client.get("http://localhost:8080/rooms").send().await?; assert_eq!(resp.status(), StatusCode::OK); let rooms = resp.json::>().await?; assert!(rooms.is_empty()); Ok(()) } async fn init_rooms(client: &Client) -> RqResult<()> { let resp = client .post("http://localhost:8080/rooms") .json(&json!({ "ROOM0": { "devices": {} }, "ROOM1": { "devices": { "therm": { "type": "Thermometer", "temperature": 22 }, "psock": { "type": "PowerSocket", "power_rate": 11, "on": false } } } })) .send() .await?; assert_eq!(resp.status(), StatusCode::CREATED); Ok(()) } async fn verify_rooms_state1(client: &Client) -> RqResult<()> { let resp = client.get("http://localhost:8080/rooms").send().await?; assert_eq!(resp.status(), StatusCode::OK); let rooms = resp.json::>().await?; assert_eq!(rooms.len(), 2); assert_eq!(rooms.get("ROOM1").unwrap().get_devices().len(), 2); Ok(()) } async fn delete_room0(client: &Client) -> RqResult<()> { let resp = client .delete("http://localhost:8080/room/ROOM0") .send() .await?; assert_eq!(resp.status(), StatusCode::ACCEPTED); Ok(()) } async fn verify_rooms_state2(client: &Client) -> RqResult<()> { let resp = client.get("http://localhost:8080/rooms").send().await?; assert_eq!(resp.status(), StatusCode::OK); let rooms = resp.json::>().await?; assert_eq!(rooms.len(), 1); assert_eq!(rooms.get("ROOM1").unwrap().get_devices().len(), 2); Ok(()) } async fn put_room(client: &Client) -> RqResult<()> { let resp = client .put("http://localhost:8080/room/ROOM") .json(&json!({ "devices": { "therm": { "type": "Thermometer", "temperature": 20 }, "psock": { "type": "PowerSocket", "power_rate": 10, "on": true } } })) .send() .await?; assert_eq!(resp.status(), StatusCode::CREATED); Ok(()) } async fn verify_rooms_state3(client: &Client) -> RqResult<()> { let resp = client.get("http://localhost:8080/rooms").send().await?; assert_eq!(resp.status(), StatusCode::OK); let rooms = resp.json::>().await?; assert_eq!(rooms.len(), 2); assert_eq!(rooms.get("ROOM").unwrap().get_devices().len(), 2); Ok(()) } async fn verify_room1_state0(client: &Client) -> RqResult<()> { let resp = client .get("http://localhost:8080/room/ROOM1") .send() .await?; assert_eq!(resp.status(), StatusCode::OK); let room = resp.json::().await?; assert_eq!(room.get_devices().len(), 2); Ok(()) } async fn verify_room1_devices_state0(client: &Client) -> RqResult<()> { let resp = client .get("http://localhost:8080/room/ROOM1/devices") .send() .await?; assert_eq!(resp.status(), StatusCode::OK); let device_map = resp.json::>().await?; assert_eq!(device_map.len(), 2); Ok(()) } async fn verify_room1_device_psock_state0(client: &Client) -> RqResult<()> { let resp = client .get("http://localhost:8080/room/ROOM1/device/psock") .send() .await?; assert_eq!(resp.status(), StatusCode::OK); let device = resp.json::().await?; let Device::PowerSocket(power_socket) = device else { panic!("PowerSocket expected"); }; assert_eq!(power_socket.get_power(), 0.0); assert_eq!(power_socket.is_on(), false); Ok(()) } async fn delete_psock(client: &Client) -> RqResult<()> { let resp = client .delete("http://localhost:8080/room/ROOM1/device/psock") .send() .await?; assert_eq!(resp.status(), StatusCode::ACCEPTED); Ok(()) } async fn verify_room1_device_psock_state1(client: &Client) -> RqResult<()> { let resp = client .get("http://localhost:8080/room/ROOM1/device/psock") .send() .await?; assert_eq!(resp.status(), StatusCode::NOT_FOUND); Ok(()) } async fn put_device(client: &Client) -> RqResult<()> { let resp = client .put("http://localhost:8080/room/ROOM1/device/TEST") .json(&json!({ "type": "PowerSocket", "power_rate": 5, "on": true })) .send() .await?; assert_eq!(resp.status(), StatusCode::CREATED); Ok(()) } async fn verify_new_device_in_place(client: &Client) -> RqResult<()> { let resp = client.get("http://localhost:8080/rooms").send().await?; assert_eq!(resp.status(), StatusCode::OK); let rooms = resp.json::>().await?; assert_eq!(rooms.len(), 2); assert_eq!(rooms.get("ROOM1").unwrap().get_devices().len(), 2); let device = rooms .get("ROOM1") .unwrap() .get_devices() .get("TEST") .unwrap(); let Device::PowerSocket(power_socket) = device else { panic!("TEST device must be a PowerSocket") }; assert!(power_socket.is_on()); assert_eq!(power_socket.get_power(), 5.0); Ok(()) } async fn print_house_report(client: &Client) -> RqResult<()> { let resp = client.get("http://localhost:8080/rooms").send().await?; assert_eq!(resp.status(), StatusCode::OK); print_resp(resp).await?; Ok(()) }