1use crate::{DataAcc, DataConn, DataHub};
6
7impl DataAcc for DataHub {
8 fn get_data_conn<C: DataConn + 'static>(&mut self, name: &str) -> errs::Result<&mut C> {
9 DataHub::get_data_conn(self, name)
10 }
11}
12
13#[cfg_attr(coverage_nightly, coverage(off))]
14#[cfg(test)]
15mod tests_of_data_acc {
16 use super::*;
17 use crate::{AsyncGroup, DataSrc, TxnFailureReport};
18 use std::cell::RefCell;
19 use std::rc::Rc;
20 use std::sync::{Arc, Mutex};
21
22 struct FooDataConn {
23 id: i8,
24 text: String,
25 committed: bool,
26 logger: Arc<Mutex<Vec<String>>>,
27 }
28
29 impl FooDataConn {
30 fn new(id: i8, s: &str, logger: Arc<Mutex<Vec<String>>>) -> Self {
31 {
32 let mut logger = logger.lock().unwrap();
33 logger.push(format!("FooDataConn::new {}", id));
34 }
35 Self {
36 id,
37 text: s.to_string(),
38 logger,
39 committed: false,
40 }
41 }
42 fn get_text(&self) -> String {
43 let mut logger = self.logger.lock().unwrap();
44 logger.push(format!("FooDataConn::get_text {}", self.id));
45 self.text.clone()
46 }
47 }
48 impl Drop for FooDataConn {
49 fn drop(&mut self) {
50 let mut logger = self.logger.lock().unwrap();
51 logger.push(format!("FooDataConn::drop {}", self.id));
52 }
53 }
54 impl DataConn for FooDataConn {
55 fn commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
56 self.committed = true;
57 let mut logger = self.logger.lock().unwrap();
58 logger.push(format!("FooDataConn::commit {}", self.id));
59 Ok(())
60 }
61 fn pre_commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
62 let mut logger = self.logger.lock().unwrap();
63 logger.push(format!("FooDataConn::pre_commit {}", self.id));
64 Ok(())
65 }
66 fn post_commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
67 let mut logger = self.logger.lock().unwrap();
68 logger.push(format!("FooDataConn::post_commit {}", self.id));
69 Ok(())
70 }
71 fn is_committed(&self) -> bool {
72 self.committed
73 }
74 fn rollback(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
75 let mut logger = self.logger.lock().unwrap();
76 logger.push(format!("FooDataConn::rollback {}", self.id));
77 Ok(())
78 }
79 fn on_txn_failure(&mut self, _ag: &mut AsyncGroup, _reports: &[TxnFailureReport]) {
80 let mut logger = self.logger.lock().unwrap();
81 logger.push(format!("FooDataConn::on_txn_failure {}", self.id));
82 }
83 fn close(&mut self) {
84 let mut logger = self.logger.lock().unwrap();
85 logger.push(format!("FooDataConn::close {}", self.id));
86 }
87 }
88
89 struct FooDataSrc {
90 id: i8,
91 logger: Arc<Mutex<Vec<String>>>,
92 fail: bool,
93 text: String,
94 }
95 impl FooDataSrc {
96 fn new(id: i8, s: &str, logger: Arc<Mutex<Vec<String>>>, fail: bool) -> Self {
97 {
98 let mut logger = logger.lock().unwrap();
99 logger.push(format!("FooDataSrc::new {}", id));
100 }
101 Self {
102 id,
103 logger,
104 fail,
105 text: s.to_string(),
106 }
107 }
108 }
109 impl Drop for FooDataSrc {
110 fn drop(&mut self) {
111 let mut logger = self.logger.lock().unwrap();
112 logger.push(format!("FooDataSrc::drop {}", self.id));
113 }
114 }
115 impl DataSrc<FooDataConn> for FooDataSrc {
116 fn setup(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
117 if self.fail {
118 {
119 let mut logger = self.logger.lock().unwrap();
120 logger.push(format!("FooDataSrc::setup {} failed", self.id));
121 }
122 return Err(errs::Err::new("XXX".to_string()));
123 }
124 {
125 let mut logger = self.logger.lock().unwrap();
126 logger.push(format!("FooDataSrc::setup {}", self.id));
127 }
128 Ok(())
129 }
130 fn close(&mut self) {
131 let mut logger = self.logger.lock().unwrap();
132 logger.push(format!("FooDataSrc::close {}", self.id));
133 }
134 fn create_data_conn(&mut self) -> errs::Result<Box<FooDataConn>> {
135 {
136 let mut logger = self.logger.lock().unwrap();
137 logger.push(format!("FooDataSrc::create_data_src {}", self.id));
138 }
139 let conn = FooDataConn::new(self.id, &self.text, self.logger.clone());
140 Ok(Box::new(conn))
141 }
142 }
143
144 struct BarDataConn {
145 id: i8,
146 text: Option<String>,
147 ds_text: Rc<RefCell<String>>,
148 committed: bool,
149 logger: Arc<Mutex<Vec<String>>>,
150 }
151 impl BarDataConn {
152 fn new(id: i8, ds_text: Rc<RefCell<String>>, logger: Arc<Mutex<Vec<String>>>) -> Self {
153 {
154 let mut logger = logger.lock().unwrap();
155 logger.push(format!("BarDataConn::new {}", id));
156 }
157 Self {
158 id,
159 text: None,
160 ds_text,
161 logger,
162 committed: false,
163 }
164 }
165 fn set_text(&mut self, s: &str) {
166 let mut logger = self.logger.lock().unwrap();
167 logger.push(format!("BarDataConn::set_text {}", self.id));
168 self.text = Some(s.to_string());
169 }
170 }
171 impl Drop for BarDataConn {
172 fn drop(&mut self) {
173 let mut logger = self.logger.lock().unwrap();
174 logger.push(format!("BarDataConn::drop {}", self.id));
175 }
176 }
177 impl DataConn for BarDataConn {
178 fn commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
179 self.committed = true;
180 match &self.text {
181 Some(s) => {
182 *self.ds_text.borrow_mut() = s.to_string();
183 }
184 None => {
185 *self.ds_text.borrow_mut() = "".to_string();
186 }
187 }
188 self.logger
189 .lock()
190 .unwrap()
191 .push(format!("BarDataConn::commit {}", self.id));
192 Ok(())
193 }
194 fn pre_commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
195 let mut logger = self.logger.lock().unwrap();
196 logger.push(format!("BarDataConn::pre_commit {}", self.id));
197 Ok(())
198 }
199 fn post_commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
200 let mut logger = self.logger.lock().unwrap();
201 logger.push(format!("BarDataConn::post_commit {}", self.id));
202 Ok(())
203 }
204 fn is_committed(&self) -> bool {
205 self.committed
206 }
207 fn rollback(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
208 let mut logger = self.logger.lock().unwrap();
209 logger.push(format!("BarDataConn::rollback {}", self.id));
210 Ok(())
211 }
212 fn on_txn_failure(&mut self, _ag: &mut AsyncGroup, _reports: &[TxnFailureReport]) {
213 let mut logger = self.logger.lock().unwrap();
214 logger.push(format!("BarDataConn::on_txn_failure {}", self.id));
215 }
216 fn close(&mut self) {
217 let mut logger = self.logger.lock().unwrap();
218 logger.push(format!("BarDataConn.text = {}", self.text.clone().unwrap()));
219 logger.push(format!("BarDataConn::close {}", self.id));
220 }
221 }
222
223 struct BarDataSrc {
224 id: i8,
225 text: Rc<RefCell<String>>,
226 logger: Arc<Mutex<Vec<String>>>,
227 }
228 impl BarDataSrc {
229 fn new(id: i8, logger: Arc<Mutex<Vec<String>>>) -> Self {
230 {
231 let mut logger = logger.lock().unwrap();
232 logger.push(format!("BarDataSrc::new {}", id));
233 }
234 Self {
235 id,
236 text: Rc::new(RefCell::new(String::new())),
237 logger,
238 }
239 }
240 }
241 impl Drop for BarDataSrc {
242 fn drop(&mut self) {
243 let mut logger = self.logger.lock().unwrap();
244 logger.push(format!("BarDataSrc::drop {}", self.id));
245 }
246 }
247 impl DataSrc<BarDataConn> for BarDataSrc {
248 fn setup(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
249 let mut logger = self.logger.lock().unwrap();
250 logger.push(format!("BarDataSrc::setup {}", self.id));
251 Ok(())
252 }
253 fn close(&mut self) {
254 let mut logger = self.logger.lock().unwrap();
255 logger.push(format!("BarDataSrc.text = {}", self.text.borrow()));
256 logger.push(format!("BarDataSrc::close {}", self.id));
257 }
258 fn create_data_conn(&mut self) -> errs::Result<Box<BarDataConn>> {
259 {
260 let mut logger = self.logger.lock().unwrap();
261 logger.push(format!("BarDataSrc::create_data_src {}", self.id));
262 }
263 let conn = BarDataConn::new(self.id, self.text.clone(), self.logger.clone());
264 Ok(Box::new(conn))
265 }
266 }
267
268 mod test_run_method {
269 use super::*;
270 use override_macro::{overridable, override_with};
271
272 #[overridable(mod = test_run_method)]
273 trait SampleData {
274 fn get_value(&mut self) -> errs::Result<String>;
275 fn set_value(&mut self, v: &str) -> errs::Result<()>;
276 }
277
278 fn sample_logic(data: &mut impl SampleData) -> errs::Result<()> {
279 let v = data.get_value()?;
280 let _ = data.set_value(&v);
281 let v = data.get_value()?;
282 let _ = data.set_value(&v);
283 Ok(())
284 }
285
286 #[overridable(mod = test_run_method)]
287 trait FooDataAcc: DataAcc {
288 fn get_value(&mut self) -> errs::Result<String> {
289 let conn = self.get_data_conn::<FooDataConn>("foo")?;
290 Ok(conn.get_text())
291 }
292 }
293
294 impl FooDataAcc for DataHub {}
295
296 #[overridable(mod = test_run_method)]
297 trait BarDataAcc: DataAcc {
298 fn set_value(&mut self, text: &str) -> errs::Result<()> {
299 let conn = self.get_data_conn::<BarDataConn>("bar")?;
300 conn.set_text(text);
301 Ok(())
302 }
303 }
304
305 impl BarDataAcc for DataHub {}
306
307 #[override_with(test_run_method::FooDataAcc, test_run_method::BarDataAcc)]
308 impl SampleData for DataHub {}
309
310 #[test]
311 fn test() {
312 let logger = Arc::new(Mutex::new(Vec::new()));
313
314 {
315 let mut data = DataHub::new();
316
317 data.uses("foo", FooDataSrc::new(1, "hello", logger.clone(), false));
318 data.uses("bar", BarDataSrc::new(2, logger.clone()));
319
320 if let Err(_) = data.run(sample_logic) {
321 panic!();
322 }
323 }
324
325 assert_eq!(
326 *logger.lock().unwrap(),
327 vec![
328 "FooDataSrc::new 1",
329 "BarDataSrc::new 2",
330 "FooDataSrc::setup 1",
331 "BarDataSrc::setup 2",
332 "FooDataSrc::create_data_src 1",
333 "FooDataConn::new 1",
334 "FooDataConn::get_text 1",
335 "BarDataSrc::create_data_src 2",
336 "BarDataConn::new 2",
337 "BarDataConn::set_text 2",
338 "FooDataConn::get_text 1",
339 "BarDataConn::set_text 2",
340 "BarDataConn.text = hello",
341 "BarDataConn::close 2",
342 "BarDataConn::drop 2",
343 "FooDataConn::close 1",
344 "FooDataConn::drop 1",
345 "BarDataSrc.text = ", "BarDataSrc::close 2",
347 "BarDataSrc::drop 2",
348 "FooDataSrc::close 1",
349 "FooDataSrc::drop 1",
350 ],
351 );
352 }
353 }
354
355 mod test_txn_method {
356 use super::*;
357 use override_macro::{overridable, override_with};
358
359 #[overridable(mod = test_txn_method)]
360 trait SampleData {
361 fn get_value(&mut self) -> errs::Result<String>;
362 fn set_value(&mut self, v: &str) -> errs::Result<()>;
363 }
364
365 fn sample_logic(data: &mut impl SampleData) -> errs::Result<()> {
366 let v = data.get_value()?;
367 let _ = data.set_value(&v);
368 let v = data.get_value()?;
369 let _ = data.set_value(&v);
370 Ok(())
371 }
372
373 #[overridable(mod = test_txn_method)]
374 trait FooDataAcc: DataAcc {
375 fn get_value(&mut self) -> errs::Result<String> {
376 let conn = self.get_data_conn::<FooDataConn>("foo")?;
377 Ok(conn.get_text())
378 }
379 }
380
381 impl FooDataAcc for DataHub {}
382
383 #[overridable(mod = test_txn_method)]
384 trait BarDataAcc: DataAcc {
385 fn set_value(&mut self, text: &str) -> errs::Result<()> {
386 let conn = self.get_data_conn::<BarDataConn>("bar")?;
387 conn.set_text(text);
388 Ok(())
389 }
390 }
391
392 impl BarDataAcc for DataHub {}
393
394 #[override_with(test_txn_method::FooDataAcc, test_txn_method::BarDataAcc)]
395 impl test_txn_method::SampleData for DataHub {}
396
397 #[test]
398 fn test() {
399 let logger = Arc::new(Mutex::new(Vec::new()));
400
401 {
402 let mut data = DataHub::new();
403
404 data.uses("foo", FooDataSrc::new(1, "hello", logger.clone(), false));
405 data.uses("bar", BarDataSrc::new(2, logger.clone()));
406
407 if let Err(_) = data.txn(sample_logic) {
408 panic!();
409 }
410 }
411
412 assert_eq!(
413 *logger.lock().unwrap(),
414 vec![
415 "FooDataSrc::new 1",
416 "BarDataSrc::new 2",
417 "FooDataSrc::setup 1",
418 "BarDataSrc::setup 2",
419 "FooDataSrc::create_data_src 1",
420 "FooDataConn::new 1",
421 "FooDataConn::get_text 1",
422 "BarDataSrc::create_data_src 2",
423 "BarDataConn::new 2",
424 "BarDataConn::set_text 2",
425 "FooDataConn::get_text 1",
426 "BarDataConn::set_text 2",
427 "FooDataConn::pre_commit 1",
428 "BarDataConn::pre_commit 2",
429 "FooDataConn::commit 1",
430 "BarDataConn::commit 2",
431 "FooDataConn::post_commit 1",
432 "BarDataConn::post_commit 2",
433 "BarDataConn.text = hello",
434 "BarDataConn::close 2",
435 "BarDataConn::drop 2",
436 "FooDataConn::close 1",
437 "FooDataConn::drop 1",
438 "BarDataSrc.text = hello", "BarDataSrc::close 2",
440 "BarDataSrc::drop 2",
441 "FooDataSrc::close 1",
442 "FooDataSrc::drop 1",
443 ],
444 );
445 }
446 }
447}