Strengthen mixed Project public-wrapper and storage oracles
This commit is contained in:
@@ -578,6 +578,35 @@ fn complete_static_architecture_and_unicode_warning_mapping() {
|
|||||||
let warning = &resolved.warnings()[0].diagnostic;
|
let warning = &resolved.warnings()[0].diagnostic;
|
||||||
assert_eq!(warning.line, 6);
|
assert_eq!(warning.line, 6);
|
||||||
assert_eq!(warning.column, 1);
|
assert_eq!(warning.column, 1);
|
||||||
|
// Same physical line: the two header-name scalars occupy seven UTF-8
|
||||||
|
// bytes. Independently authored coordinates distinguish column60 from
|
||||||
|
// byte-column65; the warning covers the complete Work declaration.
|
||||||
|
let inline = SourceBundle {
|
||||||
|
entry: "main.arcadia".into(),
|
||||||
|
files: BTreeMap::from([(
|
||||||
|
"main.arcadia".into(),
|
||||||
|
format!(
|
||||||
|
"arcadia 8;\r\nproject p \"港🌊\" id \"{}\" {{ oa_activity w \"Work\" id \"{}\" {{}} }}\r\n",
|
||||||
|
id(1),
|
||||||
|
id(2)
|
||||||
|
),
|
||||||
|
)]),
|
||||||
|
};
|
||||||
|
let inline_value = accepted(&inline);
|
||||||
|
assert_eq!(inline_value.warnings().len(), 1);
|
||||||
|
let inline_warning = &inline_value.warnings()[0];
|
||||||
|
assert_eq!(inline_warning.path, "main.arcadia");
|
||||||
|
assert_eq!(inline_warning.diagnostic.code, "unallocated_leaf");
|
||||||
|
assert_eq!(inline_warning.diagnostic.object_id, Some(id(2)));
|
||||||
|
assert_eq!(inline_warning.diagnostic.line, 2);
|
||||||
|
assert_eq!(inline_warning.diagnostic.column, 60);
|
||||||
|
assert_eq!(
|
||||||
|
inline_warning.diagnostic.span,
|
||||||
|
Span {
|
||||||
|
start: 76,
|
||||||
|
end: 141
|
||||||
|
}
|
||||||
|
);
|
||||||
let mut bad = bundle.clone();
|
let mut bad = bundle.clone();
|
||||||
*bad.files.get_mut("main.arcadia").unwrap() =
|
*bad.files.get_mut("main.arcadia").unwrap() =
|
||||||
bad.files["main.arcadia"].replace("base 1;", "base true + 1;");
|
bad.files["main.arcadia"].replace("base 1;", "base true + 1;");
|
||||||
@@ -646,19 +675,32 @@ fn mapped_warning_path_copies_are_admitted_before_retention() {
|
|||||||
assert_eq!(roomy.warnings().len(), 1);
|
assert_eq!(roomy.warnings().len(), 1);
|
||||||
assert_eq!(roomy.warnings()[0].diagnostic.code, "unnamed");
|
assert_eq!(roomy.warnings()[0].diagnostic.code, "unnamed");
|
||||||
assert_eq!(roomy.warnings()[0].path, bundle.entry);
|
assert_eq!(roomy.warnings()[0].path, bundle.entry);
|
||||||
let profile = super::super::super::budget::Limits {
|
// Retained syntax owns alias "p" (1 byte). The mapped warning owns path188
|
||||||
bytes: source.len(),
|
// + code "unnamed"7 + field "name"4 + message36 =235 additional bytes.
|
||||||
..super::super::super::budget::Limits::source8(language::ParseLimits::UNLIMITED)
|
// A per-producer cap would accept235; their simultaneous live total is236.
|
||||||
};
|
assert_eq!(bundle.entry.len(), 188);
|
||||||
let parsed = parse_with_profile(&bundle, ProjectLimits::default(), profile).unwrap();
|
assert_eq!("Give the project a descriptive name.".len(), 36);
|
||||||
let failure = match resolve(parsed) {
|
for (bytes, fits) in [(source.len(), false), (235, false), (236, true)] {
|
||||||
Ok(_) => panic!("truncated warnings or uncharged copied path"),
|
let profile = super::super::super::budget::Limits {
|
||||||
Err(e) => e,
|
bytes,
|
||||||
};
|
..super::super::super::budget::Limits::source8(language::ParseLimits::UNLIMITED)
|
||||||
assert_eq!(
|
};
|
||||||
failure.diagnostics[0].diagnostic.message,
|
let parsed = parse_with_profile(&bundle, ProjectLimits::default(), profile).unwrap();
|
||||||
"Source8 index/output byte limit exceeded."
|
match resolve(parsed) {
|
||||||
);
|
Ok(value) => {
|
||||||
|
assert!(fits, "mapped diagnostics lost their live syntax overlap");
|
||||||
|
assert_eq!(value.warnings(), roomy.warnings());
|
||||||
|
assert_eq!(value.storage.live.text, 236);
|
||||||
|
}
|
||||||
|
Err(failure) => {
|
||||||
|
assert!(!fits, "exact total must fit: {failure:?}");
|
||||||
|
assert_eq!(
|
||||||
|
failure.diagnostics[0].diagnostic.message,
|
||||||
|
"Source8 index/output byte limit exceeded."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -796,20 +838,13 @@ fn retained_nested_record_policy_cannot_be_replaced_at_resolution() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn shared_ordinary_construction_preserves_legacy_scratch_and_existing_errors() {
|
fn public_source3_and_source7_preserve_legacy_scratch_defaults_and_errors() {
|
||||||
let bundle = single(&format!("oa_activity w \"Work\" id \"{}\" {{}}", id(2)));
|
let bundle = single(&format!("oa_activity w \"Work\" id \"{}\" {{}}", id(2)));
|
||||||
let parsed = parse(&bundle, ProjectLimits::default()).unwrap();
|
// Existing source3_bridge tests compare complete public source3/JSON3
|
||||||
let file = &parsed.files[0];
|
// migration. This small shared-decoder regression uses that public wrapper
|
||||||
let mut old = file.ordinary.header.as_ref().unwrap().project.clone();
|
// too, retaining the independent exact Activity expectation below.
|
||||||
old.schema_version = 3;
|
let old_source = bundle.files["main.arcadia"].replacen("arcadia 8;", "arcadia 3;", 1);
|
||||||
let aliases = BTreeMap::from([("p".into(), id(1)), ("w".into(), id(2))]);
|
let migrated = language::parse_with_report(&old_source).unwrap();
|
||||||
let migrated = language::resolve_declarations(
|
|
||||||
old,
|
|
||||||
&file.ordinary.declarations,
|
|
||||||
&aliases,
|
|
||||||
language::ParseLimits::UNLIMITED,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(migrated.project.schema_version, SCHEMA_VERSION);
|
assert_eq!(migrated.project.schema_version, SCHEMA_VERSION);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
migrated.project.elements[&id(2)],
|
migrated.project.elements[&id(2)],
|
||||||
@@ -823,9 +858,11 @@ fn shared_ordinary_construction_preserves_legacy_scratch_and_existing_errors() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
let scenario = single(&format!("oa_scenario q \"Scenario\" id \"{}\" {{}}", id(2)));
|
let scenario = single(&format!("oa_scenario q \"Scenario\" id \"{}\" {{}}", id(2)));
|
||||||
let value = accepted(&scenario);
|
let scenario_source = scenario.files["main.arcadia"].replacen("arcadia 8;", "arcadia 7;", 1);
|
||||||
|
let value =
|
||||||
|
language::parse_limited(&scenario_source, language::ParseLimits::UNLIMITED).unwrap();
|
||||||
assert!(
|
assert!(
|
||||||
matches!(value.project.elements[&id(2)].shared(), Some(SharedBody::Scenario { viewpoint: ScenarioViewpoint::MixedLegacy, steps, .. }) if steps.is_empty())
|
matches!(value.elements[&id(2)].shared(), Some(SharedBody::Scenario { viewpoint: ScenarioViewpoint::MixedLegacy, steps, .. }) if steps.is_empty())
|
||||||
);
|
);
|
||||||
let missing = single(&format!(
|
let missing = single(&format!(
|
||||||
"node n id \"{}\" {{ diagram @d; }} diagram d \"D\" id \"{}\" {{}}",
|
"node n id \"{}\" {{ diagram @d; }} diagram d \"D\" id \"{}\" {{}}",
|
||||||
@@ -833,7 +870,9 @@ fn shared_ordinary_construction_preserves_legacy_scratch_and_existing_errors() {
|
|||||||
id(3)
|
id(3)
|
||||||
));
|
));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rejected(&missing).diagnostics[0].diagnostic.message,
|
language::parse(&missing.files["main.arcadia"].replacen("arcadia 8;", "arcadia 7;", 1))
|
||||||
|
.unwrap_err()[0]
|
||||||
|
.message,
|
||||||
"Missing required field 'element'."
|
"Missing required field 'element'."
|
||||||
);
|
);
|
||||||
let conflict = single(&format!(
|
let conflict = single(&format!(
|
||||||
@@ -842,7 +881,9 @@ fn shared_ordinary_construction_preserves_legacy_scratch_and_existing_errors() {
|
|||||||
id(3)
|
id(3)
|
||||||
));
|
));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rejected(&conflict).diagnostics[0].diagnostic.code,
|
language::parse(&conflict.files["main.arcadia"].replacen("arcadia 8;", "arcadia 7;", 1))
|
||||||
|
.unwrap_err()[0]
|
||||||
|
.code,
|
||||||
"conflicting_parent"
|
"conflicting_parent"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user