1use std::{
16 any::{Any, TypeId},
17 collections::HashMap,
18 ops::{Deref, DerefMut},
19 sync::{Mutex, OnceLock},
20};
21
22pub trait Fixture: Sized {
35 fn set_up() -> crate::Result<Self>;
41
42 fn tear_down(self) -> crate::Result<()>;
48}
49
50pub trait ConsumableFixture: Sized {
63 fn set_up() -> crate::Result<Self>;
69}
70
71pub struct FixtureOf<T>(T);
74
75impl<T: Default> ConsumableFixture for FixtureOf<T> {
76 fn set_up() -> crate::Result<Self> {
77 Ok(Self(T::default()))
78 }
79}
80
81impl<T> Deref for FixtureOf<T> {
82 type Target = T;
83
84 fn deref(&self) -> &Self::Target {
85 &self.0
86 }
87}
88
89impl<T> DerefMut for FixtureOf<T> {
90 fn deref_mut(&mut self) -> &mut Self::Target {
91 &mut self.0
92 }
93}
94
95pub trait StaticFixture: Sized + Sync + Send {
108 fn set_up_once() -> crate::Result<Self>;
114}
115
116impl<F: StaticFixture + 'static> Fixture for &'static F {
117 fn set_up() -> crate::Result<Self> {
118 static ONCE_FIXTURE_REPO: OnceLock<
119 Mutex<HashMap<TypeId, &'static (dyn Any + Sync + Send)>>,
120 > = OnceLock::new();
121 let mut map = ONCE_FIXTURE_REPO.get_or_init(|| Mutex::new(HashMap::new())).lock()?;
122 let any =
123 map.entry(TypeId::of::<F>()).or_insert_with(|| Box::leak(Box::new(F::set_up_once())));
124 match any.downcast_ref::<crate::Result<F>>() {
125 Some(Ok(ref fixture)) => Ok(fixture),
126 Some(Err(e)) => Err(e.clone()),
127 None => panic!("Downcast failed. This is a bug in GoogleTest Rust"),
128 }
129 }
130
131 fn tear_down(self) -> crate::Result<()> {
133 Ok(())
134 }
135}
136
137#[cfg(test)]
138mod tests {
139
140 use std::sync::Once;
141
142 use super::FixtureOf;
143 use super::StaticFixture;
144 use crate as googletest;
145 use crate::prelude::*;
146 use crate::test;
147 use crate::Result;
148
149 #[test]
150 fn fixture_no_fixture() -> Result<()> {
151 Ok(())
152 }
153
154 struct AlwaysSucceed;
155
156 impl Fixture for AlwaysSucceed {
157 fn set_up() -> crate::Result<Self> {
158 Ok(Self)
159 }
160
161 fn tear_down(self) -> crate::Result<()> {
162 Ok(())
163 }
164 }
165
166 #[test]
167 fn fixture_one_fixture(_: &AlwaysSucceed) -> Result<()> {
168 Ok(())
169 }
170
171 #[test]
172 fn fixture_three_fixtures(
173 _: &AlwaysSucceed,
174 _: &AlwaysSucceed,
175 _: &AlwaysSucceed,
176 ) -> Result<()> {
177 Ok(())
178 }
179
180 struct NotAFixture {
181 a_field: i32,
182 }
183
184 impl Default for NotAFixture {
185 fn default() -> Self {
186 Self { a_field: 33 }
187 }
188 }
189
190 #[test]
191 fn fixture_of_non_fixture(not_a_fixture: FixtureOf<NotAFixture>) -> Result<()> {
192 verify_that!(not_a_fixture.a_field, eq(33))
193 }
194
195 #[test]
196 fn fixture_of_non_fixture_mut(mut not_a_fixture: FixtureOf<NotAFixture>) -> Result<()> {
197 not_a_fixture.a_field += 10;
198 verify_that!(not_a_fixture.a_field, eq(43))
199 }
200 struct PanickyFixture;
201
202 impl Fixture for PanickyFixture {
203 fn set_up() -> crate::Result<Self> {
204 Ok(Self)
205 }
206
207 fn tear_down(self) -> crate::Result<()> {
208 panic!("Whoooops");
209 }
210 }
211
212 #[test]
213 #[should_panic(expected = "Whoooops")]
214 fn fixture_teardown_called_even_if_test_fail(_: &PanickyFixture) {
215 panic!("Test failed");
216 }
217
218 struct FailingTearDown;
219
220 impl Fixture for FailingTearDown {
221 fn set_up() -> crate::Result<Self> {
222 Ok(Self)
223 }
224
225 fn tear_down(self) -> crate::Result<()> {
226 Err(googletest::TestAssertionFailure::create("It must fail!".into()))
227 }
228 }
229
230 struct OnlyOnce;
231
232 impl StaticFixture for OnlyOnce {
233 fn set_up_once() -> crate::Result<Self> {
234 static ONCE: Once = Once::new();
235 assert!(!ONCE.is_completed());
236 ONCE.call_once(|| {});
237 Ok(Self)
238 }
239 }
240
241 #[test]
242 fn static_fixture_works(_: &&OnlyOnce) {}
243
244 #[test]
245 fn static_fixture_same_static_fixture_twice(once: &&OnlyOnce, twice: &&OnlyOnce) {
246 let once: *const OnlyOnce = *once;
248 let twice: *const OnlyOnce = *twice;
249 expect_eq!(once, twice);
250 }
251
252 struct AnotherStaticFixture;
253
254 impl StaticFixture for AnotherStaticFixture {
255 fn set_up_once() -> crate::Result<Self> {
256 Ok(Self)
257 }
258 }
259
260 #[test]
261 fn static_fixture_two_different_static_fixtures(_: &&OnlyOnce, _: &&AnotherStaticFixture) {}
262}