Skip to main content

sabi/
data_conn.rs

1// Copyright (C) 2024-2026 Takayuki Sato. All Rights Reserved.
2// This program is free software under MIT License.
3// See the file LICENSE in this distribution for more details.
4
5use 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/// An enum type representing the reasons for errors that can occur within `DataConn` operations.
15#[allow(clippy::enum_variant_names)]
16#[derive(Debug)]
17pub enum DataConnError {
18    /// Indicates a failure during the pre-commit process of one or more [`DataConn`] instances
19    /// involved in a transaction.
20    /// Contains a vector of data connection names and their corresponding errors.
21    FailToPreCommitDataConn {
22        /// The vector contains errors that occurred in each [`DataConn`] object.
23        errors: Vec<ErrEntry>,
24    },
25
26    /// Indicates a failure during the commit process of one or more [`DataConn`] instances
27    /// involved in a transaction.
28    /// Contains a vector of data connection names and their corresponding errors.
29    FailToCommitDataConn {
30        /// The vector contains errors that occurred in each [`DataConn`] object.
31        errors: Vec<ErrEntry>,
32    },
33
34    /// Indicates a failure during the post-commit process of one or more [`DataConn`] instances
35    /// involved in a transaction.
36    /// Contains a vector of data connection names and their corresponding errors.
37    FailToPostCommitDataConn {
38        /// The vector contains errors that occurred in each [`DataConn`] object.
39        errors: Vec<ErrEntry>,
40    },
41
42    /// Indicates a failure to cast a retrieved [`DataConn`] to the expected type.
43    FailToCastDataConn {
44        /// The name of the data connection that failed to cast.
45        name: Arc<str>,
46
47        /// The type name to which the [`DataConn`] attempted to cast.
48        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        // Using rev because eariler ones take precedence when names overlap
174        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            // Because eariler ones take precedence when names overlap
189            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                // Set this alongside the committed state by PreCommit, during the rollback process
289                //report.cause = TxnFailureCause::NoneByCommitted;
290                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                // don't break;
333            }
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", // because of async
1211                    "SyncDataConn::commit 1",
1212                    "SyncDataConn::commit 3",
1213                    "AsyncDataConn::commit 2", // because of async
1214                    "SyncDataConn::post_commit 1",
1215                    "SyncDataConn::post_commit 3",
1216                    "AsyncDataConn::post_commit 2", // because of async
1217                    "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}