use linked_hash_map::LinkedHashMap;
use crate::{field_types::*, modele, Hit, Id, IndexEntryProperty, ObjectValue};
use std::{cell::RefCell, rc::Rc};
use crate::{HitError, Kernel, Model, Plugin, Plugins};
#[derive(Debug)]
struct TestPlugin {
before_insert_count: i32,
after_insert_count: i32,
before_set_value_count: i32,
after_set_value_count: i32,
before_move_subobject_count: i32,
after_move_subobject_count: i32,
}
impl Plugin for TestPlugin {
fn on_before_add_entry(
&mut self,
_extra_data: Rc<Model>,
_id: &str,
_data: crate::ObjectValues,
_parent: crate::IndexEntryProperty,
_before_id: &Option<Id>,
_instance: &Hit,
) -> Result<(), HitError> {
self.before_insert_count += 1;
Ok(())
}
fn on_after_add_entry(
&mut self,
_extra_data: Rc<Model>,
_id: &str,
_data: crate::ObjectValues,
_parent: crate::IndexEntryProperty,
_before_id: &Option<Id>,
_instance: &mut Hit,
) -> Result<(), HitError> {
self.after_insert_count += 1;
Ok(())
}
fn on_before_set_value(
&mut self,
_property: IndexEntryProperty,
_value: &ObjectValue,
_old_value: &Option<ObjectValue>,
_instance: &Hit,
) -> Result<(), HitError> {
self.before_set_value_count += 1;
Ok(())
}
fn on_after_set_value(
&mut self,
_property: IndexEntryProperty,
_value: &ObjectValue,
_old_value: &Option<ObjectValue>,
_instance: &mut Hit,
) -> Result<(), HitError> {
self.after_set_value_count += 1;
Ok(())
}
fn on_before_move_subobject(
&mut self,
_id: &str,
_target: IndexEntryProperty,
_before_id: Option<String>,
_instance: &Hit,
) -> Result<(), HitError> {
self.before_move_subobject_count += 1;
Ok(())
}
fn on_after_move_subobject(
&mut self,
_id: &str,
_target: IndexEntryProperty,
_original_parent: IndexEntryProperty,
_before_id: Option<String>,
_instance: &mut Hit,
) -> Result<(), HitError> {
self.after_move_subobject_count += 1;
Ok(())
}
}
pub struct TestPluginKernel {
model: Rc<Model>,
model2: Rc<Model>,
test_plugin: Rc<RefCell<TestPlugin>>,
}
impl Kernel for TestPluginKernel {
fn get_model(&self, name: &str) -> Result<Rc<Model>, HitError> {
if name == "test/test" {
return Ok(self.model.clone());
}
if name == "test/test_b" {
return Ok(self.model2.clone());
}
return Err(HitError::ModelDoesNotExist(name.into()));
}
fn get_instantiable_models(&self) -> Vec<&Model> {
return vec![&self.model, &self.model2];
}
fn get_plugins(&self) -> Plugins {
let mut plugins = Plugins::new();
plugins.plugins.push(self.test_plugin.clone());
plugins
}
fn get_models(&self) -> Vec<String> {
vec!["test/test".to_string()]
}
}
fn create_test_plugin_model() -> Rc<Model> {
modele!("test/test", "Filesystem" =>
"name": FieldTypeString {
required: true
},
"subitems": FieldTypeSubobjectArray {
authorized_models: vec!["test/test".to_string()]
},
"subitems2": FieldTypeSubobjectArray {
authorized_models: vec!["test/impossible".to_string()]
},
"subitems3": FieldTypeSubobjectArray {
authorized_models: vec!["test/test".to_string()]
},
"references": FieldTypeReferenceArray {
authorized_models: vec!["test/test".to_string()]
},
"reference": FieldTypeReference {
authorized_models: vec!["test/test".to_string()]
}
)
}
fn create_test_plugin_model2() -> Rc<Model> {
modele!("test/test_b", "Filesystem" =>
"name": FieldTypeString {
required: true
},
)
}
fn create_test_plugin() -> Rc<RefCell<TestPlugin>> {
Rc::new(RefCell::new(TestPlugin {
before_insert_count: 0,
after_insert_count: 0,
before_set_value_count: 0,
after_set_value_count: 0,
before_move_subobject_count: 0,
after_move_subobject_count: 0,
}))
}
fn create_test_plugin_kernel(plugin: Rc<RefCell<TestPlugin>>) -> TestPluginKernel {
TestPluginKernel {
model: create_test_plugin_model(),
model2: create_test_plugin_model2(),
test_plugin: plugin,
}
}
#[test]
fn it_should_call_only_before_set_value_callback_only_before_an_error() {
let plugin = create_test_plugin();
let mut hit_item = Hit::new(
"id".into(),
"test/test".into(),
Rc::new(create_test_plugin_kernel(plugin.clone())),
)
.expect("Error 1");
let error = hit_item.set("id", "reference", ObjectValue::Bool(false));
assert_eq!(error.err().unwrap(), HitError::InvalidDataType());
let borrowed_plugin = plugin.borrow();
assert_eq!(borrowed_plugin.before_set_value_count, 1);
assert_eq!(borrowed_plugin.after_set_value_count, 0);
}
#[test]
fn it_should_call_both_set_value_callbacks() {
let plugin = create_test_plugin();
let mut hit_item = Hit::new(
"id".into(),
"test/test".into(),
Rc::new(create_test_plugin_kernel(plugin.clone())),
)
.expect("Error 1");
hit_item
.set("id", "name", ObjectValue::String("test".into()))
.expect("Should work");
let borrowed_plugin = plugin.borrow();
assert_eq!(borrowed_plugin.before_set_value_count, 1);
assert_eq!(borrowed_plugin.after_set_value_count, 1);
}
#[test]
fn it_should_call_both_insert_callbacks() {
let plugin = create_test_plugin();
let mut hit_item = Hit::new(
"id".into(),
"test/test".into(),
Rc::new(create_test_plugin_kernel(plugin.clone())),
)
.expect("Error 1");
hit_item
.insert(
"test/test".into(),
"id2",
LinkedHashMap::new(),
IndexEntryProperty {
id: "id".into(),
property: "subitems".into(),
},
None,
)
.expect("Error 2");
hit_item
.insert(
"test/test".into(),
"id3",
LinkedHashMap::new(),
IndexEntryProperty {
id: "id".into(),
property: "subitems".into(),
},
None,
)
.expect("Error 2");
let borrowed_plugin = plugin.borrow();
assert_eq!(borrowed_plugin.before_insert_count, 2);
assert_eq!(borrowed_plugin.after_insert_count, 2);
}
#[test]
fn it_should_call_only_before_insert_callback_when_insert_fails() {
let plugin = create_test_plugin();
let mut hit_item = Hit::new(
"id".into(),
"test/test".into(),
Rc::new(create_test_plugin_kernel(plugin.clone())),
)
.expect("Error 1");
hit_item
.insert(
"test/test_b".into(),
"id2",
LinkedHashMap::new(),
IndexEntryProperty {
id: "id".into(),
property: "subitems".into(),
},
None,
)
.expect_err("Should fail");
let borrowed_plugin = plugin.borrow();
assert_eq!(borrowed_plugin.before_insert_count, 1);
assert_eq!(borrowed_plugin.after_insert_count, 0);
}
#[test]
fn it_should_call_both_move_callbacks() {
let plugin = create_test_plugin();
let mut hit_item = Hit::new(
"id".into(),
"test/test".into(),
Rc::new(create_test_plugin_kernel(plugin.clone())),
)
.expect("Error 1");
hit_item
.insert(
"test/test".into(),
"id2",
LinkedHashMap::new(),
IndexEntryProperty {
id: "id".into(),
property: "subitems".into(),
},
None,
)
.expect("Error 2");
hit_item
.move_object(
"id2",
IndexEntryProperty {
id: "id".into(),
property: "subitems3".into(),
},
None,
)
.expect("Error 2");
let borrowed_plugin = plugin.borrow();
assert_eq!(borrowed_plugin.before_move_subobject_count, 1);
assert_eq!(borrowed_plugin.after_move_subobject_count, 1);
}