passing all tests

This commit is contained in:
2026-03-11 17:26:45 -04:00
parent 44be75f5d4
commit 2c74d0a1a6
8 changed files with 9181 additions and 1210 deletions

View File

@ -8,9 +8,11 @@ Read over this entire workflow and commit to every section of work in a task lis
Please analyze the files and directories and do not use cat, find, or the terminal to discover or read in any of these files. Analyze every file mentioned. If a directory is mentioned or a /*, please analyze the directory, every single file at its root, and recursively analyze every subdirectory and every single file in every subdirectory to capture not just critical files, but the entirety of what is requested. I state again, DO NOT just review a cherry picking of files in any folder or wildcard specified. Review 100% of all files discovered recursively!
Section 1: Documentation
Section 1: Various Documentation
- GEMINI.md at the root
- GEMINI.md at the root (JSPG doc)
- api/punc/GEMINI.md
- api/punc/generator/GEMINI.md
Section 2: Flow file for cmd interface
@ -22,7 +24,14 @@ Section 3: Source
Section 4: Test Fixtures
- Just review some of the *.json files in tests/fixtures/*
Just review some of the *.json files in fixtures/ at the root
- fixtures/allOf.json
- fixtures/ref.json
- fixtures/contains.json
- fixtures/queryer.json
- fixtures/merger.json
- fixtures/merge.json
Section 5: Build
@ -36,14 +45,19 @@ Section 7: Some PUNC Syntax
Now, review some punc type and enum source in the api project with api/ these files:
- punc/sql/tables.sql
- punc/sql/domains.sql
- punc/sql/indexes.sql
- punc/sql/functions/entity.sql
- punc/sql/functions/puncs.sql
- punc/sql/puncs/entity.sql
- punc/sql/puncs/persons.sql
- punc/sql/puncs/puncs.sql
- punc/sql/puncs/job.sql
- api/punc/sql/tables.sql
- api/punc/sql/domains.sql
- api/punc/sql/indexes.sql
- api/punc/sql/functions/entity.sql
- api/punc/sql/functions/puncs.sql
- api/punc/sql/puncs/entity.sql
- api/punc/sql/puncs/persons.sql
- api/punc/sql/puncs/puncs.sql
- api/punc/sql/puncs/job.sql
- api/contact/sql/tables.sql
- api/contact/sql/domains.sql
- api/contact/sql/indexes.sql
- api/contact/sql/domains.sql
- api/contact/sql/puncs/contacts.sql
Now you are ready to help me work on this extension.

View File

@ -63,6 +63,7 @@ fn main() {
.unwrap()
.as_array()
.expect("Tests must be an array");
let safe_filename = to_safe_identifier(file_name);
for (t_idx, test) in tests.iter().enumerate() {
let t_obj = test.as_object().expect("Test case must be an object");
if !t_obj.contains_key("description") {
@ -71,25 +72,24 @@ fn main() {
file_name, i, t_idx
);
}
}
// Use deterministic names: test_{filename}_{index}
let safe_filename = to_safe_identifier(file_name);
let fn_name = format!("test_{}_{}", safe_filename, i);
// Use deterministic names: test_{filename}_{suite_idx}_{test_idx}
let fn_name = format!("test_{}_{}_{}", safe_filename, i, t_idx);
// Write to src/tests/fixtures.rs (Std Test)
write!(
std_file,
r#"
// Write to src/tests/fixtures.rs (Std Test)
write!(
std_file,
r#"
#[test]
fn {}() {{
let path = format!("{{}}/fixtures/{}.json", env!("CARGO_MANIFEST_DIR"));
crate::tests::runner::run_test_file_at_index(&path, {}).unwrap();
crate::tests::runner::run_test_case(&path, {}, {}).unwrap();
}}
"#,
fn_name, file_name, i
)
.unwrap();
fn_name, file_name, i, t_idx
)
.unwrap();
}
}
}
}

View File

@ -137,13 +137,923 @@
"success": true,
"sql": [
"SELECT to_jsonb(t1.*) || to_jsonb(t2.*) FROM agreego.\"simple_entity\" t1 LEFT JOIN agreego.\"entity\" t2 ON t2.id = t1.id WHERE t1.id = '123'",
"INSERT INTO agreego.\"simple_entity\" (\"id\", \"name\", \"type\") VALUES ('123', 'Jane', 'simple_entity')",
"INSERT INTO agreego.\"entity\" (\"created_at\", \"created_by\", \"id\", \"modified_at\", \"modified_by\", \"type\") VALUES ('{{timestamp}}', '00000000-0000-0000-0000-000000000000', '123', '{{timestamp}}', '00000000-0000-0000-0000-000000000000', 'simple_entity')",
"INSERT INTO agreego.\"simple_entity\" (\"id\", \"name\", \"type\") VALUES ('123', 'Jane', 'simple_entity')",
"INSERT INTO agreego.change (changes, entity_id, id, kind, modified_at, modified_by) VALUES ('{\"name\":\"Jane\",\"type\":\"simple_entity\"}', '123', '{{uuid}}', 'create', '{{timestamp}}', '00000000-0000-0000-0000-000000000000')",
"SELECT pg_notify('entity', '{\"complete\":{\"created_at\":\"{{timestamp}}\",\"created_by\":\"00000000-0000-0000-0000-000000000000\",\"id\":\"123\",\"modified_at\":\"{{timestamp}}\",\"modified_by\":\"00000000-0000-0000-0000-000000000000\",\"name\":\"Jane\",\"type\":\"simple_entity\"}}')"
]
}
}
]
},
{
"description": "Hierarchical Lookups and Inserts",
"database": {
"puncs": [],
"enums": [],
"relations": [],
"types": [
{
"name": "entity",
"schemas": [
{
"$id": "entity",
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"created_by": {
"type": "string"
},
"modified_by": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"modified_at": {
"type": "string",
"format": "date-time"
}
},
"required": [
"id",
"type",
"created_by",
"created_at",
"modified_by",
"modified_at"
]
}
],
"hierarchy": [
"entity"
],
"fields": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [],
"historical": false,
"relationship": false
},
{
"name": "organization",
"schemas": [
{
"$id": "organization",
"$ref": "entity",
"properties": {
"name": {
"type": "string"
}
}
}
],
"hierarchy": [
"organization",
"entity"
],
"fields": [
"id",
"type",
"name",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"organization": [
"id",
"type",
"name"
],
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [],
"historical": true,
"relationship": false
},
{
"name": "user",
"schemas": [
{
"$id": "user",
"$ref": "organization",
"properties": {}
}
],
"hierarchy": [
"user",
"organization",
"entity"
],
"fields": [
"id",
"type",
"name",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"user": [
"id",
"type"
],
"organization": [
"id",
"type",
"name"
],
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [],
"historical": true,
"relationship": false
},
{
"name": "person",
"schemas": [
{
"$id": "person",
"$ref": "user",
"properties": {
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"date_of_birth": {
"type": "string"
},
"pronouns": {
"type": "string"
},
"contact_id": {
"type": "string"
}
}
}
],
"hierarchy": [
"person",
"user",
"organization",
"entity"
],
"fields": [
"id",
"type",
"first_name",
"last_name",
"date_of_birth",
"pronouns",
"contact_id",
"name",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"person": [
"id",
"type",
"first_name",
"last_name",
"date_of_birth",
"pronouns",
"contact_id"
],
"user": [
"id",
"type"
],
"organization": [
"id",
"type",
"name"
],
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [
"first_name",
"last_name",
"date_of_birth",
"pronouns"
],
"historical": true,
"relationship": false
},
{
"name": "order",
"schemas": [
{
"$id": "order",
"$ref": "entity",
"properties": {
"total": {
"type": "number"
},
"customer_id": {
"type": "string"
}
}
}
],
"hierarchy": [
"order",
"entity"
],
"fields": [
"id",
"type",
"total",
"customer_id",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"order": [
"id",
"type",
"total",
"customer_id"
],
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [
"id"
],
"historical": true,
"relationship": false
},
{
"name": "order_line",
"schemas": [
{
"$id": "order_line",
"$ref": "entity",
"properties": {
"order_id": {
"type": "string"
},
"product": {
"type": "string"
},
"price": {
"type": "number"
}
}
}
],
"hierarchy": [
"order_line",
"entity"
],
"fields": [
"id",
"type",
"order_id",
"product",
"price",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"order_line": [
"id",
"type",
"order_id",
"product",
"price"
],
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [],
"historical": true,
"relationship": false
}
]
},
"tests": [
{
"description": "Should query by ID if provided, rather than looking up by fields",
"action": "merge",
"data": {
"id": "123",
"type": "person",
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-01-01T00:00:00Z"
},
"expect": {
"success": true,
"sql": [
"SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*) FROM agreego.\"person\" t1 LEFT JOIN agreego.\"user\" t2 ON t2.id = t1.id LEFT JOIN agreego.\"organization\" t3 ON t3.id = t1.id LEFT JOIN agreego.\"entity\" t4 ON t4.id = t1.id WHERE t1.id = '123'",
"INSERT INTO agreego.\"entity\" (\"created_at\", \"created_by\", \"id\", \"modified_at\", \"modified_by\", \"type\") VALUES ('{{timestamp}}', '00000000-0000-0000-0000-000000000000', '123', '{{timestamp}}', '00000000-0000-0000-0000-000000000000', 'person')",
"INSERT INTO agreego.\"organization\" (\"id\", \"type\") VALUES ('123', 'person')",
"INSERT INTO agreego.\"user\" (\"id\", \"type\") VALUES ('123', 'person')",
"INSERT INTO agreego.\"person\" (\"date_of_birth\", \"first_name\", \"id\", \"last_name\", \"type\") VALUES ('1990-01-01T00:00:00Z', 'John', '123', 'Doe', 'person')",
"INSERT INTO agreego.change (changes, entity_id, id, kind, modified_at, modified_by) VALUES ('{\"date_of_birth\":\"1990-01-01T00:00:00Z\",\"first_name\":\"John\",\"last_name\":\"Doe\",\"type\":\"person\"}', '123', '{{uuid}}', 'create', '{{timestamp}}', '00000000-0000-0000-0000-000000000000')",
"SELECT pg_notify('entity', '{\"complete\":{\"created_at\":\"{{timestamp}}\",\"created_by\":\"00000000-0000-0000-0000-000000000000\",\"date_of_birth\":\"1990-01-01T00:00:00Z\",\"first_name\":\"John\",\"id\":\"123\",\"last_name\":\"Doe\",\"modified_at\":\"{{timestamp}}\",\"modified_by\":\"00000000-0000-0000-0000-000000000000\",\"type\":\"person\"}}')"
]
}
},
{
"description": "Should execute a lookup based on defined lookup_fields because no ID is provided",
"action": "merge",
"data": {
"type": "person",
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-01-01T00:00:00Z"
},
"expect": {
"success": true,
"sql": [
"SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*) FROM agreego.\"person\" t1 LEFT JOIN agreego.\"user\" t2 ON t2.id = t1.id LEFT JOIN agreego.\"organization\" t3 ON t3.id = t1.id LEFT JOIN agreego.\"entity\" t4 ON t4.id = t1.id WHERE \"first_name\" = 'John' AND \"last_name\" = 'Doe' AND \"date_of_birth\" = '1990-01-01T00:00:00Z' AND \"pronouns\" IS NULL",
"INSERT INTO agreego.\"entity\" (\"created_at\", \"created_by\", \"id\", \"modified_at\", \"modified_by\", \"type\") VALUES ('{{timestamp}}', '00000000-0000-0000-0000-000000000000', '{{uuid:person_1}}', '{{timestamp}}', '00000000-0000-0000-0000-000000000000', 'person')",
"INSERT INTO agreego.\"organization\" (\"id\", \"type\") VALUES ('{{uuid:person_1}}', 'person')",
"INSERT INTO agreego.\"user\" (\"id\", \"type\") VALUES ('{{uuid:person_1}}', 'person')",
"INSERT INTO agreego.\"person\" (\"date_of_birth\", \"first_name\", \"id\", \"last_name\", \"type\") VALUES ('1990-01-01T00:00:00Z', 'John', '{{uuid:person_1}}', 'Doe', 'person')",
"INSERT INTO agreego.change (changes, entity_id, id, kind, modified_at, modified_by) VALUES ('{\"date_of_birth\":\"1990-01-01T00:00:00Z\",\"first_name\":\"John\",\"last_name\":\"Doe\",\"type\":\"person\"}', '{{uuid:person_1}}', '{{uuid}}', 'create', '{{timestamp}}', '00000000-0000-0000-0000-000000000000')",
"SELECT pg_notify('entity', '{\"complete\":{\"created_at\":\"{{timestamp}}\",\"created_by\":\"00000000-0000-0000-0000-000000000000\",\"date_of_birth\":\"1990-01-01T00:00:00Z\",\"first_name\":\"John\",\"id\":\"{{uuid:person_1}}\",\"last_name\":\"Doe\",\"modified_at\":\"{{timestamp}}\",\"modified_by\":\"00000000-0000-0000-0000-000000000000\",\"type\":\"person\"}}')"
]
}
},
{
"description": "Should explicitly null out fields provided as empty strings",
"action": "merge",
"data": {
"id": "123",
"type": "person",
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-01-01T00:00:00Z",
"pronouns": ""
},
"expect": {
"success": true,
"sql": [
"SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*) FROM agreego.\"person\" t1 LEFT JOIN agreego.\"user\" t2 ON t2.id = t1.id LEFT JOIN agreego.\"organization\" t3 ON t3.id = t1.id LEFT JOIN agreego.\"entity\" t4 ON t4.id = t1.id WHERE t1.id = '123'",
"INSERT INTO agreego.\"entity\" (\"created_at\", \"created_by\", \"id\", \"modified_at\", \"modified_by\", \"type\") VALUES ('{{timestamp}}', '00000000-0000-0000-0000-000000000000', '123', '{{timestamp}}', '00000000-0000-0000-0000-000000000000', 'person')",
"INSERT INTO agreego.\"organization\" (\"id\", \"type\") VALUES ('123', 'person')",
"INSERT INTO agreego.\"user\" (\"id\", \"type\") VALUES ('123', 'person')",
"INSERT INTO agreego.\"person\" (\"date_of_birth\", \"first_name\", \"id\", \"last_name\", \"pronouns\", \"type\") VALUES ('1990-01-01T00:00:00Z', 'John', '123', 'Doe', NULL, 'person')",
"INSERT INTO agreego.change (changes, entity_id, id, kind, modified_at, modified_by) VALUES ('{\"date_of_birth\":\"1990-01-01T00:00:00Z\",\"first_name\":\"John\",\"last_name\":\"Doe\",\"pronouns\":\"\",\"type\":\"person\"}', '123', '{{uuid}}', 'create', '{{timestamp}}', '00000000-0000-0000-0000-000000000000')",
"SELECT pg_notify('entity', '{\"complete\":{\"created_at\":\"{{timestamp}}\",\"created_by\":\"00000000-0000-0000-0000-000000000000\",\"date_of_birth\":\"1990-01-01T00:00:00Z\",\"first_name\":\"John\",\"id\":\"123\",\"last_name\":\"Doe\",\"modified_at\":\"{{timestamp}}\",\"modified_by\":\"00000000-0000-0000-0000-000000000000\",\"pronouns\":\"\",\"type\":\"person\"}}')"
]
}
}
]
},
{
"description": "Nested Relationship Mapping",
"database": {
"puncs": [],
"enums": [
{
"id": "e-type-1",
"type": "relation_type",
"enum": "relation_type",
"values": [
"foreign_key",
"polymorphic",
"graph"
]
}
],
"relations": [
{
"id": "r-order-customer",
"type": "relation",
"constraint": "fk_order_customer",
"source_type": "order",
"source_columns": [
"customer_id"
],
"destination_type": "person",
"destination_columns": [
"id"
],
"prefix": "customer"
},
{
"id": "r-order-lines",
"type": "relation",
"constraint": "fk_order_line_order",
"source_type": "order_line",
"source_columns": [
"order_id"
],
"destination_type": "order",
"destination_columns": [
"id"
],
"prefix": "lines"
}
],
"types": [
{
"name": "entity",
"schemas": [
{
"$id": "entity",
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"created_by": {
"type": "string"
},
"modified_by": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"modified_at": {
"type": "string",
"format": "date-time"
}
},
"required": [
"id",
"type",
"created_by",
"created_at",
"modified_by",
"modified_at"
]
}
],
"hierarchy": [
"entity"
],
"fields": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [],
"historical": false,
"relationship": false
},
{
"name": "organization",
"schemas": [
{
"$id": "organization",
"$ref": "entity",
"properties": {
"name": {
"type": "string"
}
}
}
],
"hierarchy": [
"organization",
"entity"
],
"fields": [
"id",
"type",
"name",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"organization": [
"id",
"type",
"name"
],
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [],
"historical": true,
"relationship": false
},
{
"name": "user",
"schemas": [
{
"$id": "user",
"$ref": "organization",
"properties": {}
}
],
"hierarchy": [
"user",
"organization",
"entity"
],
"fields": [
"id",
"type",
"name",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"user": [
"id",
"type"
],
"organization": [
"id",
"type",
"name"
],
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [],
"historical": true,
"relationship": false
},
{
"name": "person",
"schemas": [
{
"$id": "person",
"$ref": "user",
"properties": {
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"date_of_birth": {
"type": "string"
},
"pronouns": {
"type": "string"
},
"contact_id": {
"type": "string"
}
}
}
],
"hierarchy": [
"person",
"user",
"organization",
"entity"
],
"fields": [
"id",
"type",
"first_name",
"last_name",
"date_of_birth",
"pronouns",
"contact_id",
"name",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"person": [
"id",
"type",
"first_name",
"last_name",
"date_of_birth",
"pronouns",
"contact_id"
],
"user": [
"id",
"type"
],
"organization": [
"id",
"type",
"name"
],
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [
"first_name",
"last_name",
"date_of_birth",
"pronouns"
],
"historical": true,
"relationship": false
},
{
"name": "order",
"schemas": [
{
"$id": "order",
"$ref": "entity",
"properties": {
"total": {
"type": "number"
},
"customer_id": {
"type": "string"
}
}
}
],
"hierarchy": [
"order",
"entity"
],
"fields": [
"id",
"type",
"total",
"customer_id",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"order": [
"id",
"type",
"total",
"customer_id"
],
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [
"id"
],
"historical": true,
"relationship": false
},
{
"name": "order_line",
"schemas": [
{
"$id": "order_line",
"$ref": "entity",
"properties": {
"order_id": {
"type": "string"
},
"product": {
"type": "string"
},
"price": {
"type": "number"
}
}
}
],
"hierarchy": [
"order_line",
"entity"
],
"fields": [
"id",
"type",
"order_id",
"product",
"price",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
],
"grouped_fields": {
"order_line": [
"id",
"type",
"order_id",
"product",
"price"
],
"entity": [
"id",
"type",
"created_at",
"created_by",
"modified_at",
"modified_by",
"archived"
]
},
"lookup_fields": [],
"historical": true,
"relationship": false
}
]
},
"tests": [
{
"description": "Should execute a 1:1 nested relation and cascade child IDs to parent",
"action": "merge",
"data": {
"type": "order",
"total": 100.0,
"customer": {
"type": "person",
"first_name": "Bob",
"last_name": "Smith",
"date_of_birth": "2000-01-01"
}
},
"expect": {
"success": true,
"sql": [
"SELECT to_jsonb(t1.*) || to_jsonb(t2.*) FROM agreego.\"order\" t1 LEFT JOIN agreego.\"entity\" t2 ON t2.id = t1.id WHERE \"id\" IS NULL",
"SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*) FROM agreego.\"person\" t1 LEFT JOIN agreego.\"user\" t2 ON t2.id = t1.id LEFT JOIN agreego.\"organization\" t3 ON t3.id = t1.id LEFT JOIN agreego.\"entity\" t4 ON t4.id = t1.id WHERE \"first_name\" = 'Bob' AND \"last_name\" = 'Smith' AND \"date_of_birth\" = '2000-01-01' AND \"pronouns\" IS NULL",
"INSERT INTO agreego.\"entity\" (\"created_at\", \"created_by\", \"id\", \"modified_at\", \"modified_by\", \"type\") VALUES ('{{timestamp}}', '00000000-0000-0000-0000-000000000000', '{{uuid:customer_id}}', '{{timestamp}}', '00000000-0000-0000-0000-000000000000', 'person')",
"INSERT INTO agreego.\"organization\" (\"id\", \"type\") VALUES ('{{uuid:customer_id}}', 'person')",
"INSERT INTO agreego.\"user\" (\"id\", \"type\") VALUES ('{{uuid:customer_id}}', 'person')",
"INSERT INTO agreego.\"person\" (\"date_of_birth\", \"first_name\", \"id\", \"last_name\", \"type\") VALUES ('2000-01-01', 'Bob', '{{uuid:customer_id}}', 'Smith', 'person')",
"INSERT INTO agreego.change (changes, entity_id, id, kind, modified_at, modified_by) VALUES ('{\"date_of_birth\":\"2000-01-01\",\"first_name\":\"Bob\",\"last_name\":\"Smith\",\"type\":\"person\"}', '{{uuid:customer_id}}', '{{uuid}}', 'create', '{{timestamp}}', '00000000-0000-0000-0000-000000000000')",
"SELECT pg_notify('entity', '{\"complete\":{\"created_at\":\"{{timestamp}}\",\"created_by\":\"00000000-0000-0000-0000-000000000000\",\"date_of_birth\":\"2000-01-01\",\"first_name\":\"Bob\",\"id\":\"{{uuid:customer_id}}\",\"last_name\":\"Smith\",\"modified_at\":\"{{timestamp}}\",\"modified_by\":\"00000000-0000-0000-0000-000000000000\",\"type\":\"person\"}}')",
"INSERT INTO agreego.\"entity\" (\"created_at\", \"created_by\", \"id\", \"modified_at\", \"modified_by\", \"type\") VALUES ('{{timestamp}}', '00000000-0000-0000-0000-000000000000', '{{uuid:order_id}}', '{{timestamp}}', '00000000-0000-0000-0000-000000000000', 'order')",
"INSERT INTO agreego.\"order\" (\"customer_id\", \"id\", \"total\", \"type\") VALUES ('{{uuid:customer_id}}', '{{uuid:order_id}}', 100, 'order')",
"INSERT INTO agreego.change (changes, entity_id, id, kind, modified_at, modified_by) VALUES ('{\"customer_id\":\"{{uuid:customer_id}}\",\"total\":100.0,\"type\":\"order\"}', '{{uuid:order_id}}', '{{uuid}}', 'create', '{{timestamp}}', '00000000-0000-0000-0000-000000000000')",
"SELECT pg_notify('entity', '{\"complete\":{\"created_at\":\"{{timestamp}}\",\"created_by\":\"00000000-0000-0000-0000-000000000000\",\"customer_id\":\"{{uuid:customer_id}}\",\"id\":\"{{uuid:order_id}}\",\"modified_at\":\"{{timestamp}}\",\"modified_by\":\"00000000-0000-0000-0000-000000000000\",\"total\":100.0,\"type\":\"order\"}}')"
]
}
},
{
"description": "Should execute a 1:N array relation mapping parent IDs to children",
"action": "merge",
"data": {
"id": "abc",
"type": "order",
"total": 99.0,
"lines": [
{
"type": "order_line",
"product": "Widget",
"price": 99.0
}
]
},
"expect": {
"success": true,
"sql": [
"SELECT to_jsonb(t1.*) || to_jsonb(t2.*) FROM agreego.\"order\" t1 LEFT JOIN agreego.\"entity\" t2 ON t2.id = t1.id WHERE t1.id = 'abc'",
"INSERT INTO agreego.\"entity\" (\"created_at\", \"created_by\", \"id\", \"modified_at\", \"modified_by\", \"type\") VALUES ('{{timestamp}}', '00000000-0000-0000-0000-000000000000', 'abc', '{{timestamp}}', '00000000-0000-0000-0000-000000000000', 'order')",
"INSERT INTO agreego.\"order\" (\"id\", \"total\", \"type\") VALUES ('abc', 99, 'order')",
"INSERT INTO agreego.\"entity\" (\"created_at\", \"created_by\", \"id\", \"modified_at\", \"modified_by\", \"type\") VALUES ('{{timestamp}}', '00000000-0000-0000-0000-000000000000', '{{uuid:line_id}}', '{{timestamp}}', '00000000-0000-0000-0000-000000000000', 'order_line')",
"INSERT INTO agreego.\"order_line\" (\"id\", \"order_id\", \"price\", \"product\", \"type\") VALUES ('{{uuid:line_id}}', 'abc', 99, 'Widget', 'order_line')",
"INSERT INTO agreego.change (changes, entity_id, id, kind, modified_at, modified_by) VALUES ('{\"order_id\":\"abc\",\"price\":99.0,\"product\":\"Widget\",\"type\":\"order_line\"}', '{{uuid:line_id}}', '{{uuid}}', 'create', '{{timestamp}}', '00000000-0000-0000-0000-000000000000')",
"SELECT pg_notify('entity', '{\"complete\":{\"created_at\":\"{{timestamp}}\",\"created_by\":\"00000000-0000-0000-0000-000000000000\",\"id\":\"{{uuid:line_id}}\",\"modified_at\":\"{{timestamp}}\",\"modified_by\":\"00000000-0000-0000-0000-000000000000\",\"order_id\":\"abc\",\"price\":99.0,\"product\":\"Widget\",\"type\":\"order_line\"}}')",
"INSERT INTO agreego.change (changes, entity_id, id, kind, modified_at, modified_by) VALUES ('{\"total\":99.0,\"type\":\"order\"}', 'abc', '{{uuid}}', 'create', '{{timestamp}}', '00000000-0000-0000-0000-000000000000')",
"SELECT pg_notify('entity', '{\"complete\":{\"created_at\":\"{{timestamp}}\",\"created_by\":\"00000000-0000-0000-0000-000000000000\",\"id\":\"abc\",\"modified_at\":\"{{timestamp}}\",\"modified_by\":\"00000000-0000-0000-0000-000000000000\",\"total\":99.0,\"type\":\"order\"}}')"
]
}
}
]
}
]

View File

@ -2,23 +2,38 @@ use crate::database::executors::DatabaseExecutor;
use serde_json::Value;
#[cfg(test)]
use std::sync::Mutex;
use std::cell::RefCell;
#[cfg(test)]
pub struct MockExecutor {
pub query_responses: Mutex<Vec<Result<Value, String>>>,
pub execute_responses: Mutex<Vec<Result<(), String>>>,
pub captured_queries: Mutex<Vec<String>>,
pub struct MockState {
pub captured_queries: Vec<String>,
pub query_responses: Vec<Result<Value, String>>,
pub execute_responses: Vec<Result<(), String>>,
}
#[cfg(test)]
impl MockState {
pub fn new() -> Self {
Self {
captured_queries: Default::default(),
query_responses: Default::default(),
execute_responses: Default::default(),
}
}
}
#[cfg(test)]
thread_local! {
pub static MOCK_STATE: RefCell<MockState> = RefCell::new(MockState::new());
}
#[cfg(test)]
pub struct MockExecutor {}
#[cfg(test)]
impl MockExecutor {
pub fn new() -> Self {
Self {
query_responses: Mutex::new(Vec::new()),
execute_responses: Mutex::new(Vec::new()),
captured_queries: Mutex::new(Vec::new()),
}
Self {}
}
}
@ -26,22 +41,26 @@ impl MockExecutor {
impl DatabaseExecutor for MockExecutor {
fn query(&self, sql: &str, _args: Option<&[Value]>) -> Result<Value, String> {
println!("DEBUG SQL QUERY: {}", sql);
self.captured_queries.lock().unwrap().push(sql.to_string());
let mut responses = self.query_responses.lock().unwrap();
if responses.is_empty() {
return Ok(Value::Array(vec![]));
}
responses.remove(0)
MOCK_STATE.with(|state| {
let mut s = state.borrow_mut();
s.captured_queries.push(sql.to_string());
if s.query_responses.is_empty() {
return Ok(Value::Array(vec![]));
}
s.query_responses.remove(0)
})
}
fn execute(&self, sql: &str, _args: Option<&[Value]>) -> Result<(), String> {
println!("DEBUG SQL EXECUTE: {}", sql);
self.captured_queries.lock().unwrap().push(sql.to_string());
let mut responses = self.execute_responses.lock().unwrap();
if responses.is_empty() {
return Ok(());
}
responses.remove(0)
MOCK_STATE.with(|state| {
let mut s = state.borrow_mut();
s.captured_queries.push(sql.to_string());
if s.execute_responses.is_empty() {
return Ok(());
}
s.execute_responses.remove(0)
})
}
fn auth_user_id(&self) -> Result<String, String> {
@ -54,11 +73,16 @@ impl DatabaseExecutor for MockExecutor {
#[cfg(test)]
fn get_queries(&self) -> Vec<String> {
self.captured_queries.lock().unwrap().clone()
MOCK_STATE.with(|state| state.borrow().captured_queries.clone())
}
#[cfg(test)]
fn reset_mocks(&self) {
self.captured_queries.lock().unwrap().clear();
MOCK_STATE.with(|state| {
let mut s = state.borrow_mut();
s.captured_queries.clear();
s.query_responses.clear();
s.execute_responses.clear();
});
}
}

View File

@ -76,8 +76,11 @@ impl Database {
if let Some(arr) = val.get("relations").and_then(|v| v.as_array()) {
for item in arr {
if let Ok(def) = serde_json::from_value::<Relation>(item.clone()) {
db.relations.insert(def.constraint.clone(), def);
match serde_json::from_value::<Relation>(item.clone()) {
Ok(def) => {
db.relations.insert(def.constraint.clone(), def);
}
Err(e) => println!("DATABASE RELATION PARSE FAILED: {:?}", e),
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,17 @@
use serde::Deserialize;
use std::collections::HashMap;
use std::fs;
use std::sync::{Arc, OnceLock, RwLock};
#[derive(Debug, Deserialize)]
struct TestSuite {
pub struct TestSuite {
#[allow(dead_code)]
description: String,
database: serde_json::Value,
tests: Vec<TestCase>,
pub description: String,
pub database: serde_json::Value,
pub tests: Vec<TestCase>,
}
use crate::tests::types::{ExpectBlock, TestCase};
use crate::validator::Validator;
use crate::tests::types::TestCase;
use serde_json::Value;
pub fn deserialize_some<'de, D>(deserializer: D) -> Result<Option<Value>, D::Error>
@ -22,87 +22,128 @@ where
Ok(Some(v))
}
pub fn run_test_file_at_index(path: &str, index: usize) -> Result<(), String> {
let content =
fs::read_to_string(path).unwrap_or_else(|_| panic!("Failed to read file: {}", path));
let suite: Vec<TestSuite> = serde_json::from_str(&content)
.unwrap_or_else(|e| panic!("Failed to parse JSON in {}: {}", path, e));
// Type alias for easier reading
type CompiledSuite = Arc<Vec<(TestSuite, Arc<crate::database::Database>)>>;
if index >= suite.len() {
panic!("Index {} out of bounds for file {}", index, path);
// Global cache mapping filename -> Vector of (Parsed JSON suite, Compiled Database)
static CACHE: OnceLock<RwLock<HashMap<String, CompiledSuite>>> = OnceLock::new();
fn get_cached_file(path: &str) -> CompiledSuite {
let cache_lock = CACHE.get_or_init(|| RwLock::new(HashMap::new()));
let file_data = {
let read_guard = cache_lock.read().unwrap();
read_guard.get(path).cloned()
};
match file_data {
Some(data) => data,
None => {
let mut write_guard = cache_lock.write().unwrap();
// double check in case another thread compiled while we waited for lock
if let Some(data) = write_guard.get(path) {
data.clone()
} else {
let content =
fs::read_to_string(path).unwrap_or_else(|_| panic!("Failed to read file: {}", path));
let suites: Vec<TestSuite> = serde_json::from_str(&content)
.unwrap_or_else(|e| panic!("Failed to parse JSON in {}: {}", path, e));
let mut compiled_suites = Vec::new();
for suite in suites {
let db_result = crate::database::Database::new(&suite.database);
if let Err(drop) = db_result {
let error_messages: Vec<String> = drop
.errors
.into_iter()
.map(|e| format!("Error {} at path {}: {}", e.code, e.details.path, e.message))
.collect();
panic!(
"System Setup Compilation failed for {}:\n{}",
path,
error_messages.join("\n")
);
}
compiled_suites.push((suite, Arc::new(db_result.unwrap())));
}
let new_data = Arc::new(compiled_suites);
write_guard.insert(path.to_string(), new_data.clone());
new_data
}
}
}
}
pub fn run_test_case(path: &str, suite_idx: usize, case_idx: usize) -> Result<(), String> {
let file_data = get_cached_file(path);
if suite_idx >= file_data.len() {
panic!("Suite Index {} out of bounds for file {}", suite_idx, path);
}
let group = &suite[index];
let (group, db) = &file_data[suite_idx];
if case_idx >= group.tests.len() {
panic!(
"Case Index {} out of bounds for suite {} in file {}",
case_idx, suite_idx, path
);
}
let test = &group.tests[case_idx];
let mut failures = Vec::<String>::new();
let db_json = group.database.clone();
let db_result = crate::database::Database::new(&db_json);
if let Err(drop) = db_result {
let error_messages: Vec<String> = drop
.errors
.into_iter()
.map(|e| format!("Error {} at path {}: {}", e.code, e.details.path, e.message))
.collect();
return Err(format!(
"System Setup Compilation failed:\n{}",
error_messages.join("\n")
));
}
let db = db_result.unwrap();
let validator = Validator::new(std::sync::Arc::new(db));
// 4. Run Tests
for test in group.tests.iter() {
// Provide fallback for legacy expectations if `expect` block was missing despite migration script
let expected_success = test
.expect
.as_ref()
.map(|e| e.success)
.unwrap_or(test.valid.unwrap_or(false));
let _expected_errors = test
.expect
.as_ref()
.and_then(|e| e.errors.clone())
.unwrap_or(test.expect_errors.clone().unwrap_or(vec![]));
// Provide fallback for legacy expectations if `expect` block was missing despite migration script
let _expected_success = test
.expect
.as_ref()
.map(|e| e.success)
.unwrap_or(test.valid.unwrap_or(false));
let _expected_errors = test
.expect
.as_ref()
.and_then(|e| e.errors.clone())
.unwrap_or(test.expect_errors.clone().unwrap_or(vec![]));
match test.action.as_str() {
"validate" => {
let result = test.run_validate(validator.db.clone());
if let Err(e) = result {
println!("TEST VALIDATE ERROR FOR '{}': {}", test.description, e);
failures.push(format!(
"[{}] Validate Test '{}' failed. Error: {}",
group.description, test.description, e
));
}
}
"merge" => {
let result = test.run_merge(validator.db.clone());
if let Err(e) = result {
println!("TEST MERGE ERROR FOR '{}': {}", test.description, e);
failures.push(format!(
"[{}] Merge Test '{}' failed. Error: {}",
group.description, test.description, e
));
}
}
"query" => {
let result = test.run_query(validator.db.clone());
if let Err(e) = result {
println!("TEST QUERY ERROR FOR '{}': {}", test.description, e);
failures.push(format!(
"[{}] Query Test '{}' failed. Error: {}",
group.description, test.description, e
));
}
}
_ => {
match test.action.as_str() {
"validate" => {
let result = test.run_validate(db.clone());
if let Err(e) = result {
println!("TEST VALIDATE ERROR FOR '{}': {}", test.description, e);
failures.push(format!(
"[{}] Unknown action '{}' for test '{}'",
group.description, test.action, test.description
"[{}] Validate Test '{}' failed. Error: {}",
group.description, test.description, e
));
}
}
"merge" => {
let result = test.run_merge(db.clone());
if let Err(e) = result {
println!("TEST MERGE ERROR FOR '{}': {}", test.description, e);
failures.push(format!(
"[{}] Merge Test '{}' failed. Error: {}",
group.description, test.description, e
));
}
}
"query" => {
let result = test.run_query(db.clone());
if let Err(e) = result {
println!("TEST QUERY ERROR FOR '{}': {}", test.description, e);
failures.push(format!(
"[{}] Query Test '{}' failed. Error: {}",
group.description, test.description, e
));
}
}
_ => {
failures.push(format!(
"[{}] Unknown action '{}' for test '{}'",
group.description, test.action, test.description
));
}
}
if !failures.is_empty() {