tamer: ld::xmle::lower::test: Use AIR (decouple from Asg and index)
This uses AIR---the ASG's proper public interface now---to construct the graph for tests, just as all the other modern tests do. This is change works towards encapsulating index operations (both creation and lookups) so that the index can be moved off of Asg and into AIR, where it belongs. More information on that and rationale to come. DEV-13162main
parent
b238366bee
commit
79fa10f26b
|
@ -19,31 +19,24 @@
|
|||
|
||||
use super::*;
|
||||
use crate::{
|
||||
asg::{AsgError, FragmentText, Ident, IdentKind, ObjectIndex, Source},
|
||||
asg::{
|
||||
air::{Air, AirAggregate},
|
||||
AsgError, FragmentText, Ident, IdentKind, Source,
|
||||
},
|
||||
ld::xmle::{section::PushResult, Sections},
|
||||
parse::util::SPair,
|
||||
parse::{util::SPair, ParseState},
|
||||
span::dummy::*,
|
||||
sym::SymbolId,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
fn declare(
|
||||
asg: &mut Asg,
|
||||
name: SPair,
|
||||
kind: IdentKind,
|
||||
src: Source,
|
||||
) -> Result<ObjectIndex<Ident>, AsgError> {
|
||||
let oi_root = asg.root(name);
|
||||
oi_root.declare(asg, name, kind, src)
|
||||
}
|
||||
use Air::*;
|
||||
|
||||
fn lookup_or_missing(asg: &mut Asg, name: SPair) -> ObjectIndex<Ident> {
|
||||
let oi_root = asg.root(name);
|
||||
oi_root.lookup_or_missing(asg, name)
|
||||
}
|
||||
fn asg_from_toks(toks: impl IntoIterator<Item = Air, IntoIter: Debug>) -> Asg {
|
||||
let mut sut = AirAggregate::parse(toks.into_iter());
|
||||
assert!(sut.all(|x| x.is_ok()));
|
||||
|
||||
/// Create a graph with the expected {ret,}map head/tail identifiers.
|
||||
fn make_asg() -> Asg {
|
||||
Asg::new()
|
||||
sut.finalize().unwrap().into_context()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -85,48 +78,57 @@ fn graph_sort() -> SortResult<()> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut asg = make_asg();
|
||||
let name_a_dep = SPair("adep".into(), S4);
|
||||
let name_a = SPair("a".into(), S3);
|
||||
let name_a_dep_dep = SPair("adepdep".into(), S2);
|
||||
|
||||
// Add them in an unsorted order.
|
||||
let adep = declare(
|
||||
&mut asg,
|
||||
SPair("adep".into(), S1),
|
||||
IdentKind::Meta,
|
||||
Default::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let a = declare(
|
||||
&mut asg,
|
||||
SPair("a".into(), S2),
|
||||
IdentKind::Meta,
|
||||
Default::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let adepdep = declare(
|
||||
&mut asg,
|
||||
SPair("adepdep".into(), S3),
|
||||
IdentKind::Meta,
|
||||
Default::default(),
|
||||
)
|
||||
.unwrap();
|
||||
#[rustfmt::skip]
|
||||
let toks = [
|
||||
PkgStart(S1, SPair("/pkg".into(), S1)),
|
||||
// Intentionally out-of-order.
|
||||
IdentDecl(
|
||||
name_a_dep,
|
||||
IdentKind::Meta,
|
||||
Default::default(),
|
||||
),
|
||||
|
||||
a.add_opaque_dep(&mut asg, adep);
|
||||
adep.add_opaque_dep(&mut asg, adepdep);
|
||||
IdentDecl(
|
||||
name_a,
|
||||
IdentKind::Meta,
|
||||
Default::default(),
|
||||
),
|
||||
|
||||
a.root(&mut asg);
|
||||
IdentDecl(
|
||||
name_a_dep_dep,
|
||||
IdentKind::Meta,
|
||||
Default::default(),
|
||||
),
|
||||
|
||||
IdentDep(name_a, name_a_dep),
|
||||
IdentDep(name_a_dep, name_a_dep_dep),
|
||||
IdentRoot(name_a),
|
||||
PkgEnd(S5),
|
||||
];
|
||||
|
||||
let asg = asg_from_toks(toks);
|
||||
let sections = sort(&asg, StubSections { pushed: Vec::new() })?;
|
||||
|
||||
let expected = vec![
|
||||
// Post-order
|
||||
name_a_dep_dep,
|
||||
name_a_dep,
|
||||
name_a,
|
||||
]
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(
|
||||
sections.pushed,
|
||||
vec![
|
||||
// Post-order
|
||||
asg.get(adepdep).unwrap(),
|
||||
asg.get(adep).unwrap(),
|
||||
asg.get(a).unwrap(),
|
||||
]
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>()
|
||||
expected,
|
||||
sections
|
||||
.pushed
|
||||
.iter()
|
||||
.map(|ident| ident.name())
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
|
@ -134,27 +136,30 @@ fn graph_sort() -> SortResult<()> {
|
|||
|
||||
#[test]
|
||||
fn graph_sort_missing_node() -> SortResult<()> {
|
||||
let mut asg = make_asg();
|
||||
|
||||
let sym = SPair("sym".into(), S1);
|
||||
let dep = SPair("dep".into(), S2);
|
||||
|
||||
let oi_dep = lookup_or_missing(&mut asg, dep);
|
||||
#[rustfmt::skip]
|
||||
let toks = [
|
||||
PkgStart(S1, SPair("/pkg".into(), S1)),
|
||||
IdentDecl(
|
||||
sym,
|
||||
IdentKind::Tpl,
|
||||
Source {
|
||||
virtual_: true,
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
IdentFragment(sym, FragmentText::from("foo")),
|
||||
|
||||
declare(
|
||||
&mut asg,
|
||||
sym,
|
||||
IdentKind::Tpl,
|
||||
Source {
|
||||
virtual_: true,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
.set_fragment(&mut asg, FragmentText::from("foo"))
|
||||
.unwrap()
|
||||
.add_opaque_dep(&mut asg, oi_dep)
|
||||
.root(&mut asg);
|
||||
// dep will be added as Missing
|
||||
IdentDep(sym, dep),
|
||||
|
||||
IdentRoot(sym),
|
||||
PkgEnd(S5),
|
||||
];
|
||||
|
||||
let asg = asg_from_toks(toks);
|
||||
|
||||
match sort(&asg, Sections::new()) {
|
||||
Ok(_) => panic!("Unexpected success - dependency is not in graph"),
|
||||
|
@ -170,66 +175,43 @@ fn graph_sort_missing_node() -> SortResult<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn graph_sort_no_roots_same_as_empty_graph() -> SortResult<()> {
|
||||
let mut asg = make_asg();
|
||||
|
||||
// "empty" (it has the head/tail {ret,}map objects)
|
||||
let asg_empty = make_asg();
|
||||
|
||||
let sym = SPair("sym".into(), S1);
|
||||
let dep = SPair("dep".into(), S2);
|
||||
|
||||
let oi_sym = lookup_or_missing(&mut asg, sym);
|
||||
let oi_dep = lookup_or_missing(&mut asg, dep);
|
||||
oi_sym.add_opaque_dep(&mut asg, oi_dep);
|
||||
|
||||
assert_eq!(
|
||||
sort(&asg, Sections::new()),
|
||||
sort(&asg_empty, Sections::new())
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn graph_sort_simple_cycle() -> SortResult<()> {
|
||||
let mut asg = make_asg();
|
||||
|
||||
let sym = SPair("sym".into(), S1);
|
||||
let dep = SPair("dep".into(), S2);
|
||||
|
||||
let oi_sym = declare(
|
||||
&mut asg,
|
||||
sym,
|
||||
IdentKind::Tpl,
|
||||
Source {
|
||||
virtual_: true,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
.set_fragment(&mut asg, FragmentText::from("foo"))
|
||||
.unwrap();
|
||||
#[rustfmt::skip]
|
||||
let toks = [
|
||||
PkgStart(S1, SPair("/pkg".into(), S1)),
|
||||
IdentDecl(
|
||||
sym,
|
||||
IdentKind::Tpl,
|
||||
Source {
|
||||
virtual_: true,
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
IdentFragment(sym, FragmentText::from("foo")),
|
||||
|
||||
let oi_dep = declare(
|
||||
&mut asg,
|
||||
dep,
|
||||
IdentKind::Tpl,
|
||||
Source {
|
||||
virtual_: true,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
.set_fragment(&mut asg, FragmentText::from("bar"))
|
||||
.unwrap();
|
||||
IdentDecl(
|
||||
dep,
|
||||
IdentKind::Tpl,
|
||||
Source {
|
||||
virtual_: true,
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
IdentFragment(dep, FragmentText::from("bar")),
|
||||
|
||||
oi_sym.add_opaque_dep(&mut asg, oi_dep);
|
||||
oi_dep.add_opaque_dep(&mut asg, oi_sym);
|
||||
// Produce a cycle (which will be an error)
|
||||
IdentDep(sym, dep),
|
||||
IdentDep(dep, sym),
|
||||
|
||||
oi_sym.root(&mut asg);
|
||||
IdentRoot(sym),
|
||||
PkgEnd(S5),
|
||||
];
|
||||
|
||||
let asg = asg_from_toks(toks);
|
||||
let result = sort(&asg, Sections::new());
|
||||
|
||||
match result {
|
||||
|
|
|
@ -87,6 +87,12 @@
|
|||
// Added for use with `rustfmt::skip`,
|
||||
// so that we can ignore formatting more precisely.
|
||||
#![feature(stmt_expr_attributes)]
|
||||
// Allows using `impl Trait` for associated type bounds instead of having to
|
||||
// extract it into a more verbose `where` clause.
|
||||
// This is not necessary,
|
||||
// and may not even be desirable,
|
||||
// but it's a nice option to have if `impl` would otherwise be used.
|
||||
#![feature(associated_type_bounds)]
|
||||
// We build docs for private items.
|
||||
#![allow(rustdoc::private_intra_doc_links)]
|
||||
// For sym::prefill recursive macro `static_symbols!`.
|
||||
|
|
Loading…
Reference in New Issue