Skip to main content

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