1use crate::result::{ProbarError, ProbarResult};
15use std::any::{Any, TypeId};
16use std::collections::HashMap;
17
18pub trait Fixture: Any + Send + Sync {
45 fn setup(&mut self) -> ProbarResult<()>;
51
52 fn teardown(&mut self) -> ProbarResult<()>;
58
59 fn name(&self) -> &str {
61 std::any::type_name::<Self>()
62 }
63
64 fn priority(&self) -> i32 {
66 0
67 }
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub enum FixtureState {
73 Registered,
75 SetUp,
77 TornDown,
79 Failed,
81}
82
83struct FixtureEntry {
85 fixture: Box<dyn Fixture>,
86 state: FixtureState,
87 priority: i32,
88}
89
90#[derive(Default)]
110pub struct FixtureManager {
111 fixtures: HashMap<TypeId, FixtureEntry>,
112 setup_order: Vec<TypeId>,
113}
114
115impl std::fmt::Debug for FixtureManager {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 f.debug_struct("FixtureManager")
118 .field("fixture_count", &self.fixtures.len())
119 .field("setup_order", &self.setup_order.len())
120 .finish()
121 }
122}
123
124impl FixtureManager {
125 #[must_use]
127 pub fn new() -> Self {
128 Self::default()
129 }
130
131 pub fn register<F: Fixture + 'static>(&mut self, fixture: F) {
135 let type_id = TypeId::of::<F>();
136 let priority = fixture.priority();
137
138 let _ = self.fixtures.insert(
139 type_id,
140 FixtureEntry {
141 fixture: Box::new(fixture),
142 state: FixtureState::Registered,
143 priority,
144 },
145 );
146 }
147
148 #[must_use]
150 pub fn is_registered<F: Fixture + 'static>(&self) -> bool {
151 let type_id = TypeId::of::<F>();
152 self.fixtures.contains_key(&type_id)
153 }
154
155 #[must_use]
157 pub fn count(&self) -> usize {
158 self.fixtures.len()
159 }
160
161 #[must_use]
163 pub fn state<F: Fixture + 'static>(&self) -> Option<FixtureState> {
164 let type_id = TypeId::of::<F>();
165 self.fixtures.get(&type_id).map(|e| e.state)
166 }
167
168 #[must_use]
170 pub fn get<F: Fixture + 'static>(&self) -> Option<&F> {
171 let type_id = TypeId::of::<F>();
172 self.fixtures
173 .get(&type_id)
174 .and_then(|entry| entry.fixture.as_ref().as_any().downcast_ref::<F>())
175 }
176
177 #[must_use]
179 pub fn get_mut<F: Fixture + 'static>(&mut self) -> Option<&mut F> {
180 let type_id = TypeId::of::<F>();
181 self.fixtures
182 .get_mut(&type_id)
183 .and_then(|entry| entry.fixture.as_mut().as_any_mut().downcast_mut::<F>())
184 }
185
186 pub fn setup_all(&mut self) -> ProbarResult<()> {
193 let mut ordered: Vec<(TypeId, i32)> = self
195 .fixtures
196 .iter()
197 .map(|(id, e)| (*id, e.priority))
198 .collect();
199 ordered.sort_by(|a, b| b.1.cmp(&a.1));
200
201 self.setup_order.clear();
202
203 let mut failed_info: Option<(TypeId, String)> = None;
204
205 for (type_id, _) in ordered {
206 if let Some(entry) = self.fixtures.get_mut(&type_id) {
207 if entry.state == FixtureState::Registered || entry.state == FixtureState::TornDown
208 {
209 if let Err(e) = entry.fixture.setup() {
210 let name = entry.fixture.name().to_string();
211 entry.state = FixtureState::Failed;
212 failed_info =
213 Some((type_id, format!("Fixture '{}' setup failed: {e}", name)));
214 break;
215 }
216 entry.state = FixtureState::SetUp;
217 self.setup_order.push(type_id);
218 }
219 }
220 }
221
222 if let Some((_, error_msg)) = failed_info {
224 self.teardown_setup_order()?;
225 return Err(ProbarError::FixtureError { message: error_msg });
226 }
227
228 Ok(())
229 }
230
231 pub fn teardown_all(&mut self) -> ProbarResult<()> {
238 self.teardown_setup_order()
239 }
240
241 fn teardown_setup_order(&mut self) -> ProbarResult<()> {
243 let mut first_error: Option<ProbarError> = None;
244
245 for type_id in self.setup_order.iter().rev() {
247 if let Some(entry) = self.fixtures.get_mut(type_id) {
248 if entry.state == FixtureState::SetUp {
249 if let Err(e) = entry.fixture.teardown() {
250 if first_error.is_none() {
251 first_error = Some(ProbarError::FixtureError {
252 message: format!(
253 "Fixture '{}' teardown failed: {e}",
254 entry.fixture.name()
255 ),
256 });
257 }
258 entry.state = FixtureState::Failed;
259 } else {
260 entry.state = FixtureState::TornDown;
261 }
262 }
263 }
264 }
265
266 self.setup_order.clear();
267
268 if let Some(err) = first_error {
269 Err(err)
270 } else {
271 Ok(())
272 }
273 }
274
275 pub fn setup<F: Fixture + 'static>(&mut self) -> ProbarResult<()> {
281 let type_id = TypeId::of::<F>();
282
283 let entry = self
284 .fixtures
285 .get_mut(&type_id)
286 .ok_or_else(|| ProbarError::FixtureError {
287 message: format!("Fixture '{}' not registered", std::any::type_name::<F>()),
288 })?;
289
290 if entry.state == FixtureState::SetUp {
291 return Ok(()); }
293
294 entry
295 .fixture
296 .setup()
297 .map_err(|e| ProbarError::FixtureError {
298 message: format!("Fixture '{}' setup failed: {e}", entry.fixture.name()),
299 })?;
300
301 entry.state = FixtureState::SetUp;
302
303 if !self.setup_order.contains(&type_id) {
304 self.setup_order.push(type_id);
305 }
306
307 Ok(())
308 }
309
310 pub fn teardown<F: Fixture + 'static>(&mut self) -> ProbarResult<()> {
316 let type_id = TypeId::of::<F>();
317
318 let entry = self
319 .fixtures
320 .get_mut(&type_id)
321 .ok_or_else(|| ProbarError::FixtureError {
322 message: format!("Fixture '{}' not registered", std::any::type_name::<F>()),
323 })?;
324
325 if entry.state != FixtureState::SetUp {
326 return Ok(()); }
328
329 entry
330 .fixture
331 .teardown()
332 .map_err(|e| ProbarError::FixtureError {
333 message: format!("Fixture '{}' teardown failed: {e}", entry.fixture.name()),
334 })?;
335
336 entry.state = FixtureState::TornDown;
337
338 self.setup_order.retain(|id| *id != type_id);
340
341 Ok(())
342 }
343
344 pub fn reset(&mut self) {
346 for entry in self.fixtures.values_mut() {
347 entry.state = FixtureState::Registered;
348 }
349 self.setup_order.clear();
350 }
351
352 pub fn unregister<F: Fixture + 'static>(&mut self) -> bool {
354 let type_id = TypeId::of::<F>();
355 self.setup_order.retain(|id| *id != type_id);
356 self.fixtures.remove(&type_id).is_some()
357 }
358
359 pub fn clear(&mut self) {
361 self.fixtures.clear();
362 self.setup_order.clear();
363 }
364
365 #[must_use]
367 pub fn list(&self) -> Vec<&str> {
368 self.fixtures.values().map(|e| e.fixture.name()).collect()
369 }
370}
371
372impl dyn Fixture {
373 fn as_any(&self) -> &dyn Any {
374 self
377 }
378
379 fn as_any_mut(&mut self) -> &mut dyn Any {
380 self
381 }
382}
383
384pub struct SimpleFixture {
388 name: String,
389 priority: i32,
390 setup_fn: Option<Box<dyn FnMut() -> ProbarResult<()> + Send + Sync>>,
391 teardown_fn: Option<Box<dyn FnMut() -> ProbarResult<()> + Send + Sync>>,
392 is_setup: bool,
393}
394
395impl std::fmt::Debug for SimpleFixture {
396 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
397 f.debug_struct("SimpleFixture")
398 .field("name", &self.name)
399 .field("priority", &self.priority)
400 .field("is_setup", &self.is_setup)
401 .finish()
402 }
403}
404
405impl SimpleFixture {
406 #[must_use]
408 pub fn new(name: impl Into<String>) -> Self {
409 Self {
410 name: name.into(),
411 priority: 0,
412 setup_fn: None,
413 teardown_fn: None,
414 is_setup: false,
415 }
416 }
417
418 #[must_use]
420 pub fn with_setup<F>(mut self, f: F) -> Self
421 where
422 F: FnMut() -> ProbarResult<()> + Send + Sync + 'static,
423 {
424 self.setup_fn = Some(Box::new(f));
425 self
426 }
427
428 #[must_use]
430 pub fn with_teardown<F>(mut self, f: F) -> Self
431 where
432 F: FnMut() -> ProbarResult<()> + Send + Sync + 'static,
433 {
434 self.teardown_fn = Some(Box::new(f));
435 self
436 }
437
438 #[must_use]
440 pub fn with_priority(mut self, priority: i32) -> Self {
441 self.priority = priority;
442 self
443 }
444}
445
446impl Fixture for SimpleFixture {
447 fn setup(&mut self) -> ProbarResult<()> {
448 if let Some(f) = &mut self.setup_fn {
449 f()?;
450 }
451 self.is_setup = true;
452 Ok(())
453 }
454
455 fn teardown(&mut self) -> ProbarResult<()> {
456 if let Some(f) = &mut self.teardown_fn {
457 f()?;
458 }
459 self.is_setup = false;
460 Ok(())
461 }
462
463 fn name(&self) -> &str {
464 &self.name
465 }
466
467 fn priority(&self) -> i32 {
468 self.priority
469 }
470}
471
472#[derive(Debug)]
474pub struct FixtureBuilder {
475 manager: FixtureManager,
476}
477
478impl Default for FixtureBuilder {
479 fn default() -> Self {
480 Self::new()
481 }
482}
483
484impl FixtureBuilder {
485 #[must_use]
487 pub fn new() -> Self {
488 Self {
489 manager: FixtureManager::new(),
490 }
491 }
492
493 #[must_use]
495 pub fn with_fixture<F: Fixture + 'static>(mut self, fixture: F) -> Self {
496 self.manager.register(fixture);
497 self
498 }
499
500 #[must_use]
502 pub fn build(self) -> FixtureManager {
503 self.manager
504 }
505
506 pub fn build_and_setup(mut self) -> ProbarResult<FixtureManager> {
508 self.manager.setup_all()?;
509 Ok(self.manager)
510 }
511}
512
513pub struct FixtureScope {
517 manager: FixtureManager,
518}
519
520impl FixtureScope {
521 #[must_use]
525 pub fn new(manager: FixtureManager) -> Self {
526 Self { manager }
527 }
528
529 #[must_use]
531 pub fn get<F: Fixture + 'static>(&self) -> Option<&F> {
532 self.manager.get()
533 }
534
535 #[must_use]
537 pub fn get_mut<F: Fixture + 'static>(&mut self) -> Option<&mut F> {
538 self.manager.get_mut()
539 }
540}
541
542impl Drop for FixtureScope {
543 fn drop(&mut self) {
544 let _ = self.manager.teardown_all();
546 }
547}
548
549impl std::fmt::Debug for FixtureScope {
550 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
551 f.debug_struct("FixtureScope")
552 .field("manager", &self.manager)
553 .finish()
554 }
555}
556
557#[cfg(test)]
558#[allow(clippy::unwrap_used, clippy::expect_used)]
559mod tests {
560 use super::*;
561 use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
562 use std::sync::Arc;
563
564 #[derive(Debug)]
566 struct TestFixture {
567 setup_called: Arc<AtomicBool>,
568 teardown_called: Arc<AtomicBool>,
569 priority: i32,
570 }
571
572 impl TestFixture {
573 fn new() -> Self {
574 Self {
575 setup_called: Arc::new(AtomicBool::new(false)),
576 teardown_called: Arc::new(AtomicBool::new(false)),
577 priority: 0,
578 }
579 }
580 }
581
582 impl Fixture for TestFixture {
583 fn setup(&mut self) -> ProbarResult<()> {
584 self.setup_called.store(true, Ordering::SeqCst);
585 Ok(())
586 }
587
588 fn teardown(&mut self) -> ProbarResult<()> {
589 self.teardown_called.store(true, Ordering::SeqCst);
590 Ok(())
591 }
592
593 fn priority(&self) -> i32 {
594 self.priority
595 }
596 }
597
598 #[derive(Debug)]
600 struct FailingSetupFixture;
601
602 impl Fixture for FailingSetupFixture {
603 fn setup(&mut self) -> ProbarResult<()> {
604 Err(ProbarError::FixtureError {
605 message: "Intentional setup failure".to_string(),
606 })
607 }
608
609 fn teardown(&mut self) -> ProbarResult<()> {
610 Ok(())
611 }
612 }
613
614 #[derive(Debug)]
616 struct FailingTeardownFixture;
617
618 impl Fixture for FailingTeardownFixture {
619 fn setup(&mut self) -> ProbarResult<()> {
620 Ok(())
621 }
622
623 fn teardown(&mut self) -> ProbarResult<()> {
624 Err(ProbarError::FixtureError {
625 message: "Intentional teardown failure".to_string(),
626 })
627 }
628 }
629
630 mod fixture_state_tests {
631 use super::*;
632
633 #[test]
634 fn test_state_equality() {
635 assert_eq!(FixtureState::Registered, FixtureState::Registered);
636 assert_eq!(FixtureState::SetUp, FixtureState::SetUp);
637 assert_eq!(FixtureState::TornDown, FixtureState::TornDown);
638 assert_eq!(FixtureState::Failed, FixtureState::Failed);
639 assert_ne!(FixtureState::Registered, FixtureState::SetUp);
640 }
641 }
642
643 mod fixture_manager_tests {
644 use super::*;
645
646 #[test]
647 fn test_new_manager() {
648 let manager = FixtureManager::new();
649 assert_eq!(manager.count(), 0);
650 }
651
652 #[test]
653 fn test_register_fixture() {
654 let mut manager = FixtureManager::new();
655 manager.register(TestFixture::new());
656
657 assert_eq!(manager.count(), 1);
658 assert!(manager.is_registered::<TestFixture>());
659 }
660
661 #[test]
662 fn test_state_before_setup() {
663 let mut manager = FixtureManager::new();
664 manager.register(TestFixture::new());
665
666 assert_eq!(
667 manager.state::<TestFixture>(),
668 Some(FixtureState::Registered)
669 );
670 }
671
672 #[test]
673 fn test_setup_all() {
674 let fixture = TestFixture::new();
675 let setup_called = fixture.setup_called.clone();
676
677 let mut manager = FixtureManager::new();
678 manager.register(fixture);
679 manager.setup_all().expect("Setup should succeed");
680
681 assert!(setup_called.load(Ordering::SeqCst));
682 assert_eq!(manager.state::<TestFixture>(), Some(FixtureState::SetUp));
683 }
684
685 #[test]
686 fn test_teardown_all() {
687 let fixture = TestFixture::new();
688 let teardown_called = fixture.teardown_called.clone();
689
690 let mut manager = FixtureManager::new();
691 manager.register(fixture);
692 manager.setup_all().expect("Setup should succeed");
693 manager.teardown_all().expect("Teardown should succeed");
694
695 assert!(teardown_called.load(Ordering::SeqCst));
696 assert_eq!(manager.state::<TestFixture>(), Some(FixtureState::TornDown));
697 }
698
699 #[test]
700 fn test_setup_single_fixture() {
701 let fixture = TestFixture::new();
702 let setup_called = fixture.setup_called.clone();
703
704 let mut manager = FixtureManager::new();
705 manager.register(fixture);
706 manager
707 .setup::<TestFixture>()
708 .expect("Setup should succeed");
709
710 assert!(setup_called.load(Ordering::SeqCst));
711 }
712
713 #[test]
714 fn test_teardown_single_fixture() {
715 let fixture = TestFixture::new();
716 let teardown_called = fixture.teardown_called.clone();
717
718 let mut manager = FixtureManager::new();
719 manager.register(fixture);
720 manager
721 .setup::<TestFixture>()
722 .expect("Setup should succeed");
723 manager
724 .teardown::<TestFixture>()
725 .expect("Teardown should succeed");
726
727 assert!(teardown_called.load(Ordering::SeqCst));
728 }
729
730 #[test]
731 fn test_get_fixture() {
732 let fixture = TestFixture::new();
733 let setup_called = fixture.setup_called.clone();
734
735 let mut manager = FixtureManager::new();
736 manager.register(fixture);
737
738 let retrieved = manager.get::<TestFixture>();
739 assert!(retrieved.is_some());
740 assert!(Arc::ptr_eq(&retrieved.unwrap().setup_called, &setup_called));
741 }
742
743 #[test]
744 fn test_get_unregistered_fixture() {
745 let manager = FixtureManager::new();
746 assert!(manager.get::<TestFixture>().is_none());
747 }
748
749 #[test]
750 fn test_failing_setup() {
751 let mut manager = FixtureManager::new();
752 manager.register(FailingSetupFixture);
753
754 let result = manager.setup_all();
755 assert!(result.is_err());
756 assert_eq!(
757 manager.state::<FailingSetupFixture>(),
758 Some(FixtureState::Failed)
759 );
760 }
761
762 #[test]
763 fn test_failing_teardown() {
764 let mut manager = FixtureManager::new();
765 manager.register(FailingTeardownFixture);
766
767 manager.setup_all().expect("Setup should succeed");
768 let result = manager.teardown_all();
769 assert!(result.is_err());
770 }
771
772 #[test]
773 fn test_unregister() {
774 let mut manager = FixtureManager::new();
775 manager.register(TestFixture::new());
776
777 assert!(manager.is_registered::<TestFixture>());
778 assert!(manager.unregister::<TestFixture>());
779 assert!(!manager.is_registered::<TestFixture>());
780 }
781
782 #[test]
783 fn test_clear() {
784 let mut manager = FixtureManager::new();
785 manager.register(TestFixture::new());
786 manager.clear();
787
788 assert_eq!(manager.count(), 0);
789 }
790
791 #[test]
792 fn test_reset() {
793 let mut manager = FixtureManager::new();
794 manager.register(TestFixture::new());
795 manager.setup_all().expect("Setup should succeed");
796
797 manager.reset();
798 assert_eq!(
799 manager.state::<TestFixture>(),
800 Some(FixtureState::Registered)
801 );
802 }
803
804 #[test]
805 fn test_list() {
806 let mut manager = FixtureManager::new();
807 manager.register(TestFixture::new());
808
809 let names = manager.list();
810 assert_eq!(names.len(), 1);
811 assert!(names[0].contains("TestFixture"));
812 }
813 }
814
815 mod priority_tests {
816 use super::*;
817
818 #[derive(Debug)]
819 struct OrderedFixture {
820 expected_order: u32,
821 priority: i32,
822 order_counter: Arc<AtomicU32>,
823 }
824
825 impl Fixture for OrderedFixture {
826 fn setup(&mut self) -> ProbarResult<()> {
827 let actual = self.order_counter.fetch_add(1, Ordering::SeqCst);
828 assert_eq!(actual, self.expected_order, "Wrong setup order");
829 Ok(())
830 }
831
832 fn teardown(&mut self) -> ProbarResult<()> {
833 Ok(())
834 }
835
836 fn priority(&self) -> i32 {
837 self.priority
838 }
839 }
840
841 #[test]
842 fn test_priority_order() {
843 let order = Arc::new(AtomicU32::new(0));
845
846 let mut manager = FixtureManager::new();
847
848 manager.register(OrderedFixture {
850 expected_order: 2, priority: -10,
852 order_counter: order.clone(),
853 });
854 manager.register(SimpleFixture::new("middle").with_priority(0).with_setup({
855 let order_ref = order;
856 move || {
857 let actual = order_ref.fetch_add(1, Ordering::SeqCst);
858 assert_eq!(actual, 1, "Wrong setup order for middle");
859 Ok(())
860 }
861 }));
862
863 }
866 }
867
868 mod simple_fixture_tests {
869 use super::*;
870
871 #[test]
872 fn test_simple_fixture_creation() {
873 let fixture = SimpleFixture::new("test_fixture");
874 assert_eq!(fixture.name(), "test_fixture");
875 assert_eq!(fixture.priority(), 0);
876 }
877
878 #[test]
879 fn test_simple_fixture_with_priority() {
880 let fixture = SimpleFixture::new("test").with_priority(10);
881 assert_eq!(fixture.priority(), 10);
882 }
883
884 #[test]
885 fn test_simple_fixture_setup() {
886 let called = Arc::new(AtomicBool::new(false));
887 let called_clone = called.clone();
888
889 let mut fixture = SimpleFixture::new("test").with_setup(move || {
890 called_clone.store(true, Ordering::SeqCst);
891 Ok(())
892 });
893
894 fixture.setup().expect("Setup should succeed");
895 assert!(called.load(Ordering::SeqCst));
896 }
897
898 #[test]
899 fn test_get_mut_fixture() {
900 let mut manager = FixtureManager::new();
901 manager.register(SimpleFixture::new("test"));
902
903 let fixture = manager.get_mut::<SimpleFixture>();
904 assert!(fixture.is_some());
905 assert_eq!(fixture.unwrap().name(), "test");
906 }
907
908 #[test]
909 fn test_get_mut_unregistered() {
910 let mut manager = FixtureManager::new();
911 let fixture = manager.get_mut::<TestFixture>();
912 assert!(fixture.is_none());
913 }
914
915 #[test]
916 fn test_setup_already_setup() {
917 let mut manager = FixtureManager::new();
918 manager.register(TestFixture::new());
919 manager.setup::<TestFixture>().unwrap();
920
921 let result = manager.setup::<TestFixture>();
923 assert!(result.is_ok());
924 }
925
926 #[test]
927 fn test_setup_unregistered() {
928 let mut manager = FixtureManager::new();
929 let result = manager.setup::<TestFixture>();
930 assert!(result.is_err());
931 }
932
933 #[test]
934 fn test_teardown_unregistered() {
935 let mut manager = FixtureManager::new();
936 let result = manager.teardown::<TestFixture>();
937 assert!(result.is_err());
938 }
939
940 #[test]
941 fn test_teardown_not_setup() {
942 let mut manager = FixtureManager::new();
943 manager.register(TestFixture::new());
944
945 let result = manager.teardown::<TestFixture>();
947 assert!(result.is_ok());
948 }
949
950 #[test]
951 fn test_manager_debug() {
952 let manager = FixtureManager::new();
953 let debug = format!("{:?}", manager);
954 assert!(debug.contains("FixtureManager"));
955 }
956
957 #[test]
958 fn test_simple_fixture_teardown() {
959 let called = Arc::new(AtomicBool::new(false));
960 let called_clone = called.clone();
961
962 let mut fixture = SimpleFixture::new("test").with_teardown(move || {
963 called_clone.store(true, Ordering::SeqCst);
964 Ok(())
965 });
966
967 fixture.teardown().expect("Teardown should succeed");
968 assert!(called.load(Ordering::SeqCst));
969 }
970 }
971
972 mod fixture_builder_tests {
973 use super::*;
974
975 #[test]
976 fn test_builder_new() {
977 let builder = FixtureBuilder::new();
978 let manager = builder.build();
979 assert_eq!(manager.count(), 0);
980 }
981
982 #[test]
983 fn test_builder_with_fixture() {
984 let manager = FixtureBuilder::new()
985 .with_fixture(TestFixture::new())
986 .build();
987
988 assert_eq!(manager.count(), 1);
989 }
990
991 #[test]
992 fn test_builder_and_setup() {
993 let fixture = TestFixture::new();
994 let setup_called = fixture.setup_called.clone();
995
996 let manager = FixtureBuilder::new()
997 .with_fixture(fixture)
998 .build_and_setup()
999 .expect("Setup should succeed");
1000
1001 assert!(setup_called.load(Ordering::SeqCst));
1002 assert_eq!(manager.state::<TestFixture>(), Some(FixtureState::SetUp));
1003 }
1004 }
1005
1006 mod fixture_scope_tests {
1007 use super::*;
1008
1009 #[test]
1010 fn test_scope_auto_teardown() {
1011 let fixture = TestFixture::new();
1012 let teardown_called = fixture.teardown_called.clone();
1013
1014 {
1015 let mut manager = FixtureManager::new();
1016 manager.register(fixture);
1017 manager.setup_all().expect("Setup should succeed");
1018
1019 let _scope = FixtureScope::new(manager);
1020 }
1022
1023 assert!(teardown_called.load(Ordering::SeqCst));
1024 }
1025
1026 #[test]
1027 fn test_scope_get_fixture() {
1028 let fixture = TestFixture::new();
1029 let setup_called = fixture.setup_called.clone();
1030
1031 let mut manager = FixtureManager::new();
1032 manager.register(fixture);
1033 manager.setup_all().expect("Setup should succeed");
1034
1035 let scope = FixtureScope::new(manager);
1036 let retrieved = scope.get::<TestFixture>();
1037 assert!(retrieved.is_some());
1038 assert!(Arc::ptr_eq(&retrieved.unwrap().setup_called, &setup_called));
1039 }
1040 }
1041
1042 mod additional_fixture_tests {
1043 use super::*;
1044
1045 #[test]
1046 fn test_fixture_default_name() {
1047 let fixture = TestFixture::new();
1048 let name = fixture.name();
1049 assert!(name.contains("TestFixture"));
1050 }
1051
1052 #[test]
1053 fn test_fixture_default_priority() {
1054 #[derive(Debug)]
1055 struct DefaultPriorityFixture;
1056
1057 impl Fixture for DefaultPriorityFixture {
1058 fn setup(&mut self) -> ProbarResult<()> {
1059 Ok(())
1060 }
1061 fn teardown(&mut self) -> ProbarResult<()> {
1062 Ok(())
1063 }
1064 }
1065
1066 let fixture = DefaultPriorityFixture;
1067 assert_eq!(fixture.priority(), 0);
1068 }
1069
1070 #[test]
1071 fn test_fixture_state_debug() {
1072 let state = FixtureState::SetUp;
1073 let debug = format!("{:?}", state);
1074 assert!(debug.contains("SetUp"));
1075 }
1076
1077 #[test]
1078 fn test_fixture_state_clone() {
1079 let state = FixtureState::Failed;
1080 let cloned = state;
1081 assert_eq!(state, cloned);
1082 }
1083
1084 #[test]
1085 fn test_simple_fixture_default_callbacks() {
1086 let mut fixture = SimpleFixture::new("test");
1087 assert!(fixture.setup().is_ok());
1089 assert!(fixture.teardown().is_ok());
1090 }
1091
1092 #[test]
1093 fn test_manager_default() {
1094 let manager = FixtureManager::default();
1095 assert_eq!(manager.count(), 0);
1096 }
1097
1098 #[test]
1099 fn test_unregister_nonexistent() {
1100 let mut manager = FixtureManager::new();
1101 assert!(!manager.unregister::<TestFixture>());
1102 }
1103
1104 #[test]
1105 fn test_teardown_already_torn_down() {
1106 let mut manager = FixtureManager::new();
1107 manager.register(TestFixture::new());
1108 manager.setup_all().unwrap();
1109 manager.teardown_all().unwrap();
1110
1111 let result = manager.teardown_all();
1113 assert!(result.is_ok());
1114 }
1115
1116 #[test]
1117 fn test_builder_multiple_fixtures() {
1118 let manager = FixtureBuilder::new()
1119 .with_fixture(SimpleFixture::new("first"))
1120 .with_fixture(SimpleFixture::new("second"))
1121 .build();
1122
1123 assert_eq!(manager.count(), 1);
1125 }
1126 }
1127
1128 mod coverage_enhancement_tests {
1129 use super::*;
1130
1131 #[derive(Debug)]
1133 struct PriorityFixture {
1134 name: String,
1135 priority: i32,
1136 setup_order: Arc<std::sync::Mutex<Vec<String>>>,
1137 teardown_order: Arc<std::sync::Mutex<Vec<String>>>,
1138 }
1139
1140 impl PriorityFixture {
1141 fn new(
1142 name: &str,
1143 priority: i32,
1144 setup_order: Arc<std::sync::Mutex<Vec<String>>>,
1145 teardown_order: Arc<std::sync::Mutex<Vec<String>>>,
1146 ) -> Self {
1147 Self {
1148 name: name.to_string(),
1149 priority,
1150 setup_order,
1151 teardown_order,
1152 }
1153 }
1154 }
1155
1156 impl Fixture for PriorityFixture {
1157 fn setup(&mut self) -> ProbarResult<()> {
1158 self.setup_order.lock().unwrap().push(self.name.clone());
1159 Ok(())
1160 }
1161
1162 fn teardown(&mut self) -> ProbarResult<()> {
1163 self.teardown_order.lock().unwrap().push(self.name.clone());
1164 Ok(())
1165 }
1166
1167 fn name(&self) -> &str {
1168 &self.name
1169 }
1170
1171 fn priority(&self) -> i32 {
1172 self.priority
1173 }
1174 }
1175
1176 #[allow(dead_code)] #[derive(Debug)]
1179 struct HighPriorityFailingSetupFixture {
1180 priority: i32,
1181 }
1182
1183 impl Fixture for HighPriorityFailingSetupFixture {
1184 fn setup(&mut self) -> ProbarResult<()> {
1185 Err(ProbarError::FixtureError {
1186 message: "High priority setup failure".to_string(),
1187 })
1188 }
1189
1190 fn teardown(&mut self) -> ProbarResult<()> {
1191 Ok(())
1192 }
1193
1194 fn priority(&self) -> i32 {
1195 self.priority
1196 }
1197 }
1198
1199 #[derive(Debug)]
1201 struct LowPriorityFailingSetupFixture {
1202 priority: i32,
1203 setup_order: Arc<std::sync::Mutex<Vec<String>>>,
1204 }
1205
1206 impl Fixture for LowPriorityFailingSetupFixture {
1207 fn setup(&mut self) -> ProbarResult<()> {
1208 self.setup_order
1209 .lock()
1210 .unwrap()
1211 .push("low_failing".to_string());
1212 Err(ProbarError::FixtureError {
1213 message: "Low priority setup failure".to_string(),
1214 })
1215 }
1216
1217 fn teardown(&mut self) -> ProbarResult<()> {
1218 Ok(())
1219 }
1220
1221 fn priority(&self) -> i32 {
1222 self.priority
1223 }
1224 }
1225
1226 #[derive(Debug)]
1228 struct SecondTestFixture {
1229 setup_called: Arc<AtomicBool>,
1230 teardown_called: Arc<AtomicBool>,
1231 }
1232
1233 impl SecondTestFixture {
1234 fn new() -> Self {
1235 Self {
1236 setup_called: Arc::new(AtomicBool::new(false)),
1237 teardown_called: Arc::new(AtomicBool::new(false)),
1238 }
1239 }
1240 }
1241
1242 impl Fixture for SecondTestFixture {
1243 fn setup(&mut self) -> ProbarResult<()> {
1244 self.setup_called.store(true, Ordering::SeqCst);
1245 Ok(())
1246 }
1247
1248 fn teardown(&mut self) -> ProbarResult<()> {
1249 self.teardown_called.store(true, Ordering::SeqCst);
1250 Ok(())
1251 }
1252 }
1253
1254 #[test]
1255 fn test_simple_fixture_debug() {
1256 let fixture = SimpleFixture::new("debug_test").with_priority(5);
1257 let debug = format!("{:?}", fixture);
1258 assert!(debug.contains("SimpleFixture"));
1259 assert!(debug.contains("debug_test"));
1260 assert!(debug.contains('5'));
1261 }
1262
1263 #[test]
1264 fn test_fixture_scope_debug() {
1265 let manager = FixtureManager::new();
1266 let scope = FixtureScope::new(manager);
1267 let debug = format!("{:?}", scope);
1268 assert!(debug.contains("FixtureScope"));
1269 assert!(debug.contains("FixtureManager"));
1270 }
1271
1272 #[test]
1273 fn test_fixture_builder_default() {
1274 let builder = FixtureBuilder::default();
1275 let manager = builder.build();
1276 assert_eq!(manager.count(), 0);
1277 }
1278
1279 #[test]
1280 fn test_build_and_setup_failure() {
1281 let result = FixtureBuilder::new()
1282 .with_fixture(FailingSetupFixture)
1283 .build_and_setup();
1284
1285 assert!(result.is_err());
1286 }
1287
1288 #[test]
1289 fn test_setup_all_with_rollback() {
1290 let setup_order = Arc::new(std::sync::Mutex::new(Vec::new()));
1292 let teardown_order = Arc::new(std::sync::Mutex::new(Vec::new()));
1293
1294 let mut manager = FixtureManager::new();
1295
1296 manager.register(PriorityFixture::new(
1298 "first",
1299 100,
1300 setup_order.clone(),
1301 teardown_order.clone(),
1302 ));
1303
1304 manager.register(LowPriorityFailingSetupFixture {
1306 priority: -100,
1307 setup_order: setup_order.clone(),
1308 });
1309
1310 let result = manager.setup_all();
1311 assert!(result.is_err());
1312
1313 let setup = setup_order.lock().unwrap();
1315 assert!(setup.contains(&"first".to_string()));
1316 assert!(setup.contains(&"low_failing".to_string()));
1317
1318 let teardown = teardown_order.lock().unwrap();
1320 assert!(teardown.contains(&"first".to_string()));
1321 }
1322
1323 #[test]
1324 fn test_teardown_failure_continues_others() {
1325 let mut manager = FixtureManager::new();
1327
1328 manager.register(FailingTeardownFixture);
1329 manager.register(TestFixture::new());
1330
1331 manager.setup_all().expect("Setup should succeed");
1332
1333 let result = manager.teardown_all();
1335 assert!(result.is_err());
1336 }
1337
1338 #[test]
1339 fn test_fixture_scope_get_mut() {
1340 let fixture = TestFixture::new();
1341 let setup_called = fixture.setup_called.clone();
1342
1343 let mut manager = FixtureManager::new();
1344 manager.register(fixture);
1345 manager.setup_all().expect("Setup should succeed");
1346
1347 let mut scope = FixtureScope::new(manager);
1348 let retrieved = scope.get_mut::<TestFixture>();
1349 assert!(retrieved.is_some());
1350 assert!(Arc::ptr_eq(&retrieved.unwrap().setup_called, &setup_called));
1351 }
1352
1353 #[test]
1354 fn test_fixture_scope_get_unregistered() {
1355 let manager = FixtureManager::new();
1356 let scope = FixtureScope::new(manager);
1357 assert!(scope.get::<TestFixture>().is_none());
1358 }
1359
1360 #[test]
1361 fn test_fixture_scope_get_mut_unregistered() {
1362 let manager = FixtureManager::new();
1363 let mut scope = FixtureScope::new(manager);
1364 assert!(scope.get_mut::<TestFixture>().is_none());
1365 }
1366
1367 #[test]
1368 fn test_setup_from_torn_down_state() {
1369 let mut manager = FixtureManager::new();
1371 manager.register(TestFixture::new());
1372
1373 manager.setup_all().expect("First setup should succeed");
1374 manager.teardown_all().expect("Teardown should succeed");
1375
1376 let result = manager.setup_all();
1378 assert!(result.is_ok());
1379 assert_eq!(manager.state::<TestFixture>(), Some(FixtureState::SetUp));
1380 }
1381
1382 #[test]
1383 fn test_multiple_fixture_types() {
1384 let mut manager = FixtureManager::new();
1386 manager.register(TestFixture::new());
1387 manager.register(SecondTestFixture::new());
1388
1389 assert_eq!(manager.count(), 2);
1390 assert!(manager.is_registered::<TestFixture>());
1391 assert!(manager.is_registered::<SecondTestFixture>());
1392 }
1393
1394 #[test]
1395 fn test_register_replaces_existing() {
1396 let first = TestFixture::new();
1397 let first_setup = first.setup_called.clone();
1398
1399 let second = TestFixture::new();
1400 let second_setup = second.setup_called.clone();
1401
1402 let mut manager = FixtureManager::new();
1403 manager.register(first);
1404 manager.register(second);
1405
1406 assert_eq!(manager.count(), 1);
1408
1409 manager.setup_all().expect("Setup should succeed");
1411 assert!(second_setup.load(Ordering::SeqCst));
1412 assert!(!first_setup.load(Ordering::SeqCst));
1414 }
1415
1416 #[test]
1417 fn test_single_fixture_setup_failure() {
1418 let mut manager = FixtureManager::new();
1419 manager.register(FailingSetupFixture);
1420
1421 let result = manager.setup::<FailingSetupFixture>();
1422 assert!(result.is_err());
1423 }
1424
1425 #[test]
1426 fn test_single_fixture_teardown_failure() {
1427 let mut manager = FixtureManager::new();
1428 manager.register(FailingTeardownFixture);
1429
1430 manager
1431 .setup::<FailingTeardownFixture>()
1432 .expect("Setup should succeed");
1433 let result = manager.teardown::<FailingTeardownFixture>();
1434 assert!(result.is_err());
1435 }
1436
1437 #[test]
1438 fn test_unregister_removes_from_setup_order() {
1439 let mut manager = FixtureManager::new();
1440 manager.register(TestFixture::new());
1441 manager.setup_all().expect("Setup should succeed");
1442
1443 assert!(manager.unregister::<TestFixture>());
1445 assert!(!manager.is_registered::<TestFixture>());
1446 }
1447
1448 #[test]
1449 fn test_simple_fixture_is_setup_tracking() {
1450 let mut fixture = SimpleFixture::new("test");
1451 assert!(!fixture.is_setup);
1452
1453 fixture.setup().expect("Setup should succeed");
1454 assert!(fixture.is_setup);
1455
1456 fixture.teardown().expect("Teardown should succeed");
1457 assert!(!fixture.is_setup);
1458 }
1459
1460 #[test]
1461 fn test_simple_fixture_failing_setup() {
1462 let mut fixture = SimpleFixture::new("test").with_setup(|| {
1463 Err(ProbarError::FixtureError {
1464 message: "Test failure".to_string(),
1465 })
1466 });
1467
1468 let result = fixture.setup();
1469 assert!(result.is_err());
1470 }
1471
1472 #[test]
1473 fn test_simple_fixture_failing_teardown() {
1474 let mut fixture = SimpleFixture::new("test").with_teardown(|| {
1475 Err(ProbarError::FixtureError {
1476 message: "Teardown failure".to_string(),
1477 })
1478 });
1479
1480 fixture.setup().expect("Setup should succeed");
1481 let result = fixture.teardown();
1482 assert!(result.is_err());
1483 }
1484
1485 #[test]
1486 fn test_list_multiple_fixtures() {
1487 let mut manager = FixtureManager::new();
1488 manager.register(TestFixture::new());
1489 manager.register(SecondTestFixture::new());
1490
1491 let names = manager.list();
1492 assert_eq!(names.len(), 2);
1493 }
1494
1495 #[test]
1496 fn test_state_none_for_unregistered() {
1497 let manager = FixtureManager::new();
1498 assert!(manager.state::<TestFixture>().is_none());
1499 }
1500
1501 #[test]
1502 fn test_priority_ordering_in_setup() {
1503 let setup_order = Arc::new(std::sync::Mutex::new(Vec::new()));
1504 let teardown_order = Arc::new(std::sync::Mutex::new(Vec::new()));
1505
1506 let mut manager = FixtureManager::new();
1507
1508 manager.register(PriorityFixture::new(
1510 "low",
1511 -10,
1512 setup_order.clone(),
1513 teardown_order,
1514 ));
1515
1516 let setup_clone = setup_order.clone();
1518 manager.register(
1519 SimpleFixture::new("high")
1520 .with_priority(10)
1521 .with_setup(move || {
1522 setup_clone.lock().unwrap().push("high".to_string());
1523 Ok(())
1524 }),
1525 );
1526
1527 manager.setup_all().expect("Setup should succeed");
1528
1529 let setup = setup_order.lock().unwrap();
1530 let high_idx = setup.iter().position(|s| s == "high").unwrap();
1532 let low_idx = setup.iter().position(|s| s == "low").unwrap();
1533 assert!(high_idx < low_idx, "High priority should be set up first");
1534 }
1535
1536 #[test]
1537 fn test_teardown_reverse_order() {
1538 let setup_order = Arc::new(std::sync::Mutex::new(Vec::new()));
1539 let teardown_order = Arc::new(std::sync::Mutex::new(Vec::new()));
1540
1541 let mut manager = FixtureManager::new();
1542
1543 manager.register(PriorityFixture::new(
1544 "high",
1545 100,
1546 setup_order,
1547 teardown_order.clone(),
1548 ));
1549
1550 let teardown_clone = teardown_order.clone();
1552 manager.register(SimpleFixture::new("low").with_priority(-100).with_teardown(
1553 move || {
1554 teardown_clone.lock().unwrap().push("low".to_string());
1555 Ok(())
1556 },
1557 ));
1558
1559 manager.setup_all().expect("Setup should succeed");
1560 manager.teardown_all().expect("Teardown should succeed");
1561
1562 let teardown = teardown_order.lock().unwrap();
1563 let high_idx = teardown.iter().position(|s| s == "high").unwrap();
1565 let low_idx = teardown.iter().position(|s| s == "low").unwrap();
1566 assert!(
1567 low_idx < high_idx,
1568 "Low priority (set up last) should be torn down first"
1569 );
1570 }
1571
1572 #[test]
1573 fn test_clear_empties_setup_order() {
1574 let mut manager = FixtureManager::new();
1575 manager.register(TestFixture::new());
1576 manager.setup_all().expect("Setup should succeed");
1577
1578 manager.clear();
1579 assert_eq!(manager.count(), 0);
1580 assert!(manager.list().is_empty());
1581 }
1582
1583 #[test]
1584 fn test_reset_clears_setup_order() {
1585 let fixture = TestFixture::new();
1586 let teardown_called = fixture.teardown_called.clone();
1587
1588 let mut manager = FixtureManager::new();
1589 manager.register(fixture);
1590 manager.setup_all().expect("Setup should succeed");
1591
1592 manager.reset();
1594
1595 assert!(!teardown_called.load(Ordering::SeqCst));
1597 assert_eq!(
1598 manager.state::<TestFixture>(),
1599 Some(FixtureState::Registered)
1600 );
1601 }
1602
1603 #[test]
1604 fn test_fixture_scope_drop_with_failing_teardown() {
1605 let mut manager = FixtureManager::new();
1607 manager.register(FailingTeardownFixture);
1608 manager.setup_all().expect("Setup should succeed");
1609
1610 let _scope = FixtureScope::new(manager);
1612 }
1614
1615 #[test]
1616 fn test_single_teardown_updates_state() {
1617 let mut manager = FixtureManager::new();
1618 manager.register(TestFixture::new());
1619
1620 manager
1621 .setup::<TestFixture>()
1622 .expect("Setup should succeed");
1623 assert_eq!(manager.state::<TestFixture>(), Some(FixtureState::SetUp));
1624
1625 manager
1626 .teardown::<TestFixture>()
1627 .expect("Teardown should succeed");
1628 assert_eq!(manager.state::<TestFixture>(), Some(FixtureState::TornDown));
1629 }
1630
1631 #[test]
1632 fn test_setup_adds_to_setup_order_once() {
1633 let mut manager = FixtureManager::new();
1634 manager.register(TestFixture::new());
1635
1636 manager.setup::<TestFixture>().unwrap();
1638 manager.reset();
1639 manager.setup::<TestFixture>().unwrap();
1640
1641 assert_eq!(manager.state::<TestFixture>(), Some(FixtureState::SetUp));
1643 }
1644
1645 #[test]
1646 fn test_single_fixture_teardown_removes_from_order() {
1647 let mut manager = FixtureManager::new();
1648 manager.register(TestFixture::new());
1649 manager.register(SecondTestFixture::new());
1650
1651 manager.setup_all().expect("Setup should succeed");
1652
1653 manager
1655 .teardown::<TestFixture>()
1656 .expect("Teardown should succeed");
1657
1658 assert_eq!(
1660 manager.state::<SecondTestFixture>(),
1661 Some(FixtureState::SetUp)
1662 );
1663 assert_eq!(manager.state::<TestFixture>(), Some(FixtureState::TornDown));
1664 }
1665
1666 #[test]
1667 fn test_fixture_error_message_includes_name() {
1668 let mut manager = FixtureManager::new();
1669 manager.register(FailingSetupFixture);
1670
1671 let result = manager.setup_all();
1672 assert!(result.is_err());
1673
1674 if let Err(ProbarError::FixtureError { message }) = result {
1675 assert!(message.contains("FailingSetupFixture"));
1676 assert!(message.contains("setup failed"));
1677 } else {
1678 panic!("Expected FixtureError");
1679 }
1680 }
1681
1682 #[test]
1683 fn test_teardown_error_message_includes_name() {
1684 let mut manager = FixtureManager::new();
1685 manager.register(FailingTeardownFixture);
1686 manager.setup_all().expect("Setup should succeed");
1687
1688 let result = manager.teardown_all();
1689 assert!(result.is_err());
1690
1691 if let Err(ProbarError::FixtureError { message }) = result {
1692 assert!(message.contains("FailingTeardownFixture"));
1693 assert!(message.contains("teardown failed"));
1694 } else {
1695 panic!("Expected FixtureError");
1696 }
1697 }
1698 }
1699}