diff --git a/aw-datastore/src/datastore.rs b/aw-datastore/src/datastore.rs index 26bf4b6c..04c60fcb 100644 --- a/aw-datastore/src/datastore.rs +++ b/aw-datastore/src/datastore.rs @@ -12,7 +12,6 @@ use serde_json::value::Value; use aw_models::Bucket; use aw_models::BucketMetadata; use aw_models::Event; -use aw_models::KeyValue; use rusqlite::params; use rusqlite::types::ToSql; @@ -897,7 +896,7 @@ impl DatastoreInstance { Ok(()) } - pub fn get_key_value(&self, conn: &Connection, key: &str) -> Result { + pub fn get_key_value(&self, conn: &Connection, key: &str) -> Result { let mut stmt = match conn.prepare( " SELECT * FROM key_value WHERE KEY = ?1", @@ -910,16 +909,7 @@ impl DatastoreInstance { } }; - match stmt.query_row([key], |row| { - Ok(KeyValue { - key: row.get(0)?, - value: row.get(1)?, - timestamp: Some(DateTime::from_utc( - NaiveDateTime::from_timestamp_opt(row.get(2)?, 0).unwrap(), - Utc, - )), - }) - }) { + match stmt.query_row([key], |row| row.get(1)) { Ok(result) => Ok(result), Err(err) => match err { rusqlite::Error::QueryReturnedNoRows => { @@ -932,12 +922,12 @@ impl DatastoreInstance { } } - pub fn get_keys_starting( + pub fn get_key_values( &self, conn: &Connection, pattern: &str, - ) -> Result, DatastoreError> { - let mut stmt = match conn.prepare("SELECT key FROM key_value WHERE key LIKE ?") { + ) -> Result, DatastoreError> { + let mut stmt = match conn.prepare("SELECT key, value FROM key_value WHERE key LIKE ?") { Ok(stmt) => stmt, Err(err) => { return Err(DatastoreError::InternalError(format!( @@ -946,25 +936,30 @@ impl DatastoreInstance { } }; - let mut output = Vec::::new(); + let mut output = HashMap::::new(); // Rusqlite's get wants index and item type as parameters. - let result = stmt.query_map([pattern], |row| row.get::(0)); + let result = stmt.query_map([pattern], |row| { + Ok((row.get::(0)?, row.get::(1)?)) + }); match result { - Ok(keys) => { - for row in keys { + Ok(settings) => { + for row in settings { // Unwrap to String or panic on SQL row if type is invalid. Can't happen with a // properly initialized table. - output.push(row.unwrap()); + let (key, value) = row.unwrap(); + // Only return keys starting with "settings.". + if !key.starts_with("settings.") { + continue; + } + output.insert(key, value); } Ok(output) } Err(err) => match err { - rusqlite::Error::QueryReturnedNoRows => { - Err(DatastoreError::NoSuchKey(pattern.to_string())) - } - _ => Err(DatastoreError::InternalError(format!( - "Failed to get key_value rows starting with pattern {pattern}" - ))), + rusqlite::Error::QueryReturnedNoRows => Ok(output), + _ => Err(DatastoreError::InternalError( + "Failed to get settings".to_string(), + )), }, } } diff --git a/aw-datastore/src/worker.rs b/aw-datastore/src/worker.rs index 946c772f..18eaf665 100644 --- a/aw-datastore/src/worker.rs +++ b/aw-datastore/src/worker.rs @@ -13,7 +13,6 @@ use rusqlite::TransactionBehavior; use aw_models::Bucket; use aw_models::Event; -use aw_models::KeyValue; use crate::DatastoreError; use crate::DatastoreInstance; @@ -51,8 +50,8 @@ pub enum Response { Event(Event), EventList(Vec), Count(i64), - KeyValue(KeyValue), - StringVec(Vec), + KeyValue(String), + KeyValues(HashMap), } #[allow(clippy::large_enum_variant)] @@ -74,9 +73,9 @@ pub enum Command { GetEventCount(String, Option>, Option>), DeleteEventsById(String, Vec), ForceCommit(), - InsertKeyValue(String, String), + GetKeyValues(String), GetKeyValue(String), - GetKeysStarting(String), + SetKeyValue(String, String), DeleteKeyValue(String), Close(), } @@ -275,7 +274,11 @@ impl DatastoreWorker { self.commit = true; Ok(Response::Empty()) } - Command::InsertKeyValue(key, data) => match ds.insert_key_value(tx, &key, &data) { + Command::GetKeyValues(pattern) => match ds.get_key_values(tx, pattern.as_str()) { + Ok(result) => Ok(Response::KeyValues(result)), + Err(e) => Err(e), + }, + Command::SetKeyValue(key, data) => match ds.insert_key_value(tx, &key, &data) { Ok(()) => Ok(Response::Empty()), Err(e) => Err(e), }, @@ -283,10 +286,6 @@ impl DatastoreWorker { Ok(result) => Ok(Response::KeyValue(result)), Err(e) => Err(e), }, - Command::GetKeysStarting(pattern) => match ds.get_keys_starting(tx, &pattern) { - Ok(result) => Ok(Response::StringVec(result)), - Err(e) => Err(e), - }, Command::DeleteKeyValue(key) => match ds.delete_key_value(tx, &key) { Ok(()) => Ok(Response::Empty()), Err(e) => Err(e), @@ -475,46 +474,46 @@ impl Datastore { } } - pub fn insert_key_value(&self, key: &str, data: &str) -> Result<(), DatastoreError> { - let cmd = Command::InsertKeyValue(key.to_string(), data.to_string()); - let receiver = self.requester.request(cmd).unwrap(); - - _unwrap_response(receiver) - } - - pub fn delete_key_value(&self, key: &str) -> Result<(), DatastoreError> { - let cmd = Command::DeleteKeyValue(key.to_string()); - let receiver = self.requester.request(cmd).unwrap(); - - _unwrap_response(receiver) - } - - pub fn get_key_value(&self, key: &str) -> Result { - let cmd = Command::GetKeyValue(key.to_string()); + pub fn get_key_values(&self, pattern: &str) -> Result, DatastoreError> { + let cmd = Command::GetKeyValues(pattern.to_string()); let receiver = self.requester.request(cmd).unwrap(); match receiver.collect().unwrap() { Ok(r) => match r { - Response::KeyValue(value) => Ok(value), + Response::KeyValues(value) => Ok(value), _ => panic!("Invalid response"), }, Err(e) => Err(e), } } - pub fn get_keys_starting(&self, pattern: &str) -> Result, DatastoreError> { - let cmd = Command::GetKeysStarting(pattern.to_string()); + pub fn get_key_value(&self, key: &str) -> Result { + let cmd = Command::GetKeyValue(key.to_string()); let receiver = self.requester.request(cmd).unwrap(); match receiver.collect().unwrap() { Ok(r) => match r { - Response::StringVec(value) => Ok(value), + Response::KeyValue(kv) => Ok(kv), _ => panic!("Invalid response"), }, Err(e) => Err(e), } } + pub fn set_key_value(&self, key: &str, data: &str) -> Result<(), DatastoreError> { + let cmd = Command::SetKeyValue(key.to_string(), data.to_string()); + let receiver = self.requester.request(cmd).unwrap(); + + _unwrap_response(receiver) + } + + pub fn delete_key_value(&self, key: &str) -> Result<(), DatastoreError> { + let cmd = Command::DeleteKeyValue(key.to_string()); + let receiver = self.requester.request(cmd).unwrap(); + + _unwrap_response(receiver) + } + // Should block until worker has stopped pub fn close(&self) { info!("Sending close request to database"); diff --git a/aw-datastore/tests/datastore.rs b/aw-datastore/tests/datastore.rs index 746c8e85..1290d697 100644 --- a/aw-datastore/tests/datastore.rs +++ b/aw-datastore/tests/datastore.rs @@ -169,7 +169,7 @@ mod datastore_tests { // Get all events let fetched_events_all = ds.get_events(&bucket.id, None, None, None).unwrap(); - let expected_fetched_events = vec![&e2, &e1]; + let expected_fetched_events = [&e2, &e1]; assert_eq!(fetched_events_all.len(), 2); for i in 0..fetched_events_all.len() { let expected = &expected_fetched_events[i]; @@ -268,7 +268,7 @@ mod datastore_tests { // Get all events let fetched_events_all = ds.get_events(&bucket.id, None, None, None).unwrap(); - let expected_fetched_events = vec![&e2, &e1]; + let expected_fetched_events = [&e2, &e1]; assert_eq!(fetched_events_all.len(), 2); for i in 0..fetched_events_all.len() { let expected = &expected_fetched_events[i]; @@ -286,7 +286,7 @@ mod datastore_tests { // Get all events let fetched_events_all = ds.get_events(&bucket.id, None, None, None).unwrap(); - let expected_fetched_events = vec![e2]; + let expected_fetched_events = [e2]; assert_eq!(fetched_events_all.len(), 1); for i in 0..fetched_events_all.len() { let expected = &expected_fetched_events[i]; diff --git a/aw-models/src/key_value.rs b/aw-models/src/key_value.rs deleted file mode 100644 index 6bfc87ce..00000000 --- a/aw-models/src/key_value.rs +++ /dev/null @@ -1,30 +0,0 @@ -use chrono::{DateTime, Utc}; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -use serde_json::Value; - -#[derive(Serialize, Deserialize, JsonSchema)] -pub struct Key { - pub key: String, -} - -#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug, PartialEq)] -pub struct KeyValue { - pub key: String, - pub value: Value, - pub timestamp: Option>, -} - -impl KeyValue { - pub fn new, V: Into>( - key: K, - value: V, - timestamp: DateTime, - ) -> KeyValue { - KeyValue { - key: key.into(), - value: value.into(), - timestamp: Some(timestamp), - } - } -} diff --git a/aw-models/src/lib.rs b/aw-models/src/lib.rs index 6f227443..157f7cfc 100644 --- a/aw-models/src/lib.rs +++ b/aw-models/src/lib.rs @@ -20,7 +20,6 @@ mod bucket; mod duration; mod event; mod info; -mod key_value; mod query; mod timeinterval; mod tryvec; @@ -30,8 +29,6 @@ pub use self::bucket::BucketMetadata; pub use self::bucket::BucketsExport; pub use self::event::Event; pub use self::info::Info; -pub use self::key_value::Key; -pub use self::key_value::KeyValue; pub use self::query::Query; pub use self::timeinterval::TimeInterval; pub use self::tryvec::TryVec; diff --git a/aw-query/tests/query.rs b/aw-query/tests/query.rs index 71969aaa..2bb551c1 100644 --- a/aw-query/tests/query.rs +++ b/aw-query/tests/query.rs @@ -104,7 +104,7 @@ mod query_tests { let code = String::from("True;False;a=True;return True;"); match aw_query::query(&code, &interval, &ds).unwrap() { - aw_query::DataType::Bool(b) => assert_eq!(b, true), + aw_query::DataType::Bool(b) => assert!(b), ref data => panic!("Wrong datatype, {data:?}"), }; } @@ -129,42 +129,42 @@ mod query_tests { // number comparison true let code = String::from("return 1==1;"); match aw_query::query(&code, &interval, &ds).unwrap() { - aw_query::DataType::Bool(b) => assert_eq!(b, true), + aw_query::DataType::Bool(b) => assert!(b), ref data => panic!("Wrong datatype, {data:?}"), }; // number comparison false let code = String::from("return 2==1;"); match aw_query::query(&code, &interval, &ds).unwrap() { - aw_query::DataType::Bool(b) => assert_eq!(b, false), + aw_query::DataType::Bool(b) => assert!(!b), ref data => panic!("Wrong datatype, {data:?}"), }; // string comparison true let code = String::from(r#"return "a"=="a";"#); match aw_query::query(&code, &interval, &ds).unwrap() { - aw_query::DataType::Bool(b) => assert_eq!(b, true), + aw_query::DataType::Bool(b) => assert!(b), ref data => panic!("Wrong datatype, {data:?}"), }; // string comparison false let code = String::from(r#"return "a"=="b";"#); match aw_query::query(&code, &interval, &ds).unwrap() { - aw_query::DataType::Bool(b) => assert_eq!(b, false), + aw_query::DataType::Bool(b) => assert!(!b), ref data => panic!("Wrong datatype, {data:?}"), }; // bool comparison true let code = String::from("return True==True;"); match aw_query::query(&code, &interval, &ds).unwrap() { - aw_query::DataType::Bool(b) => assert_eq!(b, true), + aw_query::DataType::Bool(b) => assert!(b), ref data => panic!("Wrong datatype, {data:?}"), }; // bool comparison false let code = String::from("return False==True;"); match aw_query::query(&code, &interval, &ds).unwrap() { - aw_query::DataType::Bool(b) => assert_eq!(b, false), + aw_query::DataType::Bool(b) => assert!(!b), ref data => panic!("Wrong datatype, {data:?}"), }; diff --git a/aw-server/src/endpoints/mod.rs b/aw-server/src/endpoints/mod.rs index a080d2a0..f8ff3dda 100644 --- a/aw-server/src/endpoints/mod.rs +++ b/aw-server/src/endpoints/mod.rs @@ -139,9 +139,9 @@ pub fn build_rocket(server_state: ServerState, config: AWConfig) -> rocket::Rock "/api/0/settings", routes![ settings::setting_get, - settings::settings_list_get, settings::setting_set, - settings::setting_delete + settings::setting_delete, + settings::settings_get, ], ) .mount("/", rocket_cors::catch_all_options_routes()); diff --git a/aw-server/src/endpoints/settings.rs b/aw-server/src/endpoints/settings.rs index d28047da..61df5784 100644 --- a/aw-server/src/endpoints/settings.rs +++ b/aw-server/src/endpoints/settings.rs @@ -2,10 +2,10 @@ use crate::endpoints::ServerState; use rocket::http::Status; use rocket::serde::json::Json; use rocket::State; +use std::collections::HashMap; use std::sync::MutexGuard; use aw_datastore::Datastore; -use aw_models::{Key, KeyValue}; use crate::endpoints::HttpErrorJson; @@ -21,51 +21,68 @@ fn parse_key(key: String) -> Result { } } -#[post("/", data = "", format = "application/json")] -pub fn setting_set( - state: &State, - message: Json, -) -> Result { - let data = message.into_inner(); - - let setting_key = parse_key(data.key)?; - - let datastore: MutexGuard<'_, Datastore> = endpoints_get_lock!(state.datastore); - let result = datastore.insert_key_value(&setting_key, &data.value.to_string()); - - match result { - Ok(_) => Ok(Status::Created), - Err(err) => Err(err.into()), - } -} - #[get("/")] -pub fn settings_list_get(state: &State) -> Result>, HttpErrorJson> { +pub fn settings_get( + state: &State, +) -> Result>, HttpErrorJson> { let datastore = endpoints_get_lock!(state.datastore); - let queryresults = match datastore.get_keys_starting("settings.%") { + let queryresults = match datastore.get_key_values("settings.%") { Ok(result) => Ok(result), Err(err) => Err(err.into()), }; - let mut output = Vec::::new(); - for i in queryresults? { - output.push(Key { key: i }); + match queryresults { + Ok(settings) => { + // strip 'settings.' prefix from keys + let mut map: HashMap = HashMap::new(); + for (key, value) in settings.iter() { + map.insert( + key.strip_prefix("settings.").unwrap_or(key).to_string(), + serde_json::from_str(value.clone().as_str()).unwrap(), + ); + } + Ok(Json(map)) + } + Err(err) => Err(err), } - - Ok(Json(output)) } #[get("/")] pub fn setting_get( state: &State, key: String, -) -> Result, HttpErrorJson> { +) -> Result, HttpErrorJson> { let setting_key = parse_key(key)?; - let datastore = endpoints_get_lock!(state.datastore); match datastore.get_key_value(&setting_key) { - Ok(result) => Ok(Json(result)), + Ok(value) => Ok(Json(serde_json::from_str(&value).unwrap())), + Err(err) => Err(err.into()), + } +} + +#[post("/", data = "", format = "application/json")] +pub fn setting_set( + state: &State, + key: String, + value: Json, +) -> Result { + let setting_key = parse_key(key)?; + let value_str = match serde_json::to_string(&value.0) { + Ok(value) => value, + Err(err) => { + return Err(HttpErrorJson::new( + Status::BadRequest, + format!("Invalid JSON: {}", err), + )) + } + }; + + let datastore: MutexGuard<'_, Datastore> = endpoints_get_lock!(state.datastore); + let result = datastore.set_key_value(&setting_key, &value_str); + + match result { + Ok(_) => Ok(Status::Created), Err(err) => Err(err.into()), } } diff --git a/aw-server/src/endpoints/util.rs b/aw-server/src/endpoints/util.rs index def7b0ae..fdf4a992 100644 --- a/aw-server/src/endpoints/util.rs +++ b/aw-server/src/endpoints/util.rs @@ -69,9 +69,9 @@ impl<'r> Responder<'r, 'static> for BucketsExportRocket { use aw_datastore::DatastoreError; -impl Into for DatastoreError { - fn into(self) -> HttpErrorJson { - match self { +impl From for HttpErrorJson { + fn from(val: DatastoreError) -> Self { + match val { DatastoreError::NoSuchBucket(bucket_id) => HttpErrorJson::new( Status::NotFound, format!("The requested bucket '{bucket_id}' does not exist"), diff --git a/aw-server/tests/api.rs b/aw-server/tests/api.rs index 18ecf67c..2d8dec30 100644 --- a/aw-server/tests/api.rs +++ b/aw-server/tests/api.rs @@ -11,14 +11,12 @@ mod api_tests { use std::path::PathBuf; use std::sync::Mutex; - use chrono::{DateTime, Utc}; use rocket::http::{ContentType, Header, Status}; use serde_json::{json, Value}; use aw_server::config; use aw_server::endpoints; - use aw_models::KeyValue; use aw_models::{Bucket, BucketsExport}; use rocket::local::blocking::Client; @@ -480,15 +478,10 @@ mod api_tests { assert_eq!(res.into_string().unwrap(), r#"{"message":"EmptyQuery"}"#); } - fn set_setting_request(client: &Client, key: &str, value: Value) -> Status { - let body = serde_json::to_string(&KeyValue { - key: key.to_string(), - value, - timestamp: None, - }) - .unwrap(); + fn set_setting_request(client: &Client, key: &str, value: &Value) -> Status { + let body = serde_json::to_string(value).unwrap(); let res = client - .post("/api/0/settings/") + .post(format!("/api/0/settings/{}", key)) .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body(body) @@ -496,33 +489,15 @@ mod api_tests { res.status() } - /// Asserts that 2 KeyValues are otherwise equal and first keyvalues timestamp is within - /// or equal with timestamp and second.timestamp - fn _equal_and_timestamp_in_range(before: DateTime, first: KeyValue, second: KeyValue) { - assert_eq!(first.key, second.key); - assert_eq!(first.value, second.value); - // Compare with second, not millisecond accuracy - assert!( - first.timestamp.unwrap().timestamp() >= before.timestamp(), - "{} wasn't after {}", - first.timestamp.unwrap().timestamp(), - before.timestamp() - ); - assert!( - first.timestamp < second.timestamp, - "{} wasn't before {}", - first.timestamp.unwrap(), - second.timestamp.unwrap() - ); - } - #[test] fn test_illegally_long_key() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // Test getting not found (getting nonexistent key) - let res = set_setting_request(&client, "thisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongk", json!("")); + let key = "thisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongk"; + let value = json!("test_value"); + let res = set_setting_request(&client, key, &value); assert_eq!(res, rocket::http::Status::BadRequest); } @@ -532,7 +507,9 @@ mod api_tests { let client = Client::untracked(server).expect("valid instance"); // Test value creation - let response_status = set_setting_request(&client, "test_key", json!("test_value")); + let key = "test_key"; + let value = json!("test_value"); + let response_status = set_setting_request(&client, key, &value); assert_eq!(response_status, rocket::http::Status::Created); } @@ -542,87 +519,89 @@ mod api_tests { let client = Client::untracked(server).expect("valid instance"); // Test getting not found (getting nonexistent key) + let key = "non_existent_key"; let res = client - .get("/api/0/settings/non_existent_key") + .get(format!("/api/0/settings/{}", key)) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::NotFound); } #[test] - fn settings_list_get() { + fn test_get_settings() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); - let response1_status = set_setting_request(&client, "test_key", json!("")); + let key1 = "test_key"; + let key2 = "test_key_2"; + let value = json!("test_value"); + let response1_status = set_setting_request(&client, key1, &value); assert_eq!(response1_status, rocket::http::Status::Created); - let response2_status = set_setting_request(&client, "test_key_2", json!("")); + let response2_status = set_setting_request(&client, key2, &value); assert_eq!(response2_status, rocket::http::Status::Created); let res = client - .get("/api/0/settings/") + .get("/api/0/settings") .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); - assert_eq!( - res.into_string().unwrap(), - r#"[{"key":"settings.test_key"},{"key":"settings.test_key_2"}]"# - ); + + let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); + let expected: Value = + serde_json::from_str(r#"{"test_key_2":"test_value","test_key":"test_value"}"#).unwrap(); + assert_eq!(deserialized, expected); } #[test] - fn test_getting_setting() { + fn test_get_setting() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); - let timestamp = Utc::now(); - let response_status = set_setting_request(&client, "test_key", json!("test_value")); + let key = "test_key"; + let value = json!("test_value"); + let response_status = set_setting_request(&client, key, &value); assert_eq!(response_status, rocket::http::Status::Created); // Test getting let res = client - .get("/api/0/settings/test_key") + .get(format!("/api/0/settings/{}", key)) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); - let deserialized: KeyValue = serde_json::from_str(&res.into_string().unwrap()).unwrap(); - _equal_and_timestamp_in_range( - timestamp, - deserialized, - KeyValue::new("settings.test_key", "test_value", Utc::now()), - ); + let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); + assert_eq!(deserialized, value); } #[test] - fn test_getting_setting_multiple_types() { + fn test_get_setting_list() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); - let timestamp = Utc::now(); - // Test array - let response_status = set_setting_request(&client, "test_key_array", json!("[1,2,3]")); + let key = "test_key_array"; + let value = json!([1, 2, 3]); + let response_status = set_setting_request(&client, key, &value); assert_eq!(response_status, rocket::http::Status::Created); let res = client - .get("/api/0/settings/test_key_array") + .get(format!("/api/0/settings/{}", key)) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); - let deserialized: KeyValue = serde_json::from_str(&res.into_string().unwrap()).unwrap(); - _equal_and_timestamp_in_range( - timestamp, - deserialized, - KeyValue::new("settings.test_key_array", "[1,2,3]", Utc::now()), - ); + let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); + assert_eq!(deserialized, value); + } + + #[test] + fn test_get_setting_dict() { + let server = setup_testserver(); + let client = Client::untracked(server).expect("valid instance"); // Test dict - let response_status = set_setting_request( - &client, - "test_key_dict", - json!("{key: 'value', another_key: 'another value'}"), - ); + let key = "test_key_dict"; + let value = json!({"key": "value", "another_key": "another value"}); + let response_status = set_setting_request(&client, key, &value); assert_eq!(response_status, rocket::http::Status::Created); let res = client @@ -630,42 +609,30 @@ mod api_tests { .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); - let deserialized: KeyValue = serde_json::from_str(&res.into_string().unwrap()).unwrap(); - _equal_and_timestamp_in_range( - timestamp, - deserialized, - KeyValue::new( - "settings.test_key_dict", - "{key: 'value', another_key: 'another value'}", - Utc::now(), - ), - ); + let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); + assert_eq!(deserialized, value); } #[test] - fn test_updating_setting() { + fn test_set_setting() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); - let timestamp = Utc::now(); - let post_1_status = set_setting_request(&client, "test_key", json!("test_value")); + let key = "test_key"; + let value1 = json!("test_value"); + let value2 = json!("changed_test_value"); + let post_1_status = set_setting_request(&client, key, &value1); assert_eq!(post_1_status, rocket::http::Status::Created); let res = client - .get("/api/0/settings/test_key") + .get(format!("/api/0/settings/{}", key)) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); - let deserialized: KeyValue = serde_json::from_str(&res.into_string().unwrap()).unwrap(); + let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); + assert_eq!(deserialized, value1); - _equal_and_timestamp_in_range( - timestamp, - deserialized, - KeyValue::new("settings.test_key", "test_value", Utc::now()), - ); - - let timestamp_2 = Utc::now(); - let post_2_status = set_setting_request(&client, "test_key", json!("changed_test_value")); + let post_2_status = set_setting_request(&client, key, &value2); assert_eq!(post_2_status, rocket::http::Status::Created); let res = client @@ -674,20 +641,17 @@ mod api_tests { .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); - let new_deserialized: KeyValue = serde_json::from_str(&res.into_string().unwrap()).unwrap(); - _equal_and_timestamp_in_range( - timestamp_2, - new_deserialized, - KeyValue::new("settings.test_key", "changed_test_value", Utc::now()), - ); + let new_deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); + assert_eq!(new_deserialized, value2); } #[test] - fn test_deleting_setting() { + fn test_delete_setting() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); - let response_status = set_setting_request(&client, "test_key", json!("")); + let value = json!("test_value"); + let response_status = set_setting_request(&client, "test_key", &value); assert_eq!(response_status, rocket::http::Status::Created); // Test deleting diff --git a/aw-transform/src/classify.rs b/aw-transform/src/classify.rs index 28fd4fbb..114650d6 100644 --- a/aw-transform/src/classify.rs +++ b/aw-transform/src/classify.rs @@ -137,12 +137,12 @@ fn test_rule() { let rule_from_regex = Rule::from(Regex::new("test").unwrap()); let rule_from_new = Rule::Regex(RegexRule::new("test", false).unwrap()); let rule_none = Rule::None; - assert_eq!(rule_from_regex.matches(&e_match), true); - assert_eq!(rule_from_new.matches(&e_match), true); - assert_eq!(rule_from_regex.matches(&e_no_match), false); - assert_eq!(rule_from_new.matches(&e_no_match), false); + assert!(rule_from_regex.matches(&e_match)); + assert!(rule_from_new.matches(&e_match)); + assert!(!rule_from_regex.matches(&e_no_match)); + assert!(!rule_from_new.matches(&e_no_match)); - assert_eq!(rule_none.matches(&e_match), false); + assert!(!rule_none.matches(&e_match)); } #[test] @@ -154,7 +154,7 @@ fn test_rule_lookahead() { .insert("test".into(), serde_json::json!("testing lookahead")); let rule_from_regex = Rule::from(Regex::new("testing (?!lookahead)").unwrap()); - assert_eq!(rule_from_regex.matches(&e_match), false); + assert!(!rule_from_regex.matches(&e_match)); } #[test]