Skip to content

Commit

Permalink
Add tests for issue #16
Browse files Browse the repository at this point in the history
  • Loading branch information
misson20000 committed Aug 4, 2024
1 parent cd03449 commit 0d6c4e1
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/view/hierarchy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ impl<'tree, 'nodeinfo> selection::tree::TreeVisitor<'tree> for AlterNodesBulkNod
#[cfg(test)]
mod tests {
use super::*;
use glib::clone;
use rusty_fork::rusty_fork_test;

fn assert_tlr_node_correct(document: &sync::Arc<document::Document>, node: &sync::Arc<structure::Node>, iter: &mut impl std::iter::Iterator<Item = gtk::TreeListRow>) {
Expand Down Expand Up @@ -634,5 +635,56 @@ mod tests {
tlm.item(1).unwrap().downcast::<gtk::TreeListRow>().unwrap().set_expanded(true);
assert_tlm_correct(&document, &tlm);
}

#[test]
fn test_nest_issue_16() {
gtk::init().unwrap();

let root = structure::Node::builder()
.name("root")
.size(0x1000)
.child(0x0, |b| b
.name("A")
.size(0x20))
.child(0x20, |b| b
.name("B")
.size(0x20))
.child(0x40, |b| b
.name("C")
.size(0x20)
.child(0x0, |b| b
.name("D")
.size(0x10)))
.build();

let document_host = sync::Arc::new(document::Builder::new(root).host());
let mut document = document_host.get();

let tlm = create_tree_list_model(document_host.clone(), document.clone(), true);
assert_tlm_correct(&document, &tlm);

for i in 0..tlm.n_items() {
let tlr = tlm.item(i).unwrap().downcast::<gtk::TreeListRow>().unwrap();
println!("{} {:?}", tlr.depth(), tlr.item().unwrap().downcast::<NodeItem>().unwrap().info().props.name);
}

document = document_host.change(document.nest(
structure::SiblingRange::new(vec![], 0, 1),
addr::Extent::sized_u64(0x0, 0x40),
structure::Properties::default(),
)).unwrap();

tlm.connect_items_changed(clone!(#[strong] document, move |tlm, _, _, _| {
println!("");
println!("items changed");
assert_tlm_correct(&document, &tlm);
for i in 0..tlm.n_items() {
let tlr = tlm.item(i).unwrap().downcast::<gtk::TreeListRow>().unwrap();
println!("{} {:?}", tlr.depth(), tlr.item().unwrap().downcast::<NodeItem>().unwrap().info().props.name);
}
}));

tlm.model().downcast::<RootListModel>().unwrap().update_document(&document);
}
}
}
93 changes: 93 additions & 0 deletions src/view/selection/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,96 @@ impl TreeSelectionModel {
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::model::addr;
use crate::model::document::structure;
use crate::util;
use rusty_fork::rusty_fork_test;

rusty_fork_test! {
#[test]
fn test_nest_crash_issue_16() {
let _pg = util::test::PanicGuard::new();

gtk::init().unwrap();

let root = structure::Node::builder()
.name("root")
.size(0x1000)
.child(0x0, |b| b
.name("A")
.size(0x20))
.child(0x20, |b| b
.name("B")
.size(0x20))
.child(0x40, |b| b
.name("C")
.size(0x20)
.child(0x0, |b| b
.name("D")
.size(0x10)))
.build();

let dh = sync::Arc::new(document::Builder::new(root).host());
let mut document = dh.get();
let mut selection = selection::TreeSelection::new(document.clone());
selection.add_single(&[0]);
selection.add_single(&[1]);
let tsh = sync::Arc::new(selection::tree::Host::new(selection));

let ter = rc::Rc::new(helpers::test::TestErrorReporter);
let tsm = TreeSelectionModel::new(ter.clone(), tsh.clone(), dh.clone());
let tlm = tsm.imp().borrow_interior().unwrap().gtk_model.clone();

for i in 0..tlm.n_items() {
let tlr = tlm.item(i).unwrap().downcast::<gtk::TreeListRow>().unwrap();
let item = tlr.item().unwrap().downcast::<hierarchy::NodeItem>().unwrap();
let info = item.info();
println!("{:?} {:?} {:?}", info.path, info.props.name, tsm.is_selected(i));
}

tsm.connect_items_changed(clone!(move |tsm, p, r, a| {
println!("");
println!("selection model changed: {}, {}, {}", p, r, a);
for i in 0..tsm.n_items() {
let tlr = tsm.item(i).unwrap().downcast::<gtk::TreeListRow>().unwrap();
let item = tlr.item().unwrap().downcast::<hierarchy::NodeItem>().unwrap();
let info = item.info();
println!("{:?} {:?} {:?}", info.path, info.props.name, tsm.is_selected(i));
}
}));

document = dh.change(document.nest(
structure::SiblingRange::new(vec![], 0, 1),
addr::Extent::sized_u64(0x0, 0x40),
structure::Properties::default(),
)).unwrap();

/* tree nest action forces selection, so we do too */
let selection = tsh.change(selection::tree::Change::SetSingle(document.clone(), vec![0])).unwrap();
let interior = tsm.imp().borrow_interior_mut().unwrap();
tsm.update_selection(interior, selection);

/* panic happens in:
TreeSelectionModel::update_selection
RootListModel::update_document
NodeItem::update_document
StructureListModel::update
Versioned::changes_since
StructureListModel::update closure
StructureListModel::port_change
emit items_changed signal
gtk_tree_list_model_items_changed cb
emit items-changed signal
TreeSelectionModel::new closure for gtk_model.connect_items_changed
emit items-changed signal
gtk_list_item_manager_model_items_changed_cb
gtk_list_item_manager_ensure_items
TreeSelectionModel::imp::is_selected
*/
}
}
}

0 comments on commit 0d6c4e1

Please sign in to comment.