test(ariadne): move Clew tests out of module
This commit is contained in:
@@ -95,6 +95,7 @@
|
|||||||
committing a top-down rewrite.
|
committing a top-down rewrite.
|
||||||
- `rules_rust` `rust_test` targets cannot set both `crate` and `srcs`.
|
- `rules_rust` `rust_test` targets cannot set both `crate` and `srcs`.
|
||||||
Use one input style per test target.
|
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/`.
|
- 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`.
|
- The flake does not currently define `formatter.x86_64-linux`.
|
||||||
Do not use `nix fmt` as a validation command until a formatter is added.
|
Do not use `nix fmt` as a validation command until a formatter is added.
|
||||||
|
|||||||
@@ -25,8 +25,12 @@ rust_binary(
|
|||||||
)
|
)
|
||||||
|
|
||||||
rust_test(
|
rust_test(
|
||||||
name = "ariadne_lib_test",
|
name = "clew_test",
|
||||||
crate = ":ariadne_lib",
|
srcs = ["clew_test.rs"],
|
||||||
|
deps = [
|
||||||
|
":ariadne_lib",
|
||||||
|
"//third_party/crates:serde_json",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
rust_test(
|
rust_test(
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ path = "lib.rs"
|
|||||||
name = "ariadne"
|
name = "ariadne"
|
||||||
path = "main.rs"
|
path = "main.rs"
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "clew_test"
|
||||||
|
path = "clew_test.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4", features = ["derive"] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|||||||
@@ -279,157 +279,3 @@ fn take_u64(object: &mut Map<String, serde_json::Value>, field: &str) -> Result<
|
|||||||
None => Err(format!("missing Clew {field} field")),
|
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":"<C>"},{"type":"bytes","repr":"b'abc'"},{"type":"truncated","class":"C","repr":"<C>"},{"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"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
151
src/ariadne/clew_test.rs
Normal file
151
src/ariadne/clew_test.rs
Normal file
@@ -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":"<C>"},{"type":"bytes","repr":"b'abc'"},{"type":"truncated","class":"C","repr":"<C>"},{"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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user