Skip to content

Commit 5b5fd3b

Browse files
committed
merge: C# ADR-0003/0004 colocation + @schema/@storage parity
Brings worktree-csharp-parity-plans onto main: - ADR-0003 constants/schemas colocated per concern; god-files deleted; @javaruntime leak removed - ADR-0004 provider model marked shipped for C# - @Schema constants; @storage first-class (enum schema + cross-attr validator + 4 tests) Conformance 174/0.
2 parents 9a3fafc + 4ef9c2b commit 5b5fd3b

49 files changed

Lines changed: 1671 additions & 1234 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Metamodel-constants barrel for the conformance test assembly (ADR-0003 §3).
2+
// Mirrors MetaObjects/GlobalUsings.cs so tests reference colocated constants as bare names.
3+
4+
global using static MetaObjects.Shared.BaseTypes;
5+
global using static MetaObjects.Shared.Structural;
6+
global using static MetaObjects.Core.Attr.AttrConstants;
7+
global using static MetaObjects.Core.Query.QueryConstants;
8+
global using static MetaObjects.Core.Field.FieldConstants;
9+
global using static MetaObjects.Core.Object.ObjectConstants;
10+
global using static MetaObjects.Core.Validator.ValidatorConstants;
11+
global using static MetaObjects.Core.Identity.IdentityConstants;
12+
global using static MetaObjects.Core.Relationship.RelationshipConstants;
13+
global using static MetaObjects.Persistence.Source.SourceConstants;
14+
global using static MetaObjects.Persistence.Origin.OriginConstants;
15+
global using static MetaObjects.Persistence.Db.DbConstants;
16+
global using static MetaObjects.Presentation.View.ViewConstants;
17+
global using static MetaObjects.Presentation.Layout.LayoutConstants;
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using MetaObjects;
4+
using MetaObjects.Loader;
5+
using Xunit;
6+
7+
namespace MetaObjects.Conformance.Tests.Loader;
8+
9+
/// <summary>
10+
/// Cross-attribute validation for @storage on field.object. Mirrors the TS
11+
/// storage-validation tests (validateFieldObjectStorage in validation-passes.ts):
12+
/// - @storage requires @objectRef on the same field.
13+
/// - @storage "flattened" requires isArray=false.
14+
/// </summary>
15+
public class FieldObjectStorageValidationTests
16+
{
17+
private static (bool ok, IReadOnlyList<ErrorCode> codes) Load(string json)
18+
{
19+
var result = new MetaDataLoader().Load([new InMemorySource(json, id: "storage.json")]);
20+
return (result.Errors.Count == 0, result.Errors.Select(e => e.Code).ToList());
21+
}
22+
23+
[Fact]
24+
public void Storage_without_objectRef_is_rejected()
25+
{
26+
var (ok, codes) = Load("""
27+
{
28+
"metadata.root": {
29+
"package": "test",
30+
"children": [
31+
{
32+
"object.entity": {
33+
"name": "Order",
34+
"children": [
35+
{ "source.dbTable": { "@name": "orders" } },
36+
{ "field.object": { "name": "addr", "@storage": "flattened" } },
37+
{ "field.long": { "name": "id" } },
38+
{ "identity.primary": { "@fields": "id" } }
39+
]
40+
}
41+
}
42+
]
43+
}
44+
}
45+
""");
46+
Assert.False(ok);
47+
Assert.Contains(ErrorCode.ERR_STORAGE_WITHOUT_OBJECT_REF, codes);
48+
}
49+
50+
[Fact]
51+
public void Storage_flattened_with_isArray_true_is_rejected()
52+
{
53+
var (ok, codes) = Load("""
54+
{
55+
"metadata.root": {
56+
"package": "test",
57+
"children": [
58+
{ "object.value": { "name": "Address", "children": [
59+
{ "field.string": { "name": "street" } }
60+
]}},
61+
{
62+
"object.entity": {
63+
"name": "Order",
64+
"children": [
65+
{ "source.dbTable": { "@name": "orders" } },
66+
{ "field.object": { "name": "addrs", "isArray": true, "@objectRef": "Address", "@storage": "flattened" } },
67+
{ "field.long": { "name": "id" } },
68+
{ "identity.primary": { "@fields": "id" } }
69+
]
70+
}
71+
}
72+
]
73+
}
74+
}
75+
""");
76+
Assert.False(ok);
77+
Assert.Contains(ErrorCode.ERR_STORAGE_FLATTENED_ARRAY, codes);
78+
}
79+
80+
[Fact]
81+
public void Storage_flattened_with_objectRef_and_isArray_false_passes()
82+
{
83+
var (ok, codes) = Load("""
84+
{
85+
"metadata.root": {
86+
"package": "test",
87+
"children": [
88+
{ "object.value": { "name": "Address", "children": [
89+
{ "field.string": { "name": "street" } }
90+
]}},
91+
{
92+
"object.entity": {
93+
"name": "Order",
94+
"children": [
95+
{ "source.dbTable": { "@name": "orders" } },
96+
{ "field.object": { "name": "addr", "@objectRef": "Address", "@storage": "flattened" } },
97+
{ "field.long": { "name": "id" } },
98+
{ "identity.primary": { "@fields": "id" } }
99+
]
100+
}
101+
}
102+
]
103+
}
104+
}
105+
""");
106+
Assert.True(ok, $"expected no errors, got: {string.Join(", ", codes)}");
107+
}
108+
109+
[Fact]
110+
public void Storage_jsonb_with_isArray_true_passes()
111+
{
112+
var (ok, codes) = Load("""
113+
{
114+
"metadata.root": {
115+
"package": "test",
116+
"children": [
117+
{ "object.value": { "name": "ContactInfo", "children": [
118+
{ "field.string": { "name": "email" } }
119+
]}},
120+
{
121+
"object.entity": {
122+
"name": "Patient",
123+
"children": [
124+
{ "source.dbTable": { "@name": "patients" } },
125+
{ "field.object": { "name": "contactInfos", "isArray": true, "@objectRef": "ContactInfo", "@storage": "jsonb" } },
126+
{ "field.long": { "name": "id" } },
127+
{ "identity.primary": { "@fields": "id" } }
128+
]
129+
}
130+
}
131+
]
132+
}
133+
}
134+
""");
135+
Assert.True(ok, $"expected no errors, got: {string.Join(", ", codes)}");
136+
}
137+
}

0 commit comments

Comments
 (0)