diff --git a/src/ast.rs b/src/ast.rs index cf4a49ea..36232e76 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -106,7 +106,8 @@ pub struct Rule { /// Exactly one variant must be provided for a rule or target. The fields are /// flattened in the manifest, so the presence of `command`, `script`, or `rule` /// determines the variant. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize)] +#[serde(untagged)] pub enum Recipe { /// A single shell command. Command { command: String }, diff --git a/src/ir.rs b/src/ir.rs index 296a2ef4..deb4eefd 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -341,10 +341,10 @@ fn find_cycle(targets: &HashMap) -> Option> { states: &mut HashMap, ) -> Option> { for dep in deps { - if targets.contains_key(dep) - && let Some(cycle) = visit(targets, dep, stack, states) - { - return Some(cycle); + if targets.contains_key(dep) { + if let Some(cycle) = visit(targets, dep, stack, states) { + return Some(cycle); + } } } None diff --git a/tests/ast_tests.rs b/tests/ast_tests.rs index a5818d0a..8ad1cb29 100644 --- a/tests/ast_tests.rs +++ b/tests/ast_tests.rs @@ -1,8 +1,9 @@ -//! Unit tests for Netsuke manifest AST deserialisation. +//! Unit tests for Netsuke manifest AST serialisation and deserialisation. use netsuke::{ast::*, manifest}; use rstest::rstest; use semver::Version; +use serde_yml::Value; /// Convenience wrapper around the library manifest parser for tests. fn parse_manifest(yaml: &str) -> anyhow::Result { @@ -362,3 +363,18 @@ fn invalid_manifests_fail(#[case] file: &str) { let path = format!("tests/data/{file}"); assert!(manifest::from_path(&path).is_err()); } + +#[rstest] +#[case(Recipe::Command { command: "echo".into() }, "command: echo")] +#[case(Recipe::Script { script: "run".into() }, "script: run")] +#[case( + Recipe::Rule { + rule: StringOrList::List(vec!["a".into(), "b".into()]), + }, + concat!("rule:\n", " - a\n", " - b"), +)] +fn serialize_recipe_variants(#[case] recipe: Recipe, #[case] expected_yaml: &str) { + let actual: Value = serde_yml::to_value(&recipe).expect("serialize"); + let expected: Value = serde_yml::from_str(expected_yaml).expect("yaml"); + assert_eq!(actual, expected); +}