// todo: test `Flame` as well. #[test] fn threaded_unchecked_u32() { use bombs::Bomb; use loom::{ thread, hint }; loom::model(|| { let (fuse, bomb) = Bomb::new(); let handle = { let bomb_clone = bomb.clone(); let h = thread::spawn(move || { let bomb = bomb_clone; thread::yield_now(); // Do nothing, but drop in here. // Loom is exhaustive so this is to test // what happens when an unsynchronised bomb // is the final to drop. drop(bomb); }); // Idk why but this casues issues otherwise. drop(bomb); h }; let flame = fuse.light(5_u32); thread::yield_now(); // while !flame.extinguished() { hint::spin_loop() } handle.join().unwrap(); }); } #[test] fn threaded_multi_u32() { use bombs::MultiBomb; use loom::{ thread, hint }; loom::model(|| { let (mut fuse, bomb) = MultiBomb::new(); let handle = { let mut bomb_clone = bomb.clone(); let h = thread::spawn(move || { let value = loop { match bomb_clone.exploded() { Some(v) => break v, None => hint::spin_loop(), } }; assert_eq!(value, 5); let value = loop { match bomb_clone.exploded() { Some(v) => break v, None => hint::spin_loop(), } }; assert_eq!(value, 24); }); // Idk why but this casues issues otherwise. drop(bomb); h }; let flame = fuse.light(5_u32); thread::yield_now(); // while !flame.extinguished() { hint::spin_loop(); } let flame = fuse.light(24); thread::yield_now(); // while !flame.extinguished() { hint::spin_loop(); } handle.join().unwrap(); }); } #[test] fn threaded_u32() { use bombs::Bomb; use loom::{ thread, hint }; loom::model(|| { let (fuse, bomb) = Bomb::new(); let handle = { let bomb_clone = bomb.clone(); let h = thread::spawn(move || { while let None = bomb_clone.exploded() { hint::spin_loop(); } assert_eq!(bomb_clone.exploded(), Some(&5)); }); // Idk why but this casues issues otherwise. drop(bomb); h }; let flame = fuse.light(5_u32); thread::yield_now(); // while !flame.extinguished() { hint::spin_loop() } handle.join().unwrap(); }); } #[test] fn simple_u32() { use bombs::Bomb; loom::model(|| { let (fuse, bomb) = Bomb::new(); let bomb_clone = bomb.clone(); assert_eq!(bomb.exploded(), None); assert_eq!(bomb_clone.exploded(), None); let flame = fuse.light(7_u32); assert_eq!(bomb.exploded(), Some(&7)); assert_eq!(bomb_clone.exploded(), Some(&7)); // assert!(!flame.extinguished()); drop(bomb_clone); drop(bomb); // assert!(flame.extinguished()); }); } #[test] fn empty_u32() { use bombs::Bomb; loom::model(|| { let (fuse, bomb) = Bomb::::new(); let bomb_clone = bomb.clone(); assert_eq!(bomb.exploded(), None); assert_eq!(bomb_clone.exploded(), None); let _fuse = std::hint::black_box(fuse); }); } #[test] fn box_dropped_correctly() { use bombs::*; loom::model(|| { let (fuse, bomb) = Bomb::new(); let bomb_clone = bomb.clone(); fuse.light(Box::new("Hello world".to_owned())); // No double-drop assert_eq!(&**bomb.exploded().unwrap(), "Hello world"); assert_eq!(&**bomb_clone.exploded().unwrap(), "Hello world"); assert_eq!(&**bomb.exploded().unwrap(), "Hello world"); }); } #[test] fn multi_box_dropped_correctly() { use bombs::*; loom::model(|| { let (mut fuse, mut bomb) = MultiBomb::new(); let mut bomb_clone = bomb.clone(); fuse.light(Box::new("Hello".to_owned())); fuse.light(Box::new(" world".to_owned())); // No double-drop assert_eq!(&*bomb.exploded().unwrap(), "Hello"); assert_eq!(&*bomb_clone.exploded().unwrap(), "Hello"); assert_eq!(&*bomb.exploded().unwrap(), " world"); assert_eq!(&*bomb_clone.exploded().unwrap(), " world"); assert_eq!(bomb.exploded(), None); assert_eq!(bomb_clone.exploded(), None); }); }