tamer: obj::xmle::xir::test: Extract into own file

These are getting large and messy.

And I now notice that I never completed the header test after
prototyping.  Shame on me.

Also, errata from the previous commit message: the diffs are identical
_except for attribute escaping_ that is unnecessary; we're outputting data
read directly from existing XML files (output by Saxon), so characters are
already escaped as needed.

DEV-10561
main
Mike Gerwitz 2021-09-30 13:24:40 -04:00
parent 7269e68b00
commit 42188e80e7
3 changed files with 341 additions and 331 deletions

View File

@ -27,7 +27,7 @@
//! This IR should be converted into a higher-level IR quickly,
//! especially considering that it will be going away in the future.
use crate::sym::{GlobalSymbolResolve, SymbolId, st};
use crate::sym::{st, GlobalSymbolResolve, SymbolId};
use std::convert::TryFrom;
use std::result::Result;

View File

@ -247,334 +247,5 @@ pub fn lower_iter<'a, T: IdentObjectData>(
)
}
// Note: at the time of writing, the Xir tree did not exist, and so these
// assert verbosely on the stream itself.
#[cfg(test)]
pub mod test {
use super::*;
use crate::convert::ExpectInto;
use crate::ir::legacyir::SymDtype;
use crate::ir::{
asg::{Dim, IdentKind, Source},
xir::{
pred::{not, open},
tree::{parser_from, Attr},
},
};
use crate::sym::{GlobalSymbolIntern, GlobalSymbolResolve};
type TestResult = Result<(), Box<dyn std::error::Error>>;
macro_rules! assert_attr{
($attrs:ident, $name:ident, $expected:expr, $($args:expr),*) => {
assert_eq!(
$attrs.find($name).and_then(|a| a.value_atom()),
$expected,
$($args),*
)
}
}
#[test]
fn test_produces_header() -> TestResult {
let empty = Sections::<IdentObject>::new();
let name = "test-pkg".intern();
let relroot = "rel/root/".intern();
let result = lower_iter(&empty, name, relroot)
.take_while(|tok| match tok {
// TODO
Token::Close(_, _) => false,
_ => true,
})
.collect::<Vec<Token>>();
assert_eq!(Token::Open(QN_PACKAGE, LSPAN), result[0]);
Ok(())
}
#[test]
fn test_closes_package() -> TestResult {
let empty = Sections::<IdentObject>::new();
let result =
lower_iter(&empty, "foo".intern(), "relroot".intern()).last();
assert_eq!(Some(Token::Close(Some(QN_PACKAGE), LSPAN)), result);
Ok(())
}
#[test]
fn test_writes_deps() -> TestResult {
let mut sections = Sections::new();
let relroot = "relroot-deps".intern();
let objs = [
IdentObject::Ident(
"cgentest".intern(),
IdentKind::Cgen(Dim::from_u8(1)),
Source {
yields: Some("yieldsValue".intern()),
parent: Some("cparent".intern()),
generated: true,
pkg_name: Some("pkg/name".intern()),
..Default::default()
},
),
IdentObject::Ident(
"classtest".intern(),
IdentKind::Class(Dim::from_u8(2)),
Default::default(),
),
IdentObject::Ident(
"consttest".intern(),
IdentKind::Const(Dim::from_u8(0), SymDtype::Boolean),
Default::default(),
),
IdentObject::Ident(
"functest".intern(),
IdentKind::Func(Dim::from_u8(1), SymDtype::Integer),
Default::default(),
),
IdentObject::Ident(
"gentest".intern(),
IdentKind::Gen(Dim::from_u8(1), SymDtype::Boolean),
Default::default(),
),
IdentObject::Ident(
"lparamtest".intern(),
IdentKind::Gen(Dim::from_u8(2), SymDtype::Float),
Default::default(),
),
IdentObject::Ident(
"paramtest".intern(),
IdentKind::Gen(Dim::from_u8(0), SymDtype::Integer),
Default::default(),
),
IdentObject::Ident(
"ratetest".intern(),
IdentKind::Rate(SymDtype::Integer),
Default::default(),
),
IdentObject::Ident(
"tpltest".intern(),
IdentKind::Tpl,
Default::default(),
),
IdentObject::Ident(
"typetest".intern(),
IdentKind::Type(SymDtype::Integer),
Default::default(),
),
IdentObject::Ident(
"mapheadtest".intern(),
IdentKind::MapHead,
Default::default(),
),
IdentObject::Ident(
"maptest".intern(),
IdentKind::Map,
Default::default(),
),
IdentObject::Ident(
"maptailtest".intern(),
IdentKind::MapTail,
Default::default(),
),
IdentObject::Ident(
"retmapheadtest".intern(),
IdentKind::RetMapHead,
Default::default(),
),
IdentObject::Ident(
"retmaptest".intern(),
IdentKind::RetMap,
Default::default(),
),
IdentObject::Ident(
"retmaptailtest".intern(),
IdentKind::RetMapTail,
Default::default(),
),
IdentObject::Ident(
"metatest".intern(),
IdentKind::Meta,
Source {
desc: Some("test desc".intern()),
..Default::default()
},
),
IdentObject::Ident(
"worksheettest".intern(),
IdentKind::Worksheet,
Default::default(),
),
];
objs.iter().for_each(|x| sections.consts.push_body(x));
let mut iter = parser_from(
lower_iter(&sections, "pkg".intern(), relroot)
.skip_while(not(open(QN_L_DEP))),
);
let given = iter
.next()
.expect("tree object expected")
.unwrap() // Tree
.into_element()
.expect("element expected");
// Sanity check to ensure we have the element we're expecting.
assert_eq!(QN_L_DEP, given.name());
let children = given.children();
assert_eq!(
children.len(),
objs.len(),
"expected child node for each dependency"
);
let p_syms = children.into_iter().map(|child| {
let ele =
child.as_element().expect("child expected to be an element");
assert_eq!(QN_P_SYM, ele.name());
ele
});
p_syms.enumerate().for_each(|(i, ele)| {
let ident = objs[i].as_ident().unwrap();
let attrs = ele.attrs();
assert_eq!(
attrs.find(QN_NAME).and_then(|a| a.value_atom()),
Some(AttrValue::Escaped(ident.name().unwrap())),
);
assert_eq!(
attrs.find(QN_TYPE).and_then(|a| a.value_atom()),
Some(AttrValue::Escaped(ident.kind().unwrap().as_sym()))
);
let generated =
attrs.find(QN_GENERATED).and_then(|a| a.value_atom());
if let Some(Source {
generated: true, ..
}) = ident.src()
{
assert_eq!(
generated,
Some(AttrValue::Escaped("true".intern()))
);
} else {
assert_eq!(generated, None);
}
if let Some(Source { parent, .. }) = ident.src() {
assert_attr!(
attrs,
QN_PARENT,
parent.map(|x| AttrValue::Escaped(x)),
);
}
if let Some(Source { yields, .. }) = ident.src() {
assert_attr!(
attrs,
QN_YIELDS,
yields.map(|x| AttrValue::Escaped(x)),
);
}
if let Some(Source {
desc: Some(desc), ..
}) = ident.src()
{
// We must take extra effort to compare these, since desc is
// uninterned and therefore cannot be compared as a
// `SymbolId`. Once the reader takes care of creating the
// symbol, we'll have no such problem.
match attrs.find(QN_DESC).and_then(|a| a.value_atom()) {
Some(AttrValue::Escaped(given)) => {
assert_eq!(desc.lookup_str(), given.lookup_str());
}
invalid => panic!("unexpected desc: {:?}", invalid),
}
}
if let Some(Source {
pkg_name: Some(pkg_name),
..
}) = ident.src()
{
match attrs.find("src".unwrap_into()) {
Some(Attr::Extensible(parts)) => {
assert_eq!(
parts.value_fragments(),
&vec![
(AttrValue::Escaped(relroot), LSPAN),
(AttrValue::Escaped(*pkg_name), LSPAN),
]
);
}
invalid => panic!("unexpected desc: {:?}", invalid),
}
}
// Object-specific attributes
match ident.kind().unwrap() {
IdentKind::Cgen(dim) | IdentKind::Class(dim) => {
assert_attr!(
attrs,
QN_DIM,
Some(AttrValue::Escaped((*dim).into())),
"invalid {:?} @dim",
ident.kind()
);
}
IdentKind::Const(dim, dtype)
| IdentKind::Func(dim, dtype)
| IdentKind::Gen(dim, dtype)
| IdentKind::Lparam(dim, dtype)
| IdentKind::Param(dim, dtype) => {
assert_attr!(
attrs,
QN_DIM,
Some(AttrValue::Escaped((*dim).into())),
"invalid {:?} @dim",
ident.kind()
);
assert_attr!(
attrs,
QN_DTYPE,
Some(AttrValue::Escaped((*dtype).into())),
"invalid {:?} @dtype",
ident.kind()
);
}
IdentKind::Rate(dtype) | IdentKind::Type(dtype) => {
assert_attr!(
attrs,
QN_DTYPE,
Some(AttrValue::Escaped((*dtype).into())),
"invalid {:?} @dim",
ident.kind()
);
}
// The others have no additional attributes
_ => {}
}
});
Ok(())
}
}
pub mod test;

