diff options
| author | Arnaud Bailly <arnaud.bailly@iohk.io> | 2024-10-04 08:41:05 +0200 |
|---|---|---|
| committer | Arnaud Bailly <arnaud@pankzsoft.com> | 2024-10-04 14:59:40 +0200 |
| commit | 47533afd36990b486f1a5d66851f886510c04c20 (patch) | |
| tree | 6d520c63fe6ee63d70df852a7a7974c1983aba58 | |
| parent | 5c2288f43acfc0aa2b89ab27402dc3b1cef28b08 (diff) | |
| download | lambda-nantes-47533afd36990b486f1a5d66851f886510c04c20.tar.gz | |
Client can only register once with same URL
Actually, logic is now mocked so tests should be refactored to test
the logic one level down
| -rw-r--r-- | rust/src/web.rs | 94 |
1 files changed, 67 insertions, 27 deletions
diff --git a/rust/src/web.rs b/rust/src/web.rs index af74a09..257817d 100644 --- a/rust/src/web.rs +++ b/rust/src/web.rs @@ -1,6 +1,7 @@ use std::{ env::args, io::{stdin, stdout, IsTerminal}, + sync::Mutex, }; use actix_web::{ @@ -13,20 +14,14 @@ struct Registration { url: String, } -trait IdGenerator { - fn next_id(&self) -> String; +trait AppState { + fn register(&mut self, registration: &Registration) -> RegistrationResult; } #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] enum RegistrationResult { - Success(RegistrationSuccess), - Failure(RegistrationFailure), -} - -#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] -struct RegistrationSuccess { - id: String, - url: String, + RegistrationSuccess { id: String, url: String }, + UrlAlreadyRegistered { url: String }, } #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] @@ -36,17 +31,14 @@ enum RegistrationFailure { #[post("/register")] async fn register( - id_gen: web::Data<dyn IdGenerator>, + app_state: web::Data<Mutex<dyn AppState>>, registration: web::Json<Registration>, ) -> impl Responder { - let id = id_gen.next_id(); - let success = RegistrationSuccess { - id, - url: registration.url.clone(), - }; - HttpResponse::Ok() - .content_type(ContentType::json()) - .body(serde_json::to_string(&RegistrationResult::Success(success)).unwrap()) + let result = app_state.lock().unwrap().register(®istration); + match result { + RegistrationResult::RegistrationSuccess { .. } => HttpResponse::Ok().json(result), + RegistrationResult::UrlAlreadyRegistered { .. } => HttpResponse::BadRequest().json(result), + } } #[actix_web::main] @@ -65,33 +57,43 @@ mod app_tests { use super::*; - struct ConstantIdGenerator { + struct DummyAppState { id: String, } - impl ConstantIdGenerator { + impl DummyAppState { fn new(id: String) -> Self { Self { id } } } - impl IdGenerator for ConstantIdGenerator { - fn next_id(&self) -> String { - self.id.clone() + impl AppState for DummyAppState { + fn register(&mut self, registration: &Registration) -> RegistrationResult { + if self.id == "" { + return RegistrationResult::UrlAlreadyRegistered { + url: registration.url.clone(), + }; + } else { + RegistrationResult::RegistrationSuccess { + id: self.id.clone(), + url: registration.url.clone(), + } + } } } #[actix_web::test] async fn post_registration_returns_success_with_unique_id() { let id = "0123456789abcdef0123456789abcdef".to_string(); - let id_generator: Arc<dyn IdGenerator> = Arc::new(ConstantIdGenerator::new(id.clone())); + let dummy_state: Arc<Mutex<dyn AppState>> = + Arc::new(Mutex::new(DummyAppState::new(id.clone()))); // FIXME should only be called once, move to setup // env_logger::init(); let app = test::init_service( App::new() .wrap(Logger::default()) - .app_data(web::Data::from(id_generator)) + .app_data(web::Data::from(dummy_state)) .service(register), ) .await; @@ -109,7 +111,45 @@ mod app_tests { let body = resp.into_body(); let bytes = body::to_bytes(body).await; assert_eq!( - RegistrationResult::Success(RegistrationSuccess { id, url }), + RegistrationResult::RegistrationSuccess { id, url }, + serde_json::from_slice(&bytes.unwrap()).unwrap() + ); + } + + #[actix_web::test] + async fn post_registration_fails_given_url_is_already_registered() { + let dummy_state: Arc<Mutex<dyn AppState>> = + Arc::new(Mutex::new(DummyAppState::new("".to_string()))); + + let app = test::init_service( + App::new() + .wrap(Logger::default()) + .app_data(web::Data::from(dummy_state)) + .service(register), + ) + .await; + let url = "http://192.168.1.1".to_string(); + let _ = test::TestRequest::post() + .uri("/register") + .set_json(Registration { url: url.clone() }) + .insert_header(ContentType::json()) + .to_request(); + + // second request with the same URL + let req = test::TestRequest::post() + .uri("/register") + .set_json(Registration { url: url.clone() }) + .insert_header(ContentType::json()) + .to_request(); + + let resp = test::call_service(&app, req).await; + + assert!(resp.status().is_client_error()); + + let body = resp.into_body(); + let bytes = body::to_bytes(body).await; + assert_eq!( + RegistrationResult::UrlAlreadyRegistered { url }, serde_json::from_slice(&bytes.unwrap()).unwrap() ); } |
