diff --git a/meilisearch/src/routes/logs.rs b/meilisearch/src/routes/logs.rs index 7ce7d7ea1..ae93f0ea5 100644 --- a/meilisearch/src/routes/logs.rs +++ b/meilisearch/src/routes/logs.rs @@ -32,7 +32,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) { ); } -#[derive(Debug, Default, Clone, Copy, Deserr)] +#[derive(Debug, Default, Clone, Copy, Deserr, PartialEq, Eq)] #[deserr(rename_all = lowercase)] pub enum LogMode { #[default] @@ -82,13 +82,33 @@ impl MergeWithError for DeserrJsonError { } #[derive(Debug, Deserr)] -#[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields)] +#[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields, validate = validate_get_logs -> DeserrJsonError)] pub struct GetLogs { #[deserr(default = "info".parse().unwrap(), try_from(&String) = MyTargets::from_str -> DeserrJsonError)] target: MyTargets, #[deserr(default, error = DeserrJsonError)] mode: LogMode, + + #[deserr(default = false, error = DeserrJsonError)] + profile_memory: bool, +} + +fn validate_get_logs( + logs: GetLogs, + location: ValuePointerRef, +) -> Result { + if logs.profile_memory && logs.mode != LogMode::Profile { + Err(deserr::take_cf_content(E::error::( + None, + ErrorKind::Unexpected { + msg: format!("`profile_memory` can only be used while profiling code and is not compatible with the {:?} mode.", logs.mode), + }, + location, + ))) + } else { + Ok(logs) + } } struct LogWriter { diff --git a/meilisearch/tests/logs/error.rs b/meilisearch/tests/logs/error.rs index c1755c299..7cbc39b1f 100644 --- a/meilisearch/tests/logs/error.rs +++ b/meilisearch/tests/logs/error.rs @@ -97,6 +97,63 @@ async fn logs_stream_bad_mode() { "###); } +#[actix_rt::test] +async fn logs_stream_bad_profile_memory() { + let server = Server::new().await; + + // Wrong type + let (response, code) = + server.service.post("/logs/stream", json!({ "profileMemory": "tamo" })).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(response, @r###" + { + "message": "Invalid value type at `.profileMemory`: expected a boolean, but found a string: `\"tamo\"`", + "code": "bad_request", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#bad_request" + } + "###); + + // Wrong type + let (response, code) = + server.service.post("/logs/stream", json!({ "profileMemory": ["hello", "kefir"] })).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(response, @r###" + { + "message": "Invalid value type at `.profileMemory`: expected a boolean, but found an array: `[\"hello\",\"kefir\"]`", + "code": "bad_request", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#bad_request" + } + "###); + + // Used with default parameters + let (response, code) = + server.service.post("/logs/stream", json!({ "profileMemory": true })).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(response, @r###" + { + "message": "Invalid value: `profile_memory` can only be used while profiling code and is not compatible with the Fmt mode.", + "code": "invalid_settings_typo_tolerance", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_settings_typo_tolerance" + } + "###); + + // Used with an unsupported mode + let (response, code) = + server.service.post("/logs/stream", json!({ "mode": "fmt", "profileMemory": true })).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(response, @r###" + { + "message": "Invalid value: `profile_memory` can only be used while profiling code and is not compatible with the Fmt mode.", + "code": "invalid_settings_typo_tolerance", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_settings_typo_tolerance" + } + "###); +} + #[actix_rt::test] async fn logs_stream_without_enabling_the_route() { let server = Server::new().await;