From 0437ad5200ecabe7591ff89a6fe6e6f1bbc2a81d Mon Sep 17 00:00:00 2001 From: alexion Date: Fri, 11 Sep 2026 21:25:08 -0400 Subject: [PATCH] test(ariadne): move Clew tests out of module --- AGENTS.md | 1 + src/ariadne/BUILD | 8 +- src/ariadne/Cargo.toml | 4 + src/ariadne/clew.rs | 154 --------------------------------------- src/ariadne/clew_test.rs | 151 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 162 insertions(+), 156 deletions(-) create mode 100644 src/ariadne/clew_test.rs diff --git a/AGENTS.md b/AGENTS.md index bb3f712..632e91d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -95,6 +95,7 @@ committing a top-down rewrite. - `rules_rust` `rust_test` targets cannot set both `crate` and `srcs`. Use one input style per test target. +- Rust tests in this monorepo live in separate `*_test.rs` files, not inline `#[cfg(test)]` modules. - In this monorepo, "dotfiles" refers to the dotfiles/NixOS configuration under `src/dotfiles/` and `configs/nixos/`. - The flake does not currently define `formatter.x86_64-linux`. Do not use `nix fmt` as a validation command until a formatter is added. diff --git a/src/ariadne/BUILD b/src/ariadne/BUILD index efb91fd..d035e0b 100644 --- a/src/ariadne/BUILD +++ b/src/ariadne/BUILD @@ -25,8 +25,12 @@ rust_binary( ) rust_test( - name = "ariadne_lib_test", - crate = ":ariadne_lib", + name = "clew_test", + srcs = ["clew_test.rs"], + deps = [ + ":ariadne_lib", + "//third_party/crates:serde_json", + ], ) rust_test( diff --git a/src/ariadne/Cargo.toml b/src/ariadne/Cargo.toml index 9479df0..a6a4d46 100644 --- a/src/ariadne/Cargo.toml +++ b/src/ariadne/Cargo.toml @@ -10,6 +10,10 @@ path = "lib.rs" name = "ariadne" path = "main.rs" +[[test]] +name = "clew_test" +path = "clew_test.rs" + [dependencies] clap = { version = "4", features = ["derive"] } serde = { version = "1.0", features = ["derive"] } diff --git a/src/ariadne/clew.rs b/src/ariadne/clew.rs index 6b364f6..94bb6f7 100644 --- a/src/ariadne/clew.rs +++ b/src/ariadne/clew.rs @@ -279,157 +279,3 @@ fn take_u64(object: &mut Map, field: &str) -> Result< None => Err(format!("missing Clew {field} field")), } } - -#[cfg(test)] -mod tests { - use super::*; - - fn document_with(roots: &str) -> String { - format!( - r#"{{ - "schema":"clew-renpy-ast-v1", - "source":"/tmp/game/script.rpyc", - "game_root":"/tmp/game", - "slot":2, - "python_version":"2.7.18", - "renpy_version":"8.4.0", - "metadata":null, - "roots":{roots} - }}"# - ) - } - - #[test] - fn parses_minimal_document() { - let document = from_bytes(document_with("null").as_bytes()).unwrap(); - - assert_eq!(document.schema, "clew-renpy-ast-v1"); - assert_eq!(document.slot, 2); - assert_eq!(document.roots, Value::Null); - } - - #[test] - fn rejects_wrong_schema() { - let json = br#"{ - "schema":"other", - "source":"/tmp/game/script.rpyc", - "game_root":"/tmp/game", - "slot":2, - "python_version":"2.7.18", - "renpy_version":null, - "metadata":null, - "roots":null - }"#; - - assert!(matches!( - from_bytes(json).unwrap_err(), - Error::SchemaMismatch { - expected: "clew-renpy-ast-v1", - actual - } if actual == "other" - )); - } - - #[test] - fn parses_primitive_values() { - let document = from_bytes( - document_with(r#"{"type":"list","items":[null,true,7,1.5,"text"]}"#).as_bytes(), - ) - .unwrap(); - - assert_eq!( - document.roots, - Value::List(vec![ - Value::Null, - Value::Bool(true), - Value::Number(Number::from(7)), - Value::Number(Number::from_f64(1.5).unwrap()), - Value::String("text".to_string()), - ]) - ); - } - - #[test] - fn parses_tuple_and_dict_values() { - let document = from_bytes( - document_with(r#"{"type":"dict","items":[{"key":"names","value":{"type":"tuple","items":["a","b"]}}]}"#) - .as_bytes(), - ) - .unwrap(); - - assert_eq!( - document.roots, - Value::Dict(vec![DictEntry { - key: Value::String("names".to_string()), - value: Value::Tuple(vec![ - Value::String("a".to_string()), - Value::String("b".to_string()) - ]), - }]) - ); - } - - #[test] - fn parses_object_and_reference_values() { - let document = from_bytes( - document_with( - r#"{"type":"list","items":[{"type":"object","id":1,"class":"renpy.ast.Label","attributes":{"name":"start","next":{"type":"ref","id":1}}},{"type":"ref","id":1}]}"#, - ) - .as_bytes(), - ) - .unwrap(); - - let Value::List(items) = document.roots else { - panic!("roots should be a list"); - }; - assert_eq!(items.len(), 2); - assert_eq!(items[1], Value::Ref { id: 1 }); - let Value::Object(object) = &items[0] else { - panic!("first item should be an object"); - }; - assert_eq!(object.id, 1); - assert_eq!(object.class_name, "renpy.ast.Label"); - assert_eq!( - object.attributes["name"], - Value::String("start".to_string()) - ); - } - - #[test] - fn parses_special_tag_values() { - let document = from_bytes( - document_with( - r#"{"type":"list","items":[{"type":"function","name":"f","module":"m","filename":"file.py","firstlineno":9},{"type":"method","name":"g","module":"m","receiver_class":"C"},{"type":"python-type","name":"Label","module":"renpy.ast"},{"type":"repr","class":"C","repr":""},{"type":"bytes","repr":"b'abc'"},{"type":"truncated","class":"C","repr":""},{"type":"recursion","class":"list"},{"type":"attribute-error","class":"Exception","repr":"Exception('x')"}]}"#, - ) - .as_bytes(), - ) - .unwrap(); - - let Value::List(items) = document.roots else { - panic!("roots should be a list"); - }; - assert_eq!(items.len(), 8); - assert!(matches!(items[0], Value::Function(_))); - assert!(matches!(items[1], Value::Method(_))); - assert!(matches!(items[2], Value::PythonType(_))); - assert!(matches!(items[3], Value::Repr { .. })); - assert!(matches!(items[4], Value::Bytes { .. })); - assert!(matches!(items[5], Value::Truncated { .. })); - assert!(matches!(items[6], Value::Recursion { .. })); - assert!(matches!(items[7], Value::AttributeError { .. })); - } - - #[test] - fn rejects_unknown_tags() { - let error = from_bytes(document_with(r#"{"type":"future"}"#).as_bytes()).unwrap_err(); - - match error { - Error::Json(error) => assert!( - error - .to_string() - .contains("unknown Clew value type: future") - ), - Error::SchemaMismatch { .. } => panic!("unknown tags should be JSON shape errors"), - } - } -} diff --git a/src/ariadne/clew_test.rs b/src/ariadne/clew_test.rs new file mode 100644 index 0000000..9462859 --- /dev/null +++ b/src/ariadne/clew_test.rs @@ -0,0 +1,151 @@ +use ariadne::clew::{self, DictEntry, Error, Value}; +use serde_json::Number; + +fn document_with(roots: &str) -> String { + format!( + r#"{{ + "schema":"clew-renpy-ast-v1", + "source":"/tmp/game/script.rpyc", + "game_root":"/tmp/game", + "slot":2, + "python_version":"2.7.18", + "renpy_version":"8.4.0", + "metadata":null, + "roots":{roots} + }}"# + ) +} + +#[test] +fn parses_minimal_document() { + let document = clew::from_bytes(document_with("null").as_bytes()).unwrap(); + + assert_eq!(document.schema, "clew-renpy-ast-v1"); + assert_eq!(document.slot, 2); + assert_eq!(document.roots, Value::Null); +} + +#[test] +fn rejects_wrong_schema() { + let json = br#"{ + "schema":"other", + "source":"/tmp/game/script.rpyc", + "game_root":"/tmp/game", + "slot":2, + "python_version":"2.7.18", + "renpy_version":null, + "metadata":null, + "roots":null + }"#; + + assert!(matches!( + clew::from_bytes(json).unwrap_err(), + Error::SchemaMismatch { + expected: "clew-renpy-ast-v1", + actual + } if actual == "other" + )); +} + +#[test] +fn parses_primitive_values() { + let document = clew::from_bytes( + document_with(r#"{"type":"list","items":[null,true,7,1.5,"text"]}"#).as_bytes(), + ) + .unwrap(); + + assert_eq!( + document.roots, + Value::List(vec![ + Value::Null, + Value::Bool(true), + Value::Number(Number::from(7)), + Value::Number(Number::from_f64(1.5).unwrap()), + Value::String("text".to_string()), + ]) + ); +} + +#[test] +fn parses_tuple_and_dict_values() { + let document = clew::from_bytes( + document_with(r#"{"type":"dict","items":[{"key":"names","value":{"type":"tuple","items":["a","b"]}}]}"#) + .as_bytes(), + ) + .unwrap(); + + assert_eq!( + document.roots, + Value::Dict(vec![DictEntry { + key: Value::String("names".to_string()), + value: Value::Tuple(vec![ + Value::String("a".to_string()), + Value::String("b".to_string()) + ]), + }]) + ); +} + +#[test] +fn parses_object_and_reference_values() { + let document = clew::from_bytes( + document_with( + r#"{"type":"list","items":[{"type":"object","id":1,"class":"renpy.ast.Label","attributes":{"name":"start","next":{"type":"ref","id":1}}},{"type":"ref","id":1}]}"#, + ) + .as_bytes(), + ) + .unwrap(); + + let Value::List(items) = document.roots else { + panic!("roots should be a list"); + }; + assert_eq!(items.len(), 2); + assert_eq!(items[1], Value::Ref { id: 1 }); + let Value::Object(object) = &items[0] else { + panic!("first item should be an object"); + }; + assert_eq!(object.id, 1); + assert_eq!(object.class_name, "renpy.ast.Label"); + assert_eq!( + object.attributes["name"], + Value::String("start".to_string()) + ); +} + +#[test] +fn parses_special_tag_values() { + let document = clew::from_bytes( + document_with( + r#"{"type":"list","items":[{"type":"function","name":"f","module":"m","filename":"file.py","firstlineno":9},{"type":"method","name":"g","module":"m","receiver_class":"C"},{"type":"python-type","name":"Label","module":"renpy.ast"},{"type":"repr","class":"C","repr":""},{"type":"bytes","repr":"b'abc'"},{"type":"truncated","class":"C","repr":""},{"type":"recursion","class":"list"},{"type":"attribute-error","class":"Exception","repr":"Exception('x')"}]}"#, + ) + .as_bytes(), + ) + .unwrap(); + + let Value::List(items) = document.roots else { + panic!("roots should be a list"); + }; + assert_eq!(items.len(), 8); + assert!(matches!(items[0], Value::Function(_))); + assert!(matches!(items[1], Value::Method(_))); + assert!(matches!(items[2], Value::PythonType(_))); + assert!(matches!(items[3], Value::Repr { .. })); + assert!(matches!(items[4], Value::Bytes { .. })); + assert!(matches!(items[5], Value::Truncated { .. })); + assert!(matches!(items[6], Value::Recursion { .. })); + assert!(matches!(items[7], Value::AttributeError { .. })); +} + +#[test] +fn rejects_unknown_tags() { + let error = clew::from_bytes(document_with(r#"{"type":"future"}"#).as_bytes()).unwrap_err(); + + match error { + Error::Json(error) => assert!( + error + .to_string() + .contains("unknown Clew value type: future") + ), + Error::SchemaMismatch { .. } => panic!("unknown tags should be JSON shape errors"), + } +}