vesys-bank-server/http-server/src/main.rs

205 lines
6.6 KiB
Rust

#[macro_use]
extern crate log;
use std::sync::RwLock;
use actix_web::middleware::TrailingSlash;
use actix_web::web::{Data, ServiceConfig};
use actix_web::{middleware, web, App, HttpServer};
use bank::bank::Bank;
use crate::handlers::close_account;
use crate::handlers::create_account;
use crate::handlers::deposit;
use crate::handlers::get_account;
use crate::handlers::get_account_nrs;
use crate::handlers::pong;
use crate::handlers::transfer;
use crate::handlers::withdraw;
pub struct AppState {
bank: RwLock<Bank>,
}
mod handlers;
fn config_app(app_data: Data<AppState>) -> Box<dyn Fn(&mut ServiceConfig)> {
Box::new(move |cfg: &mut ServiceConfig| {
cfg.app_data(app_data.clone()).service(pong::route).service(
web::scope("/accounts")
.service(create_account::route)
.service(get_account::route)
.service(deposit::route)
.service(close_account::route)
.service(get_account_nrs::route)
.service(withdraw::route)
.service(transfer::route),
);
})
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
pretty_env_logger::init();
let app_data = web::Data::new(AppState {
bank: RwLock::new(Bank::new()),
});
HttpServer::new(move || {
App::new()
.wrap(middleware::NormalizePath::new(TrailingSlash::Trim))
.configure(config_app(app_data.clone()))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
#[cfg(test)]
mod tests {
use actix_web::body::to_bytes;
use actix_web::{test, App};
use serde_json::Value;
use crate::create_account::OwnerData;
use crate::handlers::AmountData;
use crate::transfer::TransferData;
use super::*;
#[actix_web::test]
async fn test_routes() {
// TODO: split up into separate tests
let app_data = web::Data::new(AppState {
bank: RwLock::new(Bank::new()),
});
let app = test::init_service(
App::new()
.wrap(middleware::NormalizePath::new(TrailingSlash::Trim))
.configure(config_app(app_data)),
)
.await;
let payload = OwnerData {
owner: "aaa".to_string(),
};
let req = test::TestRequest::post()
.uri("/accounts")
.set_form(&payload)
.to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
let body_bytes = to_bytes(resp.into_body()).await.unwrap();
let response_json: Value = serde_json::from_slice(&body_bytes).unwrap();
let nr = response_json["nr"].as_str().unwrap();
assert!(!nr.is_empty());
let payload = AmountData { amount: 10_f64 };
let req = test::TestRequest::post()
.uri(&format!("/accounts/{}/withdraw", nr))
.set_form(&payload)
.to_request();
let resp = test::call_service(&app, req).await;
assert!(!resp.status().is_success());
let req = test::TestRequest::post()
.uri(&format!("/accounts/{}/deposit", nr))
.set_form(&payload)
.to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
let req = test::TestRequest::get()
.uri(&format!("/accounts/{}", nr))
.to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
let body_bytes = to_bytes(resp.into_body()).await.unwrap();
let response_json: Value = serde_json::from_slice(&body_bytes).unwrap();
let balance = response_json["balance"].as_f64().unwrap();
assert_eq!(10_f64, balance);
let payload = OwnerData {
owner: "bbb".to_string(),
};
let req = test::TestRequest::post()
.uri("/accounts")
.set_form(&payload)
.to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
let body_bytes = to_bytes(resp.into_body()).await.unwrap();
let response_json: Value = serde_json::from_slice(&body_bytes).unwrap();
let nr2 = response_json["nr"].as_str().unwrap();
let payload = TransferData {
from: nr.to_string(),
to: nr2.to_string(),
amount: 5_f64,
};
let req = test::TestRequest::post()
.uri("/accounts/transfer")
.set_form(&payload)
.to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
let req = test::TestRequest::get()
.uri(&format!("/accounts/{}", nr2))
.to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
let body_bytes = to_bytes(resp.into_body()).await.unwrap();
let response_json: Value = serde_json::from_slice(&body_bytes).unwrap();
let balance = response_json["balance"].as_f64().unwrap();
assert_eq!(5_f64, balance);
let req = test::TestRequest::post()
.uri(&format!("/accounts/{}/close", nr))
.to_request();
let resp = test::call_service(&app, req).await;
assert!(!resp.status().is_success());
let payload = AmountData { amount: 5_f64 };
let req = test::TestRequest::post()
.uri(&format!("/accounts/{}/withdraw", nr))
.set_form(&payload)
.to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
let req = test::TestRequest::get().uri("/accounts").to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
let body_bytes = to_bytes(resp.into_body()).await.unwrap();
let response_json: Value = serde_json::from_slice(&body_bytes).unwrap();
let nrs = response_json.as_array().unwrap();
assert_eq!(2, nrs.len());
let req = test::TestRequest::post()
.uri(&format!("/accounts/{}/close", nr))
.to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
let req = test::TestRequest::get().uri("/accounts").to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
let body_bytes = to_bytes(resp.into_body()).await.unwrap();
let response_json: Value = serde_json::from_slice(&body_bytes).unwrap();
let nrs = response_json.as_array().unwrap();
assert_eq!(1, nrs.len());
}
}