use super::*;
use crate::snippets::types::{SnippetMetadata, SourceOrigin};
use crate::snippets::validators::SnippetValidator;
struct CappedValidator {
language: crate::snippets::types::Language,
ceiling: ValidationLevel,
}
impl SnippetValidator for CappedValidator {
fn language(&self) -> crate::snippets::types::Language {
self.language
}
fn is_available(&self) -> bool {
true
}
fn validate(
&self,
_snippet: &Snippet,
_level: ValidationLevel,
_timeout_secs: u64,
) -> Result<(SnippetStatus, Option<String>)> {
Ok((SnippetStatus::Pass, None))
}
fn max_level(&self) -> ValidationLevel {
self.ceiling
}
}
fn network_snippet() -> Snippet {
Snippet {
id: None,
path: "example.md".into(),
language: crate::snippets::types::Language::Rust,
title: None,
code: "fn main() {}".into(),
start_line: 1,
block_index: 0,
annotation: None,
metadata: SnippetMetadata {
side_effect: Some(SideEffectClass::Network),
..SnippetMetadata::default()
},
source_origin: SourceOrigin {
path: "example.md".into(),
line: 1,
block_index: 0,
},
}
}
#[test]
fn validator_ceiling_passes_instead_of_downgrading() {
let mut registry = ValidatorRegistry::new();
registry.register(Box::new(CappedValidator {
language: crate::snippets::types::Language::Rust,
ceiling: ValidationLevel::Syntax,
}));
let config = RunnerConfig {
level: ValidationLevel::TypeCheck,
parallelism: 1,
cache_dir: None,
allowed_side_effects: vec![SideEffectClass::Network],
..RunnerConfig::default()
};
let summary = run_validation(&[network_snippet()], ®istry, &config).expect("validation completes");
assert_eq!(summary.results[0].status, SnippetStatus::Pass);
assert!(summary.results[0].capability_capped);
assert_eq!(summary.downgraded, 0);
assert_eq!(summary.capability_capped, 1);
assert_eq!(summary.results[0].effective_level, ValidationLevel::Syntax);
assert_eq!(
summary.results[0].downgrade_reason,
Some(DowngradeReason::ValidatorCapability)
);
}
#[test]
fn annotation_downgrade_is_not_treated_as_a_capability_ceiling() {
let mut registry = ValidatorRegistry::new();
registry.register(Box::new(CappedValidator {
language: crate::snippets::types::Language::Rust,
ceiling: ValidationLevel::Run,
}));
let mut snippet = network_snippet();
snippet.annotation = Some(crate::snippets::types::SnippetAnnotation {
kind: SnippetAnnotationKind::SyntaxOnly,
reason: None,
});
let config = RunnerConfig {
level: ValidationLevel::TypeCheck,
parallelism: 1,
cache_dir: None,
allowed_side_effects: vec![SideEffectClass::Network],
..RunnerConfig::default()
};
let summary = run_validation(&[snippet], ®istry, &config).expect("validation completes");
assert_eq!(summary.results[0].status, SnippetStatus::Downgraded);
assert!(!summary.results[0].capability_capped);
assert_eq!(summary.downgraded, 1);
assert_eq!(summary.capability_capped, 0);
assert_eq!(summary.results[0].downgrade_reason, Some(DowngradeReason::Annotation));
}
struct EnvironmentLimitedValidator {
language: crate::snippets::types::Language,
}
impl SnippetValidator for EnvironmentLimitedValidator {
fn language(&self) -> crate::snippets::types::Language {
self.language
}
fn is_available(&self) -> bool {
true
}
fn validate(
&self,
_snippet: &Snippet,
_level: ValidationLevel,
_timeout_secs: u64,
) -> Result<(SnippetStatus, Option<String>)> {
Ok((SnippetStatus::Pass, None))
}
fn max_level(&self) -> ValidationLevel {
ValidationLevel::Run
}
fn achievable_level(&self, requested: ValidationLevel) -> ValidationLevel {
if requested == ValidationLevel::TypeCheck {
ValidationLevel::Syntax
} else {
ValidationLevel::Run
}
}
}
#[test]
fn environment_limited_validator_downgrades_instead_of_capability_capping() {
let mut registry = ValidatorRegistry::new();
registry.register(Box::new(EnvironmentLimitedValidator {
language: crate::snippets::types::Language::Rust,
}));
let config = RunnerConfig {
level: ValidationLevel::TypeCheck,
parallelism: 1,
cache_dir: None,
allowed_side_effects: vec![SideEffectClass::Network],
..RunnerConfig::default()
};
let summary = run_validation(&[network_snippet()], ®istry, &config).expect("validation completes");
assert_eq!(summary.results[0].status, SnippetStatus::Downgraded);
assert!(!summary.results[0].capability_capped);
assert_eq!(summary.results[0].effective_level, ValidationLevel::Syntax);
assert_eq!(summary.downgraded, 1);
assert_eq!(summary.capability_capped, 0);
assert_eq!(summary.results[0].downgrade_reason, Some(DowngradeReason::Environment));
}
struct StructurallyCappedAchievableValidator {
language: crate::snippets::types::Language,
}
impl SnippetValidator for StructurallyCappedAchievableValidator {
fn language(&self) -> crate::snippets::types::Language {
self.language
}
fn is_available(&self) -> bool {
true
}
fn validate(
&self,
_snippet: &Snippet,
_level: ValidationLevel,
_timeout_secs: u64,
) -> Result<(SnippetStatus, Option<String>)> {
Ok((SnippetStatus::Pass, None))
}
fn max_level(&self) -> ValidationLevel {
ValidationLevel::Run
}
fn achievable_level(&self, requested: ValidationLevel) -> ValidationLevel {
if requested == ValidationLevel::TypeCheck {
ValidationLevel::Syntax
} else {
ValidationLevel::Run
}
}
fn achievable_level_is_structural(&self, requested: ValidationLevel) -> bool {
requested == ValidationLevel::TypeCheck
}
}
#[test]
fn structural_achievable_level_gap_is_capability_capped_not_downgraded() {
let mut registry = ValidatorRegistry::new();
registry.register(Box::new(StructurallyCappedAchievableValidator {
language: crate::snippets::types::Language::Rust,
}));
let config = RunnerConfig {
level: ValidationLevel::TypeCheck,
parallelism: 1,
cache_dir: None,
allowed_side_effects: vec![SideEffectClass::Network],
..RunnerConfig::default()
};
let summary = run_validation(&[network_snippet()], ®istry, &config).expect("validation completes");
assert_eq!(summary.results[0].status, SnippetStatus::Pass);
assert!(summary.results[0].capability_capped);
assert_eq!(summary.results[0].effective_level, ValidationLevel::Syntax);
assert_eq!(summary.downgraded, 0);
assert_eq!(summary.capability_capped, 1);
assert_eq!(
summary.results[0].downgrade_reason,
Some(DowngradeReason::ValidatorCapability)
);
}
#[test]
fn declared_level_contract_passes_instead_of_downgrading() {
let mut registry = ValidatorRegistry::new();
registry.register(Box::new(CappedValidator {
language: crate::snippets::types::Language::Rust,
ceiling: ValidationLevel::Run,
}));
let mut snippet = network_snippet();
snippet.metadata.level = Some(ValidationLevel::Syntax);
let config = RunnerConfig {
level: ValidationLevel::TypeCheck,
parallelism: 1,
cache_dir: None,
allowed_side_effects: vec![SideEffectClass::Network],
..RunnerConfig::default()
};
let summary = run_validation(&[snippet], ®istry, &config).expect("validation completes");
assert_eq!(summary.results[0].status, SnippetStatus::Pass);
assert!(!summary.results[0].capability_capped);
assert_eq!(summary.results[0].effective_level, ValidationLevel::Syntax);
assert_eq!(summary.downgraded, 0);
assert_eq!(summary.capability_capped, 0);
assert_eq!(summary.results[0].downgrade_reason, Some(DowngradeReason::Declared));
assert_eq!(
summary.results[0].message.as_deref(),
Some("requested typecheck, validated at declared level syntax")
);
}
#[test]
fn declared_typecheck_ceiling_names_the_clamped_run_request() {
let mut registry = ValidatorRegistry::new();
registry.register(Box::new(CappedValidator {
language: crate::snippets::types::Language::Rust,
ceiling: ValidationLevel::Run,
}));
let mut snippet = network_snippet();
snippet.metadata.level = Some(ValidationLevel::TypeCheck);
let config = RunnerConfig {
level: ValidationLevel::Run,
parallelism: 1,
cache_dir: None,
allowed_side_effects: vec![SideEffectClass::Network],
..RunnerConfig::default()
};
let summary = run_validation(&[snippet], ®istry, &config).expect("validation completes");
assert_eq!(summary.results[0].status, SnippetStatus::Pass);
assert_eq!(summary.results[0].effective_level, ValidationLevel::TypeCheck);
assert_eq!(summary.results[0].downgrade_reason, Some(DowngradeReason::Declared));
assert_eq!(
summary.results[0].message.as_deref(),
Some("requested run, validated at declared level typecheck"),
"a `run` request clamped by a snippet's declared level must name both the request and \
the level it was clamped to, not just the clamped level"
);
}
#[test]
fn legitimately_configured_lower_level_has_no_downgrade_reason() {
let mut registry = ValidatorRegistry::new();
registry.register(Box::new(CappedValidator {
language: crate::snippets::types::Language::Rust,
ceiling: ValidationLevel::Run,
}));
let config = RunnerConfig {
level: ValidationLevel::TypeCheck,
parallelism: 1,
cache_dir: None,
allowed_side_effects: vec![SideEffectClass::Network],
..RunnerConfig::default()
};
let summary = run_validation(&[network_snippet()], ®istry, &config).expect("validation completes");
assert_eq!(summary.results[0].status, SnippetStatus::Pass);
assert_eq!(summary.results[0].effective_level, ValidationLevel::TypeCheck);
assert_eq!(summary.results[0].downgrade_reason, None);
assert_eq!(summary.results[0].message, None);
}
#[test]
fn declared_level_the_validator_cannot_reach_still_downgrades() {
let mut registry = ValidatorRegistry::new();
registry.register(Box::new(EnvironmentLimitedValidator {
language: crate::snippets::types::Language::Rust,
}));
let mut snippet = network_snippet();
snippet.metadata.level = Some(ValidationLevel::Compile);
let config = RunnerConfig {
level: ValidationLevel::TypeCheck,
parallelism: 1,
cache_dir: None,
allowed_side_effects: vec![SideEffectClass::Network],
..RunnerConfig::default()
};
let summary = run_validation(&[snippet], ®istry, &config).expect("validation completes");
assert_eq!(summary.results[0].status, SnippetStatus::Downgraded);
assert!(!summary.results[0].capability_capped);
assert_eq!(summary.results[0].effective_level, ValidationLevel::Syntax);
assert_eq!(summary.results[0].downgrade_reason, Some(DowngradeReason::Environment));
}
#[test]
fn validator_at_or_above_requested_level_is_not_capped() {
let mut registry = ValidatorRegistry::new();
registry.register(Box::new(CappedValidator {
language: crate::snippets::types::Language::Rust,
ceiling: ValidationLevel::Run,
}));
let config = RunnerConfig {
level: ValidationLevel::Syntax,
parallelism: 1,
cache_dir: None,
allowed_side_effects: vec![SideEffectClass::Network],
..RunnerConfig::default()
};
let summary = run_validation(&[network_snippet()], ®istry, &config).expect("validation completes");
assert_eq!(summary.results[0].status, SnippetStatus::Pass);
assert!(!summary.results[0].capability_capped);
assert_eq!(summary.capability_capped, 0);
}