|
8 | 8 | //! A mock implementation of our instance-binding pattern in pure rust. |
9 | 9 | //! |
10 | 10 | //! Used so we can run miri on this, which we cannot when we are running in itest against Godot. |
| 11 | +//! |
| 12 | +//! Currently, the panicking `GdCell` is suitable only for single-threaded use. Without `experimental-threads` enabled, |
| 13 | +//! godot-rust will block access to bindings from any thread other than the main one. |
11 | 14 |
|
12 | 15 | use std::collections::HashMap; |
13 | 16 | use std::error::Error; |
@@ -55,131 +58,3 @@ fn all_calls_work() { |
55 | 58 | } |
56 | 59 | } |
57 | 60 | } |
58 | | - |
59 | | -/// Run each method both from the main thread and a newly created thread. |
60 | | -#[test] |
61 | | -fn calls_different_thread() { |
62 | | - use std::thread; |
63 | | - |
64 | | - let instance_id = MyClass::init(); |
65 | | - |
66 | | - // We're not running in parallel, so it will never fail to increment completely. |
67 | | - for (f, _, expected_increment) in CALLS { |
68 | | - let start = unsafe { get_int(instance_id) }; |
69 | | - unsafe { |
70 | | - f(instance_id).unwrap(); |
71 | | - |
72 | | - assert_id_is(instance_id, start + expected_increment); |
73 | | - } |
74 | | - let start = start + expected_increment; |
75 | | - thread::spawn(move || unsafe { f(instance_id).unwrap() }) |
76 | | - .join() |
77 | | - .unwrap(); |
78 | | - unsafe { |
79 | | - assert_id_is(instance_id, start + expected_increment); |
80 | | - } |
81 | | - } |
82 | | -} |
83 | | - |
84 | | -/// Call each method from different threads, allowing them to run in parallel. |
85 | | -/// |
86 | | -/// This may cause borrow failures, we do a best-effort attempt at estimating the value then. We can detect |
87 | | -/// if the first call failed, so then we know the integer was incremented by 0. Otherwise, we at least know |
88 | | -/// the range of values that it can be incremented by. |
89 | | -#[test] |
90 | | -fn calls_parallel() { |
91 | | - use std::thread; |
92 | | - |
93 | | - let instance_id = MyClass::init(); |
94 | | - let mut handles = Vec::new(); |
95 | | - |
96 | | - for (f, min_increment, max_increment) in CALLS { |
97 | | - let handle = thread::spawn(move || unsafe { |
98 | | - f(instance_id).map_or((0, 0), |_| (*min_increment, *max_increment)) |
99 | | - }); |
100 | | - handles.push(handle); |
101 | | - } |
102 | | - |
103 | | - let (min_expected, max_expected) = handles |
104 | | - .into_iter() |
105 | | - .map(|handle| handle.join().unwrap()) |
106 | | - .reduce(|(curr_min, curr_max), (min, max)| (curr_min + min, curr_max + max)) |
107 | | - .unwrap(); |
108 | | - |
109 | | - unsafe { |
110 | | - assert!(get_int(instance_id) >= min_expected); |
111 | | - assert!(get_int(instance_id) <= max_expected); |
112 | | - } |
113 | | -} |
114 | | - |
115 | | -/// Call each method from different threads, allowing them to run in parallel. |
116 | | -/// |
117 | | -/// This may cause borrow failures, we do a best-effort attempt at estimating the value then. We can detect |
118 | | -/// if the first call failed, so then we know the integer was incremented by 0. Otherwise, we at least know |
119 | | -/// the range of values that it can be incremented by. |
120 | | -/// |
121 | | -/// Runs each method several times in a row. This should reduce the non-determinism that comes from |
122 | | -/// scheduling of threads. |
123 | | -#[test] |
124 | | -fn calls_parallel_many_serial() { |
125 | | - use std::thread; |
126 | | - |
127 | | - let instance_id = MyClass::init(); |
128 | | - let mut handles = Vec::new(); |
129 | | - |
130 | | - for (f, min_increment, max_increment) in CALLS { |
131 | | - for _ in 0..10 { |
132 | | - let handle = thread::spawn(move || unsafe { |
133 | | - f(instance_id).map_or((0, 0), |_| (*min_increment, *max_increment)) |
134 | | - }); |
135 | | - handles.push(handle); |
136 | | - } |
137 | | - } |
138 | | - |
139 | | - let (min_expected, max_expected) = handles |
140 | | - .into_iter() |
141 | | - .map(|handle| handle.join().unwrap()) |
142 | | - .reduce(|(curr_min, curr_max), (min, max)| (curr_min + min, curr_max + max)) |
143 | | - .unwrap(); |
144 | | - |
145 | | - unsafe { |
146 | | - assert!(get_int(instance_id) >= min_expected); |
147 | | - assert!(get_int(instance_id) <= max_expected); |
148 | | - } |
149 | | -} |
150 | | - |
151 | | -/// Call each method from different threads, allowing them to run in parallel. |
152 | | -/// |
153 | | -/// This may cause borrow failures, we do a best-effort attempt at estimating the value then. We can detect |
154 | | -/// if the first call failed, so then we know the integer was incremented by 0. Otherwise, we at least know |
155 | | -/// the range of values that it can be incremented by. |
156 | | -/// |
157 | | -/// Runs all the tests several times. This is different from [`calls_parallel_many_serial`] as that calls the |
158 | | -/// methods like AAA...BBB...CCC..., whereas this interleaves the methods like ABC...ABC...ABC... |
159 | | -#[test] |
160 | | -fn calls_parallel_many_parallel() { |
161 | | - use std::thread; |
162 | | - |
163 | | - let instance_id = MyClass::init(); |
164 | | - let mut handles = Vec::new(); |
165 | | - |
166 | | - for _ in 0..10 { |
167 | | - for (f, min_increment, max_increment) in CALLS { |
168 | | - let handle = thread::spawn(move || unsafe { |
169 | | - f(instance_id).map_or((0, 0), |_| (*min_increment, *max_increment)) |
170 | | - }); |
171 | | - handles.push(handle); |
172 | | - } |
173 | | - } |
174 | | - |
175 | | - let (min_expected, max_expected) = handles |
176 | | - .into_iter() |
177 | | - .map(|handle| handle.join().unwrap()) |
178 | | - .reduce(|(curr_min, curr_max), (min, max)| (curr_min + min, curr_max + max)) |
179 | | - .unwrap(); |
180 | | - |
181 | | - unsafe { |
182 | | - assert!(get_int(instance_id) >= min_expected); |
183 | | - assert!(get_int(instance_id) <= max_expected); |
184 | | - } |
185 | | -} |
0 commit comments