1use crate::db::{CustomDataItem, Icon, IconId, Times, entry::Entry, node::*, rc_refcell_node};
2use std::collections::HashMap;
3use uuid::Uuid;
4
5pub(crate) enum SearchField {
6 Uuid,
7 Title,
8}
9
10impl SearchField {
11 pub(crate) fn matches(&self, node: &NodePtr, field_value: &str) -> bool {
12 match self {
13 SearchField::Uuid => node.borrow().get_uuid().to_string() == field_value,
14 SearchField::Title => match node.borrow().get_title() {
15 Some(title) => title == field_value,
16 None => false,
17 },
18 }
19 }
20}
21
22#[derive(Debug, Clone)]
24#[cfg_attr(feature = "serialization", derive(serde::Serialize))]
25pub struct Group {
26 pub(crate) uuid: Uuid,
28
29 pub(crate) name: Option<String>,
31
32 pub(crate) notes: Option<String>,
34
35 pub(crate) tags: Vec<String>,
37
38 pub(crate) icon: Icon,
40
41 pub(crate) children: Vec<SerializableNodePtr>,
43
44 pub(crate) times: Times,
46
47 pub(crate) custom_data: HashMap<String, CustomDataItem>,
49
50 pub(crate) is_expanded: bool,
52
53 pub(crate) default_autotype_sequence: Option<String>,
55
56 pub(crate) enable_autotype: Option<bool>,
58
59 pub(crate) enable_searching: Option<bool>,
61
62 pub(crate) last_top_visible_entry: Option<Uuid>,
66
67 pub(crate) parent: Option<Uuid>,
68
69 pub(crate) previous_parent_group: Option<Uuid>,
71}
72
73impl Default for Group {
74 fn default() -> Self {
75 Self {
76 uuid: Uuid::new_v4(),
77 name: Some("Default Group".to_string()),
78 notes: None,
79 tags: Vec::new(),
80 icon: Icon::BuiltIn(IconId::FOLDER),
81 children: Vec::new(),
82 times: Times::new(),
83 custom_data: Default::default(),
84 is_expanded: false,
85 default_autotype_sequence: None,
86 enable_autotype: None,
87 enable_searching: None,
88 last_top_visible_entry: None,
89 parent: None,
90 previous_parent_group: None,
91 }
92 }
93}
94
95impl PartialEq for Group {
96 fn eq(&self, other: &Self) -> bool {
97 self.uuid == other.uuid
98 && self.compare_children(other)
99 && self.times == other.times
100 && self.name == other.name
101 && self.notes == other.notes
102 && self.icon == other.icon
103 && self.is_expanded == other.is_expanded
104 && self.default_autotype_sequence == other.default_autotype_sequence
105 && self.enable_autotype == other.enable_autotype
106 && self.enable_searching == other.enable_searching
107 && self.last_top_visible_entry == other.last_top_visible_entry
108 && self.custom_data == other.custom_data
109 }
111}
112
113impl Eq for Group {}
114
115impl Node for Group {
116 fn duplicate(&self) -> NodePtr {
117 let mut new_group = self.clone();
118 new_group.parent = None;
119 new_group.children = self
120 .children
121 .iter()
122 .map(|child| {
123 let child = child.borrow().duplicate();
124 child.borrow_mut().set_parent(Some(new_group.uuid));
125 child.into()
126 })
127 .collect();
128 rc_refcell_node(new_group)
129 }
130
131 fn get_uuid(&self) -> Uuid {
132 self.uuid
133 }
134
135 fn set_uuid(&mut self, uuid: Uuid) {
136 self.uuid = uuid;
137 }
138
139 fn get_title(&self) -> Option<&str> {
140 self.name.as_deref()
141 }
142
143 fn set_title(&mut self, title: Option<&str>) {
144 self.name = title.map(std::string::ToString::to_string);
145 }
146
147 fn get_notes(&self) -> Option<&str> {
148 self.notes.as_deref()
149 }
150
151 fn set_notes(&mut self, notes: Option<&str>) {
152 self.notes = notes.map(std::string::ToString::to_string);
153 }
154
155 fn get_icon(&self) -> Icon {
156 self.icon
157 }
158
159 fn set_icon(&mut self, icon: Icon) {
160 self.icon = icon;
161 }
162
163 fn get_times(&self) -> &Times {
164 &self.times
165 }
166
167 fn get_times_mut(&mut self) -> &mut Times {
168 &mut self.times
169 }
170
171 fn get_parent(&self) -> Option<Uuid> {
172 self.parent
173 }
174
175 fn set_parent(&mut self, parent: Option<Uuid>) {
176 self.parent = parent;
177 }
178}
179
180impl Group {
181 pub fn new(name: &str) -> Group {
182 Group {
183 name: Some(name.to_string()),
184 ..Group::default()
185 }
186 }
187
188 pub fn get_children(&self) -> Vec<NodePtr> {
189 self.children.iter().map(|c| c.into()).collect()
190 }
191
192 fn compare_children(&self, other: &Self) -> bool {
193 if self.children.len() != other.children.len() {
194 return false;
195 }
196 self.children.iter().zip(other.children.iter()).all(|(a, b)| {
197 if let (Some(a), Some(b)) = (a.borrow().downcast_ref::<Group>(), b.borrow().downcast_ref::<Group>()) {
198 a == b
199 } else if let (Some(a), Some(b)) = (a.borrow().downcast_ref::<Entry>(), b.borrow().downcast_ref::<Entry>()) {
200 a == b
201 } else {
202 false
203 }
204 })
205 }
206
207 pub fn set_name(&mut self, name: &str) {
208 self.name = Some(name.to_string());
209 }
210
211 pub fn tags(&self) -> &[String] {
212 &self.tags
213 }
214
215 pub fn get_tags_mut(&mut self) -> &mut Vec<String> {
216 &mut self.tags
217 }
218
219 pub fn custom_data(&self) -> &HashMap<String, CustomDataItem> {
220 &self.custom_data
221 }
222
223 pub fn custom_data_mut(&mut self) -> &mut HashMap<String, CustomDataItem> {
224 &mut self.custom_data
225 }
226
227 pub fn previous_parent_group(&self) -> Option<Uuid> {
228 self.previous_parent_group
229 }
230
231 pub fn add_child(&mut self, child: NodePtr, index: usize) {
232 child.borrow_mut().set_parent(Some(self.get_uuid()));
233 if index < self.children.len() {
234 self.children.insert(index, child.into());
235 } else {
236 self.children.push(child.into());
237 }
238 }
239
240 pub fn get(group: &NodePtr, path: &[&str]) -> Option<NodePtr> {
257 Self::get_internal(group, path, SearchField::Title)
258 }
259
260 pub fn get_by_uuid<T: AsRef<str>>(group: &NodePtr, path: &[T]) -> Option<NodePtr> {
261 Self::get_internal(group, path, SearchField::Uuid)
262 }
263
264 fn get_internal<T: AsRef<str>>(group: &NodePtr, path: &[T], search_field: SearchField) -> Option<NodePtr> {
265 if path.is_empty() {
266 Some(group.clone())
267 } else if path.len() == 1 {
268 group_get_children(group)
269 .unwrap_or_default()
270 .iter()
271 .find_map(|node| match search_field.matches(node, path[0].as_ref()) {
272 true => Some(node.clone()),
273 false => None,
274 })
275 } else {
276 let head = path[0].as_ref();
277 let tail = &path[1..path.len()];
278 let head_group = group_get_children(group).unwrap_or_default().iter().find_map(|node| {
279 if node_is_group(node) && search_field.matches(node, head) {
280 Some(node.clone())
281 } else {
282 None
283 }
284 })?;
285
286 Self::get_internal(&head_group, tail, search_field)
287 }
288 }
289
290 pub fn entries(&self) -> Vec<NodePtr> {
291 let mut response: Vec<NodePtr> = vec![];
292 for node in &self.children {
293 if node_is_entry(node) {
294 response.push(node.into());
295 }
296 }
297 response
298 }
299
300 pub fn groups(&self) -> Vec<NodePtr> {
301 let mut response: Vec<NodePtr> = vec![];
302 for node in &self.children {
303 if node_is_group(node) {
304 response.push(node.into());
305 }
306 }
307 response
308 }
309
310 pub fn reset_children(&mut self, children: Vec<NodePtr>) {
311 let uuid = self.get_uuid();
312 children.iter().for_each(|c| c.borrow_mut().set_parent(Some(uuid)));
313 self.children = children.into_iter().map(|c| c.into()).collect();
314 }
315}
316
317#[allow(unused_imports)]
318#[cfg(test)]
319mod group_tests {
320 use super::{Entry, Group, Node, Times};
321 #[cfg(feature = "merge")]
322 use crate::db::merge::entry_set_field_and_commit;
323 use crate::db::{rc_refcell_node, *};
324 use std::{thread, time};
325
326 #[cfg(feature = "merge")]
327 #[test]
328 fn test_merge_idempotence() {
329 let destination_group = rc_refcell_node(Group::new("group1"));
330 let entry = rc_refcell_node(Entry::default());
331 let _entry_uuid = entry.borrow().get_uuid();
332 entry_set_field_and_commit(&entry, "Title", "entry1").unwrap();
333 let count = group_get_children(&destination_group).unwrap().len();
334 group_add_child(&destination_group, entry, count).unwrap();
335
336 let source_group = destination_group.borrow().duplicate();
337
338 let sg2: NodePtr = source_group.clone();
339 let merge_result = Group::merge(&destination_group, &sg2).unwrap();
340 assert_eq!(merge_result.warnings.len(), 0);
341 assert_eq!(merge_result.events.len(), 0);
342
343 with_node::<Group, _, _>(&destination_group, |destination_group| {
344 assert_eq!(destination_group.children.len(), 1);
345 with_node::<Group, _, _>(&source_group, |source_group| {
348 assert_eq!(destination_group, source_group);
349 });
350
351 let entry = destination_group.entries()[0].clone();
352 entry_set_field_and_commit(&entry, "Title", "entry1_updated").unwrap();
353 });
354 let merge_result = Group::merge(&destination_group, &sg2).unwrap();
355 assert_eq!(merge_result.warnings.len(), 0);
356 assert_eq!(merge_result.events.len(), 0);
357
358 let destination_group_just_after_merge = destination_group.borrow().duplicate();
359 let merge_result = Group::merge(&destination_group, &sg2).unwrap();
360 assert_eq!(merge_result.warnings.len(), 0);
361 assert_eq!(merge_result.events.len(), 0);
362
363 assert!(node_is_equals_to(&destination_group_just_after_merge, &destination_group));
366 }
367
368 #[cfg(feature = "merge")]
369 #[test]
370 fn test_merge_add_new_entry() {
371 let destination_group = rc_refcell_node(Group::new("group1"));
372 let source_group = rc_refcell_node(Group::new("group1"));
373
374 let entry = rc_refcell_node(Entry::default());
375 let entry_uuid = entry.borrow().get_uuid();
376 entry_set_field_and_commit(&entry, "Title", "entry1").unwrap();
377 group_add_child(&source_group, entry, 0).unwrap();
378
379 let merge_result = Group::merge(&destination_group, &source_group).unwrap();
380 assert_eq!(merge_result.warnings.len(), 0);
381 assert_eq!(merge_result.events.len(), 1);
382 {
383 assert_eq!(group_get_children(&destination_group).unwrap().len(), 1);
384 let new_entry = search_node_by_uuid_with_specific_type::<Entry>(&destination_group, entry_uuid);
385 assert!(new_entry.is_some());
386 assert_eq!(new_entry.unwrap().borrow().get_title().unwrap(), "entry1");
387 }
388
389 let merge_result = Group::merge(&destination_group, &source_group).unwrap();
391 assert_eq!(merge_result.warnings.len(), 0);
392 assert_eq!(merge_result.events.len(), 0);
393 assert_eq!(group_get_children(&destination_group).unwrap().len(), 1);
394 }
395
396 #[cfg(feature = "merge")]
397 #[test]
398 fn test_merge_add_new_non_root_entry() {
399 let destination_group = rc_refcell_node(Group::new("group1"));
400 let destination_sub_group = rc_refcell_node(Group::new("subgroup1"));
401
402 group_add_child(&destination_group, destination_sub_group, 0).unwrap();
403
404 let source_group = destination_group.borrow().duplicate();
405 let source_sub_group = with_node::<Group, _, _>(&source_group, |g| g.groups()[0].clone()).unwrap();
406
407 let entry: NodePtr = rc_refcell_node(Entry::default());
408 let _entry_uuid = entry.borrow().get_uuid();
409 entry_set_field_and_commit(&entry, "Title", "entry1").unwrap();
410 let count = group_get_children(&source_sub_group).unwrap().len();
411 group_add_child(&source_sub_group, entry, count).unwrap();
412
413 let merge_result = Group::merge(&destination_group, &source_group).unwrap();
414 assert_eq!(merge_result.warnings.len(), 0);
415 assert_eq!(merge_result.events.len(), 1);
416 let destination_entries = with_node::<Group, _, _>(&destination_group, |g| g.get_all_entries(&[])).unwrap();
417 assert_eq!(destination_entries.len(), 1);
418 let (_created_entry, created_entry_location) = destination_entries.first().unwrap();
419 println!("{created_entry_location:?}");
420 assert_eq!(created_entry_location.len(), 2);
421 }
422
423 #[cfg(feature = "merge")]
424 #[test]
425 fn test_merge_add_new_entry_new_group() {
426 let destination_group = rc_refcell_node(Group::new("group1"));
427 let _destination_sub_group = rc_refcell_node(Group::new("subgroup1"));
428 let source_group = rc_refcell_node(Group::new("group1"));
429 let source_sub_group = rc_refcell_node(Group::new("subgroup1"));
430
431 let entry = rc_refcell_node(Entry::default());
432 let _entry_uuid = entry.borrow().get_uuid();
433 entry_set_field_and_commit(&entry, "Title", "entry1").unwrap();
434 group_add_child(&source_sub_group, entry, 0).unwrap();
435 group_add_child(&source_group, source_sub_group, 0).unwrap();
436
437 let merge_result = Group::merge(&destination_group, &source_group).unwrap();
438 assert_eq!(merge_result.warnings.len(), 0);
439 assert_eq!(merge_result.events.len(), 1);
440
441 with_node::<Group, _, _>(&destination_group, |destination_group| {
442 let destination_entries = destination_group.get_all_entries(&[]);
443 assert_eq!(destination_entries.len(), 1);
444 let (_, created_entry_location) = destination_entries.first().unwrap();
445 assert_eq!(created_entry_location.len(), 2);
446 });
447 }
448
449 #[cfg(feature = "merge")]
450 #[test]
451 fn test_merge_entry_relocation_existing_group() {
452 let entry = rc_refcell_node(Entry::default());
453 let entry_uuid = entry.borrow().get_uuid();
454 entry_set_field_and_commit(&entry, "Title", "entry1").unwrap();
455
456 let destination_group = rc_refcell_node(Group::new("group1"));
457 let destination_sub_group1 = rc_refcell_node(Group::new("subgroup1"));
458 let destination_sub_group2 = rc_refcell_node(Group::new("subgroup2"));
459 let destination_sub_group2_uuid = destination_sub_group2.borrow().get_uuid();
460 group_add_child(&destination_sub_group1, entry, 0).unwrap();
461 group_add_child(&destination_group, destination_sub_group1.borrow().duplicate(), 0).unwrap();
462 group_add_child(&destination_group, destination_sub_group2.borrow().duplicate(), 1).unwrap();
463
464 let source_group = destination_group.borrow().duplicate();
465 assert_eq!(
466 with_node::<Group, _, _>(&source_group, |g| g.get_all_entries(&[])).unwrap().len(),
467 1
468 );
469
470 let destination_group_uuid = destination_group.borrow().get_uuid();
471 let destination_sub_group1_uuid = destination_sub_group1.borrow().get_uuid();
472
473 let location = vec![destination_group_uuid, destination_sub_group1_uuid];
474 let removed_entry = Group::remove_entry(&source_group, entry_uuid, &location).unwrap();
475
476 removed_entry.borrow_mut().get_times_mut().set_location_changed(Some(Times::now()));
477 assert!(
478 with_node::<Group, _, _>(&source_group, |g| g.get_all_entries(&[]))
479 .unwrap()
480 .is_empty()
481 );
482 with_node_mut::<Entry, _, _>(&removed_entry, |entry| {
485 entry.update_history();
486 });
487
488 let location = vec![destination_group_uuid, destination_sub_group2_uuid];
489
490 Group::insert_entry(&source_group, removed_entry, &location).unwrap();
491
492 let merge_result = Group::merge(&destination_group, &source_group).unwrap();
493 assert_eq!(merge_result.warnings.len(), 0);
494 assert_eq!(merge_result.events.len(), 1);
495
496 let destination_entries = with_node::<Group, _, _>(&destination_group, |g| g.get_all_entries(&[])).unwrap();
497 assert_eq!(destination_entries.len(), 1);
498 let (_moved_entry, moved_entry_location) = destination_entries.first().unwrap();
499 assert_eq!(moved_entry_location.len(), 2);
500 assert_eq!(moved_entry_location[0], destination_group_uuid);
501 assert_eq!(moved_entry_location[1], destination_sub_group2_uuid);
502 }
503
504 #[cfg(feature = "merge")]
505 #[test]
506 fn test_merge_entry_relocation_new_group() {
507 let entry = rc_refcell_node(Entry::default());
508 let _entry_uuid = entry.borrow().get_uuid();
509 entry_set_field_and_commit(&entry, "Title", "entry1").unwrap();
510
511 let destination_group = rc_refcell_node(Group::new("group1"));
512 let uuid1 = destination_group.borrow().get_uuid();
513 let destination_sub_group = rc_refcell_node(Group::new("subgroup1"));
514 group_add_child(&destination_sub_group, entry.borrow().duplicate(), 0).unwrap();
515 group_add_child(&destination_group, destination_sub_group, 0).unwrap();
516
517 let source_group = destination_group.borrow().duplicate();
518 let source_sub_group = rc_refcell_node(Group::new("subgroup2"));
519 let uuid2 = source_sub_group.borrow().get_uuid();
520 thread::sleep(time::Duration::from_secs(1));
521 with_node_mut::<Entry, _, _>(&entry, |entry| {
522 entry.times.set_location_changed(Some(Times::now()));
523 entry.update_history();
526 });
527 group_add_child(&source_sub_group, entry, 0).unwrap();
528 with_node_mut::<Group, _, _>(&source_group, |g| {
529 g.reset_children(vec![]);
530 g.add_child(source_sub_group, 0);
531 })
532 .unwrap();
533
534 let merge_result = Group::merge(&destination_group, &source_group).unwrap();
535 assert_eq!(merge_result.warnings.len(), 0);
536 assert_eq!(merge_result.events.len(), 1);
537
538 let destination_entries = with_node::<Group, _, _>(&destination_group, |g| g.get_all_entries(&[])).unwrap();
539 assert_eq!(destination_entries.len(), 1);
540 let (_, created_entry_location) = destination_entries.first().unwrap();
541 assert_eq!(created_entry_location.len(), 2);
542 assert_eq!(created_entry_location[0], uuid1);
543 assert_eq!(created_entry_location[1], uuid2);
544 }
545
546 #[cfg(feature = "merge")]
547 #[test]
548 fn test_update_in_destination_no_conflict() {
549 let destination_group = rc_refcell_node(Group::new("group1"));
550
551 let entry = rc_refcell_node(Entry::default());
552 let _entry_uuid = entry.borrow().get_uuid();
553 entry_set_field_and_commit(&entry, "Title", "entry1").unwrap();
554
555 group_add_child(&destination_group, entry, 0).unwrap();
556
557 let source_group = destination_group.borrow().duplicate();
558
559 let entry = with_node::<Group, _, _>(&destination_group, |g| g.entries()[0].clone()).unwrap();
560 entry_set_field_and_commit(&entry, "Title", "entry1_updated").unwrap();
561
562 let merge_result = Group::merge(&destination_group, &source_group).unwrap();
563 assert_eq!(merge_result.warnings.len(), 0);
564 assert_eq!(merge_result.events.len(), 0);
565
566 let entry = with_node::<Group, _, _>(&destination_group, |g| g.entries()[0].clone()).unwrap();
567 assert_eq!(entry.borrow().get_title(), Some("entry1_updated"));
568 }
569
570 #[cfg(feature = "merge")]
571 #[test]
572 fn test_update_in_source_no_conflict() {
573 let destination_group = rc_refcell_node(Group::new("group1"));
574
575 let entry = rc_refcell_node(Entry::default());
576 let _entry_uuid = entry.borrow().get_uuid();
577 entry_set_field_and_commit(&entry, "Title", "entry1").unwrap();
578 group_add_child(&destination_group, entry, 0).unwrap();
579
580 let source_group = destination_group.borrow().duplicate();
581
582 let entry = with_node::<Group, _, _>(&source_group, |g| g.entries()[0].clone()).unwrap();
583 entry_set_field_and_commit(&entry, "Title", "entry1_updated").unwrap();
584
585 let merge_result = Group::merge(&destination_group, &source_group).unwrap();
586 assert_eq!(merge_result.warnings.len(), 0);
587 assert_eq!(merge_result.events.len(), 1);
588
589 let entry = with_node::<Group, _, _>(&destination_group, |g| g.entries()[0].clone()).unwrap();
590 assert_eq!(entry.borrow().get_title(), Some("entry1_updated"));
591 }
592
593 #[cfg(feature = "merge")]
594 #[test]
595 fn test_update_with_conflicts() {
596 let destination_group = rc_refcell_node(Group::new("group1"));
597
598 let entry = rc_refcell_node(Entry::default());
599 let _entry_uuid = entry.borrow().get_uuid();
600 entry_set_field_and_commit(&entry, "Title", "entry1").unwrap();
601 group_add_child(&destination_group, entry, 0).unwrap();
602
603 let source_group = destination_group.borrow().duplicate();
604
605 let entry = with_node::<Group, _, _>(&destination_group, |g| g.entries()[0].clone()).unwrap();
606 entry_set_field_and_commit(&entry, "Title", "entry1_updated_from_destination").unwrap();
607
608 let entry = with_node::<Group, _, _>(&source_group, |g| g.entries()[0].clone()).unwrap();
609 entry_set_field_and_commit(&entry, "Title", "entry1_updated_from_source").unwrap();
610
611 let merge_result = Group::merge(&destination_group, &source_group).unwrap();
612 assert_eq!(merge_result.warnings.len(), 0);
613 assert_eq!(merge_result.events.len(), 1);
614
615 let entry = with_node::<Group, _, _>(&destination_group, |g| g.entries()[0].clone()).unwrap();
616 assert_eq!(entry.borrow().get_title(), Some("entry1_updated_from_source"));
617
618 let merged_history = with_node::<Entry, _, _>(&entry, |e| e.history.clone().unwrap()).unwrap();
619 assert!(merged_history.is_ordered());
620 assert_eq!(merged_history.entries.len(), 3);
621 let merged_entry = &merged_history.entries[1];
622 assert_eq!(merged_entry.get_title(), Some("entry1_updated_from_destination"));
623
624 let destination_group_dup = destination_group.borrow().duplicate();
626 let merge_result = Group::merge(&destination_group, &destination_group_dup).unwrap();
627 assert_eq!(merge_result.warnings.len(), 0);
628 assert_eq!(merge_result.events.len(), 0);
629 }
630
631 #[test]
632 fn get() {
633 let db = Database::new(Default::default());
634
635 let general_group = rc_refcell_node(Group::new("General"));
636 let sample_entry = rc_refcell_node(Entry::default());
637 sample_entry.borrow_mut().set_title(Some("Sample Entry #2"));
638 group_add_child(&general_group, sample_entry, 0).unwrap();
639 group_add_child(&db.root, general_group, 0).unwrap();
640
641 assert!(Group::get(&db.root, &["General", "Sample Entry #2"]).is_some());
642 assert!(Group::get(&db.root, &["General"]).is_some());
643 assert!(Group::get(&db.root, &["Invalid Group"]).is_none());
644 assert!(Group::get(&db.root, &[]).is_some());
645 }
646
647 #[test]
648 fn get_by_uuid() {
649 let db = Database::new(Default::default());
650
651 let general_group = rc_refcell_node(Group::new("General"));
652 let general_group_uuid = general_group.borrow().get_uuid().to_string();
653 let sample_entry = rc_refcell_node(Entry::default());
654 let sample_entry_uuid = sample_entry.borrow().get_uuid().to_string();
655 sample_entry.borrow_mut().set_title(Some("Sample Entry #2"));
656 group_add_child(&general_group, sample_entry, 0).unwrap();
657 group_add_child(&db.root, general_group, 0).unwrap();
658
659 let invalid_uuid = uuid::Uuid::new_v4().to_string();
660
661 let group_path: [&str; 1] = [general_group_uuid.as_ref()];
663 let entry_path: [&str; 2] = [general_group_uuid.as_ref(), sample_entry_uuid.as_ref()];
664 let invalid_path: [&str; 1] = [invalid_uuid.as_ref()];
665 let empty_path: [&str; 0] = [];
666
667 assert!(Group::get_by_uuid(&db.root, &group_path).is_some());
668 assert!(Group::get_by_uuid(&db.root, &entry_path).is_some());
669 assert!(Group::get_by_uuid(&db.root, &invalid_path).is_none());
670 assert!(Group::get_by_uuid(&db.root, &empty_path).is_some());
671
672 let group_path = vec![general_group_uuid.clone()];
674 let entry_path = vec![general_group_uuid.clone(), sample_entry_uuid.clone()];
675 let invalid_path = vec![invalid_uuid.clone()];
676 let empty_path: Vec<String> = vec![];
677
678 assert!(Group::get_by_uuid(&db.root, &group_path).is_some());
679 assert!(Group::get_by_uuid(&db.root, &entry_path).is_some());
680 assert!(Group::get_by_uuid(&db.root, &invalid_path).is_none());
681 assert!(Group::get_by_uuid(&db.root, &empty_path).is_some());
682 }
683}