ortho_config 0.9.0

A configuration management library for Rust, inspired by esbuild.
Documentation
//! Property coverage for compact agent-context JSON round trips.

use super::*;
use crate::serialize_agent_context;
use proptest::{collection::vec, option, prelude::*};

proptest! {
    #[test]
    fn to_json_always_round_trips(context in any_agent_context()) {
        let json = serialize_agent_context(&context).expect("serialize compact agent context");
        let parsed: AgentContext =
            serde_json::from_str(&json).expect("parse compact agent context");

        prop_assert_eq!(parsed, context);
    }
}

fn any_agent_context() -> impl Strategy<Value = AgentContext> {
    (package_name(), vec(any_agent_command(), 0..4)).prop_map(|(package, commands)| AgentContext {
        schema_version: ORTHO_AGENT_CONTEXT_SCHEMA_VERSION.to_owned(),
        kind: crate::agent_context_kind(&package),
        package,
        commands,
        profiles: SupportDeclaration { supported: false },
        feedback: SupportDeclaration { supported: false },
        policy: AgentPolicy {
            agent_native: PolicyMode::Warn,
        },
        skill_manifests: Vec::new(),
    })
}

fn any_agent_command() -> impl Strategy<Value = AgentCommand> {
    (
        vec(command_segment(), 1..4),
        option::of(summary()),
        option::of(command_segment()),
        vec(any_agent_input(), 0..4),
        vec(output_mode(), 0..4),
        interaction_mode(),
        mutation_effect(),
        option::of(async_submission()),
        option::of(delivery_route()),
        option::of(pagination_contract()),
        vec(any_agent_example(), 0..4),
    )
        .prop_map(
            |(
                path,
                summary,
                canonical_verb,
                inputs,
                output_modes,
                interaction_mode,
                mutation_effect,
                async_submission,
                delivery_route,
                pagination,
                examples,
            )| AgentCommand {
                path,
                summary,
                canonical_verb,
                inputs,
                output_modes,
                interaction_mode,
                mutation_effect,
                async_submission,
                delivery_route,
                pagination,
                examples,
            },
        )
}

fn any_agent_input() -> impl Strategy<Value = AgentInput> {
    (
        command_segment(),
        option::of(command_segment()),
        option::of(value_type()),
        any::<bool>(),
        option::of(summary()),
        vec(summary(), 0..4),
    )
        .prop_map(
            |(name, long, value_type, required, default, enum_values)| AgentInput {
                name,
                long,
                value_type,
                required,
                default,
                enum_values,
            },
        )
}

fn any_agent_example() -> impl Strategy<Value = AgentExample> {
    (summary(), option::of(output_mode())).prop_map(|(command, output_mode)| AgentExample {
        command,
        output_mode,
    })
}

fn async_submission() -> impl Strategy<Value = AsyncSubmission> {
    (async_submission_mode(), option::of(summary()))
        .prop_map(|(mode, noun)| AsyncSubmission { mode, noun })
}

fn async_submission_mode() -> impl Strategy<Value = AsyncSubmissionMode> {
    prop_oneof![
        Just(AsyncSubmissionMode::Inline),
        Just(AsyncSubmissionMode::Submit),
    ]
}

fn delivery_route() -> impl Strategy<Value = DeliveryRoute> {
    (any::<bool>(), option::of(summary()))
        .prop_map(|(supported, target)| DeliveryRoute { supported, target })
}

fn pagination_contract() -> impl Strategy<Value = PaginationContract> {
    (option::of(command_segment()), option::of(command_segment())).prop_map(
        |(limit_input, cursor_input)| PaginationContract {
            limit_input,
            cursor_input,
        },
    )
}

fn output_mode() -> impl Strategy<Value = String> {
    prop_oneof![Just("json".to_owned()), Just("text".to_owned())]
}

fn value_type() -> impl Strategy<Value = String> {
    prop_oneof![
        Just("string".to_owned()),
        Just("bool".to_owned()),
        Just("path".to_owned()),
        Just("enum".to_owned()),
    ]
}

fn interaction_mode() -> impl Strategy<Value = InteractionMode> {
    prop_oneof![
        Just(InteractionMode::Unknown),
        Just(InteractionMode::NonInteractive),
        Just(InteractionMode::Interactive),
    ]
}

fn mutation_effect() -> impl Strategy<Value = MutationEffect> {
    prop_oneof![
        Just(MutationEffect::Unknown),
        Just(MutationEffect::ReadOnly),
        Just(MutationEffect::Write),
        Just(MutationEffect::Delete),
        Just(MutationEffect::Submit),
    ]
}

fn package_name() -> impl Strategy<Value = String> {
    "[A-Za-z0-9_.-]{0,16}"
}

fn command_segment() -> impl Strategy<Value = String> {
    "[a-z][a-z0-9-]{0,12}"
}

fn summary() -> impl Strategy<Value = String> {
    "[A-Za-z0-9 .,;-]{0,48}"
}