use kaptan_config::{ ConfigAggregate, ConfigSection, ConfigValue, ConfigViolation, FieldId, FieldWriteError, ValidateFields, ValidationRule, }; use kaptan_config_derive::ConfigValidate; #[derive(ConfigValidate)] struct LocalSection { #[config( id = 1, key = "local.first", unit = "count", default = 2, range(min = 1, max = 9) )] first: u32, #[config( id = 2, key = "local.second", unit = "count", default = 4, range(min = 1, max = 9) )] second: u32, } #[derive(ConfigValidate)] #[config(post = Self::validate_order)] struct OrderedSection { #[config( id = 3, key = "ordered.minimum", unit = "count", default = 1, range(min = 0, max = 9) )] minimum: u32, #[config( id = 4, key = "ordered.maximum", unit = "count", default = 2, range(min = 0, max = 9) )] maximum: u32, } impl OrderedSection { fn validate_order(&self) -> Result<(), ConfigViolation> { if self.minimum > self.maximum { return Err(ConfigViolation::related( FieldId::new(3), FieldId::new(4), ValidationRule::Inconsistent, )); } Ok(()) } } #[derive(ConfigValidate)] struct Aggregate { #[config(section)] local: LocalSection, #[config(section)] ordered: OrderedSection, } #[test] fn generated_section_owns_every_declared_scalar_path() { let mut section = LocalSection::default_section().unwrap(); assert_eq!(LocalSection::FIELD_COUNT, 2); assert_eq!( section.field_value(FieldId::new(2)), Some(ConfigValue::U32(4)) ); section .set_field(FieldId::new(2), ConfigValue::U32(8)) .unwrap(); assert_eq!( section.field_value(FieldId::new(2)), Some(ConfigValue::U32(8)) ); assert_eq!( section.set_field(FieldId::new(2), ConfigValue::U32(0)), Err(FieldWriteError::Violation(ConfigViolation::field( FieldId::new(2), ValidationRule::BelowMinimum, ))) ); assert_eq!( section.field_value(FieldId::new(2)), Some(ConfigValue::U32(8)) ); } #[test] fn aggregate_routes_writes_and_defers_declared_post_validation() { let mut aggregate = Aggregate::default_aggregate().unwrap(); assert_eq!(Aggregate::FIELD_COUNT, 4); assert_eq!( aggregate.field_value(FieldId::new(2)), Some(ConfigValue::U32(4)) ); aggregate .set_field(FieldId::new(3), ConfigValue::U32(3)) .unwrap(); assert!(matches!( aggregate.validate_fields(), Err(issue) if issue.primary() == Some(FieldId::new(3)) && issue.related_field() == Some(FieldId::new(4)) && issue.rule() == ValidationRule::Inconsistent )); aggregate .set_field(FieldId::new(4), ConfigValue::U32(3)) .unwrap(); aggregate.validate_fields().unwrap(); }