Skip to content

Commit

Permalink
Get some basic tests to work, and also print execution
Browse files Browse the repository at this point in the history
Signed-off-by: Enrico Ghiorzi <[email protected]>
  • Loading branch information
EnricoGhiorzi committed May 20, 2024
1 parent 05d9640 commit f64600d
Show file tree
Hide file tree
Showing 25 changed files with 427 additions and 108 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ jobs:
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
run: cargo test --verbose --workspace
14 changes: 14 additions & 0 deletions scan_core/src/program_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,20 @@ impl ProgramGraph {
mod tests {
use super::*;

#[test]
fn transitions() -> Result<(), PgError> {
let mut builder = ProgramGraphBuilder::new();
let initial = builder.initial_location();
let r#final = builder.new_location();
let action = builder.new_action();
builder.add_transition(initial, action, r#final, None)?;
let mut pg = builder.build();
assert_eq!(pg.possible_transitions(), vec![(action, r#final)]);
pg.transition(action, r#final)?;
assert!(pg.possible_transitions().is_empty());
Ok(())
}

#[test]
fn program_graph() -> Result<(), PgError> {
// Create Program Graph
Expand Down
75 changes: 34 additions & 41 deletions scan_fmt_xml/src/cs_builder.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
use anyhow::anyhow;
use std::collections::{HashMap, HashSet};

use crate::parser::*;
use anyhow::anyhow;
use log::{info, trace};
use scan_core::*;
use std::collections::{HashMap, HashSet};

#[derive(Debug)]
pub struct CsModel {
cs: ChannelSystem,
fsm_names: HashMap<PgId, String>,
// skill_ids: HashMap<String, PgId>,
// skill_names: HashMap<PgId, String>,
// component_ids: HashMap<String, PgId>,
// component_names: HashMap<PgId, String>,
pub cs: ChannelSystem,
pub fsm_names: HashMap<PgId, String>,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -55,28 +50,24 @@ pub struct Sc2CsVisitor {

impl Sc2CsVisitor {
pub fn visit(parser: Parser) -> anyhow::Result<CsModel> {
// Add base types
// FIXME: Is there a better way? Const object?
let base_types: [(String, Type); 3] = [
(String::from("Boolean"), Type::Boolean),
(String::from("int32"), Type::Integer),
(String::from("URI"), Type::Integer),
];

let mut model = Sc2CsVisitor {
cs: ChannelSystemBuilder::new(),
scan_types: HashMap::new(),
scan_types: HashMap::from_iter(base_types.into_iter()),
enums: HashMap::new(),
// skill_ids: HashMap::new(),
// component_ids: HashMap::new(),
fsm_builders: HashMap::new(),
events: Vec::new(),
event_indexes: HashMap::new(),
parameters: HashMap::new(),
};

// FIXME: Is there a better way? Const object?
// Add base types
model
.scan_types
.insert(String::from("int32"), Type::Integer);
model.scan_types.insert(String::from("URI"), Type::Integer);
model
.scan_types
.insert(String::from("Boolean"), Type::Boolean);

model.build_types(&parser.types)?;

model.prebuild_processes(&parser)?;
Expand Down Expand Up @@ -186,6 +177,7 @@ impl Sc2CsVisitor {
}
for transition in state.transitions.iter() {
if let Some(ref event) = transition.event {
// Event may or may not have been processed before
let event_index = self.event_index(event);
let builder = self.events.get_mut(event_index).expect("index must exist");
builder.receivers.insert(pg_id);
Expand Down Expand Up @@ -213,7 +205,6 @@ impl Sc2CsVisitor {
target: _,
params,
} => {
// WARN FIXME target could be an expression!
let event_index = self.event_index(event);
let builder = self.events.get_mut(event_index).expect("index must exist");
builder.senders.insert(pg_id);
Expand Down Expand Up @@ -567,13 +558,19 @@ impl Sc2CsVisitor {
fn build_fsm(&mut self, fsm: &Fsm) -> anyhow::Result<()> {
trace!("build fsm {}", fsm.id);
// Initialize fsm.
let pg_builder = self.fsm_builder(&fsm.id);
let pg_builder = self
.fsm_builders
.get(&fsm.id)
.expect("builder must already exist");
let pg_id = pg_builder.pg_id;
let pg_index = pg_builder.index as Integer;
let ext_queue = pg_builder.ext_queue;
// Initial location of Program Graph.
let initial_loc = self.cs.initial_location(pg_id)?;
let initialize = self.cs.new_action(pg_id)?;
let initial_loc = self
.cs
.initial_location(pg_id)
.expect("program graph must exist");
let initialize = self.cs.new_action(pg_id).expect("program graph must exist");
// Initialize variables from datamodel
let mut vars = HashMap::new();
for (location, (type_name, expr)) in fsm.datamodel.iter() {
Expand Down Expand Up @@ -822,7 +819,14 @@ impl Sc2CsVisitor {

// Consider each of the state's transitions.
for transition in state.transitions.iter() {
trace!("build transition {transition:#?}");
trace!(
"build {} transition to {}",
transition
.event
.as_ref()
.unwrap_or(&"eventless".to_string()),
transition.target
);
// Get or create the location corresponding to the target state.
let target_loc = states.get(&transition.target).cloned().unwrap_or_else(|| {
let target_loc = self.cs.new_location(pg_id).expect("pg_id should exist");
Expand Down Expand Up @@ -1137,6 +1141,9 @@ impl Sc2CsVisitor {
.ok_or(anyhow!("not utf8"))?;
match ident {
"_event" => todo!(),
// enum_const if self.enums.contains_key(&(enum_type, enum_const.to_owned())) => {
// todo!()
// }
var_ident => vars
.get(var_ident)
.ok_or(anyhow!("unknown variable"))
Expand Down Expand Up @@ -1277,23 +1284,9 @@ impl Sc2CsVisitor {
.iter()
.map(|(name, id)| (id.pg_id, name.to_owned()))
.collect();
// let skill_names = self
// .skill_ids
// .iter()
// .map(|(name, id)| (*id, name.to_owned()))
// .collect();
// let component_names = self
// .component_ids
// .iter()
// .map(|(name, id)| (*id, name.to_owned()))
// .collect();
CsModel {
cs: self.cs.build(),
fsm_names,
// skill_ids: self.skill_ids,
// skill_names,
// component_ids: self.component_ids,
// component_names,
}
}
}
2 changes: 0 additions & 2 deletions scan_fmt_xml/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
mod cs_builder;
mod parser;

use parser::*;

pub use cs_builder::Sc2CsVisitor;
pub use parser::Parser;
5 changes: 0 additions & 5 deletions scan_fmt_xml/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,6 @@ impl Parser {
Ok(spec)
}

pub fn build_model(self) -> ChannelSystem {
let cs = ChannelSystemBuilder::new();
cs.build()
}

fn parse_process<R: BufRead>(
&mut self,
tag: events::BytesStart<'_>,
Expand Down
10 changes: 4 additions & 6 deletions scan_fmt_xml/src/parser/bt.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use std::io::BufRead;
use std::str;

use super::vocabulary::*;
use crate::parser::{ParserError, ParserErrorType};
use anyhow::anyhow;
use log::{error, info, trace, warn};
use quick_xml::events::attributes::{AttrError, Attribute};
use quick_xml::{events, events::Event, Reader};

use super::vocabulary::*;
use crate::{ParserError, ParserErrorType};
use std::io::BufRead;
use std::str;

#[derive(Debug, Clone)]
pub enum BtNode {
Expand Down
14 changes: 6 additions & 8 deletions scan_fmt_xml/src/parser/fsm.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
use std::collections::HashMap;
use std::fmt::Debug;
use std::io::{BufRead, Read};
use std::str;

use super::vocabulary::*;
use crate::parser::{ParserError, ParserErrorType};
use anyhow::anyhow;
use boa_ast::{Expression as BoaExpression, StatementListItem};
use log::{error, info, trace, warn};
use quick_xml::events::attributes::{AttrError, Attribute};
use quick_xml::{events, events::Event, Reader};

use super::vocabulary::*;
use crate::{ParserError, ParserErrorType};
use std::collections::HashMap;
use std::fmt::Debug;
use std::io::{BufRead, Read};
use std::str;

#[derive(Debug, Clone, PartialEq, Eq)]
enum ScxmlTag {
Expand Down
6 changes: 2 additions & 4 deletions scan_fmt_xml/src/parser/omg_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ use quick_xml::{
};
use std::str;

use crate::{
parser::ConvinceTag, ParserError, ParserErrorType, ATTR_ID, TAG_DATA_TYPE_LIST,
TAG_ENUMERATION, TAG_LABEL,
};
use crate::parser::vocabulary::{ATTR_ID, TAG_DATA_TYPE_LIST, TAG_ENUMERATION, TAG_LABEL};
use crate::parser::{ConvinceTag, ParserError, ParserErrorType};

#[derive(Debug, Clone)]
pub enum OmgType {
Expand Down
40 changes: 40 additions & 0 deletions scan_fmt_xml/tests/basic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use anyhow::anyhow;
use scan_fmt_xml::*;
use std::{path::PathBuf, str::FromStr};

const MAXSTEP: usize = 1000;

#[test]
fn fsm() -> anyhow::Result<()> {
test(PathBuf::from_str("./tests/test_fsm/model.xml")?)
}

#[test]
fn datamodel() -> anyhow::Result<()> {
test(PathBuf::from_str("./tests/test_datamodel/model.xml")?)
}

// #[test]
// fn enumdata() -> anyhow::Result<()> {
// test(PathBuf::from_str("./tests/test_enumdata/model.xml")?)
// }

#[test]
fn send() -> anyhow::Result<()> {
test(PathBuf::from_str("./tests/test_send/model.xml")?)
}

fn test(file: PathBuf) -> anyhow::Result<()> {
let parser = Parser::parse(file)?;
let mut model = Sc2CsVisitor::visit(parser)?;
let mut steps = 0;
assert!(!model.cs.possible_transitions().is_empty());
while let Some((pg_id, act, loc)) = model.cs.possible_transitions().first().cloned() {
model.cs.transition(pg_id, act, loc)?;
steps += 1;
if steps >= MAXSTEP {
return Err(anyhow!("step limit reached"));
}
}
Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
version="1.0"
xmlns="http://www.w3.org/2005/07/scxml"
datamodel="ecmascript"
name="AlarmBatteryLow"
name="fsm"
initial="idle">

<datamodel>
Expand Down
File renamed without changes.
File renamed without changes.
28 changes: 28 additions & 0 deletions scan_fmt_xml/tests/test_enumdata/fsm.scxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<scxml
version="1.0"
xmlns="http://www.w3.org/2005/07/scxml"
datamodel="ecmascript"
name="fsm"
initial="idle">

<datamodel>
<!-- TYPE state:TickResponse -->
<data id="state" expr="FAILURE"/>
</datamodel>

<state id="idle">
<transition target="running" cond="state == FAILURE"/>
</state>

<state id="running">
<onentry>
<assign location="state" expr="RUNNING"/>
</onentry>
<transition target="finished" cond="state == RUNNING"/>
<onexit>
<assign location="state" expr="SUCCESS"/>
</onexit>
</state>

<state id="finished"/>
</scxml>
15 changes: 15 additions & 0 deletions scan_fmt_xml/tests/test_enumdata/model.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<specification xmlns="..." xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="...">

<model>

<types path="./types.xml" />

<processList>
<process id="fsm" moc="fsm" path="./fsm.scxml" />
</processList>

</model>

<properties path="./properties.xml"/>
</specification>
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@
version="1.0"
xmlns="http://www.w3.org/2005/07/scxml"
datamodel="ecmascript"
name="AlarmBatteryLow"
name="fsm"
initial="idle">

<datamodel>
</datamodel>

<state id="idle">
<transition target="running"/>
</state>

<state id="running">
<transition target="finished"/>
<state id="running">
<transition target="finished"/>
</state>

<state id="finished"/>
Expand Down
File renamed without changes.
Loading

0 comments on commit f64600d

Please sign in to comment.