mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-21 02:28:07 +02:00
Extract remaining crowded compiler test modules
Files where inline tests crowded out production code (test/prod ratio ≥ 0.8) move to sibling files via `#[path]`. Files where production dominates (query_input.rs, schema_plan.rs) stay inline — extracting would add noise, not reduce it. - ir/lower.rs: 1239 → 577 lines (ratio 1.15) - catalog/mod.rs: 594 → 326 lines (ratio 0.83) - query/lint.rs: 562 → 314 lines (ratio 0.80) catalog/tests.rs uses the shorter name since it's inside a module directory (no ambiguity with filename). All 229 compiler tests green, identical count to before. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f2c3b11508
commit
54101f7e2c
6 changed files with 1184 additions and 1184 deletions
|
|
@ -310,253 +310,5 @@ fn severity_rank(severity: QueryLintSeverity) -> u8 {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::build_catalog;
|
||||
use crate::schema::parser::parse_schema;
|
||||
|
||||
fn catalog(schema: &str) -> Catalog {
|
||||
let schema = parse_schema(schema).unwrap();
|
||||
build_catalog(&schema).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_failure_returns_structured_error_output() {
|
||||
let output = lint_query_file(
|
||||
&catalog("node Person { name: String }"),
|
||||
"query broken(",
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert_eq!(output.status, QueryLintStatus::Error);
|
||||
assert_eq!(output.queries_processed, 0);
|
||||
assert_eq!(output.errors, 1);
|
||||
assert!(output.results.is_empty());
|
||||
assert_eq!(output.findings.len(), 1);
|
||||
assert_eq!(output.findings[0].severity, QueryLintSeverity::Error);
|
||||
assert_eq!(output.findings[0].code, PARSE_ERROR_CODE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mixed_valid_and_invalid_queries_preserve_per_query_results() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Person {
|
||||
slug: String @key
|
||||
name: String?
|
||||
}
|
||||
"#,
|
||||
),
|
||||
r#"
|
||||
query list_people() {
|
||||
match { $p: Person }
|
||||
return { $p.name }
|
||||
}
|
||||
|
||||
query bad_update($slug: String) {
|
||||
update Person set { missing: "nope" } where slug = $slug
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert_eq!(output.queries_processed, 2);
|
||||
assert_eq!(output.results[0].name, "list_people");
|
||||
assert_eq!(output.results[0].status, QueryLintStatus::Ok);
|
||||
assert_eq!(output.results[1].name, "bad_update");
|
||||
assert_eq!(output.results[1].status, QueryLintStatus::Error);
|
||||
assert!(
|
||||
output.results[1]
|
||||
.error
|
||||
.as_deref()
|
||||
.unwrap_or_default()
|
||||
.contains("has no property")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hardcoded_mutation_warning_only_fires_for_mutation_queries() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Person {
|
||||
slug: String @key
|
||||
name: String?
|
||||
}
|
||||
"#,
|
||||
),
|
||||
r#"
|
||||
query list_people() {
|
||||
match { $p: Person }
|
||||
return { $p.name }
|
||||
}
|
||||
|
||||
query insert_person() {
|
||||
insert Person { slug: "p1", name: "P1" }
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert!(output.results[0].warnings.is_empty());
|
||||
assert_eq!(
|
||||
output.results[1].warnings,
|
||||
vec![HARDCODED_MUTATION_WARNING.to_string()]
|
||||
);
|
||||
assert_eq!(output.warnings, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn l201_warns_for_nullable_uncovered_update_fields() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Policy {
|
||||
slug: String @key
|
||||
name: String?
|
||||
effectiveTo: DateTime?
|
||||
}
|
||||
"#,
|
||||
),
|
||||
r#"
|
||||
query update_policy($slug: String, $name: String) {
|
||||
update Policy set { name: $name } where slug = $slug
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert_eq!(output.findings.len(), 1);
|
||||
assert_eq!(output.findings[0].code, L201_CODE);
|
||||
assert_eq!(
|
||||
output.findings[0].message,
|
||||
"Policy.effectiveTo exists in schema but no update query sets it"
|
||||
);
|
||||
assert_eq!(output.findings[0].query_names, vec!["update_policy"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn l201_does_not_fire_without_valid_update_queries() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Policy {
|
||||
slug: String @key
|
||||
effectiveTo: DateTime?
|
||||
}
|
||||
"#,
|
||||
),
|
||||
r#"
|
||||
query insert_policy($slug: String) {
|
||||
insert Policy { slug: $slug }
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert!(output.findings.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn l201_excludes_embed_target_properties() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Doc {
|
||||
slug: String @key
|
||||
body: String?
|
||||
summary: String?
|
||||
embedding: Vector(3)? @embed(body)
|
||||
}
|
||||
"#,
|
||||
),
|
||||
r#"
|
||||
query update_doc($slug: String, $body: String) {
|
||||
update Doc set { body: $body } where slug = $slug
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert_eq!(output.findings.len(), 1);
|
||||
assert_eq!(output.findings[0].property.as_deref(), Some("summary"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn l201_excludes_key_properties_even_if_catalog_is_modified() {
|
||||
let mut catalog = catalog(
|
||||
r#"
|
||||
node Policy {
|
||||
slug: String @key
|
||||
name: String?
|
||||
}
|
||||
"#,
|
||||
);
|
||||
catalog
|
||||
.node_types
|
||||
.get_mut("Policy")
|
||||
.unwrap()
|
||||
.properties
|
||||
.get_mut("slug")
|
||||
.unwrap()
|
||||
.nullable = true;
|
||||
|
||||
let output = lint_query_file(
|
||||
&catalog,
|
||||
r#"
|
||||
query update_policy($slug: String, $name: String) {
|
||||
update Policy set { name: $name } where slug = $slug
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert!(
|
||||
output
|
||||
.findings
|
||||
.iter()
|
||||
.all(|finding| finding.property.as_deref() != Some("slug"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn findings_and_query_names_are_deterministic() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Policy {
|
||||
slug: String @key
|
||||
c_field: String?
|
||||
b_field: String?
|
||||
a_field: String?
|
||||
}
|
||||
"#,
|
||||
),
|
||||
&r#"
|
||||
query update_b($slug: String) {
|
||||
update Policy set { a_field: "x" } where slug = $slug
|
||||
}
|
||||
|
||||
query update_a($slug: String) {
|
||||
update Policy set { a_field: "x" } where slug = $slug
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert_eq!(output.findings.len(), 2);
|
||||
assert_eq!(output.findings[0].property.as_deref(), Some("b_field"));
|
||||
assert_eq!(output.findings[1].property.as_deref(), Some("c_field"));
|
||||
assert_eq!(output.findings[0].query_names, vec!["update_a", "update_b"]);
|
||||
assert_eq!(output.findings[1].query_names, vec!["update_a", "update_b"]);
|
||||
}
|
||||
}
|
||||
#[path = "lint_tests.rs"]
|
||||
mod tests;
|
||||
|
|
|
|||
248
crates/omnigraph-compiler/src/query/lint_tests.rs
Normal file
248
crates/omnigraph-compiler/src/query/lint_tests.rs
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
use super::*;
|
||||
use crate::build_catalog;
|
||||
use crate::schema::parser::parse_schema;
|
||||
|
||||
fn catalog(schema: &str) -> Catalog {
|
||||
let schema = parse_schema(schema).unwrap();
|
||||
build_catalog(&schema).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_failure_returns_structured_error_output() {
|
||||
let output = lint_query_file(
|
||||
&catalog("node Person { name: String }"),
|
||||
"query broken(",
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert_eq!(output.status, QueryLintStatus::Error);
|
||||
assert_eq!(output.queries_processed, 0);
|
||||
assert_eq!(output.errors, 1);
|
||||
assert!(output.results.is_empty());
|
||||
assert_eq!(output.findings.len(), 1);
|
||||
assert_eq!(output.findings[0].severity, QueryLintSeverity::Error);
|
||||
assert_eq!(output.findings[0].code, PARSE_ERROR_CODE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mixed_valid_and_invalid_queries_preserve_per_query_results() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Person {
|
||||
slug: String @key
|
||||
name: String?
|
||||
}
|
||||
"#,
|
||||
),
|
||||
r#"
|
||||
query list_people() {
|
||||
match { $p: Person }
|
||||
return { $p.name }
|
||||
}
|
||||
|
||||
query bad_update($slug: String) {
|
||||
update Person set { missing: "nope" } where slug = $slug
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert_eq!(output.queries_processed, 2);
|
||||
assert_eq!(output.results[0].name, "list_people");
|
||||
assert_eq!(output.results[0].status, QueryLintStatus::Ok);
|
||||
assert_eq!(output.results[1].name, "bad_update");
|
||||
assert_eq!(output.results[1].status, QueryLintStatus::Error);
|
||||
assert!(
|
||||
output.results[1]
|
||||
.error
|
||||
.as_deref()
|
||||
.unwrap_or_default()
|
||||
.contains("has no property")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hardcoded_mutation_warning_only_fires_for_mutation_queries() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Person {
|
||||
slug: String @key
|
||||
name: String?
|
||||
}
|
||||
"#,
|
||||
),
|
||||
r#"
|
||||
query list_people() {
|
||||
match { $p: Person }
|
||||
return { $p.name }
|
||||
}
|
||||
|
||||
query insert_person() {
|
||||
insert Person { slug: "p1", name: "P1" }
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert!(output.results[0].warnings.is_empty());
|
||||
assert_eq!(
|
||||
output.results[1].warnings,
|
||||
vec![HARDCODED_MUTATION_WARNING.to_string()]
|
||||
);
|
||||
assert_eq!(output.warnings, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn l201_warns_for_nullable_uncovered_update_fields() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Policy {
|
||||
slug: String @key
|
||||
name: String?
|
||||
effectiveTo: DateTime?
|
||||
}
|
||||
"#,
|
||||
),
|
||||
r#"
|
||||
query update_policy($slug: String, $name: String) {
|
||||
update Policy set { name: $name } where slug = $slug
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert_eq!(output.findings.len(), 1);
|
||||
assert_eq!(output.findings[0].code, L201_CODE);
|
||||
assert_eq!(
|
||||
output.findings[0].message,
|
||||
"Policy.effectiveTo exists in schema but no update query sets it"
|
||||
);
|
||||
assert_eq!(output.findings[0].query_names, vec!["update_policy"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn l201_does_not_fire_without_valid_update_queries() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Policy {
|
||||
slug: String @key
|
||||
effectiveTo: DateTime?
|
||||
}
|
||||
"#,
|
||||
),
|
||||
r#"
|
||||
query insert_policy($slug: String) {
|
||||
insert Policy { slug: $slug }
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert!(output.findings.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn l201_excludes_embed_target_properties() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Doc {
|
||||
slug: String @key
|
||||
body: String?
|
||||
summary: String?
|
||||
embedding: Vector(3)? @embed(body)
|
||||
}
|
||||
"#,
|
||||
),
|
||||
r#"
|
||||
query update_doc($slug: String, $body: String) {
|
||||
update Doc set { body: $body } where slug = $slug
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert_eq!(output.findings.len(), 1);
|
||||
assert_eq!(output.findings[0].property.as_deref(), Some("summary"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn l201_excludes_key_properties_even_if_catalog_is_modified() {
|
||||
let mut catalog = catalog(
|
||||
r#"
|
||||
node Policy {
|
||||
slug: String @key
|
||||
name: String?
|
||||
}
|
||||
"#,
|
||||
);
|
||||
catalog
|
||||
.node_types
|
||||
.get_mut("Policy")
|
||||
.unwrap()
|
||||
.properties
|
||||
.get_mut("slug")
|
||||
.unwrap()
|
||||
.nullable = true;
|
||||
|
||||
let output = lint_query_file(
|
||||
&catalog,
|
||||
r#"
|
||||
query update_policy($slug: String, $name: String) {
|
||||
update Policy set { name: $name } where slug = $slug
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert!(
|
||||
output
|
||||
.findings
|
||||
.iter()
|
||||
.all(|finding| finding.property.as_deref() != Some("slug"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn findings_and_query_names_are_deterministic() {
|
||||
let output = lint_query_file(
|
||||
&catalog(
|
||||
r#"
|
||||
node Policy {
|
||||
slug: String @key
|
||||
c_field: String?
|
||||
b_field: String?
|
||||
a_field: String?
|
||||
}
|
||||
"#,
|
||||
),
|
||||
&r#"
|
||||
query update_b($slug: String) {
|
||||
update Policy set { a_field: "x" } where slug = $slug
|
||||
}
|
||||
|
||||
query update_a($slug: String) {
|
||||
update Policy set { a_field: "x" } where slug = $slug
|
||||
}
|
||||
"#,
|
||||
"/tmp/queries.gq",
|
||||
QueryLintSchemaSource::file("/tmp/schema.pg"),
|
||||
);
|
||||
|
||||
assert_eq!(output.findings.len(), 2);
|
||||
assert_eq!(output.findings[0].property.as_deref(), Some("b_field"));
|
||||
assert_eq!(output.findings[1].property.as_deref(), Some("c_field"));
|
||||
assert_eq!(output.findings[0].query_names, vec!["update_a", "update_b"]);
|
||||
assert_eq!(output.findings[1].query_names, vec!["update_a", "update_b"]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue