1use crate::{
6 AsyncGroup, DataConn, DataConnContainer, DataConnManager, ErrEntry, SendSyncNonNull,
7 TxnFailureCause, TxnFailureReport, TxnFailureRollback,
8};
9
10use std::collections::HashMap;
11use std::sync::Arc;
12use std::{any, mem};
13
14#[allow(clippy::enum_variant_names)]
16#[derive(Debug)]
17pub enum DataConnError {
18 FailToPreCommitDataConn {
22 errors: Vec<ErrEntry>,
24 },
25
26 FailToCommitDataConn {
30 errors: Vec<ErrEntry>,
32 },
33
34 FailToPostCommitDataConn {
38 errors: Vec<ErrEntry>,
40 },
41
42 FailToCastDataConn {
44 name: Arc<str>,
46
47 target_type: &'static str,
49 },
50}
51
52impl<C> DataConnContainer<C>
53where
54 C: DataConn + 'static,
55{
56 pub(crate) fn new(name: impl Into<Arc<str>>, data_conn: Box<C>) -> Self {
57 Self {
58 drop_fn: drop_data_conn::<C>,
59 is_fn: is_data_conn::<C>,
60 type_fn: type_of_data_conn::<C>,
61 commit_fn: commit_data_conn::<C>,
62 pre_commit_fn: pre_commit_data_conn::<C>,
63 post_commit_fn: post_commit_data_conn::<C>,
64 is_committed_fn: is_committed_data_conn::<C>,
65 rollback_fn: rollback_data_conn::<C>,
66 on_txn_failure_fn: on_txn_failure_data_conn::<C>,
67 close_fn: close_data_conn::<C>,
68
69 name: name.into(),
70 data_conn,
71 }
72 }
73}
74
75fn drop_data_conn<C>(ptr: *const DataConnContainer)
76where
77 C: DataConn + 'static,
78{
79 let typed_ptr = ptr as *mut DataConnContainer<C>;
80 unsafe {
81 drop(Box::from_raw(typed_ptr));
82 }
83}
84
85fn is_data_conn<C>(type_id: any::TypeId) -> bool
86where
87 C: DataConn + 'static,
88{
89 any::TypeId::of::<C>() == type_id
90}
91
92fn type_of_data_conn<C>() -> &'static str
93where
94 C: DataConn + 'static,
95{
96 any::type_name::<C>()
97}
98
99fn commit_data_conn<C>(ptr: *const DataConnContainer, ag: &mut AsyncGroup) -> errs::Result<()>
100where
101 C: DataConn + 'static,
102{
103 let typed_ptr = ptr as *mut DataConnContainer<C>;
104 unsafe { (*typed_ptr).data_conn.commit(ag) }
105}
106
107fn pre_commit_data_conn<C>(ptr: *const DataConnContainer, ag: &mut AsyncGroup) -> errs::Result<()>
108where
109 C: DataConn + 'static,
110{
111 let typed_ptr = ptr as *mut DataConnContainer<C>;
112 unsafe { (*typed_ptr).data_conn.pre_commit(ag) }
113}
114
115fn post_commit_data_conn<C>(ptr: *const DataConnContainer, ag: &mut AsyncGroup) -> errs::Result<()>
116where
117 C: DataConn + 'static,
118{
119 let typed_ptr = ptr as *mut DataConnContainer<C>;
120 unsafe { (*typed_ptr).data_conn.post_commit(ag) }
121}
122
123fn is_committed_data_conn<C>(ptr: *const DataConnContainer) -> bool
124where
125 C: DataConn + 'static,
126{
127 let typed_ptr = ptr as *mut DataConnContainer<C>;
128 unsafe { (*typed_ptr).data_conn.is_committed() }
129}
130
131fn rollback_data_conn<C>(ptr: *const DataConnContainer, ag: &mut AsyncGroup) -> errs::Result<()>
132where
133 C: DataConn + 'static,
134{
135 let typed_ptr = ptr as *mut DataConnContainer<C>;
136 unsafe { (*typed_ptr).data_conn.rollback(ag) }
137}
138
139fn on_txn_failure_data_conn<C>(
140 ptr: *const DataConnContainer,
141 ag: &mut AsyncGroup,
142 reports: &[TxnFailureReport],
143) where
144 C: DataConn + 'static,
145{
146 let typed_ptr = ptr as *mut DataConnContainer<C>;
147 unsafe {
148 (*typed_ptr).data_conn.on_txn_failure(ag, reports);
149 }
150}
151
152fn close_data_conn<C>(ptr: *const DataConnContainer)
153where
154 C: DataConn + 'static,
155{
156 let typed_ptr = ptr as *mut DataConnContainer<C>;
157 unsafe {
158 (*typed_ptr).data_conn.close();
159 }
160}
161
162impl DataConnManager {
163 pub(crate) fn new() -> Self {
164 Self {
165 vec: Vec::new(),
166 index_map: HashMap::new(),
167 committed: false,
168 }
169 }
170
171 pub(crate) fn with_commit_order(names: &[&str]) -> Self {
172 let mut index_map = HashMap::with_capacity(names.len());
173 for (i, nm) in names.iter().rev().enumerate() {
175 index_map.insert((*nm).into(), names.len() - 1 - i);
176 }
177
178 Self {
179 vec: vec![None; names.len()],
180 index_map,
181 committed: false,
182 }
183 }
184
185 pub(crate) fn add(&mut self, ssnnptr: SendSyncNonNull<DataConnContainer>) {
186 let name = unsafe { (*ssnnptr.non_null_ptr.as_ptr()).name.clone() };
187 if let Some(index) = self.index_map.get(&name) {
188 if self.vec[*index].is_none() {
190 self.vec[*index] = Some(ssnnptr);
191 }
192 } else {
193 let index = self.vec.len();
194 self.vec.push(Some(ssnnptr));
195 self.index_map.insert(name.clone(), index);
196 }
197 }
198
199 pub(crate) fn find_by_name(
200 &self,
201 name: impl AsRef<str>,
202 ) -> Option<SendSyncNonNull<DataConnContainer>> {
203 if let Some(index) = self.index_map.get(name.as_ref()) {
204 if *index < self.vec.len() {
205 if let Some(ssnnptr) = &self.vec[*index] {
206 let ptr = ssnnptr.non_null_ptr.as_ptr();
207 let cont_name = unsafe { &(*ptr).name };
208 if cont_name.as_ref() == name.as_ref() {
209 return Some(*ssnnptr);
210 }
211 }
212 }
213 }
214
215 None
216 }
217
218 pub(crate) fn to_typed_ptr<C>(
219 ssnnptr: &SendSyncNonNull<DataConnContainer>,
220 ) -> errs::Result<*mut DataConnContainer<C>>
221 where
222 C: DataConn + 'static,
223 {
224 let ptr = ssnnptr.non_null_ptr.as_ptr();
225 let name = unsafe { &(*ptr).name };
226 let type_id = any::TypeId::of::<C>();
227 let is_fn = unsafe { (*ptr).is_fn };
228
229 if !is_fn(type_id) {
230 return Err(errs::Err::new(DataConnError::FailToCastDataConn {
231 name: name.clone(),
232 target_type: any::type_name::<C>(),
233 }));
234 }
235
236 let typed_ptr = ptr as *mut DataConnContainer<C>;
237 Ok(typed_ptr)
238 }
239
240 pub(crate) fn new_failure_reports(&self) -> Vec<TxnFailureReport> {
241 let mut reports = Vec::new();
242 for ssnnptr in self.vec.iter().flatten() {
243 let ptr = ssnnptr.non_null_ptr.as_ptr();
244 let name = unsafe { (*ptr).name.clone() };
245 let type_fn = unsafe { (*ptr).type_fn };
246 let report = TxnFailureReport::new(name, type_fn());
247 reports.push(report);
248 }
249 reports
250 }
251
252 pub(crate) fn commit(&mut self, reports: &mut [TxnFailureReport]) -> errs::Result<()> {
253 let mut errors = Vec::new();
254
255 let mut ag = AsyncGroup::new();
256 for (i, ssnnptr) in self.vec.iter().flatten().enumerate() {
257 let ptr = ssnnptr.non_null_ptr.as_ptr();
258 let pre_commit_fn = unsafe { (*ptr).pre_commit_fn };
259 let name = unsafe { &(*ptr).name };
260 ag._index = i;
261 ag._name = name.clone();
262 if let Err(err) = pre_commit_fn(ptr, &mut ag) {
263 errors.push(ErrEntry {
264 index: i,
265 name: name.clone(),
266 err,
267 });
268 break;
269 }
270 }
271 ag.join_and_collect_errors(&mut errors);
272
273 if !errors.is_empty() {
274 for ee in errors.iter() {
275 let report = &mut reports[ee.index];
276 report.cause = TxnFailureCause::LogicFailure(ee.err.clone());
277 }
278 return Err(errs::Err::new(DataConnError::FailToPreCommitDataConn {
279 errors,
280 }));
281 }
282
283 let mut ag = AsyncGroup::new();
284 for (i, ssnnptr) in self.vec.iter().flatten().enumerate() {
285 let ptr = ssnnptr.non_null_ptr.as_ptr();
286 let is_committed_fn = unsafe { (*ptr).is_committed_fn };
287 if is_committed_fn(ptr) {
288 continue;
291 }
292 let commit_fn = unsafe { (*ptr).commit_fn };
293 let name = unsafe { &(*ptr).name };
294 ag._index = i;
295 ag._name = name.clone();
296 if let Err(err) = commit_fn(ptr, &mut ag) {
297 errors.push(ErrEntry {
298 index: i,
299 name: name.clone(),
300 err,
301 });
302 break;
303 }
304 }
305 ag.join_and_collect_errors(&mut errors);
306
307 if !errors.is_empty() {
308 for ee in errors.iter() {
309 let report = &mut reports[ee.index];
310 report.cause = TxnFailureCause::CommitFailure(ee.err.clone());
311 }
312 return Err(errs::Err::new(DataConnError::FailToCommitDataConn {
313 errors,
314 }));
315 }
316
317 self.committed = true;
318
319 let mut ag = AsyncGroup::new();
320 for (i, ssnnptr) in self.vec.iter().flatten().enumerate() {
321 let ptr = ssnnptr.non_null_ptr.as_ptr();
322 let post_commit_fn = unsafe { (*ptr).post_commit_fn };
323 let name = unsafe { &(*ptr).name };
324 ag._index = i;
325 ag._name = name.clone();
326 if let Err(err) = post_commit_fn(ptr, &mut ag) {
327 errors.push(ErrEntry {
328 index: i,
329 name: name.clone(),
330 err,
331 });
332 }
334 }
335 ag.join_and_collect_errors(&mut errors);
336
337 if !errors.is_empty() {
338 for ee in errors.iter() {
339 let report = &mut reports[ee.index];
340 report.cause = TxnFailureCause::PostCommitFailure(ee.err.clone());
341 }
342 return Err(errs::Err::new(DataConnError::FailToPostCommitDataConn {
343 errors,
344 }));
345 }
346
347 Ok(())
348 }
349
350 pub(crate) fn rollback(&mut self, mut reports: Vec<TxnFailureReport>) {
351 let mut errors = Vec::new();
352
353 let mut ag = AsyncGroup::new();
354 for (i, ssnnptr) in self.vec.iter().flatten().enumerate() {
355 let ptr = ssnnptr.non_null_ptr.as_ptr();
356 let report = &mut reports[i];
357 let is_committed_fn = unsafe { (*ptr).is_committed_fn };
358 if is_committed_fn(ptr) {
359 if let TxnFailureCause::NoneByUncommitted = report.cause {
360 report.cause = TxnFailureCause::NoneByCommitted;
361 }
362 continue;
363 }
364 if self.committed {
365 continue;
366 }
367 let rollback_fn = unsafe { (*ptr).rollback_fn };
368 let name = unsafe { &(*ptr).name };
369 ag._index = i;
370 ag._name = name.clone();
371 if let Err(err) = rollback_fn(ptr, &mut ag) {
372 errors.push(ErrEntry {
373 index: i,
374 name: name.clone(),
375 err,
376 });
377 } else {
378 report.rollback = TxnFailureRollback::NoneByRolledBack;
379 }
380 }
381 ag.join_and_collect_errors(&mut errors);
382
383 if !errors.is_empty() {
384 for ee in errors.into_iter() {
385 let report = &mut reports[ee.index];
386 report.rollback = TxnFailureRollback::RollbackFailure(ee.err);
387 }
388 }
389
390 let mut ag = AsyncGroup::new();
391 for ssnnptr in self.vec.iter().flatten() {
392 let ptr = ssnnptr.non_null_ptr.as_ptr();
393 let on_txn_failure_fn = unsafe { (*ptr).on_txn_failure_fn };
394 on_txn_failure_fn(ptr, &mut ag, &reports);
395 }
396 ag.join_and_ignore_errors();
397 }
398
399 pub(crate) fn close(&mut self) {
400 self.index_map.clear();
401
402 let vec: Vec<Option<SendSyncNonNull<DataConnContainer>>> = mem::take(&mut self.vec);
403 for ssnnptr in vec.iter().flatten().rev() {
404 let ptr = ssnnptr.non_null_ptr.as_ptr();
405 let close_fn = unsafe { (*ptr).close_fn };
406 let drop_fn = unsafe { (*ptr).drop_fn };
407 close_fn(ptr);
408 drop_fn(ptr);
409 }
410 }
411}
412
413impl Drop for DataConnManager {
414 fn drop(&mut self) {
415 self.close();
416 }
417}
418
419#[cfg_attr(coverage_nightly, coverage(off))]
420#[cfg(test)]
421mod tests_of_data_conn {
422 use super::*;
423 use std::sync::{
424 atomic::{AtomicBool, Ordering},
425 Arc, Mutex,
426 };
427 use std::{ptr, thread, time};
428
429 const BASE_LINE: u32 = line!();
430
431 #[derive(PartialEq, Copy, Clone)]
432 enum Fail {
433 Not,
434 Commit,
435 PreCommit,
436 PostCommit,
437 Rollback,
438 PreCommitBecomeCommitted,
439 }
440
441 struct SyncDataConn {
442 id: i8,
443 committed: bool,
444 fail: Fail,
445 logger: Arc<Mutex<Vec<String>>>,
446 }
447 impl SyncDataConn {
448 fn new(id: i8, logger: Arc<Mutex<Vec<String>>>, fail: Fail) -> Self {
449 logger
450 .lock()
451 .unwrap()
452 .push(format!("SyncDataConn::new {}", id));
453 Self {
454 id,
455 committed: false,
456 fail,
457 logger,
458 }
459 }
460 }
461 impl Drop for SyncDataConn {
462 fn drop(&mut self) {
463 self.logger
464 .lock()
465 .unwrap()
466 .push(format!("SyncDataConn::drop {}", self.id));
467 }
468 }
469 impl DataConn for SyncDataConn {
470 fn commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
471 if self.fail == Fail::Commit {
472 self.logger
473 .lock()
474 .unwrap()
475 .push(format!("SyncDataConn::commit {} failed", self.id));
476 return Err(errs::Err::new("ZZZ".to_string()));
477 }
478 self.committed = true;
479 self.logger
480 .lock()
481 .unwrap()
482 .push(format!("SyncDataConn::commit {}", self.id));
483 Ok(())
484 }
485 fn pre_commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
486 if self.fail == Fail::PreCommit {
487 self.logger
488 .lock()
489 .unwrap()
490 .push(format!("SyncDataConn::pre_commit {} failed", self.id));
491 return Err(errs::Err::new("zzz".to_string()));
492 }
493 self.logger
494 .lock()
495 .unwrap()
496 .push(format!("SyncDataConn::pre_commit {}", self.id));
497 if self.fail == Fail::PreCommitBecomeCommitted {
498 self.committed = true;
499 }
500 Ok(())
501 }
502 fn post_commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
503 if self.fail == Fail::PostCommit {
504 self.logger
505 .lock()
506 .unwrap()
507 .push(format!("SyncDataConn::post_commit {} failed", self.id));
508 return Err(errs::Err::new("!!!".to_string()));
509 }
510 self.logger
511 .lock()
512 .unwrap()
513 .push(format!("SyncDataConn::post_commit {}", self.id));
514 Ok(())
515 }
516 fn is_committed(&self) -> bool {
517 self.committed
518 }
519 fn rollback(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
520 if self.fail == Fail::Rollback {
521 self.logger
522 .lock()
523 .unwrap()
524 .push(format!("SyncDataConn::rollback {} failed", self.id));
525 return Err(errs::Err::new("???".to_string()));
526 }
527 self.logger
528 .lock()
529 .unwrap()
530 .push(format!("SyncDataConn::rollback {}", self.id));
531 Ok(())
532 }
533 fn on_txn_failure(&mut self, _ag: &mut AsyncGroup, reports: &[TxnFailureReport]) {
534 let mut logger = self.logger.lock().unwrap();
535 logger.push(format!("SyncDataConn::on_txn_failure {}", self.id));
536 logger.push(format!("TxnFailureReports={:?}", reports));
537 }
538 fn close(&mut self) {
539 self.logger
540 .lock()
541 .unwrap()
542 .push(format!("SyncDataConn::close {}", self.id));
543 }
544 }
545
546 struct AsyncDataConn {
547 id: i8,
548 committed: Arc<AtomicBool>,
549 fail: Fail,
550 logger: Arc<Mutex<Vec<String>>>,
551 }
552 impl AsyncDataConn {
553 fn new(id: i8, logger: Arc<Mutex<Vec<String>>>, fail: Fail) -> Self {
554 logger
555 .lock()
556 .unwrap()
557 .push(format!("AsyncDataConn::new {}", id));
558 Self {
559 id,
560 committed: Arc::new(AtomicBool::new(false)),
561 fail,
562 logger,
563 }
564 }
565 }
566 impl Drop for AsyncDataConn {
567 fn drop(&mut self) {
568 self.logger
569 .lock()
570 .unwrap()
571 .push(format!("AsyncDataConn::drop {}", self.id));
572 }
573 }
574 impl DataConn for AsyncDataConn {
575 fn commit(&mut self, ag: &mut AsyncGroup) -> errs::Result<()> {
576 let fail = self.fail;
577 let logger = self.logger.clone();
578 let id = self.id;
579 let committed = self.committed.clone();
580 ag.add(move || {
581 thread::sleep(time::Duration::from_millis(100));
582 if fail == Fail::Commit {
583 logger
584 .lock()
585 .unwrap()
586 .push(format!("AsyncDataConn::commit {} failed", id));
587 return Err(errs::Err::new("YYY".to_string()));
588 }
589 committed.store(true, Ordering::Release);
590 logger
591 .lock()
592 .unwrap()
593 .push(format!("AsyncDataConn::commit {}", id));
594 Ok(())
595 });
596 Ok(())
597 }
598 fn pre_commit(&mut self, ag: &mut AsyncGroup) -> errs::Result<()> {
599 let fail = self.fail;
600 let logger = self.logger.clone();
601 let id = self.id;
602 let committed = self.committed.clone();
603 ag.add(move || {
604 thread::sleep(time::Duration::from_millis(100));
605 if fail == Fail::PreCommit {
606 logger
607 .lock()
608 .unwrap()
609 .push(format!("AsyncDataConn::pre_commit {} failed", id));
610 return Err(errs::Err::new("yyy".to_string()));
611 }
612 if fail == Fail::PreCommitBecomeCommitted {
613 committed.store(true, Ordering::Release);
614 }
615 logger
616 .lock()
617 .unwrap()
618 .push(format!("AsyncDataConn::pre_commit {}", id));
619 Ok(())
620 });
621 Ok(())
622 }
623 fn post_commit(&mut self, ag: &mut AsyncGroup) -> errs::Result<()> {
624 let logger = self.logger.clone();
625 let id = self.id;
626 let fail = self.fail;
627 ag.add(move || {
628 thread::sleep(time::Duration::from_millis(100));
629 if fail == Fail::PostCommit {
630 logger
631 .lock()
632 .unwrap()
633 .push(format!("AsyncDataConn::post_commit {} failed", id));
634 return Err(errs::Err::new("!!!".to_string()));
635 }
636 logger
637 .lock()
638 .unwrap()
639 .push(format!("AsyncDataConn::post_commit {}", id));
640 Ok(())
641 });
642 Ok(())
643 }
644 fn is_committed(&self) -> bool {
645 self.committed.load(Ordering::Acquire)
646 }
647 fn rollback(&mut self, ag: &mut AsyncGroup) -> errs::Result<()> {
648 let logger = self.logger.clone();
649 let fail = self.fail;
650 let id = self.id;
651 ag.add(move || {
652 thread::sleep(time::Duration::from_millis(100));
653 if fail == Fail::Rollback {
654 logger
655 .lock()
656 .unwrap()
657 .push(format!("AsyncDataConn::rollback {} failed", id));
658 return Err(errs::Err::new("???".to_string()));
659 }
660 logger
661 .lock()
662 .unwrap()
663 .push(format!("AsyncDataConn::rollback {}", id));
664 Ok(())
665 });
666 Ok(())
667 }
668 fn on_txn_failure(&mut self, ag: &mut AsyncGroup, reports: &[TxnFailureReport]) {
669 let reports_log = format!("TxnFailureReports={:?}", reports);
670 let logger = self.logger.clone();
671 let id = self.id;
672 ag.add(move || {
673 thread::sleep(time::Duration::from_millis(100));
674 let mut logger = logger.lock().unwrap();
675 logger.push(format!("AsyncDataConn::on_txn_failure {}", id));
676 logger.push(reports_log);
677 Ok(())
678 });
679 }
680 fn close(&mut self) {
681 self.logger
682 .lock()
683 .unwrap()
684 .push(format!("AsyncDataConn::close {}", self.id));
685 }
686 }
687
688 struct NoCommitDataConn {
689 id: i8,
690 logger: Arc<Mutex<Vec<String>>>,
691 }
692 impl NoCommitDataConn {
693 fn new(id: i8, logger: Arc<Mutex<Vec<String>>>) -> Self {
694 logger
695 .lock()
696 .unwrap()
697 .push(format!("NoCommitDataConn::new {}", id));
698 Self { id, logger }
699 }
700 }
701 impl Drop for NoCommitDataConn {
702 fn drop(&mut self) {
703 self.logger
704 .lock()
705 .unwrap()
706 .push(format!("NoCommitDataConn::drop {}", self.id));
707 }
708 }
709 impl DataConn for NoCommitDataConn {
710 fn commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
711 self.logger
712 .lock()
713 .unwrap()
714 .push(format!("NoCommitDataConn::commit {}", self.id));
715 Ok(())
716 }
717 fn pre_commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
718 self.logger
719 .lock()
720 .unwrap()
721 .push(format!("NoCommitDataConn::pre_commit {}", self.id));
722 Ok(())
723 }
724 fn post_commit(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
725 self.logger
726 .lock()
727 .unwrap()
728 .push(format!("NoCommitDataConn::post_commit {}", self.id));
729 Ok(())
730 }
731 fn is_committed(&self) -> bool {
732 false
733 }
734 fn rollback(&mut self, _ag: &mut AsyncGroup) -> errs::Result<()> {
735 self.logger
736 .lock()
737 .unwrap()
738 .push(format!("NoCommitDataConn::rollback {}", self.id));
739 Ok(())
740 }
741 fn on_txn_failure(&mut self, _ag: &mut AsyncGroup, reports: &[TxnFailureReport]) {
742 let mut logger = self.logger.lock().unwrap();
743 logger.push(format!("NoCommitDataConn::on_txn_failure {}", self.id));
744 logger.push(format!("TxnFailureReports={:?}", reports));
745 }
746 fn close(&mut self) {
747 self.logger
748 .lock()
749 .unwrap()
750 .push(format!("NoCommitDataConn::close {}", self.id));
751 }
752 }
753
754 mod tests_of_data_conn_manager {
755 use super::*;
756 use std::panic::panic_any;
757
758 #[test]
759 fn test_new() {
760 let manager = DataConnManager::new();
761 assert!(manager.vec.is_empty());
762 assert!(manager.index_map.is_empty());
763 }
764
765 #[test]
766 fn test_with_commit_order() {
767 let manager = DataConnManager::with_commit_order(&["bar", "baz", "foo"]);
768 assert_eq!(manager.vec.len(), 3);
769 assert!(manager.vec[0].is_none());
770 assert!(manager.vec[1].is_none());
771 assert!(manager.vec[2].is_none());
772 assert_eq!(manager.index_map.len(), 3);
773 assert_eq!(*manager.index_map.get("foo").unwrap(), 2);
774 assert_eq!(*manager.index_map.get("bar").unwrap(), 0);
775 assert_eq!(*manager.index_map.get("baz").unwrap(), 1);
776 }
777
778 #[test]
779 fn test_new_and_add() {
780 let logger = Arc::new(Mutex::new(Vec::new()));
781
782 let mut manager = DataConnManager::new();
783 assert!(manager.vec.is_empty());
784 assert!(manager.index_map.is_empty());
785
786 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
787 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
788 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
789 let ssnnptr = SendSyncNonNull::new(nnptr);
790 manager.add(ssnnptr);
791 assert_eq!(manager.vec.len(), 1);
792 assert_eq!(manager.index_map.len(), 1);
793 assert_eq!(*manager.index_map.get("foo").unwrap(), 0);
794
795 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
796 let boxed = Box::new(DataConnContainer::new("bar".to_string(), Box::new(conn)));
797 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
798 let ssnnptr = SendSyncNonNull::new(nnptr);
799 manager.add(ssnnptr);
800 assert_eq!(manager.vec.len(), 2);
801 assert_eq!(manager.index_map.len(), 2);
802 assert_eq!(*manager.index_map.get("foo").unwrap(), 0);
803 assert_eq!(*manager.index_map.get("bar").unwrap(), 1);
804 }
805
806 #[test]
807 fn test_new_and_add_when_overlapping_name() {
808 let logger = Arc::new(Mutex::new(Vec::new()));
809
810 let mut manager = DataConnManager::new();
811 assert!(manager.vec.is_empty());
812 assert!(manager.index_map.is_empty());
813
814 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
815 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
816 let nnptr0 = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
817 let ssnnptr = SendSyncNonNull::new(nnptr0);
818 manager.add(ssnnptr);
819 assert_eq!(manager.vec.len(), 1);
820 assert_eq!(manager.index_map.len(), 1);
821 assert_eq!(*manager.index_map.get("foo").unwrap(), 0);
822 assert_eq!(manager.vec[0].clone().unwrap().non_null_ptr, nnptr0);
823
824 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
825 let boxed = Box::new(DataConnContainer::new("foo".to_string(), Box::new(conn)));
826 let nnptr1 = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
827 let ssnnptr = SendSyncNonNull::new(nnptr1);
828 manager.add(ssnnptr);
829 assert_eq!(manager.vec.len(), 1);
830 assert_eq!(manager.index_map.len(), 1);
831 assert_eq!(*manager.index_map.get("foo").unwrap(), 0);
832 assert_eq!(manager.vec[0].clone().unwrap().non_null_ptr, nnptr0);
833 }
834
835 #[test]
836 fn test_with_commit_order_and_add() {
837 let logger = Arc::new(Mutex::new(Vec::new()));
838
839 let mut manager = DataConnManager::with_commit_order(&["bar", "baz", "foo"]);
840 assert_eq!(manager.vec.len(), 3);
841 assert!(manager.vec[0].is_none());
842 assert!(manager.vec[1].is_none());
843 assert!(manager.vec[2].is_none());
844 assert_eq!(manager.index_map.len(), 3);
845 assert_eq!(*manager.index_map.get("foo").unwrap(), 2);
846 assert_eq!(*manager.index_map.get("bar").unwrap(), 0);
847 assert_eq!(*manager.index_map.get("baz").unwrap(), 1);
848
849 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
850 let boxed = Box::new(DataConnContainer::new("foo".to_string(), Box::new(conn)));
851 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
852 let ssnnptr = SendSyncNonNull::new(nnptr);
853 manager.add(ssnnptr);
854 assert_eq!(manager.vec.len(), 3);
855 assert_eq!(manager.index_map.len(), 3);
856 assert_eq!(*manager.index_map.get("foo").unwrap(), 2);
857
858 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
859 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
860 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
861 let ssnnptr = SendSyncNonNull::new(nnptr);
862 manager.add(ssnnptr);
863 assert_eq!(manager.vec.len(), 3);
864 assert_eq!(manager.index_map.len(), 3);
865 assert_eq!(*manager.index_map.get("foo").unwrap(), 2);
866 assert_eq!(*manager.index_map.get("bar").unwrap(), 0);
867
868 let conn = SyncDataConn::new(3, logger.clone(), Fail::Not);
869 let boxed = Box::new(DataConnContainer::new("qux", Box::new(conn)));
870 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
871 let ssnnptr = SendSyncNonNull::new(nnptr);
872 manager.add(ssnnptr);
873 assert_eq!(manager.vec.len(), 4);
874 assert_eq!(manager.index_map.len(), 4);
875 assert_eq!(*manager.index_map.get("foo").unwrap(), 2);
876 assert_eq!(*manager.index_map.get("bar").unwrap(), 0);
877 assert_eq!(*manager.index_map.get("qux").unwrap(), 3);
878 }
879
880 #[test]
881 fn test_with_commit_order_and_add_when_overlapping_name() {
882 let logger = Arc::new(Mutex::new(Vec::new()));
883
884 let mut manager = DataConnManager::with_commit_order(&["bar", "baz", "foo"]);
885 assert_eq!(manager.vec.len(), 3);
886 assert!(manager.vec[0].is_none());
887 assert!(manager.vec[1].is_none());
888 assert!(manager.vec[2].is_none());
889 assert_eq!(manager.index_map.len(), 3);
890
891 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
892 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
893 let nnptr0 = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
894 let ssnnptr = SendSyncNonNull::new(nnptr0);
895 manager.add(ssnnptr);
896 assert_eq!(manager.vec.len(), 3);
897 assert_eq!(manager.index_map.len(), 3);
898 assert_eq!(*manager.index_map.get("foo").unwrap(), 2);
899 assert_eq!(manager.vec[2].clone().unwrap().non_null_ptr, nnptr0);
900
901 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
902 let boxed = Box::new(DataConnContainer::new("foo".to_string(), Box::new(conn)));
903 let nnptr1 = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
904 let ssnnptr = SendSyncNonNull::new(nnptr1);
905 manager.add(ssnnptr);
906 assert_eq!(manager.vec.len(), 3);
907 assert_eq!(manager.index_map.len(), 3);
908 assert_eq!(*manager.index_map.get("foo").unwrap(), 2);
909 assert_eq!(manager.vec[2].clone().unwrap().non_null_ptr, nnptr0);
910 }
911
912 #[test]
913 fn test_find_by_name_but_none() {
914 let manager = DataConnManager::new();
915 assert!(manager.find_by_name("foo").is_none());
916 assert!(manager.find_by_name("bar").is_none());
917 }
918
919 #[test]
920 fn test_find_by_name_and_found() {
921 let logger = Arc::new(Mutex::new(Vec::new()));
922
923 let mut manager = DataConnManager::new();
924
925 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
926 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
927 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
928 let ssnnptr = SendSyncNonNull::new(nnptr);
929 manager.add(ssnnptr);
930
931 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
932 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
933 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
934 let ssnnptr = SendSyncNonNull::new(nnptr);
935 manager.add(ssnnptr);
936
937 if let Some(ssnnptr) = manager.find_by_name("foo") {
938 let name = unsafe { (*ssnnptr.non_null_ptr.as_ptr()).name.clone() };
939 assert_eq!(name.as_ref(), "foo");
940 } else {
941 panic!();
942 }
943
944 if let Some(ssnnptr) = manager.find_by_name("bar") {
945 let name = unsafe { (*ssnnptr.non_null_ptr.as_ptr()).name.clone() };
946 assert_eq!(name.as_ref(), "bar");
947 } else {
948 panic!();
949 }
950 }
951
952 #[test]
953 fn test_find_by_name_of_ordered_dataconn() {
954 let logger = Arc::new(Mutex::new(Vec::new()));
955
956 let mut manager = DataConnManager::with_commit_order(&["baz", "qux", "foo"]);
957
958 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
959 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
960 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
961 let ssnnptr = SendSyncNonNull::new(nnptr);
962 manager.add(ssnnptr);
963
964 let conn = SyncDataConn::new(2, logger.clone(), Fail::Not);
965 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
966 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
967 let ssnnptr = SendSyncNonNull::new(nnptr);
968 manager.add(ssnnptr);
969
970 let conn = SyncDataConn::new(3, logger.clone(), Fail::Not);
971 let boxed = Box::new(DataConnContainer::new("baz", Box::new(conn)));
972 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
973 let ssnnptr = SendSyncNonNull::new(nnptr);
974 manager.add(ssnnptr);
975
976 if let Some(ssnnptr) = manager.find_by_name("foo") {
977 let name = unsafe { (*ssnnptr.non_null_ptr.as_ptr()).name.clone() };
978 assert_eq!(name.as_ref(), "foo");
979 } else {
980 panic!();
981 }
982
983 if let Some(ssnnptr) = manager.find_by_name("bar") {
984 let name = unsafe { (*ssnnptr.non_null_ptr.as_ptr()).name.clone() };
985 assert_eq!(name.as_ref(), "bar");
986 } else {
987 panic!();
988 }
989
990 if let Some(ssnnptr) = manager.find_by_name("baz") {
991 let name = unsafe { (*ssnnptr.non_null_ptr.as_ptr()).name.clone() };
992 assert_eq!(name.as_ref(), "baz");
993 } else {
994 panic!();
995 }
996
997 assert!(manager.find_by_name("qux").is_none());
998 }
999
1000 #[test]
1001 fn test_to_typed_ptr() {
1002 let logger = Arc::new(Mutex::new(Vec::new()));
1003
1004 let mut manager = DataConnManager::new();
1005
1006 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
1007 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1008 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1009 let ssnnptr = SendSyncNonNull::new(nnptr);
1010 manager.add(ssnnptr);
1011
1012 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
1013 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1014 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1015 let ssnnptr = SendSyncNonNull::new(nnptr);
1016 manager.add(ssnnptr);
1017
1018 let ssnnptr = manager.find_by_name("foo").unwrap();
1019 if let Ok(typed_ssnnptr) = DataConnManager::to_typed_ptr::<SyncDataConn>(&ssnnptr) {
1020 assert_eq!(any::type_name_of_val(&typed_ssnnptr), "*mut sabi::DataConnContainer<sabi::data_conn::tests_of_data_conn::SyncDataConn>");
1021 assert_eq!(unsafe { (*typed_ssnnptr).name.clone() }, "foo".into());
1022 } else {
1023 panic!();
1024 }
1025
1026 let ssnnptr = manager.find_by_name("bar").unwrap();
1027 if let Ok(typed_ssnnptr) = DataConnManager::to_typed_ptr::<AsyncDataConn>(&ssnnptr) {
1028 assert_eq!(any::type_name_of_val(&typed_ssnnptr), "*mut sabi::DataConnContainer<sabi::data_conn::tests_of_data_conn::AsyncDataConn>");
1029 assert_eq!(unsafe { (*typed_ssnnptr).name.clone() }, "bar".into());
1030 } else {
1031 panic!();
1032 }
1033 }
1034
1035 #[test]
1036 fn test_to_typed_ptr_but_fail() {
1037 let logger = Arc::new(Mutex::new(Vec::new()));
1038
1039 let mut manager = DataConnManager::new();
1040
1041 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
1042 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1043 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1044 let ssnnptr = SendSyncNonNull::new(nnptr);
1045 manager.add(ssnnptr);
1046
1047 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
1048 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1049 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1050 let ssnnptr = SendSyncNonNull::new(nnptr);
1051 manager.add(ssnnptr);
1052
1053 let ssnnptr = manager.find_by_name("foo").unwrap();
1054 if let Err(err) = DataConnManager::to_typed_ptr::<AsyncDataConn>(&ssnnptr) {
1055 match err.reason::<DataConnError>() {
1056 Ok(DataConnError::FailToCastDataConn { name, target_type }) => {
1057 assert_eq!(name.as_ref(), "foo");
1058 assert_eq!(
1059 *target_type,
1060 "sabi::data_conn::tests_of_data_conn::AsyncDataConn"
1061 );
1062 }
1063 _ => panic!(),
1064 }
1065 } else {
1066 panic!();
1067 }
1068
1069 let ssnnptr = manager.find_by_name("bar").unwrap();
1070 if let Err(err) = DataConnManager::to_typed_ptr::<SyncDataConn>(&ssnnptr) {
1071 match err.reason::<DataConnError>() {
1072 Ok(DataConnError::FailToCastDataConn { name, target_type }) => {
1073 assert_eq!(name.as_ref(), "bar");
1074 assert_eq!(
1075 *target_type,
1076 "sabi::data_conn::tests_of_data_conn::SyncDataConn"
1077 );
1078 }
1079 _ => panic!(),
1080 }
1081 } else {
1082 panic!();
1083 }
1084 }
1085
1086 #[test]
1087 fn test_new_failure_reports() {
1088 let logger = Arc::new(Mutex::new(Vec::new()));
1089
1090 let mut manager = DataConnManager::new();
1091
1092 let vec = manager.new_failure_reports();
1093 assert_eq!(vec.len(), 0);
1094
1095 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
1096 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1097 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1098 let ssnnptr = SendSyncNonNull::new(nnptr);
1099 manager.add(ssnnptr);
1100
1101 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
1102 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1103 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1104 let ssnnptr = SendSyncNonNull::new(nnptr);
1105 manager.add(ssnnptr);
1106
1107 let vec = manager.new_failure_reports();
1108 assert_eq!(vec.len(), 2);
1109
1110 let report = &vec[0];
1111 assert_eq!(report.data_conn_name, "foo".into());
1112 assert_eq!(
1113 report.data_conn_type,
1114 "sabi::data_conn::tests_of_data_conn::SyncDataConn"
1115 );
1116
1117 let report = &vec[1];
1118 assert_eq!(report.data_conn_name, "bar".into());
1119 assert_eq!(
1120 report.data_conn_type,
1121 "sabi::data_conn::tests_of_data_conn::AsyncDataConn"
1122 );
1123 }
1124
1125 #[test]
1126 fn test_commit_and_rollback_ok() {
1127 let logger = Arc::new(Mutex::new(Vec::new()));
1128
1129 {
1130 let mut manager = DataConnManager::new();
1131
1132 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
1133 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1134 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1135 let ssnnptr = SendSyncNonNull::new(nnptr);
1136 manager.add(ssnnptr);
1137
1138 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
1139 let boxed = Box::new(DataConnContainer::new("bar".to_string(), Box::new(conn)));
1140 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1141 let ssnnptr = SendSyncNonNull::new(nnptr);
1142 manager.add(ssnnptr);
1143
1144 let mut reports = manager.new_failure_reports();
1145 assert!(manager.commit(&mut reports).is_ok());
1146 manager.rollback(reports);
1147 }
1148
1149 assert_eq!(
1150 *logger.lock().unwrap(),
1151 &[
1152 "SyncDataConn::new 1",
1153 "AsyncDataConn::new 2",
1154 "SyncDataConn::pre_commit 1",
1155 "AsyncDataConn::pre_commit 2",
1156 "SyncDataConn::commit 1",
1157 "AsyncDataConn::commit 2",
1158 "SyncDataConn::post_commit 1",
1159 "AsyncDataConn::post_commit 2",
1160 "SyncDataConn::on_txn_failure 1",
1161 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }]",
1162 "AsyncDataConn::on_txn_failure 2",
1163 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }]",
1164 "AsyncDataConn::close 2",
1165 "AsyncDataConn::drop 2",
1166 "SyncDataConn::close 1",
1167 "SyncDataConn::drop 1",
1168 ]
1169 );
1170 }
1171
1172 #[test]
1173 fn test_commit_with_order_and_rollback_ok() {
1174 let logger = Arc::new(Mutex::new(Vec::new()));
1175
1176 {
1177 let mut manager = DataConnManager::with_commit_order(&["bar", "baz", "foo"]);
1178
1179 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
1180 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1181 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1182 let ssnnptr = SendSyncNonNull::new(nnptr);
1183 manager.add(ssnnptr);
1184
1185 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
1186 let boxed = Box::new(DataConnContainer::new("bar".to_string(), Box::new(conn)));
1187 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1188 let ssnnptr = SendSyncNonNull::new(nnptr);
1189 manager.add(ssnnptr);
1190
1191 let conn = SyncDataConn::new(3, logger.clone(), Fail::Not);
1192 let boxed = Box::new(DataConnContainer::new("qux", Box::new(conn)));
1193 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1194 let ssnnptr = SendSyncNonNull::new(nnptr);
1195 manager.add(ssnnptr);
1196
1197 let mut reports = manager.new_failure_reports();
1198 assert!(manager.commit(&mut reports).is_ok());
1199 manager.rollback(reports);
1200 }
1201
1202 assert_eq!(
1203 *logger.lock().unwrap(),
1204 &[
1205 "SyncDataConn::new 1",
1206 "AsyncDataConn::new 2",
1207 "SyncDataConn::new 3",
1208 "SyncDataConn::pre_commit 1",
1209 "SyncDataConn::pre_commit 3",
1210 "AsyncDataConn::pre_commit 2", "SyncDataConn::commit 1",
1212 "SyncDataConn::commit 3",
1213 "AsyncDataConn::commit 2", "SyncDataConn::post_commit 1",
1215 "SyncDataConn::post_commit 3",
1216 "AsyncDataConn::post_commit 2", "SyncDataConn::on_txn_failure 1",
1218 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"qux\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }]",
1219 "SyncDataConn::on_txn_failure 3",
1220 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"qux\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }]",
1221 "AsyncDataConn::on_txn_failure 2",
1222 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"qux\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }]",
1223 "SyncDataConn::close 3",
1224 "SyncDataConn::drop 3",
1225 "SyncDataConn::close 1",
1226 "SyncDataConn::drop 1",
1227 "AsyncDataConn::close 2",
1228 "AsyncDataConn::drop 2",
1229 ]
1230 );
1231 }
1232
1233 #[test]
1234 fn test_commit_and_rollback_but_fail_first_sync_pre_commit() {
1235 let logger = Arc::new(Mutex::new(Vec::new()));
1236
1237 {
1238 let mut manager = DataConnManager::new();
1239
1240 let conn = SyncDataConn::new(1, logger.clone(), Fail::PreCommit);
1241 let boxed = Box::new(DataConnContainer::new("foo".to_string(), Box::new(conn)));
1242 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1243 let ssnnptr = SendSyncNonNull::new(nnptr);
1244 manager.add(ssnnptr);
1245
1246 let conn = AsyncDataConn::new(2, logger.clone(), Fail::PreCommit);
1247 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1248 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1249 let ssnnptr = SendSyncNonNull::new(nnptr);
1250 manager.add(ssnnptr);
1251
1252 let mut reports = manager.new_failure_reports();
1253
1254 if let Err(e) = manager.commit(&mut reports) {
1255 match e.reason::<DataConnError>() {
1256 Ok(DataConnError::FailToPreCommitDataConn { errors }) => {
1257 assert_eq!(errors.len(), 1);
1258 assert_eq!(errors[0].index, 0);
1259 assert_eq!(errors[0].name, "foo".into());
1260 assert_eq!(errors[0].err.reason::<String>().unwrap(), "zzz");
1261 }
1262 _ => panic!(),
1263 }
1264 } else {
1265 panic!();
1266 }
1267
1268 manager.rollback(reports);
1269 }
1270
1271 #[cfg(unix)]
1272 assert_eq!(
1273 *logger.lock().unwrap(),
1274 &[
1275 "SyncDataConn::new 1",
1276 "AsyncDataConn::new 2",
1277 "SyncDataConn::pre_commit 1 failed",
1278 "SyncDataConn::rollback 1",
1279 "AsyncDataConn::rollback 2",
1280 "SyncDataConn::on_txn_failure 1",
1281 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"zzz\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 62),
1282 "AsyncDataConn::on_txn_failure 2",
1283 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"zzz\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 62),
1284 "AsyncDataConn::close 2",
1285 "AsyncDataConn::drop 2",
1286 "SyncDataConn::close 1",
1287 "SyncDataConn::drop 1",
1288 ]
1289 );
1290 #[cfg(windows)]
1291 assert_eq!(
1292 *logger.lock().unwrap(),
1293 &[
1294 "SyncDataConn::new 1",
1295 "AsyncDataConn::new 2",
1296 "SyncDataConn::pre_commit 1 failed",
1297 "SyncDataConn::rollback 1",
1298 "AsyncDataConn::rollback 2",
1299 "SyncDataConn::on_txn_failure 1",
1300 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"zzz\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 62),
1301 "AsyncDataConn::on_txn_failure 2",
1302 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"zzz\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 62),
1303 "AsyncDataConn::close 2",
1304 "AsyncDataConn::drop 2",
1305 "SyncDataConn::close 1",
1306 "SyncDataConn::drop 1",
1307 ]
1308 );
1309 }
1310
1311 #[test]
1312 fn test_commit_and_rollback_but_fail_first_async_pre_commit() {
1313 let logger = Arc::new(Mutex::new(Vec::new()));
1314
1315 {
1316 let mut manager = DataConnManager::new();
1317
1318 let conn = AsyncDataConn::new(2, logger.clone(), Fail::PreCommit);
1319 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1320 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1321 let ssnnptr = SendSyncNonNull::new(nnptr);
1322 manager.add(ssnnptr);
1323
1324 let conn = SyncDataConn::new(1, logger.clone(), Fail::PreCommit);
1325 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1326 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1327 let ssnnptr = SendSyncNonNull::new(nnptr);
1328 manager.add(ssnnptr);
1329
1330 let mut reports = manager.new_failure_reports();
1331
1332 if let Err(e) = manager.commit(&mut reports) {
1333 match e.reason::<DataConnError>() {
1334 Ok(DataConnError::FailToPreCommitDataConn { errors }) => {
1335 assert_eq!(errors.len(), 2);
1336 assert_eq!(errors[0].index, 1);
1337 assert_eq!(errors[0].name, "foo".into());
1338 assert_eq!(errors[0].err.reason::<String>().unwrap(), "zzz");
1339 assert_eq!(errors[1].index, 0);
1340 assert_eq!(errors[1].name, "bar".into());
1341 assert_eq!(errors[1].err.reason::<String>().unwrap(), "yyy");
1342 }
1343 _ => panic!(),
1344 }
1345 } else {
1346 panic!();
1347 }
1348
1349 manager.rollback(reports);
1350 }
1351
1352 #[cfg(unix)]
1353 assert_eq!(
1354 *logger.lock().unwrap(),
1355 &[
1356 "AsyncDataConn::new 2",
1357 "SyncDataConn::new 1",
1358 "SyncDataConn::pre_commit 1 failed",
1359 "AsyncDataConn::pre_commit 2 failed",
1360 "SyncDataConn::rollback 1",
1361 "AsyncDataConn::rollback 2",
1362 "SyncDataConn::on_txn_failure 1",
1363 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"yyy\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"zzz\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 181, BASE_LINE + 62),
1364 "AsyncDataConn::on_txn_failure 2",
1365 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"yyy\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"zzz\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 181, BASE_LINE + 62),
1366 "SyncDataConn::close 1",
1367 "SyncDataConn::drop 1",
1368 "AsyncDataConn::close 2",
1369 "AsyncDataConn::drop 2",
1370 ]
1371 );
1372 #[cfg(windows)]
1373 assert_eq!(
1374 *logger.lock().unwrap(),
1375 &[
1376 "AsyncDataConn::new 2",
1377 "SyncDataConn::new 1",
1378 "SyncDataConn::pre_commit 1 failed",
1379 "AsyncDataConn::pre_commit 2 failed",
1380 "SyncDataConn::rollback 1",
1381 "AsyncDataConn::rollback 2",
1382 "SyncDataConn::on_txn_failure 1",
1383 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"yyy\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"zzz\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 181, BASE_LINE + 62),
1384 "AsyncDataConn::on_txn_failure 2",
1385 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"yyy\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"zzz\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 181, BASE_LINE + 62),
1386 "SyncDataConn::close 1",
1387 "SyncDataConn::drop 1",
1388 "AsyncDataConn::close 2",
1389 "AsyncDataConn::drop 2",
1390 ]
1391 );
1392 }
1393
1394 #[test]
1395 fn test_commit_and_rollback_but_fail_second_pre_commit() {
1396 let logger = Arc::new(Mutex::new(Vec::new()));
1397
1398 {
1399 let mut manager = DataConnManager::new();
1400
1401 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
1402 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1403 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1404 let ssnnptr = SendSyncNonNull::new(nnptr);
1405 manager.add(ssnnptr);
1406
1407 let conn = AsyncDataConn::new(2, logger.clone(), Fail::PreCommit);
1408 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1409 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1410 let ssnnptr = SendSyncNonNull::new(nnptr);
1411 manager.add(ssnnptr);
1412
1413 let mut reports = manager.new_failure_reports();
1414
1415 if let Err(e) = manager.commit(&mut reports) {
1416 match e.reason::<DataConnError>() {
1417 Ok(DataConnError::FailToPreCommitDataConn { errors }) => {
1418 assert_eq!(errors.len(), 1);
1419 assert_eq!(errors[0].index, 1);
1420 assert_eq!(errors[0].name, "bar".into());
1421 assert_eq!(errors[0].err.reason::<String>().unwrap(), "yyy");
1422 }
1423 _ => panic!(),
1424 }
1425 } else {
1426 panic!();
1427 }
1428
1429 manager.rollback(reports);
1430 }
1431
1432 #[cfg(unix)]
1433 assert_eq!(
1434 *logger.lock().unwrap(),
1435 &[
1436 "SyncDataConn::new 1",
1437 "AsyncDataConn::new 2",
1438 "SyncDataConn::pre_commit 1",
1439 "AsyncDataConn::pre_commit 2 failed",
1440 "SyncDataConn::rollback 1",
1441 "AsyncDataConn::rollback 2",
1442 "SyncDataConn::on_txn_failure 1",
1443 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"yyy\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 181),
1444 "AsyncDataConn::on_txn_failure 2",
1445 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"yyy\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 181),
1446 "AsyncDataConn::close 2",
1447 "AsyncDataConn::drop 2",
1448 "SyncDataConn::close 1",
1449 "SyncDataConn::drop 1",
1450 ]
1451 );
1452 #[cfg(windows)]
1453 assert_eq!(
1454 *logger.lock().unwrap(),
1455 &[
1456 "SyncDataConn::new 1",
1457 "AsyncDataConn::new 2",
1458 "SyncDataConn::pre_commit 1",
1459 "AsyncDataConn::pre_commit 2 failed",
1460 "SyncDataConn::rollback 1",
1461 "AsyncDataConn::rollback 2",
1462 "SyncDataConn::on_txn_failure 1",
1463 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"yyy\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 181),
1464 "AsyncDataConn::on_txn_failure 2",
1465 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: LogicFailure(errs::Err {{ reason = alloc::string::String \"yyy\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 181),
1466 "AsyncDataConn::close 2",
1467 "AsyncDataConn::drop 2",
1468 "SyncDataConn::close 1",
1469 "SyncDataConn::drop 1",
1470 ]
1471 );
1472 }
1473
1474 #[test]
1475 fn test_commit_and_rollback_but_fail_first_sync_commit() {
1476 let logger = Arc::new(Mutex::new(Vec::new()));
1477
1478 {
1479 let mut manager = DataConnManager::new();
1480
1481 let conn = SyncDataConn::new(1, logger.clone(), Fail::Commit);
1482 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1483 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1484 let ssnnptr = SendSyncNonNull::new(nnptr);
1485 manager.add(ssnnptr);
1486
1487 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Commit);
1488 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1489 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1490 let ssnnptr = SendSyncNonNull::new(nnptr);
1491 manager.add(ssnnptr);
1492
1493 let mut reports = manager.new_failure_reports();
1494
1495 if let Err(e) = manager.commit(&mut reports) {
1496 match e.reason::<DataConnError>() {
1497 Ok(DataConnError::FailToCommitDataConn { errors }) => {
1498 assert_eq!(errors.len(), 1);
1499 assert_eq!(errors[0].index, 0);
1500 assert_eq!(errors[0].name, "foo".into());
1501 assert_eq!(errors[0].err.reason::<String>().unwrap(), "ZZZ");
1502 }
1503 _ => panic!(),
1504 }
1505 } else {
1506 panic!();
1507 }
1508
1509 manager.rollback(reports);
1510 }
1511
1512 #[cfg(unix)]
1513 assert_eq!(
1514 *logger.lock().unwrap(),
1515 &[
1516 "SyncDataConn::new 1",
1517 "AsyncDataConn::new 2",
1518 "SyncDataConn::pre_commit 1",
1519 "AsyncDataConn::pre_commit 2",
1520 "SyncDataConn::commit 1 failed",
1521 "SyncDataConn::rollback 1",
1522 "AsyncDataConn::rollback 2",
1523 "SyncDataConn::on_txn_failure 1",
1524 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"ZZZ\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 47),
1525 "AsyncDataConn::on_txn_failure 2",
1526 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"ZZZ\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 47),
1527 "AsyncDataConn::close 2",
1528 "AsyncDataConn::drop 2",
1529 "SyncDataConn::close 1",
1530 "SyncDataConn::drop 1",
1531 ]
1532 );
1533 #[cfg(windows)]
1534 assert_eq!(
1535 *logger.lock().unwrap(),
1536 &[
1537 "SyncDataConn::new 1",
1538 "AsyncDataConn::new 2",
1539 "SyncDataConn::pre_commit 1",
1540 "AsyncDataConn::pre_commit 2",
1541 "SyncDataConn::commit 1 failed",
1542 "SyncDataConn::rollback 1",
1543 "AsyncDataConn::rollback 2",
1544 "SyncDataConn::on_txn_failure 1",
1545 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"ZZZ\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 47),
1546 "AsyncDataConn::on_txn_failure 2",
1547 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"ZZZ\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 47),
1548 "AsyncDataConn::close 2",
1549 "AsyncDataConn::drop 2",
1550 "SyncDataConn::close 1",
1551 "SyncDataConn::drop 1",
1552 ]
1553 );
1554 }
1555
1556 #[test]
1557 fn test_commit_and_rollback_but_fail_first_async_commit() {
1558 let logger = Arc::new(Mutex::new(Vec::new()));
1559
1560 {
1561 let mut manager = DataConnManager::new();
1562
1563 let conn = AsyncDataConn::new(1, logger.clone(), Fail::Commit);
1564 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1565 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1566 let ssnnptr = SendSyncNonNull::new(nnptr);
1567 manager.add(ssnnptr);
1568
1569 let conn = SyncDataConn::new(2, logger.clone(), Fail::Not);
1570 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1571 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1572 let ssnnptr = SendSyncNonNull::new(nnptr);
1573 manager.add(ssnnptr);
1574
1575 let mut reports = manager.new_failure_reports();
1576
1577 if let Err(e) = manager.commit(&mut reports) {
1578 match e.reason::<DataConnError>() {
1579 Ok(DataConnError::FailToCommitDataConn { errors }) => {
1580 assert_eq!(errors.len(), 1);
1581 assert_eq!(errors[0].index, 0);
1582 assert_eq!(errors[0].name, "foo".into());
1583 assert_eq!(errors[0].err.reason::<String>().unwrap(), "YYY");
1584 }
1585 _ => panic!(),
1586 }
1587 } else {
1588 panic!();
1589 }
1590
1591 manager.rollback(reports);
1592 }
1593
1594 #[cfg(unix)]
1595 assert_eq!(
1596 *logger.lock().unwrap(),
1597 &[
1598 "AsyncDataConn::new 1",
1599 "SyncDataConn::new 2",
1600 "SyncDataConn::pre_commit 2",
1601 "AsyncDataConn::pre_commit 1",
1602 "SyncDataConn::commit 2",
1603 "AsyncDataConn::commit 1 failed",
1604 "AsyncDataConn::rollback 1",
1605 "SyncDataConn::on_txn_failure 2",
1606 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}]", BASE_LINE + 158),
1607 "AsyncDataConn::on_txn_failure 1",
1608 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}]", BASE_LINE + 158),
1609 "SyncDataConn::close 2",
1610 "SyncDataConn::drop 2",
1611 "AsyncDataConn::close 1",
1612 "AsyncDataConn::drop 1",
1613 ]
1614 );
1615 #[cfg(windows)]
1616 assert_eq!(
1617 *logger.lock().unwrap(),
1618 &[
1619 "AsyncDataConn::new 1",
1620 "SyncDataConn::new 2",
1621 "SyncDataConn::pre_commit 2",
1622 "AsyncDataConn::pre_commit 1",
1623 "SyncDataConn::commit 2",
1624 "AsyncDataConn::commit 1 failed",
1625 "AsyncDataConn::rollback 1",
1626 "SyncDataConn::on_txn_failure 2",
1627 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}]", BASE_LINE + 158),
1628 "AsyncDataConn::on_txn_failure 1",
1629 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}]", BASE_LINE + 158),
1630 "SyncDataConn::close 2",
1631 "SyncDataConn::drop 2",
1632 "AsyncDataConn::close 1",
1633 "AsyncDataConn::drop 1",
1634 ]
1635 );
1636 }
1637
1638 #[test]
1639 fn test_commit_and_rollback_but_fail_second_commit() {
1640 let logger = Arc::new(Mutex::new(Vec::new()));
1641
1642 {
1643 let mut manager = DataConnManager::new();
1644
1645 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
1646 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1647 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1648 let ssnnptr = SendSyncNonNull::new(nnptr);
1649 manager.add(ssnnptr);
1650
1651 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Commit);
1652 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1653 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1654 let ssnnptr = SendSyncNonNull::new(nnptr);
1655 manager.add(ssnnptr);
1656
1657 let mut reports = manager.new_failure_reports();
1658
1659 if let Err(e) = manager.commit(&mut reports) {
1660 match e.reason::<DataConnError>() {
1661 Ok(DataConnError::FailToCommitDataConn { errors }) => {
1662 assert_eq!(errors.len(), 1);
1663 assert_eq!(errors[0].index, 1);
1664 assert_eq!(errors[0].name, "bar".into());
1665 assert_eq!(errors[0].err.reason::<String>().unwrap(), "YYY");
1666 }
1667 _ => panic!(),
1668 }
1669 } else {
1670 panic!();
1671 }
1672
1673 manager.rollback(reports);
1674 }
1675
1676 #[cfg(unix)]
1677 assert_eq!(
1678 *logger.lock().unwrap(),
1679 &[
1680 "SyncDataConn::new 1",
1681 "AsyncDataConn::new 2",
1682 "SyncDataConn::pre_commit 1",
1683 "AsyncDataConn::pre_commit 2",
1684 "SyncDataConn::commit 1",
1685 "AsyncDataConn::commit 2 failed",
1686 "AsyncDataConn::rollback 2",
1687 "SyncDataConn::on_txn_failure 1",
1688 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
1689 "AsyncDataConn::on_txn_failure 2",
1690 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
1691 "AsyncDataConn::close 2",
1692 "AsyncDataConn::drop 2",
1693 "SyncDataConn::close 1",
1694 "SyncDataConn::drop 1",
1695 ]
1696 );
1697 #[cfg(windows)]
1698 assert_eq!(
1699 *logger.lock().unwrap(),
1700 &[
1701 "SyncDataConn::new 1",
1702 "AsyncDataConn::new 2",
1703 "SyncDataConn::pre_commit 1",
1704 "AsyncDataConn::pre_commit 2",
1705 "SyncDataConn::commit 1",
1706 "AsyncDataConn::commit 2 failed",
1707 "AsyncDataConn::rollback 2",
1708 "SyncDataConn::on_txn_failure 1",
1709 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
1710 "AsyncDataConn::on_txn_failure 2",
1711 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
1712 "AsyncDataConn::close 2",
1713 "AsyncDataConn::drop 2",
1714 "SyncDataConn::close 1",
1715 "SyncDataConn::drop 1",
1716 ]
1717 );
1718 }
1719
1720 #[test]
1721 fn test_commit_and_rollback_but_fail_first_sync_post_commit() {
1722 let logger = Arc::new(Mutex::new(Vec::new()));
1723
1724 {
1725 let mut manager = DataConnManager::new();
1726
1727 let conn = SyncDataConn::new(1, logger.clone(), Fail::PostCommit);
1728 let boxed = Box::new(DataConnContainer::new("foo".to_string(), Box::new(conn)));
1729 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1730 let ssnnptr = SendSyncNonNull::new(nnptr);
1731 manager.add(ssnnptr);
1732
1733 let conn = AsyncDataConn::new(2, logger.clone(), Fail::PostCommit);
1734 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1735 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1736 let ssnnptr = SendSyncNonNull::new(nnptr);
1737 manager.add(ssnnptr);
1738
1739 let mut reports = manager.new_failure_reports();
1740
1741 if let Err(e) = manager.commit(&mut reports) {
1742 match e.reason::<DataConnError>() {
1743 Ok(DataConnError::FailToPostCommitDataConn { errors }) => {
1744 assert_eq!(errors.len(), 2);
1745 assert_eq!(errors[0].index, 0);
1746 assert_eq!(errors[0].name, "foo".into());
1747 assert_eq!(errors[0].err.reason::<String>().unwrap(), "!!!");
1748 assert_eq!(errors[1].index, 1);
1749 assert_eq!(errors[1].name, "bar".into());
1750 assert_eq!(errors[1].err.reason::<String>().unwrap(), "!!!");
1751 }
1752 _ => panic!(),
1753 }
1754 } else {
1755 panic!();
1756 }
1757
1758 manager.rollback(reports);
1759 }
1760
1761 #[cfg(unix)]
1762 assert_eq!(
1763 *logger.lock().unwrap(),
1764 &[
1765 "SyncDataConn::new 1",
1766 "AsyncDataConn::new 2",
1767 "SyncDataConn::pre_commit 1",
1768 "AsyncDataConn::pre_commit 2",
1769 "SyncDataConn::commit 1",
1770 "AsyncDataConn::commit 2",
1771 "SyncDataConn::post_commit 1 failed",
1772 "AsyncDataConn::post_commit 2 failed",
1773 "SyncDataConn::on_txn_failure 1",
1774 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 79, BASE_LINE + 205),
1775 "AsyncDataConn::on_txn_failure 2",
1776 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 79, BASE_LINE + 205),
1777 "AsyncDataConn::close 2",
1778 "AsyncDataConn::drop 2",
1779 "SyncDataConn::close 1",
1780 "SyncDataConn::drop 1",
1781 ]
1782 );
1783 #[cfg(windows)]
1784 assert_eq!(
1785 *logger.lock().unwrap(),
1786 &[
1787 "SyncDataConn::new 1",
1788 "AsyncDataConn::new 2",
1789 "SyncDataConn::pre_commit 1",
1790 "AsyncDataConn::pre_commit 2",
1791 "SyncDataConn::commit 1",
1792 "AsyncDataConn::commit 2",
1793 "SyncDataConn::post_commit 1 failed",
1794 "AsyncDataConn::post_commit 2 failed",
1795 "SyncDataConn::on_txn_failure 1",
1796 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 79, BASE_LINE + 205),
1797 "AsyncDataConn::on_txn_failure 2",
1798 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 79, BASE_LINE + 205),
1799 "AsyncDataConn::close 2",
1800 "AsyncDataConn::drop 2",
1801 "SyncDataConn::close 1",
1802 "SyncDataConn::drop 1",
1803 ]
1804 );
1805 }
1806
1807 #[test]
1808 fn test_commit_and_rollback_but_fail_first_async_post_commit() {
1809 let logger = Arc::new(Mutex::new(Vec::new()));
1810
1811 {
1812 let mut manager = DataConnManager::new();
1813
1814 let conn = AsyncDataConn::new(2, logger.clone(), Fail::PostCommit);
1815 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1816 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1817 let ssnnptr = SendSyncNonNull::new(nnptr);
1818 manager.add(ssnnptr);
1819
1820 let conn = SyncDataConn::new(1, logger.clone(), Fail::PostCommit);
1821 let boxed = Box::new(DataConnContainer::new("foo".to_string(), Box::new(conn)));
1822 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1823 let ssnnptr = SendSyncNonNull::new(nnptr);
1824 manager.add(ssnnptr);
1825
1826 let mut reports = manager.new_failure_reports();
1827
1828 if let Err(e) = manager.commit(&mut reports) {
1829 match e.reason::<DataConnError>() {
1830 Ok(DataConnError::FailToPostCommitDataConn { errors }) => {
1831 assert_eq!(errors.len(), 2);
1832 assert_eq!(errors[0].index, 1);
1833 assert_eq!(errors[0].name, "foo".into());
1834 assert_eq!(errors[0].err.reason::<String>().unwrap(), "!!!");
1835 assert_eq!(errors[1].index, 0);
1836 assert_eq!(errors[1].name, "bar".into());
1837 assert_eq!(errors[1].err.reason::<String>().unwrap(), "!!!");
1838 }
1839 _ => panic!(),
1840 }
1841 } else {
1842 panic!();
1843 }
1844
1845 manager.rollback(reports);
1846 }
1847
1848 #[cfg(unix)]
1849 assert_eq!(
1850 *logger.lock().unwrap(),
1851 &[
1852 "AsyncDataConn::new 2",
1853 "SyncDataConn::new 1",
1854 "SyncDataConn::pre_commit 1",
1855 "AsyncDataConn::pre_commit 2",
1856 "SyncDataConn::commit 1",
1857 "AsyncDataConn::commit 2",
1858 "SyncDataConn::post_commit 1 failed",
1859 "AsyncDataConn::post_commit 2 failed",
1860 "SyncDataConn::on_txn_failure 1",
1861 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 205, BASE_LINE + 79),
1862 "AsyncDataConn::on_txn_failure 2",
1863 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 205, BASE_LINE + 79),
1864 "SyncDataConn::close 1",
1865 "SyncDataConn::drop 1",
1866 "AsyncDataConn::close 2",
1867 "AsyncDataConn::drop 2",
1868 ]
1869 );
1870 #[cfg(windows)]
1871 assert_eq!(
1872 *logger.lock().unwrap(),
1873 &[
1874 "AsyncDataConn::new 2",
1875 "SyncDataConn::new 1",
1876 "SyncDataConn::pre_commit 1",
1877 "AsyncDataConn::pre_commit 2",
1878 "SyncDataConn::commit 1",
1879 "AsyncDataConn::commit 2",
1880 "SyncDataConn::post_commit 1 failed",
1881 "AsyncDataConn::post_commit 2 failed",
1882 "SyncDataConn::on_txn_failure 1",
1883 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 205, BASE_LINE + 79),
1884 "AsyncDataConn::on_txn_failure 2",
1885 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 205, BASE_LINE + 79),
1886 "SyncDataConn::close 1",
1887 "SyncDataConn::drop 1",
1888 "AsyncDataConn::close 2",
1889 "AsyncDataConn::drop 2",
1890 ]
1891 );
1892 }
1893
1894 #[test]
1895 fn test_commit_and_rollback_but_fail_second_post_commit() {
1896 let logger = Arc::new(Mutex::new(Vec::new()));
1897
1898 {
1899 let mut manager = DataConnManager::new();
1900
1901 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
1902 let boxed = Box::new(DataConnContainer::new("foo".to_string(), Box::new(conn)));
1903 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1904 let ssnnptr = SendSyncNonNull::new(nnptr);
1905 manager.add(ssnnptr);
1906
1907 let conn = AsyncDataConn::new(2, logger.clone(), Fail::PostCommit);
1908 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1909 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1910 let ssnnptr = SendSyncNonNull::new(nnptr);
1911 manager.add(ssnnptr);
1912
1913 let mut reports = manager.new_failure_reports();
1914
1915 if let Err(e) = manager.commit(&mut reports) {
1916 match e.reason::<DataConnError>() {
1917 Ok(DataConnError::FailToPostCommitDataConn { errors }) => {
1918 assert_eq!(errors.len(), 1);
1919 assert_eq!(errors[0].index, 1);
1920 assert_eq!(errors[0].name, "bar".into());
1921 assert_eq!(errors[0].err.reason::<String>().unwrap(), "!!!");
1922 }
1923 _ => panic!(),
1924 }
1925 } else {
1926 panic!();
1927 }
1928
1929 manager.rollback(reports);
1930 }
1931
1932 #[cfg(unix)]
1933 assert_eq!(
1934 *logger.lock().unwrap(),
1935 &[
1936 "SyncDataConn::new 1",
1937 "AsyncDataConn::new 2",
1938 "SyncDataConn::pre_commit 1",
1939 "AsyncDataConn::pre_commit 2",
1940 "SyncDataConn::commit 1",
1941 "AsyncDataConn::commit 2",
1942 "SyncDataConn::post_commit 1",
1943 "AsyncDataConn::post_commit 2 failed",
1944 "SyncDataConn::on_txn_failure 1",
1945 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 205),
1946 "AsyncDataConn::on_txn_failure 2",
1947 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 205),
1948 "AsyncDataConn::close 2",
1949 "AsyncDataConn::drop 2",
1950 "SyncDataConn::close 1",
1951 "SyncDataConn::drop 1",
1952 ]
1953 );
1954 #[cfg(windows)]
1955 assert_eq!(
1956 *logger.lock().unwrap(),
1957 &[
1958 "SyncDataConn::new 1",
1959 "AsyncDataConn::new 2",
1960 "SyncDataConn::pre_commit 1",
1961 "AsyncDataConn::pre_commit 2",
1962 "SyncDataConn::commit 1",
1963 "AsyncDataConn::commit 2",
1964 "SyncDataConn::post_commit 1",
1965 "AsyncDataConn::post_commit 2 failed",
1966 "SyncDataConn::on_txn_failure 1",
1967 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 205),
1968 "AsyncDataConn::on_txn_failure 2",
1969 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err {{ reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByNotRolledBack }}]", BASE_LINE + 205),
1970 "AsyncDataConn::close 2",
1971 "AsyncDataConn::drop 2",
1972 "SyncDataConn::close 1",
1973 "SyncDataConn::drop 1",
1974 ]
1975 );
1976 }
1977
1978 #[test]
1979 fn test_commit_and_rollback_but_fail_second_post_commit_and_contains_no_commit() {
1980 let logger = Arc::new(Mutex::new(Vec::<String>::new()));
1981
1982 {
1983 let mut manager = DataConnManager::new();
1984
1985 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
1986 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
1987 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1988 let ssnnptr = SendSyncNonNull::new(nnptr);
1989 manager.add(ssnnptr);
1990
1991 let conn = AsyncDataConn::new(2, logger.clone(), Fail::PostCommit);
1992 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
1993 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
1994 let ssnnptr = SendSyncNonNull::new(nnptr);
1995 manager.add(ssnnptr);
1996
1997 let conn = NoCommitDataConn::new(3, logger.clone());
1998 let boxed = Box::new(DataConnContainer::new("baz", Box::new(conn)));
1999 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2000 let ssnnptr = SendSyncNonNull::new(nnptr);
2001 manager.add(ssnnptr);
2002
2003 let mut reports = manager.new_failure_reports();
2004
2005 if let Err(e) = manager.commit(&mut reports) {
2006 match e.reason::<DataConnError>() {
2007 Ok(DataConnError::FailToPostCommitDataConn { errors }) => {
2008 assert_eq!(errors.len(), 1);
2009 assert_eq!(errors[0].index, 1);
2010 assert_eq!(errors[0].name, "bar".into());
2011 assert_eq!(errors[0].err.reason::<String>().unwrap(), "!!!");
2012 }
2013 _ => panic_any(e),
2014 }
2015 } else {
2016 panic!();
2017 }
2018
2019 manager.rollback(reports);
2020 }
2021
2022 #[cfg(unix)]
2023 assert_eq!(
2024 &logger.lock().unwrap()[0..24],
2025 &[
2026 "SyncDataConn::new 1",
2027 "AsyncDataConn::new 2",
2028 "NoCommitDataConn::new 3",
2029 "SyncDataConn::pre_commit 1",
2030 "NoCommitDataConn::pre_commit 3",
2031 "AsyncDataConn::pre_commit 2",
2032 "SyncDataConn::commit 1",
2033 "NoCommitDataConn::commit 3",
2034 "AsyncDataConn::commit 2",
2035 "SyncDataConn::post_commit 1",
2036 "NoCommitDataConn::post_commit 3",
2037 "AsyncDataConn::post_commit 2 failed",
2038 "SyncDataConn::on_txn_failure 1",
2039 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err { reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = 634 }), rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"baz\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::NoCommitDataConn\", cause: NoneByUncommitted, rollback: NoneByNotRolledBack }]",
2040 "NoCommitDataConn::on_txn_failure 3",
2041 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err { reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = 634 }), rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"baz\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::NoCommitDataConn\", cause: NoneByUncommitted, rollback: NoneByNotRolledBack }]",
2042 "AsyncDataConn::on_txn_failure 2",
2043 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err { reason = alloc::string::String \"!!!\", file = src/data_conn.rs, line = 634 }), rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"baz\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::NoCommitDataConn\", cause: NoneByUncommitted, rollback: NoneByNotRolledBack }]",
2044 "NoCommitDataConn::close 3",
2045 "NoCommitDataConn::drop 3",
2046 "AsyncDataConn::close 2",
2047 "AsyncDataConn::drop 2",
2048 "SyncDataConn::close 1",
2049 "SyncDataConn::drop 1",
2050 ]
2051 );
2052 #[cfg(windows)]
2053 assert_eq!(
2054 &logger.lock().unwrap()[0..24],
2055 &[
2056 "SyncDataConn::new 1",
2057 "AsyncDataConn::new 2",
2058 "NoCommitDataConn::new 3",
2059 "SyncDataConn::pre_commit 1",
2060 "NoCommitDataConn::pre_commit 3",
2061 "AsyncDataConn::pre_commit 2",
2062 "SyncDataConn::commit 1",
2063 "NoCommitDataConn::commit 3",
2064 "AsyncDataConn::commit 2",
2065 "SyncDataConn::post_commit 1",
2066 "NoCommitDataConn::post_commit 3",
2067 "AsyncDataConn::post_commit 2 failed",
2068 "SyncDataConn::on_txn_failure 1",
2069 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err { reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = 634 }), rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"baz\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::NoCommitDataConn\", cause: NoneByUncommitted, rollback: NoneByNotRolledBack }]",
2070 "NoCommitDataConn::on_txn_failure 3",
2071 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err { reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = 634 }), rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"baz\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::NoCommitDataConn\", cause: NoneByUncommitted, rollback: NoneByNotRolledBack }]",
2072 "AsyncDataConn::on_txn_failure 2",
2073 "TxnFailureReports=[TxnFailureReport { data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: PostCommitFailure(errs::Err { reason = alloc::string::String \"!!!\", file = src\\data_conn.rs, line = 634 }), rollback: NoneByNotRolledBack }, TxnFailureReport { data_conn_name: \"baz\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::NoCommitDataConn\", cause: NoneByUncommitted, rollback: NoneByNotRolledBack }]",
2074 "NoCommitDataConn::close 3",
2075 "NoCommitDataConn::drop 3",
2076 "AsyncDataConn::close 2",
2077 "AsyncDataConn::drop 2",
2078 "SyncDataConn::close 1",
2079 "SyncDataConn::drop 1",
2080 ]
2081 );
2082 }
2083
2084 #[test]
2085 fn test_only_rollback_and_first_is_sync() {
2086 let logger = Arc::new(Mutex::new(Vec::new()));
2087
2088 {
2089 let mut manager = DataConnManager::new();
2090
2091 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
2092 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
2093 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2094 let ssnnptr = SendSyncNonNull::new(nnptr);
2095 manager.add(ssnnptr);
2096
2097 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
2098 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
2099 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2100 let ssnnptr = SendSyncNonNull::new(nnptr);
2101 manager.add(ssnnptr);
2102
2103 let reports = manager.new_failure_reports();
2104 manager.rollback(reports);
2105 }
2106
2107 assert_eq!(
2108 *logger.lock().unwrap(),
2109 &[
2110 "SyncDataConn::new 1",
2111 "AsyncDataConn::new 2",
2112 "SyncDataConn::rollback 1",
2113 "AsyncDataConn::rollback 2",
2114 "SyncDataConn::on_txn_failure 1",
2115 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]"),
2116 "AsyncDataConn::on_txn_failure 2",
2117 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]"),
2118 "AsyncDataConn::close 2",
2119 "AsyncDataConn::drop 2",
2120 "SyncDataConn::close 1",
2121 "SyncDataConn::drop 1",
2122 ]
2123 );
2124 }
2125
2126 #[test]
2127 fn test_only_rollback_and_first_is_async() {
2128 let logger = Arc::new(Mutex::new(Vec::new()));
2129
2130 {
2131 let mut manager = DataConnManager::new();
2132
2133 let conn = AsyncDataConn::new(1, logger.clone(), Fail::Not);
2134 let boxed = Box::new(DataConnContainer::new("foo".to_string(), Box::new(conn)));
2135 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2136 let ssnnptr = SendSyncNonNull::new(nnptr);
2137 manager.add(ssnnptr);
2138
2139 let conn = SyncDataConn::new(2, logger.clone(), Fail::Not);
2140 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
2141 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2142 let ssnnptr = SendSyncNonNull::new(nnptr);
2143 manager.add(ssnnptr);
2144
2145 let reports = manager.new_failure_reports();
2146 manager.rollback(reports);
2147 }
2148
2149 assert_eq!(
2150 *logger.lock().unwrap(),
2151 &[
2152 "AsyncDataConn::new 1",
2153 "SyncDataConn::new 2",
2154 "SyncDataConn::rollback 2",
2155 "AsyncDataConn::rollback 1",
2156 "SyncDataConn::on_txn_failure 2",
2157 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]"),
2158 "AsyncDataConn::on_txn_failure 1",
2159 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]"),
2160 "SyncDataConn::close 2",
2161 "SyncDataConn::drop 2",
2162 "AsyncDataConn::close 1",
2163 "AsyncDataConn::drop 1",
2164 ]
2165 );
2166 }
2167
2168 #[test]
2169 fn test_only_rollback_and_second_rollback_failed() {
2170 let logger = Arc::new(Mutex::new(Vec::new()));
2171
2172 {
2173 let mut manager = DataConnManager::new();
2174
2175 let conn = SyncDataConn::new(1, logger.clone(), Fail::Not);
2176 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
2177 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2178 let ssnnptr = SendSyncNonNull::new(nnptr);
2179 manager.add(ssnnptr);
2180
2181 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Rollback);
2182 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
2183 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2184 let ssnnptr = SendSyncNonNull::new(nnptr);
2185 manager.add(ssnnptr);
2186
2187 let reports = manager.new_failure_reports();
2188 manager.rollback(reports);
2189 }
2190
2191 #[cfg(unix)]
2192 assert_eq!(*logger.lock().unwrap(), &[
2193 "SyncDataConn::new 1",
2194 "AsyncDataConn::new 2",
2195 "SyncDataConn::rollback 1",
2196 "AsyncDataConn::rollback 2 failed",
2197 "SyncDataConn::on_txn_failure 1",
2198 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src/data_conn.rs, line = {} }}) }}]", BASE_LINE + 229),
2199 "AsyncDataConn::on_txn_failure 2",
2200 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src/data_conn.rs, line = {} }}) }}]", BASE_LINE + 229),
2201 "AsyncDataConn::close 2",
2202 "AsyncDataConn::drop 2",
2203 "SyncDataConn::close 1",
2204 "SyncDataConn::drop 1",
2205 ]);
2206 #[cfg(windows)]
2207 assert_eq!(*logger.lock().unwrap(), &[
2208 "SyncDataConn::new 1",
2209 "AsyncDataConn::new 2",
2210 "SyncDataConn::rollback 1",
2211 "AsyncDataConn::rollback 2 failed",
2212 "SyncDataConn::on_txn_failure 1",
2213 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src\\data_conn.rs, line = {} }}) }}]", BASE_LINE + 229),
2214 "AsyncDataConn::on_txn_failure 2",
2215 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src\\data_conn.rs, line = {} }}) }}]", BASE_LINE + 229),
2216 "AsyncDataConn::close 2",
2217 "AsyncDataConn::drop 2",
2218 "SyncDataConn::close 1",
2219 "SyncDataConn::drop 1",
2220 ]);
2221 }
2222
2223 #[test]
2224 fn test_only_rollback_and_first_rollback_failed() {
2225 let logger = Arc::new(Mutex::new(Vec::new()));
2226
2227 {
2228 let mut manager = DataConnManager::new();
2229
2230 let conn = SyncDataConn::new(1, logger.clone(), Fail::Rollback);
2231 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
2232 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2233 let ssnnptr = SendSyncNonNull::new(nnptr);
2234 manager.add(ssnnptr);
2235
2236 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Not);
2237 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
2238 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2239 let ssnnptr = SendSyncNonNull::new(nnptr);
2240 manager.add(ssnnptr);
2241
2242 let reports = manager.new_failure_reports();
2243 manager.rollback(reports);
2244 }
2245
2246 #[cfg(unix)]
2247 assert_eq!(*logger.lock().unwrap(), &[
2248 "SyncDataConn::new 1",
2249 "AsyncDataConn::new 2",
2250 "SyncDataConn::rollback 1 failed",
2251 "AsyncDataConn::rollback 2",
2252 "SyncDataConn::on_txn_failure 1",
2253 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src/data_conn.rs, line = {} }}) }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 96),
2254 "AsyncDataConn::on_txn_failure 2",
2255 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src/data_conn.rs, line = {} }}) }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 96),
2256 "AsyncDataConn::close 2",
2257 "AsyncDataConn::drop 2",
2258 "SyncDataConn::close 1",
2259 "SyncDataConn::drop 1",
2260 ]);
2261 #[cfg(windows)]
2262 assert_eq!(*logger.lock().unwrap(), &[
2263 "SyncDataConn::new 1",
2264 "AsyncDataConn::new 2",
2265 "SyncDataConn::rollback 1 failed",
2266 "AsyncDataConn::rollback 2",
2267 "SyncDataConn::on_txn_failure 1",
2268 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src\\data_conn.rs, line = {} }}) }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 96),
2269 "AsyncDataConn::on_txn_failure 2",
2270 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src\\data_conn.rs, line = {} }}) }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: NoneByRolledBack }}]", BASE_LINE + 96),
2271 "AsyncDataConn::close 2",
2272 "AsyncDataConn::drop 2",
2273 "SyncDataConn::close 1",
2274 "SyncDataConn::drop 1",
2275 ]);
2276 }
2277
2278 #[test]
2279 fn test_commit_and_rollback_and_first_commit_failed_and_second_rollback_failed() {
2280 let logger = Arc::new(Mutex::new(Vec::new()));
2281
2282 {
2283 let mut manager = DataConnManager::new();
2284
2285 let conn = SyncDataConn::new(1, logger.clone(), Fail::Commit);
2286 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
2287 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2288 let ssnnptr = SendSyncNonNull::new(nnptr);
2289 manager.add(ssnnptr);
2290
2291 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Rollback);
2292 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
2293 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2294 let ssnnptr = SendSyncNonNull::new(nnptr);
2295 manager.add(ssnnptr);
2296
2297 let mut reports = manager.new_failure_reports();
2298 if let Err(e) = manager.commit(&mut reports) {
2299 match e.reason::<DataConnError>() {
2300 Ok(DataConnError::FailToCommitDataConn { errors }) => {
2301 assert_eq!(errors.len(), 1);
2302 assert_eq!(errors[0].index, 0);
2303 assert_eq!(errors[0].name, "foo".into());
2304 assert_eq!(errors[0].err.reason::<String>().unwrap(), "ZZZ");
2305 }
2306 _ => panic!(),
2307 }
2308 } else {
2309 panic!();
2310 }
2311 manager.rollback(reports);
2312 }
2313
2314 #[cfg(unix)]
2315 assert_eq!(*logger.lock().unwrap(), &[
2316 "SyncDataConn::new 1",
2317 "AsyncDataConn::new 2",
2318 "SyncDataConn::pre_commit 1",
2319 "AsyncDataConn::pre_commit 2",
2320 "SyncDataConn::commit 1 failed",
2321 "SyncDataConn::rollback 1",
2322 "AsyncDataConn::rollback 2 failed",
2323 "SyncDataConn::on_txn_failure 1",
2324 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"ZZZ\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src/data_conn.rs, line = {} }}) }}]", BASE_LINE + 47, BASE_LINE + 229),
2325 "AsyncDataConn::on_txn_failure 2",
2326 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"ZZZ\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src/data_conn.rs, line = {} }}) }}]", BASE_LINE + 47, BASE_LINE + 229),
2327 "AsyncDataConn::close 2",
2328 "AsyncDataConn::drop 2",
2329 "SyncDataConn::close 1",
2330 "SyncDataConn::drop 1",
2331 ]);
2332 #[cfg(windows)]
2333 assert_eq!(*logger.lock().unwrap(), &[
2334 "SyncDataConn::new 1",
2335 "AsyncDataConn::new 2",
2336 "SyncDataConn::pre_commit 1",
2337 "AsyncDataConn::pre_commit 2",
2338 "SyncDataConn::commit 1 failed",
2339 "SyncDataConn::rollback 1",
2340 "AsyncDataConn::rollback 2 failed",
2341 "SyncDataConn::on_txn_failure 1",
2342 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"ZZZ\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src\\data_conn.rs, line = {} }}) }}]", BASE_LINE + 47, BASE_LINE + 229),
2343 "AsyncDataConn::on_txn_failure 2",
2344 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"ZZZ\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByUncommitted, rollback: RollbackFailure(errs::Err {{ reason = alloc::string::String \"???\", file = src\\data_conn.rs, line = {} }}) }}]", BASE_LINE + 47, BASE_LINE + 229),
2345 "AsyncDataConn::close 2",
2346 "AsyncDataConn::drop 2",
2347 "SyncDataConn::close 1",
2348 "SyncDataConn::drop 1",
2349 ]);
2350 }
2351
2352 #[test]
2353 fn test_commit_and_rollback_and_secod_commit_failed_and_first_rollback_failed() {
2354 let logger = Arc::new(Mutex::new(Vec::new()));
2355
2356 {
2357 let mut manager = DataConnManager::new();
2358
2359 let conn = SyncDataConn::new(1, logger.clone(), Fail::Rollback);
2360 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
2361 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2362 let ssnnptr = SendSyncNonNull::new(nnptr);
2363 manager.add(ssnnptr);
2364
2365 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Commit);
2366 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
2367 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2368 let ssnnptr = SendSyncNonNull::new(nnptr);
2369 manager.add(ssnnptr);
2370
2371 let mut reports = manager.new_failure_reports();
2372 if let Err(e) = manager.commit(&mut reports) {
2373 match e.reason::<DataConnError>() {
2374 Ok(DataConnError::FailToCommitDataConn { errors }) => {
2375 assert_eq!(errors.len(), 1);
2376 assert_eq!(errors[0].index, 1);
2377 assert_eq!(errors[0].name, "bar".into());
2378 assert_eq!(errors[0].err.reason::<String>().unwrap(), "YYY");
2379 }
2380 _ => panic!(),
2381 }
2382 } else {
2383 panic!();
2384 }
2385 manager.rollback(reports);
2386 }
2387
2388 #[cfg(unix)]
2389 assert_eq!(*logger.lock().unwrap(), &[
2390 "SyncDataConn::new 1",
2391 "AsyncDataConn::new 2",
2392 "SyncDataConn::pre_commit 1",
2393 "AsyncDataConn::pre_commit 2",
2394 "SyncDataConn::commit 1",
2395 "AsyncDataConn::commit 2 failed",
2396 "AsyncDataConn::rollback 2",
2397 "SyncDataConn::on_txn_failure 1",
2398 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
2399 "AsyncDataConn::on_txn_failure 2",
2400 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
2401 "AsyncDataConn::close 2",
2402 "AsyncDataConn::drop 2",
2403 "SyncDataConn::close 1",
2404 "SyncDataConn::drop 1",
2405 ]);
2406 #[cfg(windows)]
2407 assert_eq!(*logger.lock().unwrap(), &[
2408 "SyncDataConn::new 1",
2409 "AsyncDataConn::new 2",
2410 "SyncDataConn::pre_commit 1",
2411 "AsyncDataConn::pre_commit 2",
2412 "SyncDataConn::commit 1",
2413 "AsyncDataConn::commit 2 failed",
2414 "AsyncDataConn::rollback 2",
2415 "SyncDataConn::on_txn_failure 1",
2416 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
2417 "AsyncDataConn::on_txn_failure 2",
2418 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
2419 "AsyncDataConn::close 2",
2420 "AsyncDataConn::drop 2",
2421 "SyncDataConn::close 1",
2422 "SyncDataConn::drop 1",
2423 ]);
2424 }
2425
2426 #[test]
2427 fn test_commit_and_rollback_and_pre_commit_become_committed_and_ok() {
2428 let logger = Arc::new(Mutex::new(Vec::new()));
2429
2430 {
2431 let mut manager = DataConnManager::new();
2432
2433 let conn = SyncDataConn::new(1, logger.clone(), Fail::PreCommitBecomeCommitted);
2434 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
2435 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2436 let ssnnptr = SendSyncNonNull::new(nnptr);
2437 manager.add(ssnnptr);
2438
2439 let conn = AsyncDataConn::new(2, logger.clone(), Fail::PreCommitBecomeCommitted);
2440 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
2441 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2442 let ssnnptr = SendSyncNonNull::new(nnptr);
2443 manager.add(ssnnptr);
2444
2445 let mut reports = manager.new_failure_reports();
2446 assert!(manager.commit(&mut reports).is_ok());
2447 manager.rollback(reports);
2448 }
2449
2450 assert_eq!(*logger.lock().unwrap(), &[
2451 "SyncDataConn::new 1",
2452 "AsyncDataConn::new 2",
2453 "SyncDataConn::pre_commit 1",
2454 "AsyncDataConn::pre_commit 2",
2455 "SyncDataConn::post_commit 1",
2456 "AsyncDataConn::post_commit 2",
2457 "SyncDataConn::on_txn_failure 1",
2458 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}]"),
2459 "AsyncDataConn::on_txn_failure 2",
2460 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}]"),
2461 "AsyncDataConn::close 2",
2462 "AsyncDataConn::drop 2",
2463 "SyncDataConn::close 1",
2464 "SyncDataConn::drop 1",
2465 ]);
2466 }
2467
2468 #[test]
2469 fn test_commit_and_rollback_and_pre_commit_become_committed_but_failed() {
2470 let logger = Arc::new(Mutex::new(Vec::new()));
2471
2472 {
2473 let mut manager = DataConnManager::new();
2474
2475 let conn = SyncDataConn::new(1, logger.clone(), Fail::PreCommitBecomeCommitted);
2476 let boxed = Box::new(DataConnContainer::new("foo", Box::new(conn)));
2477 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2478 let ssnnptr = SendSyncNonNull::new(nnptr);
2479 manager.add(ssnnptr);
2480
2481 let conn = AsyncDataConn::new(2, logger.clone(), Fail::Commit);
2482 let boxed = Box::new(DataConnContainer::new("bar", Box::new(conn)));
2483 let nnptr = ptr::NonNull::from(Box::leak(boxed)).cast::<DataConnContainer>();
2484 let ssnnptr = SendSyncNonNull::new(nnptr);
2485 manager.add(ssnnptr);
2486
2487 let mut reports = manager.new_failure_reports();
2488 if let Err(e) = manager.commit(&mut reports) {
2489 match e.reason::<DataConnError>() {
2490 Ok(DataConnError::FailToCommitDataConn { errors }) => {
2491 assert_eq!(errors.len(), 1);
2492 assert_eq!(errors[0].index, 1);
2493 assert_eq!(errors[0].name, "bar".into());
2494 assert_eq!(errors[0].err.reason::<String>().unwrap(), "YYY");
2495 }
2496 _ => panic!(),
2497 }
2498 } else {
2499 panic!();
2500 }
2501 manager.rollback(reports);
2502 }
2503
2504 #[cfg(unix)]
2505 assert_eq!(*logger.lock().unwrap(), &[
2506 "SyncDataConn::new 1",
2507 "AsyncDataConn::new 2",
2508 "SyncDataConn::pre_commit 1",
2509 "AsyncDataConn::pre_commit 2",
2510 "AsyncDataConn::commit 2 failed",
2511 "AsyncDataConn::rollback 2",
2512 "SyncDataConn::on_txn_failure 1",
2513 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
2514 "AsyncDataConn::on_txn_failure 2",
2515 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src/data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
2516 "AsyncDataConn::close 2",
2517 "AsyncDataConn::drop 2",
2518 "SyncDataConn::close 1",
2519 "SyncDataConn::drop 1",
2520 ]);
2521 #[cfg(windows)]
2522 assert_eq!(*logger.lock().unwrap(), &[
2523 "SyncDataConn::new 1",
2524 "AsyncDataConn::new 2",
2525 "SyncDataConn::pre_commit 1",
2526 "AsyncDataConn::pre_commit 2",
2527 "AsyncDataConn::commit 2 failed",
2528 "AsyncDataConn::rollback 2",
2529 "SyncDataConn::on_txn_failure 1",
2530 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
2531 "AsyncDataConn::on_txn_failure 2",
2532 &format!("TxnFailureReports=[TxnFailureReport {{ data_conn_name: \"foo\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::SyncDataConn\", cause: NoneByCommitted, rollback: NoneByNotRolledBack }}, TxnFailureReport {{ data_conn_name: \"bar\", data_conn_type: \"sabi::data_conn::tests_of_data_conn::AsyncDataConn\", cause: CommitFailure(errs::Err {{ reason = alloc::string::String \"YYY\", file = src\\data_conn.rs, line = {} }}), rollback: NoneByRolledBack }}]", BASE_LINE + 158),
2533 "AsyncDataConn::close 2",
2534 "AsyncDataConn::drop 2",
2535 "SyncDataConn::close 1",
2536 "SyncDataConn::drop 1",
2537 ]);
2538 }
2539 }
2540}