use serde::{Deserialize, Serialize};
use crate::budget::BudgetPolicy;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum Criticality {
Critical,
#[default]
Normal,
Low,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum ExpectedResult {
#[default]
Success,
Failure,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Scenario {
pub name: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub tags: Vec<String>,
#[serde(default)]
pub criticality: Criticality,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub owner: Option<String>,
#[serde(default)]
pub expected: ExpectedResult,
#[serde(default)]
pub budget: BudgetPolicy,
#[serde(default = "default_samples")]
pub samples: u32,
}
fn default_samples() -> u32 {
1
}
impl Scenario {
#[must_use]
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
description: String::new(),
tags: Vec::new(),
criticality: Criticality::Normal,
owner: None,
expected: ExpectedResult::Success,
budget: BudgetPolicy::default(),
samples: 1,
}
}
#[must_use]
pub fn has_tag(&self, tag: &str) -> bool {
self.tags.iter().any(|t| t == tag)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_are_sane() {
let s = Scenario::new("swap/happy_path");
assert_eq!(s.samples, 1);
assert_eq!(s.expected, ExpectedResult::Success);
assert_eq!(s.criticality, Criticality::Normal);
}
#[test]
fn tag_filtering() {
let mut s = Scenario::new("swap/large_pool");
s.tags = vec!["swap".into(), "hot-path".into()];
assert!(s.has_tag("hot-path"));
assert!(!s.has_tag("admin"));
}
}