Skip to content

Commit c8cfa81

Browse files
committed
add a test
1 parent 46b66b4 commit c8cfa81

File tree

2 files changed

+172
-2
lines changed

2 files changed

+172
-2
lines changed

nexus/db-queries/src/db/datastore/fm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ mod tests {
990990
.collect::<BTreeSet<_>>();
991991
assert_eq!(dbg!(&listed_orphans), &orphans_v1);
992992

993-
// Next, create a new sitrep which descends from sitrep 0.
993+
// Next, create a new sitrep which descends from sitrep 1.
994994
let sitrep2 = fm::Sitrep {
995995
metadata: fm::SitrepMetadata {
996996
id: SitrepUuid::new_v4(),
@@ -1006,7 +1006,7 @@ mod tests {
10061006
.await
10071007
.expect("inserting child sitrep should succeed");
10081008

1009-
// Now, create some orphaned sitreps which also descend from sitreo 0.
1009+
// Now, create some orphaned sitreps which also descend from sitrep 1.
10101010
let mut orphans_v2 = BTreeSet::new();
10111011
for i in 1..5 {
10121012
insert_orphan(

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

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,173 @@ impl SitrepGc {
175175
status
176176
}
177177
}
178+
179+
#[cfg(test)]
180+
mod tests {
181+
use super::*;
182+
use chrono::Utc;
183+
use nexus_db_queries::db::datastore::fm::InsertSitrepError;
184+
use nexus_db_queries::db::pub_test_utils::TestDatabase;
185+
use nexus_types::fm;
186+
use omicron_common::api::external::Error;
187+
use omicron_test_utils::dev;
188+
use omicron_uuid_kinds::CollectionUuid;
189+
use omicron_uuid_kinds::OmicronZoneUuid;
190+
use omicron_uuid_kinds::SitrepUuid;
191+
use std::collections::BTreeSet;
192+
193+
#[tokio::test]
194+
async fn test_orphaned_sitrep_gc() {
195+
let logctx = dev::test_setup_log("test_orphaned_sitrep_gc");
196+
let db = TestDatabase::new_with_datastore(&logctx.log).await;
197+
let (opctx, datastore) = (db.opctx(), db.datastore());
198+
199+
let mut task = SitrepGc::new(datastore.clone());
200+
201+
// First, insert an initial sitrep. This should succeed.
202+
let sitrep1 = fm::Sitrep {
203+
metadata: fm::SitrepMetadata {
204+
id: SitrepUuid::new_v4(),
205+
inv_collection_id: CollectionUuid::new_v4(),
206+
creator_id: OmicronZoneUuid::new_v4(),
207+
comment: "test sitrep v1".to_string(),
208+
time_created: Utc::now(),
209+
parent_sitrep_id: None,
210+
},
211+
};
212+
datastore
213+
.fm_sitrep_insert(&opctx, &sitrep1)
214+
.await
215+
.expect("inserting initial sitrep should succeed");
216+
217+
// Now, create some orphaned sitreps which also have no parent.
218+
let mut orphans = BTreeSet::new();
219+
for i in 1..5 {
220+
insert_orphan(&datastore, &opctx, &mut orphans, None, 1, i).await;
221+
}
222+
223+
// Next, create a new sitrep which descends from sitrep 1.
224+
let sitrep2 = fm::Sitrep {
225+
metadata: fm::SitrepMetadata {
226+
id: SitrepUuid::new_v4(),
227+
inv_collection_id: CollectionUuid::new_v4(),
228+
creator_id: OmicronZoneUuid::new_v4(),
229+
comment: "test sitrep v2".to_string(),
230+
time_created: Utc::now(),
231+
parent_sitrep_id: Some(sitrep1.metadata.id),
232+
},
233+
};
234+
datastore
235+
.fm_sitrep_insert(&opctx, &sitrep2)
236+
.await
237+
.expect("inserting child sitrep should succeed");
238+
239+
// Now, create some orphaned sitreps which also descend from sitrep 1.
240+
for i in 1..4 {
241+
insert_orphan(
242+
&datastore,
243+
&opctx,
244+
&mut orphans,
245+
Some(sitrep1.metadata.id),
246+
2,
247+
i,
248+
)
249+
.await;
250+
}
251+
252+
// Make sure the orphans exist.
253+
for &id in &orphans {
254+
match datastore.fm_sitrep_metadata_read(&opctx, id).await {
255+
Ok(_) => {}
256+
Err(Error::NotFound { .. }) => {
257+
panic!("orphaned sitrep {id} should exist");
258+
}
259+
Err(e) => {
260+
panic!(
261+
"unexpected error reading orphaned sitrep {id}: {e}"
262+
);
263+
}
264+
}
265+
}
266+
267+
// Activate the background task.
268+
let status = dbg!(task.actually_activate(opctx).await);
269+
270+
// Now, the orphans should all be gone.
271+
for &id in &orphans {
272+
match datastore.fm_sitrep_metadata_read(&opctx, id).await {
273+
Ok(_) => {
274+
panic!(
275+
"orphaned sitrep {id} should have been deleted, \
276+
but it appears to still exist!"
277+
)
278+
}
279+
Err(Error::NotFound { .. }) => {
280+
// Okay, it's gone.
281+
}
282+
Err(e) => {
283+
panic!(
284+
"unexpected error reading orphaned sitrep {id}: {e}"
285+
);
286+
}
287+
}
288+
}
289+
// But the non-orphaned sitreps should still be there!
290+
datastore
291+
.fm_sitrep_metadata_read(&opctx, sitrep1.id())
292+
.await
293+
.expect("sitrep 1 should still exist");
294+
datastore
295+
.fm_sitrep_metadata_read(&opctx, sitrep2.id())
296+
.await
297+
.expect("sitrep 2 should still exist");
298+
299+
assert_eq!(status.errors, Vec::<String>::new());
300+
assert_eq!(status.versions_scanned, 2);
301+
assert_eq!(
302+
status.orphaned_sitreps.get(&1),
303+
Some(&OrphanedSitreps { found: 4, deleted: 4 })
304+
);
305+
assert_eq!(
306+
status.orphaned_sitreps.get(&2),
307+
Some(&OrphanedSitreps { found: 3, deleted: 3 })
308+
);
309+
310+
db.terminate().await;
311+
logctx.cleanup_successful();
312+
}
313+
314+
async fn insert_orphan(
315+
datastore: &DataStore,
316+
opctx: &OpContext,
317+
orphans: &mut BTreeSet<SitrepUuid>,
318+
parent_sitrep_id: Option<SitrepUuid>,
319+
v: usize,
320+
i: usize,
321+
) {
322+
let sitrep = fm::Sitrep {
323+
metadata: fm::SitrepMetadata {
324+
id: SitrepUuid::new_v4(),
325+
inv_collection_id: CollectionUuid::new_v4(),
326+
creator_id: OmicronZoneUuid::new_v4(),
327+
comment: format!("test sitrep v{i}; orphan {i}"),
328+
time_created: Utc::now(),
329+
parent_sitrep_id,
330+
},
331+
};
332+
match datastore.fm_sitrep_insert(&opctx, &sitrep).await {
333+
Ok(_) => {
334+
panic!("inserting sitrep v{v} orphan {i} should not succeed")
335+
}
336+
Err(InsertSitrepError::ParentNotCurrent(id)) => {
337+
orphans.insert(id);
338+
}
339+
Err(InsertSitrepError::Other(e)) => {
340+
panic!(
341+
"expected inserting sitrep v{v} orphan {i} to fail because \
342+
its parent is out of date, but saw an unexpected error: {e}"
343+
);
344+
}
345+
}
346+
}
347+
}

0 commit comments

Comments
 (0)