Skip to content

Commit 8522c68

Browse files
committed
add sitrep loader test
1 parent aae8d15 commit 8522c68

File tree

1 file changed

+140
-1
lines changed

1 file changed

+140
-1
lines changed

nexus/src/app/background/tasks/fm_sitrep_load.rs

Lines changed: 140 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,5 +175,144 @@ impl SitrepLoader {
175175

176176
#[cfg(test)]
177177
mod test {
178-
// TODO
178+
use super::*;
179+
use crate::app::background::BackgroundTask;
180+
use nexus_db_queries::db::pub_test_utils::TestDatabase;
181+
use nexus_types::fm::SitrepMetadata;
182+
use omicron_test_utils::dev;
183+
use omicron_uuid_kinds::CollectionUuid;
184+
use omicron_uuid_kinds::OmicronZoneUuid;
185+
use omicron_uuid_kinds::SitrepUuid;
186+
187+
#[tokio::test]
188+
async fn test_load_sitreps() {
189+
let logctx = dev::test_setup_log("test_inventory_loader");
190+
let db = TestDatabase::new_with_datastore(&logctx.log).await;
191+
let (opctx, datastore) = (db.opctx(), db.datastore());
192+
193+
let (tx, mut sitrep_rx) = watch::channel(None);
194+
let mut task = SitrepLoader::new(datastore.clone(), tx);
195+
196+
// Initially, there should be no sitrep.
197+
let status = task.activate(&opctx).await;
198+
assert_eq!(*sitrep_rx.borrow_and_update(), None);
199+
let status = serde_json::from_value::<Status>(status).unwrap();
200+
assert_eq!(status, Status::NoSitrep);
201+
202+
// Now, create an initial sitrep.
203+
let sitrep1_id = SitrepUuid::new_v4();
204+
let sitrep1 = Sitrep {
205+
metadata: SitrepMetadata {
206+
id: sitrep1_id,
207+
inv_collection_id: CollectionUuid::new_v4(),
208+
parent_sitrep_id: None,
209+
creator_id: OmicronZoneUuid::new_v4(),
210+
comment: "test sitrep 1".to_string(),
211+
time_created: Utc::now(),
212+
},
213+
};
214+
datastore
215+
.fm_sitrep_insert(&opctx, &sitrep1)
216+
.await
217+
.expect("sitrep should be inserted successfully");
218+
219+
// It should be loaded.
220+
let status = task.activate(&opctx).await;
221+
assert_eq!(
222+
true,
223+
sitrep_rx.has_changed().unwrap(),
224+
"sitrep watch should have changed when a sitrep was loaded"
225+
);
226+
let snapshot = sitrep_rx
227+
.borrow_and_update()
228+
.clone()
229+
.expect("the new sitrep should have been loaded");
230+
let (ref loaded_version1, ref loaded_sitrep) = *snapshot;
231+
// N.B.: we just compare the IDs here as comparing the whole struct may
232+
// not be equal, since the `time_created` field may have been rounded in
233+
// CRDB. Which is a shame, but whatever. :/
234+
assert_eq!(loaded_sitrep.metadata.id, sitrep1.metadata.id);
235+
dbg!(loaded_version1);
236+
let status = serde_json::from_value::<Status>(status).unwrap();
237+
match status {
238+
Status::Loaded { version, .. } => {
239+
assert_eq!(&version, loaded_version1);
240+
}
241+
status => panic!("expected Status::Loaded, got {status:?}",),
242+
};
243+
244+
// A subsequent activation should see the same sitrep.
245+
let status = task.activate(&opctx).await;
246+
assert_eq!(
247+
false,
248+
sitrep_rx.has_changed().unwrap(),
249+
"sitrep watch should not change if the same sitrep was loaded"
250+
);
251+
let snapshot = sitrep_rx
252+
.borrow_and_update()
253+
.clone()
254+
.expect("the same should have been loaded");
255+
let (ref loaded_version2, ref loaded_sitrep) = *snapshot;
256+
assert_eq!(loaded_sitrep.metadata.id, sitrep1.metadata.id);
257+
dbg!(loaded_version1, loaded_version2);
258+
let status = serde_json::from_value::<Status>(status).unwrap();
259+
match status {
260+
Status::Loaded { version, .. } => {
261+
assert_eq!(&version, loaded_version2);
262+
}
263+
status => panic!("expected Status::Loaded, got {status:?}",),
264+
};
265+
266+
// Now, create a new sitrep.
267+
let sitrep2_id = SitrepUuid::new_v4();
268+
let sitrep2 = Sitrep {
269+
metadata: SitrepMetadata {
270+
id: sitrep2_id,
271+
inv_collection_id: CollectionUuid::new_v4(),
272+
parent_sitrep_id: Some(sitrep1_id),
273+
creator_id: OmicronZoneUuid::new_v4(),
274+
comment: "test sitrep 2".to_string(),
275+
time_created: Utc::now(),
276+
},
277+
};
278+
datastore
279+
.fm_sitrep_insert(&opctx, &sitrep2)
280+
.await
281+
.expect("sitrep2 should be inserted successfully");
282+
283+
// It should be loaded.
284+
let status = task.activate(&opctx).await;
285+
assert_eq!(
286+
true,
287+
sitrep_rx.has_changed().unwrap(),
288+
"loading a new sitrep should update the watch"
289+
);
290+
let snapshot = sitrep_rx
291+
.borrow_and_update()
292+
.clone()
293+
.expect("the new sitrep should have been loaded");
294+
let (ref loaded_version3, ref loaded_sitrep) = *snapshot;
295+
assert_eq!(loaded_sitrep.metadata.id, sitrep2.metadata.id);
296+
dbg!(loaded_version3);
297+
assert_ne!(loaded_version3, loaded_version2);
298+
let status = serde_json::from_value::<Status>(status).unwrap();
299+
match status {
300+
Status::Loaded { version, .. } => {
301+
assert_eq!(&version, loaded_version3);
302+
}
303+
status => panic!("expected Status::Loaded, got {status:?}",),
304+
};
305+
306+
// XXX(eliza): It would be nice to also be able to test that an orphaned
307+
// sitrep (which has not been linked into the sitrep history chain) is
308+
// *not* loaded even if it exists. However, that would require
309+
// `nexus-db-queries` to expose separate interfaces for creating a
310+
// sitrep and inserting it into the history, which I have intentionally
311+
// chosen *not* to do to make it harder to do it by mistake.
312+
// So, ¯\_(ツ)_/¯
313+
314+
// Cleanup
315+
db.terminate().await;
316+
logctx.cleanup_successful();
317+
}
179318
}

0 commit comments

Comments
 (0)