]> git.proxmox.com Git - rustc.git/blob - vendor/salsa/tests/panic_safely.rs
New upstream version 1.48.0+dfsg1
[rustc.git] / vendor / salsa / tests / panic_safely.rs
1 use salsa::{Database, ParallelDatabase, Snapshot};
2 use std::panic::{self, AssertUnwindSafe};
3 use std::sync::atomic::{AtomicU32, Ordering::SeqCst};
4
5 #[salsa::query_group(PanicSafelyStruct)]
6 trait PanicSafelyDatabase: salsa::Database {
7 #[salsa::input]
8 fn one(&self) -> usize;
9
10 fn panic_safely(&self) -> ();
11
12 fn outer(&self) -> ();
13 }
14
15 fn panic_safely(db: &dyn PanicSafelyDatabase) -> () {
16 assert_eq!(db.one(), 1);
17 }
18
19 static OUTER_CALLS: AtomicU32 = AtomicU32::new(0);
20
21 fn outer(db: &dyn PanicSafelyDatabase) -> () {
22 OUTER_CALLS.fetch_add(1, SeqCst);
23 db.panic_safely();
24 }
25
26 #[salsa::database(PanicSafelyStruct)]
27 #[derive(Default)]
28 struct DatabaseStruct {
29 storage: salsa::Storage<Self>,
30 }
31
32 impl salsa::Database for DatabaseStruct {}
33
34 impl salsa::ParallelDatabase for DatabaseStruct {
35 fn snapshot(&self) -> Snapshot<Self> {
36 Snapshot::new(DatabaseStruct {
37 storage: self.storage.snapshot(),
38 })
39 }
40 }
41
42 #[test]
43 fn should_panic_safely() {
44 let mut db = DatabaseStruct::default();
45 db.set_one(0);
46
47 // Invoke `db.panic_safely() without having set `db.one`. `db.one` will
48 // return 0 and we should catch the panic.
49 let result = panic::catch_unwind(AssertUnwindSafe({
50 let db = db.snapshot();
51 move || db.panic_safely()
52 }));
53 assert!(result.is_err());
54
55 // Set `db.one` to 1 and assert ok
56 db.set_one(1);
57 let result = panic::catch_unwind(AssertUnwindSafe(|| db.panic_safely()));
58 assert!(result.is_ok());
59
60 // Check, that memoized outer is not invalidated by a panic
61 {
62 assert_eq!(OUTER_CALLS.load(SeqCst), 0);
63 db.outer();
64 assert_eq!(OUTER_CALLS.load(SeqCst), 1);
65
66 db.set_one(0);
67 let result = panic::catch_unwind(AssertUnwindSafe(|| db.outer()));
68 assert!(result.is_err());
69 assert_eq!(OUTER_CALLS.load(SeqCst), 1);
70
71 db.set_one(1);
72 db.outer();
73 assert_eq!(OUTER_CALLS.load(SeqCst), 1);
74 }
75 }
76
77 #[test]
78 fn storages_are_unwind_safe() {
79 fn check_unwind_safe<T: std::panic::UnwindSafe>() {}
80 check_unwind_safe::<&DatabaseStruct>();
81 }
82
83 #[test]
84 fn panics_clear_query_stack() {
85 let db = DatabaseStruct::default();
86
87 // Invoke `db.panic_if_not_one() without having set `db.input`. `db.input`
88 // will default to 0 and we should catch the panic.
89 let result = panic::catch_unwind(AssertUnwindSafe(|| db.panic_safely()));
90 assert!(result.is_err());
91
92 // The database has been poisoned and any attempt to increment the
93 // revision should panic.
94 assert_eq!(db.salsa_runtime().active_query(), None);
95 }