View File

@ -0,0 +1,339 @@
// Test lowering operations into XIR.
//
// Copyright (C) 2014-2021 Ryan Specialty Group, LLC.
//
// This file is part of TAME.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
use super::*;
use crate::convert::ExpectInto;
use crate::ir::legacyir::SymDtype;
use crate::ir::{
asg::{Dim, IdentKind, Source},
xir::{
pred::{not, open},
tree::{parser_from, Attr},
},
};
use crate::sym::{GlobalSymbolIntern, GlobalSymbolResolve};
type TestResult = Result<(), Box<dyn std::error::Error>>;
macro_rules! assert_attr{
($attrs:ident, $name:ident, $expected:expr, $($args:expr),*) => {
assert_eq!(
$attrs.find($name).and_then(|a| a.value_atom()),
$expected,
$($args),*
)
}
}
#[test]
fn test_produces_header() -> TestResult {
let empty = Sections::<IdentObject>::new();
let name = "test-pkg".intern();
let relroot = "rel/root/".intern();
let result = lower_iter(&empty, name, relroot)
.take_while(|tok| match tok {
// TODO
Token::Close(_, _) => false,
_ => true,
})
.collect::<Vec<Token>>();
assert_eq!(Token::Open(QN_PACKAGE, LSPAN), result[0]);
Ok(())
}
#[test]
fn test_closes_package() -> TestResult {
let empty = Sections::<IdentObject>::new();
let result = lower_iter(&empty, "foo".intern(), "relroot".intern()).last();
assert_eq!(Some(Token::Close(Some(QN_PACKAGE), LSPAN)), result);
Ok(())
}
#[test]
fn test_writes_deps() -> TestResult {
let mut sections = Sections::new();
let relroot = "relroot-deps".intern();
let objs = [
IdentObject::Ident(
"cgentest".intern(),
IdentKind::Cgen(Dim::from_u8(1)),
Source {
yields: Some("yieldsValue".intern()),
parent: Some("cparent".intern()),
generated: true,
pkg_name: Some("pkg/name".intern()),
..Default::default()
},
),
IdentObject::Ident(
"classtest".intern(),
IdentKind::Class(Dim::from_u8(2)),
Default::default(),
),
IdentObject::Ident(
"consttest".intern(),
IdentKind::Const(Dim::from_u8(0), SymDtype::Boolean),
Default::default(),
),
IdentObject::Ident(
"functest".intern(),
IdentKind::Func(Dim::from_u8(1), SymDtype::Integer),
Default::default(),
),
IdentObject::Ident(
"gentest".intern(),
IdentKind::Gen(Dim::from_u8(1), SymDtype::Boolean),
Default::default(),
),
IdentObject::Ident(
"lparamtest".intern(),
IdentKind::Gen(Dim::from_u8(2), SymDtype::Float),
Default::default(),
),
IdentObject::Ident(
"paramtest".intern(),
IdentKind::Gen(Dim::from_u8(0), SymDtype::Integer),
Default::default(),
),
IdentObject::Ident(
"ratetest".intern(),
IdentKind::Rate(SymDtype::Integer),
Default::default(),
),
IdentObject::Ident(
"tpltest".intern(),
IdentKind::Tpl,
Default::default(),
),
IdentObject::Ident(
"typetest".intern(),
IdentKind::Type(SymDtype::Integer),
Default::default(),
),
IdentObject::Ident(
"mapheadtest".intern(),
IdentKind::MapHead,
Default::default(),
),
IdentObject::Ident(
"maptest".intern(),
IdentKind::Map,
Default::default(),
),
IdentObject::Ident(
"maptailtest".intern(),
IdentKind::MapTail,
Default::default(),
),
IdentObject::Ident(
"retmapheadtest".intern(),
IdentKind::RetMapHead,
Default::default(),
),
IdentObject::Ident(
"retmaptest".intern(),
IdentKind::RetMap,
Default::default(),
),
IdentObject::Ident(
"retmaptailtest".intern(),
IdentKind::RetMapTail,
Default::default(),
),
IdentObject::Ident(
"metatest".intern(),
IdentKind::Meta,
Source {
desc: Some("test desc".intern()),
..Default::default()
},
),
IdentObject::Ident(
"worksheettest".intern(),
IdentKind::Worksheet,
Default::default(),
),
];
objs.iter().for_each(|x| sections.consts.push_body(x));
let mut iter = parser_from(
lower_iter(&sections, "pkg".intern(), relroot)
.skip_while(not(open(QN_L_DEP))),
);
let given = iter
.next()
.expect("tree object expected")
.unwrap() // Tree
.into_element()
.expect("element expected");
// Sanity check to ensure we have the element we're expecting.
assert_eq!(QN_L_DEP, given.name());
let children = given.children();
assert_eq!(
children.len(),
objs.len(),
"expected child node for each dependency"
);
let p_syms = children.into_iter().map(|child| {
let ele = child.as_element().expect("child expected to be an element");
assert_eq!(QN_P_SYM, ele.name());
ele
});
p_syms.enumerate().for_each(|(i, ele)| {
let ident = objs[i].as_ident().unwrap();
let attrs = ele.attrs();
assert_eq!(
attrs.find(QN_NAME).and_then(|a| a.value_atom()),
Some(AttrValue::Escaped(ident.name().unwrap())),
);
assert_eq!(
attrs.find(QN_TYPE).and_then(|a| a.value_atom()),
Some(AttrValue::Escaped(ident.kind().unwrap().as_sym()))
);
let generated = attrs.find(QN_GENERATED).and_then(|a| a.value_atom());
if let Some(Source {
generated: true, ..
}) = ident.src()
{
assert_eq!(generated, Some(AttrValue::Escaped("true".intern())));
} else {
assert_eq!(generated, None);
}
if let Some(Source { parent, .. }) = ident.src() {
assert_attr!(
attrs,
QN_PARENT,
parent.map(|x| AttrValue::Escaped(x)),
);
}
if let Some(Source { yields, .. }) = ident.src() {
assert_attr!(
attrs,
QN_YIELDS,
yields.map(|x| AttrValue::Escaped(x)),
);
}
if let Some(Source {
desc: Some(desc), ..
}) = ident.src()
{
// We must take extra effort to compare these, since desc is
// uninterned and therefore cannot be compared as a
// `SymbolId`. Once the reader takes care of creating the
// symbol, we'll have no such problem.
match attrs.find(QN_DESC).and_then(|a| a.value_atom()) {
Some(AttrValue::Escaped(given)) => {
assert_eq!(desc.lookup_str(), given.lookup_str());
}
invalid => panic!("unexpected desc: {:?}", invalid),
}
}
if let Some(Source {
pkg_name: Some(pkg_name),
..
}) = ident.src()
{
match attrs.find("src".unwrap_into()) {
Some(Attr::Extensible(parts)) => {
assert_eq!(
parts.value_fragments(),
&vec![
(AttrValue::Escaped(relroot), LSPAN),
(AttrValue::Escaped(*pkg_name), LSPAN),
]
);
}
invalid => panic!("unexpected desc: {:?}", invalid),
}
}
// Object-specific attributes
match ident.kind().unwrap() {
IdentKind::Cgen(dim) | IdentKind::Class(dim) => {
assert_attr!(
attrs,
QN_DIM,
Some(AttrValue::Escaped((*dim).into())),
"invalid {:?} @dim",
ident.kind()
);
}
IdentKind::Const(dim, dtype)
| IdentKind::Func(dim, dtype)
| IdentKind::Gen(dim, dtype)
| IdentKind::Lparam(dim, dtype)
| IdentKind::Param(dim, dtype) => {
assert_attr!(
attrs,
QN_DIM,
Some(AttrValue::Escaped((*dim).into())),
"invalid {:?} @dim",
ident.kind()
);
assert_attr!(
attrs,
QN_DTYPE,
Some(AttrValue::Escaped((*dtype).into())),
"invalid {:?} @dtype",
ident.kind()
);
}
IdentKind::Rate(dtype) | IdentKind::Type(dtype) => {
assert_attr!(
attrs,
QN_DTYPE,
Some(AttrValue::Escaped((*dtype).into())),
"invalid {:?} @dim",
ident.kind()
);
}
// The others have no additional attributes
_ => {}
}
});
Ok(())
}