use dever_runtime::{ adapter::{Document, Schema}, value::secret::Secret, }; use serde::Deserialize; const SCHEMAS: &[Schema] = &[Schema { name: "demo.value", implementations: &["local", "remote"], }]; #[derive(Deserialize)] #[serde(deny_unknown_fields)] struct Input { offset: i64, token: Secret, } #[test] fn selection_is_explicit_and_only_the_selected_setting_is_decoded() { let text = r#"{"adapter":{"demo.value":{"use":"remote","setting":{"offset":41,"token":"fixture-only-token"}}}}"#; for _ in 0..100 { let document = Document::parse(text.into()).unwrap(); let selections = document.select(SCHEMAS).unwrap(); assert_eq!(selections[0].index, 1); let input: Input = selections[0].decode().unwrap(); assert_eq!(input.offset, 41); assert_eq!(format!("{:?}", input.token), "Secret([REDACTED])"); drop(selections); drop(document); assert_eq!(format!("{:?}", input.token), "Secret([REDACTED])"); } let document = Document::parse(r#"{"adapter":{"demo.\u0076alue":{"use":"\u006cocal"}}}"#.into()).unwrap(); assert_eq!(document.select(SCHEMAS).unwrap()[0].index, 0); let document = Document::parse("{}".into()).unwrap(); assert!(document.select(SCHEMAS).is_err()); let single = [Schema { name: "demo.value", implementations: &["default"], }]; let selections = document.select(&single).unwrap(); assert_eq!(selections[0].index, 0); assert!(selections[0].without_setting().is_ok()); assert!(selections[0].decode::().is_err()); } #[test] fn invalid_configuration_is_bounded_strict_and_redacted() { for text in [ "[]", "[{}]", "null", "{} {}", "{", r#"{"adapter":null}"#, r#"{"adapter":{},"adapter":{}}"#, r#"{"adapter":{"demo.value":["local",{}]}}"#, r#"{"adapter":{"demo.value":{"use":null}}}"#, r#"{"adapter":{"demo.value":{"use":"fixture-only-token"}}}"#, r#"{"adapter":{"fixture-only-token":{"use":"local"}}}"#, r#"{"adapter":{"demo.value":{"use":"local","fixture-only-token":1}}}"#, r#"{"adapter":{"demo.value":{"use":"local","use":"remote"}}}"#, r#"{"adapter":{"demo.value":{"use":"local","setting":{"token":"a","token":"b"}}}}"#, ] { let error = match Document::parse(text.into()) { Err(error) => error, Ok(document) => document.select(SCHEMAS).err().expect(text), }; assert!(!error.contains("fixture-only-token"), "{error}"); } let too_large = format!("{{\"text\":\"{}\"}}", "x".repeat(16 * 1024 * 1024)); assert!(Document::parse(too_large).is_err()); for setting in [ "null", "{}", r#"{"offset":"fixture-only-token","token":"x"}"#, r#"{"offset":1,"token":5}"#, r#"{"offset":1,"token":"x","extra":"fixture-only-token"}"#, ] { let document = Document::parse(format!( r#"{{"adapter":{{"demo.value":{{"use":"local","setting":{setting}}}}}}}"# )) .unwrap(); let selections = document.select(SCHEMAS).unwrap(); let error = selections[0].decode::().err().expect(setting); assert!(!error.contains("fixture-only-token")); assert!(selections[0].without_setting().is_err()); } }