Skip to content

Commit

Permalink
Add max depth elem dfs to AutosarModel and ArxmlFile
Browse files Browse the repository at this point in the history
This adds tests for the elements_dfs_with_max_depth() implementations,
as well.
  • Loading branch information
shahn authored and DanielT committed Aug 19, 2024
1 parent f2041d0 commit dc9fa16
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 3 deletions.
60 changes: 59 additions & 1 deletion autosar-data/src/arxmlfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,31 @@ impl ArxmlFile {
/// ```
#[must_use]
pub fn elements_dfs(&self) -> ArxmlFileElementsDfsIterator {
ArxmlFileElementsDfsIterator::new(self)
ArxmlFileElementsDfsIterator::new(self, 0)
}

/// Create a depth first iterator over all [Element]s in this file, up to a maximum depth
///
/// In a multi-file model it will not return any elements from other files.
///
/// # Example
///
/// ```
/// # use autosar_data::*;
/// # let model = AutosarModel::new();
/// # let file = model.create_file("test", AutosarVersion::Autosar_00050).unwrap();
/// # let element = model.root_element();
/// # element.create_sub_element(ElementName::ArPackages).unwrap();
/// # let sub_elem = element.get_sub_element(ElementName::ArPackages).unwrap();
/// # sub_elem.create_named_sub_element(ElementName::ArPackage, "test2").unwrap();
/// for (depth, elem) in file.elements_dfs_with_max_depth(1) {
/// assert!(depth <= 1);
/// // ...
/// }
/// ```
#[must_use]
pub fn elements_dfs_with_max_depth(&self, max_depth: usize) -> ArxmlFileElementsDfsIterator {
ArxmlFileElementsDfsIterator::new(self, max_depth)
}

/// Serialize the content of the file to a String
Expand Down Expand Up @@ -445,6 +469,40 @@ mod test {
assert_eq!(file_elem_count, file_elem_count_2);
}

#[test]
fn elements_dfs_with_max_depth() {
const FILEBUF: &[u8] = r#"<?xml version="1.0" encoding="utf-8"?>
<AUTOSAR xsi:schemaLocation="http://autosar.org/schema/r4.0 AUTOSAR_00050.xsd" xmlns="http://autosar.org/schema/r4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<AR-PACKAGES>
<AR-PACKAGE><SHORT-NAME>Pkg_A</SHORT-NAME><ELEMENTS>
<ECUC-MODULE-CONFIGURATION-VALUES><SHORT-NAME>BswModule</SHORT-NAME><CONTAINERS><ECUC-CONTAINER-VALUE>
<SHORT-NAME>BswModuleValues</SHORT-NAME>
<PARAMETER-VALUES>
<ECUC-NUMERICAL-PARAM-VALUE>
<DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/REF_A</DEFINITION-REF>
</ECUC-NUMERICAL-PARAM-VALUE>
<ECUC-NUMERICAL-PARAM-VALUE>
<DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/REF_B</DEFINITION-REF>
</ECUC-NUMERICAL-PARAM-VALUE>
<ECUC-NUMERICAL-PARAM-VALUE>
<DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/REF_C</DEFINITION-REF>
</ECUC-NUMERICAL-PARAM-VALUE>
</PARAMETER-VALUES>
</ECUC-CONTAINER-VALUE></CONTAINERS></ECUC-MODULE-CONFIGURATION-VALUES>
</ELEMENTS></AR-PACKAGE>
<AR-PACKAGE><SHORT-NAME>Pkg_B</SHORT-NAME></AR-PACKAGE>
<AR-PACKAGE><SHORT-NAME>Pkg_C</SHORT-NAME></AR-PACKAGE>
</AR-PACKAGES></AUTOSAR>"#.as_bytes();
let model = AutosarModel::new();
let (file, _) = model.load_buffer(FILEBUF, "test1", true).unwrap();
let all_count = file.elements_dfs().count();
let lvl2_count = file.elements_dfs_with_max_depth(2).count();
assert!(all_count > lvl2_count);
for elem in file.elements_dfs_with_max_depth(2) {
assert!(elem.0 <= 2);
}
}

#[test]
fn multiple_files_1() {
// two files are created, both contain AUTOSAR. Then a child element of AUTOSAR is created, which is present in both files
Expand Down
59 changes: 59 additions & 0 deletions autosar-data/src/autosarmodel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,31 @@ impl AutosarModel {
self.root_element().elements_dfs()
}

/// Create a depth first iterator over all [Element]s in this model, up to a maximum depth
///
/// The iterator returns all elements from the merged model, consisting of
/// data from all arxml files loaded in this model.
///
/// # Example
///
/// ```
/// # use autosar_data::*;
/// # let model = AutosarModel::new();
/// # let file = model.create_file("test", AutosarVersion::Autosar_00050).unwrap();
/// # let element = model.root_element();
/// # element.create_sub_element(ElementName::ArPackages).unwrap();
/// # let sub_elem = element.get_sub_element(ElementName::ArPackages).unwrap();
/// # sub_elem.create_named_sub_element(ElementName::ArPackage, "test2").unwrap();
/// for (depth, elem) in model.elements_dfs_with_max_depth(1) {
/// assert!(depth <= 1);
/// // ...
/// }
/// ```
#[must_use]
pub fn elements_dfs_with_max_depth(&self, max_depth: usize) -> ElementsDfsIterator {
self.root_element().elements_dfs_with_max_depth(max_depth)
}

/// Recursively sort all elements in the model. This is exactly identical to calling `sort()` on the root element of the model.
///
/// All sub elements of the root element are sorted alphabetically.
Expand Down Expand Up @@ -1479,4 +1504,38 @@ mod test {
assert_eq!(ct, ct2);
assert_eq!(format!("{ct:#?}"), format!("{ct2:#?}"));
}

#[test]
fn elements_dfs_with_max_depth() {
const FILEBUF: &[u8] = r#"<?xml version="1.0" encoding="utf-8"?>
<AUTOSAR xsi:schemaLocation="http://autosar.org/schema/r4.0 AUTOSAR_00050.xsd" xmlns="http://autosar.org/schema/r4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<AR-PACKAGES>
<AR-PACKAGE><SHORT-NAME>Pkg_A</SHORT-NAME><ELEMENTS>
<ECUC-MODULE-CONFIGURATION-VALUES><SHORT-NAME>BswModule</SHORT-NAME><CONTAINERS><ECUC-CONTAINER-VALUE>
<SHORT-NAME>BswModuleValues</SHORT-NAME>
<PARAMETER-VALUES>
<ECUC-NUMERICAL-PARAM-VALUE>
<DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/REF_A</DEFINITION-REF>
</ECUC-NUMERICAL-PARAM-VALUE>
<ECUC-NUMERICAL-PARAM-VALUE>
<DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/REF_B</DEFINITION-REF>
</ECUC-NUMERICAL-PARAM-VALUE>
<ECUC-NUMERICAL-PARAM-VALUE>
<DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/REF_C</DEFINITION-REF>
</ECUC-NUMERICAL-PARAM-VALUE>
</PARAMETER-VALUES>
</ECUC-CONTAINER-VALUE></CONTAINERS></ECUC-MODULE-CONFIGURATION-VALUES>
</ELEMENTS></AR-PACKAGE>
<AR-PACKAGE><SHORT-NAME>Pkg_B</SHORT-NAME></AR-PACKAGE>
<AR-PACKAGE><SHORT-NAME>Pkg_C</SHORT-NAME></AR-PACKAGE>
</AR-PACKAGES></AUTOSAR>"#.as_bytes();
let model = AutosarModel::new();
let (_, _) = model.load_buffer(FILEBUF, "test1", true).unwrap();
let all_count = model.elements_dfs().count();
let lvl2_count = model.elements_dfs_with_max_depth(2).count();
assert!(all_count > lvl2_count);
for elem in model.elements_dfs_with_max_depth(2) {
assert!(elem.0 <= 2);
}
}
}
45 changes: 45 additions & 0 deletions autosar-data/src/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3991,5 +3991,50 @@ mod test {
assert!(item7 > item6);
assert!(item6 < item7);
}

#[test]
fn elements_dfs_with_max_depth() {
const FILEBUF: &[u8] = r#"<?xml version="1.0" encoding="utf-8"?>
<AUTOSAR xsi:schemaLocation="http://autosar.org/schema/r4.0 AUTOSAR_00050.xsd" xmlns="http://autosar.org/schema/r4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<AR-PACKAGES>
<AR-PACKAGE><SHORT-NAME>Pkg_A</SHORT-NAME><ELEMENTS>
<ECUC-MODULE-CONFIGURATION-VALUES><SHORT-NAME>BswModule</SHORT-NAME><CONTAINERS><ECUC-CONTAINER-VALUE>
<SHORT-NAME>BswModuleValues</SHORT-NAME>
<PARAMETER-VALUES>
<ECUC-NUMERICAL-PARAM-VALUE>
<DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/REF_A</DEFINITION-REF>
</ECUC-NUMERICAL-PARAM-VALUE>
<ECUC-NUMERICAL-PARAM-VALUE>
<DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/REF_B</DEFINITION-REF>
</ECUC-NUMERICAL-PARAM-VALUE>
<ECUC-NUMERICAL-PARAM-VALUE>
<DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/REF_C</DEFINITION-REF>
</ECUC-NUMERICAL-PARAM-VALUE>
</PARAMETER-VALUES>
</ECUC-CONTAINER-VALUE></CONTAINERS></ECUC-MODULE-CONFIGURATION-VALUES>
</ELEMENTS></AR-PACKAGE>
<AR-PACKAGE><SHORT-NAME>Pkg_B</SHORT-NAME></AR-PACKAGE>
<AR-PACKAGE><SHORT-NAME>Pkg_C</SHORT-NAME></AR-PACKAGE>
</AR-PACKAGES></AUTOSAR>"#.as_bytes();
let model = AutosarModel::new();
let (_, _) = model.load_buffer(FILEBUF, "test1", true).unwrap();
let root_elem = model.root_element();
let ar_packages_elem = root_elem.get_sub_element(ElementName::ArPackages).unwrap();
let root_all_count = root_elem.elements_dfs().count();
let ar_packages_all_count = ar_packages_elem.elements_dfs().count();
assert_eq!(root_all_count, ar_packages_all_count + 1);

let root_lvl3_count = root_elem.elements_dfs_with_max_depth(3).count();
let ar_packages_lvl2_count = ar_packages_elem.elements_dfs_with_max_depth(2).count();
assert_eq!(root_lvl3_count, ar_packages_lvl2_count + 1);

root_elem.elements_dfs_with_max_depth(3).skip(1).zip(
ar_packages_elem.elements_dfs_with_max_depth(2)
).for_each(|((_, x), (_, y))| assert_eq!(x, y));

for elem in ar_packages_elem.elements_dfs_with_max_depth(2) {
assert!(elem.0 <= 2);
}
}
}

4 changes: 2 additions & 2 deletions autosar-data/src/iterators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ pub struct ArxmlFileElementsDfsIterator {
}

impl ArxmlFileElementsDfsIterator {
pub(crate) fn new(file: &ArxmlFile) -> Self {
pub(crate) fn new(file: &ArxmlFile, max_depth: usize) -> Self {
let weak_file = file.downgrade();
let dfs_iter = file.model().ok().map(|m| m.elements_dfs());
let dfs_iter = file.model().ok().map(|m| m.elements_dfs_with_max_depth(max_depth));
Self { weak_file, dfs_iter }
}
}
Expand Down

0 comments on commit dc9fa16

Please sign in to comment.