1use std::collections::{HashMap, VecDeque};
6use std::future::Future;
7use std::pin::Pin;
8
9use errs::Err;
10use futures::future;
11use tokio::runtime;
12
13#[derive(Debug)]
15pub enum AsyncGroupError {
16 FailToCreateAsyncRuntime,
19}
20
21pub struct AsyncGroup<'a> {
28 task_vec: VecDeque<Pin<Box<dyn Future<Output = Result<(), Err>> + Send + 'static>>>,
29 name_vec: VecDeque<String>,
30 pub(crate) name: &'a str,
31}
32
33impl<'a> AsyncGroup<'_> {
34 pub(crate) fn new() -> Self {
35 Self {
36 task_vec: VecDeque::new(),
37 name_vec: VecDeque::new(),
38 name: "",
39 }
40 }
41
42 pub fn add<Fut>(&mut self, future: Fut)
56 where
57 Fut: Future<Output = Result<(), Err>> + Send + 'static,
58 {
59 self.task_vec.push_back(Box::pin(future));
60 self.name_vec.push_back(self.name.to_string());
61 }
62
63 pub(crate) fn join_and_collect_errors(mut self, err_map: &mut HashMap<String, Err>) {
64 match runtime::Runtime::new() {
65 Ok(rt) => {
66 rt.block_on(async {
67 let result_all = future::join_all(self.task_vec).await;
68 for result in result_all.into_iter() {
69 if let Some(name) = self.name_vec.pop_front() {
70 if let Err(err) = result {
71 err_map.insert(name, err);
72 }
73 }
74 }
75 });
76 }
77 Err(err) => {
78 err_map.insert(
79 "sabi::AsyncGroup".to_string(),
80 Err::with_source(AsyncGroupError::FailToCreateAsyncRuntime, err),
81 );
82 }
83 }
84 }
85
86 pub(crate) fn join_and_ignore_errors(self) {
87 match runtime::Runtime::new() {
88 Ok(rt) => {
89 rt.block_on(async {
90 let _ = future::join_all(self.task_vec).await;
91 });
92 }
93 Err(err) => {
94 let _ = Err::with_source(AsyncGroupError::FailToCreateAsyncRuntime, err);
95 }
96 }
97 }
98
99 pub(crate) async fn join_and_collect_errors_async(
100 mut self,
101 err_map: &mut HashMap<String, Err>,
102 ) {
103 let result_all = future::join_all(self.task_vec).await;
104 for result in result_all.into_iter() {
105 if let Some(name) = self.name_vec.pop_front() {
106 if let Err(err) = result {
107 err_map.insert(name, err);
108 }
109 }
110 }
111 }
112
113 pub(crate) async fn join_and_ignore_errors_async(self) {
114 let _ = future::join_all(self.task_vec).await;
115 }
116}
117
118#[cfg(test)]
119mod tests_of_async_group {
120 use super::*;
121 use std::sync::{Arc, Mutex};
122 use tokio::time;
123
124 const BASE_LINE: u32 = line!();
125
126 #[derive(Debug, PartialEq)]
127 enum Reasons {
128 BadFlag(bool),
129 BadString(String),
130 BadNumber(i64),
131 }
132
133 struct StructA {
134 flag: Arc<Mutex<bool>>,
135 will_fail: bool,
136 }
137
138 impl StructA {
139 fn new(will_fail: bool) -> Self {
140 Self {
141 flag: Arc::new(Mutex::new(false)),
142 will_fail,
143 }
144 }
145
146 fn process(&self, ag: &mut AsyncGroup) {
147 let flag_clone = self.flag.clone();
148 let will_fail = self.will_fail;
149 ag.add(async move {
150 let _ = time::sleep(time::Duration::from_millis(100)).await;
152
153 {
154 let mut flag = flag_clone.lock().unwrap();
155 if will_fail {
156 return Err(Err::new(Reasons::BadFlag(*flag)));
157 }
158 *flag = true;
159 }
160
161 Ok(())
162 });
163 }
164 }
165
166 struct StructB {
167 string: Arc<Mutex<String>>,
168 flag: Arc<Mutex<bool>>,
169 will_fail: bool,
170 }
171
172 impl StructB {
173 fn new(will_fail: bool) -> Self {
174 Self {
175 string: Arc::new(Mutex::new("-".to_string())),
176 flag: Arc::new(Mutex::new(false)),
177 will_fail,
178 }
179 }
180
181 fn process(&self, ag: &mut AsyncGroup) {
182 let string_clone = self.string.clone();
183 let flag_clone = self.flag.clone();
184 let will_fail = self.will_fail;
185 ag.add(async move {
186 let _ = time::sleep(time::Duration::from_millis(300)).await;
188
189 {
190 let mut string = string_clone.lock().unwrap();
191 let mut flag = flag_clone.lock().unwrap();
192 if will_fail {
193 return Err(Err::new(Reasons::BadString(string.to_string())));
194 }
195 *flag = true;
196 *string = "hello".to_string();
197 }
198 Ok(())
199 });
200 }
201 }
202
203 struct StructC {
204 number: Arc<Mutex<i64>>,
205 will_fail: bool,
206 }
207
208 impl StructC {
209 fn new(will_fail: bool) -> Self {
210 Self {
211 number: Arc::new(Mutex::new(123)),
212 will_fail,
213 }
214 }
215
216 fn process(&self, ag: &mut AsyncGroup) {
217 let number_clone = self.number.clone();
218 let will_fail = self.will_fail;
219 ag.add(async move {
220 let _ = time::sleep(time::Duration::from_millis(50)).await;
222
223 {
224 let mut number = number_clone.lock().unwrap();
225 if will_fail {
226 return Err(Err::new(Reasons::BadNumber(*number)));
227 }
228 *number = 987;
229 }
230 Ok(())
231 });
232 }
233 }
234
235 mod test_join_and_collect_errors {
236 use super::*;
237
238 #[test]
239 fn zero() {
240 let ag = AsyncGroup::new();
241 let mut m = HashMap::<String, Err>::new();
242
243 ag.join_and_collect_errors(&mut m);
244 assert_eq!(m.len(), 0);
245 }
246
247 #[test]
248 fn single_ok() {
249 let mut ag = AsyncGroup::new();
250 let mut m = HashMap::<String, Err>::new();
251
252 let struct_a = StructA::new(false);
253 assert_eq!(*struct_a.flag.lock().unwrap(), false);
254
255 ag.name = "foo";
256 struct_a.process(&mut ag);
257
258 ag.join_and_collect_errors(&mut m);
259 assert_eq!(m.len(), 0);
260 assert_eq!(*struct_a.flag.lock().unwrap(), true);
261 }
262
263 #[test]
264 fn single_fail() {
265 let mut ag = AsyncGroup::new();
266 let mut m = HashMap::<String, Err>::new();
267
268 let struct_a = StructA::new(true);
269 assert_eq!(*struct_a.flag.lock().unwrap(), false);
270
271 ag.name = "foo";
272 struct_a.process(&mut ag);
273
274 ag.join_and_collect_errors(&mut m);
275 assert_eq!(m.len(), 1);
276 assert_eq!(*struct_a.flag.lock().unwrap(), false);
277
278 #[cfg(unix)]
279 assert_eq!(
280 format!("{:?}", *(m.get("foo").unwrap())),
281 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadFlag(false), file = src/async_group.rs, line = ".to_string() + &(BASE_LINE + 32).to_string() + " }"
282 );
283 #[cfg(windows)]
284 assert_eq!(
285 format!("{:?}", *(m.get("foo").unwrap())),
286 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadFlag(false), file = src\\async_group.rs, line = ".to_string() + &(BASE_LINE + 32).to_string() + " }"
287 );
288 }
289
290 #[test]
291 fn multiple_ok() {
292 let mut ag = AsyncGroup::new();
293 let mut m = HashMap::<String, Err>::new();
294
295 let struct_a = StructA::new(false);
296 assert_eq!(*struct_a.flag.lock().unwrap(), false);
297
298 let struct_b = StructB::new(false);
299 assert_eq!(*struct_b.flag.lock().unwrap(), false);
300 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
301
302 let struct_c = StructC::new(false);
303 assert_eq!(*struct_c.number.lock().unwrap(), 123);
304
305 ag.name = "foo";
306 struct_a.process(&mut ag);
307
308 ag.name = "bar";
309 struct_b.process(&mut ag);
310
311 ag.name = "baz";
312 struct_c.process(&mut ag);
313
314 ag.join_and_collect_errors(&mut m);
315 assert_eq!(m.len(), 0);
316 assert_eq!(*struct_a.flag.lock().unwrap(), true);
317 assert_eq!(*struct_b.flag.lock().unwrap(), true);
318 assert_eq!(*struct_b.string.lock().unwrap(), "hello".to_string());
319 assert_eq!(*struct_c.number.lock().unwrap(), 987);
320 }
321
322 #[test]
323 fn multiple_processes_and_single_fail() {
324 let mut ag = AsyncGroup::new();
325 let mut m = HashMap::<String, Err>::new();
326
327 let struct_a = StructA::new(false);
328 assert_eq!(*struct_a.flag.lock().unwrap(), false);
329
330 let struct_b = StructB::new(true);
331 assert_eq!(*struct_b.flag.lock().unwrap(), false);
332 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
333
334 let struct_c = StructC::new(false);
335 assert_eq!(*struct_c.number.lock().unwrap(), 123);
336
337 ag.name = "foo";
338 struct_a.process(&mut ag);
339
340 ag.name = "bar";
341 struct_b.process(&mut ag);
342
343 ag.name = "baz";
344 struct_c.process(&mut ag);
345
346 ag.join_and_collect_errors(&mut m);
347 assert_eq!(m.len(), 1);
348
349 #[cfg(unix)]
350 assert_eq!(
351 format!("{:?}", *(m.get("bar").unwrap())),
352 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadString(\"-\"), file = src/async_group.rs, line = ".to_string() + &(BASE_LINE + 69).to_string() + " }",
353 );
354 #[cfg(windows)]
355 assert_eq!(
356 format!("{:?}", *(m.get("bar").unwrap())),
357 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadString(\"-\"), file = src\\async_group.rs, line = ".to_string() + &(BASE_LINE + 69).to_string() + " }",
358 );
359
360 assert_eq!(*struct_a.flag.lock().unwrap(), true);
361 assert_eq!(*struct_b.flag.lock().unwrap(), false);
362 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
363 assert_eq!(*struct_c.number.lock().unwrap(), 987);
364 }
365
366 #[test]
367 fn multiple_fail() {
368 let mut ag = AsyncGroup::new();
369 let mut m = HashMap::<String, Err>::new();
370
371 let struct_a = StructA::new(true);
372 assert_eq!(*struct_a.flag.lock().unwrap(), false);
373
374 let struct_b = StructB::new(true);
375 assert_eq!(*struct_b.flag.lock().unwrap(), false);
376 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
377
378 let struct_c = StructC::new(true);
379 assert_eq!(*struct_c.number.lock().unwrap(), 123);
380
381 ag.name = "foo";
382 struct_a.process(&mut ag);
383
384 ag.name = "bar";
385 struct_b.process(&mut ag);
386
387 ag.name = "baz";
388 struct_c.process(&mut ag);
389
390 ag.join_and_collect_errors(&mut m);
391 assert_eq!(m.len(), 3);
392
393 #[cfg(unix)]
394 assert_eq!(
395 format!("{:?}", *(m.get("foo").unwrap())),
396 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadFlag(false), file = src/async_group.rs, line = ".to_string() + &(BASE_LINE + 32).to_string() + " }",
397 );
398 #[cfg(windows)]
399 assert_eq!(
400 format!("{:?}", *(m.get("foo").unwrap())),
401 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadFlag(false), file = src\\async_group.rs, line = ".to_string() + &(BASE_LINE + 32).to_string() + " }",
402 );
403 #[cfg(unix)]
404 assert_eq!(
405 format!("{:?}", *(m.get("bar").unwrap())),
406 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadString(\"-\"), file = src/async_group.rs, line = ".to_string() + &(BASE_LINE + 69).to_string() + " }",
407 );
408 #[cfg(windows)]
409 assert_eq!(
410 format!("{:?}", *(m.get("bar").unwrap())),
411 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadString(\"-\"), file = src\\async_group.rs, line = ".to_string() + &(BASE_LINE + 69).to_string() + " }",
412 );
413 #[cfg(unix)]
414 assert_eq!(
415 format!("{:?}", *(m.get("baz").unwrap())),
416 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadNumber(123), file = src/async_group.rs, line = ".to_string() + &(BASE_LINE + 102).to_string() + " }",
417 );
418 #[cfg(windows)]
419 assert_eq!(
420 format!("{:?}", *(m.get("baz").unwrap())),
421 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadNumber(123), file = src\\async_group.rs, line = ".to_string() + &(BASE_LINE + 102).to_string() + " }",
422 );
423
424 assert_eq!(*struct_a.flag.lock().unwrap(), false);
425 assert_eq!(*struct_b.flag.lock().unwrap(), false);
426 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
427 assert_eq!(*struct_c.number.lock().unwrap(), 123);
428 }
429 }
430
431 mod test_join_and_ignore_errors {
432 use super::*;
433
434 #[test]
435 fn zero() {
436 let ag = AsyncGroup::new();
437
438 ag.join_and_ignore_errors();
439 }
440
441 #[test]
442 fn single_ok() {
443 let mut ag = AsyncGroup::new();
444
445 let struct_a = StructA::new(false);
446 assert_eq!(*struct_a.flag.lock().unwrap(), false);
447
448 ag.name = "foo";
449 struct_a.process(&mut ag);
450
451 ag.join_and_ignore_errors();
452 assert_eq!(*struct_a.flag.lock().unwrap(), true);
453 }
454
455 #[test]
456 fn single_fail() {
457 let mut ag = AsyncGroup::new();
458
459 let struct_a = StructA::new(true);
460 assert_eq!(*struct_a.flag.lock().unwrap(), false);
461
462 ag.name = "foo";
463 struct_a.process(&mut ag);
464
465 ag.join_and_ignore_errors();
466 assert_eq!(*struct_a.flag.lock().unwrap(), false);
467 }
468
469 #[test]
470 fn multiple_ok() {
471 let mut ag = AsyncGroup::new();
472
473 let struct_a = StructA::new(false);
474 assert_eq!(*struct_a.flag.lock().unwrap(), false);
475
476 let struct_b = StructB::new(false);
477 assert_eq!(*struct_b.flag.lock().unwrap(), false);
478 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
479
480 let struct_c = StructC::new(false);
481 assert_eq!(*struct_c.number.lock().unwrap(), 123);
482
483 ag.name = "foo";
484 struct_a.process(&mut ag);
485
486 ag.name = "bar";
487 struct_b.process(&mut ag);
488
489 ag.name = "baz";
490 struct_c.process(&mut ag);
491
492 ag.join_and_ignore_errors();
493
494 assert_eq!(*struct_a.flag.lock().unwrap(), true);
495 assert_eq!(*struct_b.flag.lock().unwrap(), true);
496 assert_eq!(*struct_b.string.lock().unwrap(), "hello".to_string());
497 assert_eq!(*struct_c.number.lock().unwrap(), 987);
498 }
499
500 #[test]
501 fn multiple_processes_and_single_fail() {
502 let mut ag = AsyncGroup::new();
503
504 let struct_a = StructA::new(false);
505 assert_eq!(*struct_a.flag.lock().unwrap(), false);
506
507 let struct_b = StructB::new(true);
508 assert_eq!(*struct_b.flag.lock().unwrap(), false);
509 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
510
511 let struct_c = StructC::new(false);
512 assert_eq!(*struct_c.number.lock().unwrap(), 123);
513
514 ag.name = "foo";
515 struct_a.process(&mut ag);
516
517 ag.name = "bar";
518 struct_b.process(&mut ag);
519
520 ag.name = "baz";
521 struct_c.process(&mut ag);
522
523 ag.join_and_ignore_errors();
524
525 assert_eq!(*struct_a.flag.lock().unwrap(), true);
526 assert_eq!(*struct_b.flag.lock().unwrap(), false);
527 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
528 assert_eq!(*struct_c.number.lock().unwrap(), 987);
529 }
530
531 #[test]
532 fn multiple_fail() {
533 let mut ag = AsyncGroup::new();
534
535 let struct_a = StructA::new(true);
536 assert_eq!(*struct_a.flag.lock().unwrap(), false);
537
538 let struct_b = StructB::new(true);
539 assert_eq!(*struct_b.flag.lock().unwrap(), false);
540 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
541
542 let struct_c = StructC::new(true);
543 assert_eq!(*struct_c.number.lock().unwrap(), 123);
544
545 ag.name = "foo";
546 struct_a.process(&mut ag);
547
548 ag.name = "bar";
549 struct_b.process(&mut ag);
550
551 ag.name = "baz";
552 struct_c.process(&mut ag);
553
554 ag.join_and_ignore_errors();
555
556 assert_eq!(*struct_a.flag.lock().unwrap(), false);
557 assert_eq!(*struct_b.flag.lock().unwrap(), false);
558 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
559 assert_eq!(*struct_c.number.lock().unwrap(), 123);
560 }
561 }
562
563 mod test_join_and_collect_errors_async {
564 use super::*;
565
566 #[tokio::test]
567 async fn zero() {
568 let ag = AsyncGroup::new();
569 let mut m = HashMap::<String, Err>::new();
570
571 ag.join_and_collect_errors_async(&mut m).await;
572 assert_eq!(m.len(), 0);
573 }
574
575 #[tokio::test]
576 async fn single_ok() {
577 let mut ag = AsyncGroup::new();
578 let mut m = HashMap::<String, Err>::new();
579
580 let struct_a = StructA::new(false);
581 assert_eq!(*struct_a.flag.lock().unwrap(), false);
582
583 ag.name = "foo";
584 struct_a.process(&mut ag);
585
586 ag.join_and_collect_errors_async(&mut m).await;
587 assert_eq!(m.len(), 0);
588 assert_eq!(*struct_a.flag.lock().unwrap(), true);
589 }
590
591 #[tokio::test]
592 async fn single_fail() {
593 let mut ag = AsyncGroup::new();
594 let mut m = HashMap::<String, Err>::new();
595
596 let struct_a = StructA::new(true);
597 assert_eq!(*struct_a.flag.lock().unwrap(), false);
598
599 ag.name = "foo";
600 struct_a.process(&mut ag);
601
602 ag.join_and_collect_errors_async(&mut m).await;
603 assert_eq!(m.len(), 1);
604 assert_eq!(*struct_a.flag.lock().unwrap(), false);
605
606 #[cfg(unix)]
607 assert_eq!(
608 format!("{:?}", *(m.get("foo").unwrap())),
609 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadFlag(false), file = src/async_group.rs, line = ".to_string() + &(BASE_LINE + 32).to_string() + " }"
610 );
611 #[cfg(windows)]
612 assert_eq!(
613 format!("{:?}", *(m.get("foo").unwrap())),
614 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadFlag(false), file = src\\async_group.rs, line = ".to_string() + &(BASE_LINE + 32).to_string() + " }"
615 );
616 }
617
618 #[tokio::test]
619 async fn multiple_ok() {
620 let mut ag = AsyncGroup::new();
621 let mut m = HashMap::<String, Err>::new();
622
623 let struct_a = StructA::new(false);
624 assert_eq!(*struct_a.flag.lock().unwrap(), false);
625
626 let struct_b = StructB::new(false);
627 assert_eq!(*struct_b.flag.lock().unwrap(), false);
628 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
629
630 let struct_c = StructC::new(false);
631 assert_eq!(*struct_c.number.lock().unwrap(), 123);
632
633 ag.name = "foo";
634 struct_a.process(&mut ag);
635
636 ag.name = "bar";
637 struct_b.process(&mut ag);
638
639 ag.name = "baz";
640 struct_c.process(&mut ag);
641
642 ag.join_and_collect_errors_async(&mut m).await;
643 assert_eq!(m.len(), 0);
644 assert_eq!(*struct_a.flag.lock().unwrap(), true);
645 assert_eq!(*struct_b.flag.lock().unwrap(), true);
646 assert_eq!(*struct_b.string.lock().unwrap(), "hello".to_string());
647 assert_eq!(*struct_c.number.lock().unwrap(), 987);
648 }
649
650 #[tokio::test]
651 async fn multiple_processes_and_single_fail() {
652 let mut ag = AsyncGroup::new();
653 let mut m = HashMap::<String, Err>::new();
654
655 let struct_a = StructA::new(false);
656 assert_eq!(*struct_a.flag.lock().unwrap(), false);
657
658 let struct_b = StructB::new(true);
659 assert_eq!(*struct_b.flag.lock().unwrap(), false);
660 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
661
662 let struct_c = StructC::new(false);
663 assert_eq!(*struct_c.number.lock().unwrap(), 123);
664
665 ag.name = "foo";
666 struct_a.process(&mut ag);
667
668 ag.name = "bar";
669 struct_b.process(&mut ag);
670
671 ag.name = "baz";
672 struct_c.process(&mut ag);
673
674 ag.join_and_collect_errors_async(&mut m).await;
675 assert_eq!(m.len(), 1);
676
677 #[cfg(unix)]
678 assert_eq!(
679 format!("{:?}", *(m.get("bar").unwrap())),
680 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadString(\"-\"), file = src/async_group.rs, line = ".to_string() + &(BASE_LINE + 69).to_string() + " }",
681 );
682 #[cfg(windows)]
683 assert_eq!(
684 format!("{:?}", *(m.get("bar").unwrap())),
685 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadString(\"-\"), file = src\\async_group.rs, line = ".to_string() + &(BASE_LINE + 69).to_string() + " }",
686 );
687
688 assert_eq!(*struct_a.flag.lock().unwrap(), true);
689 assert_eq!(*struct_b.flag.lock().unwrap(), false);
690 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
691 assert_eq!(*struct_c.number.lock().unwrap(), 987);
692 }
693
694 #[tokio::test]
695 async fn multiple_fail() {
696 let mut ag = AsyncGroup::new();
697 let mut m = HashMap::<String, Err>::new();
698
699 let struct_a = StructA::new(true);
700 assert_eq!(*struct_a.flag.lock().unwrap(), false);
701
702 let struct_b = StructB::new(true);
703 assert_eq!(*struct_b.flag.lock().unwrap(), false);
704 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
705
706 let struct_c = StructC::new(true);
707 assert_eq!(*struct_c.number.lock().unwrap(), 123);
708
709 ag.name = "foo";
710 struct_a.process(&mut ag);
711
712 ag.name = "bar";
713 struct_b.process(&mut ag);
714
715 ag.name = "baz";
716 struct_c.process(&mut ag);
717
718 ag.join_and_collect_errors_async(&mut m).await;
719 assert_eq!(m.len(), 3);
720
721 #[cfg(unix)]
722 assert_eq!(
723 format!("{:?}", *(m.get("foo").unwrap())),
724 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadFlag(false), file = src/async_group.rs, line = ".to_string() + &(BASE_LINE + 32).to_string() + " }",
725 );
726 #[cfg(windows)]
727 assert_eq!(
728 format!("{:?}", *(m.get("foo").unwrap())),
729 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadFlag(false), file = src\\async_group.rs, line = ".to_string() + &(BASE_LINE + 32).to_string() + " }",
730 );
731 #[cfg(unix)]
732 assert_eq!(
733 format!("{:?}", *(m.get("bar").unwrap())),
734 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadString(\"-\"), file = src/async_group.rs, line = ".to_string() + &(BASE_LINE + 69).to_string() + " }",
735 );
736 #[cfg(windows)]
737 assert_eq!(
738 format!("{:?}", *(m.get("bar").unwrap())),
739 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadString(\"-\"), file = src\\async_group.rs, line = ".to_string() + &(BASE_LINE + 69).to_string() + " }",
740 );
741 #[cfg(unix)]
742 assert_eq!(
743 format!("{:?}", *(m.get("baz").unwrap())),
744 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadNumber(123), file = src/async_group.rs, line = ".to_string() + &(BASE_LINE + 102).to_string() + " }",
745 );
746 #[cfg(windows)]
747 assert_eq!(
748 format!("{:?}", *(m.get("baz").unwrap())),
749 "errs::Err { reason = sabi::async_group::tests_of_async_group::Reasons BadNumber(123), file = src\\async_group.rs, line = ".to_string() + &(BASE_LINE + 102).to_string() + " }",
750 );
751
752 assert_eq!(*struct_a.flag.lock().unwrap(), false);
753 assert_eq!(*struct_b.flag.lock().unwrap(), false);
754 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
755 assert_eq!(*struct_c.number.lock().unwrap(), 123);
756 }
757 }
758
759 mod test_join_and_ignore_errors_async {
760 use super::*;
761
762 #[tokio::test]
763 async fn zero() {
764 let ag = AsyncGroup::new();
765
766 ag.join_and_ignore_errors_async().await;
767 }
768
769 #[tokio::test]
770 async fn single_ok() {
771 let mut ag = AsyncGroup::new();
772
773 let struct_a = StructA::new(false);
774 assert_eq!(*struct_a.flag.lock().unwrap(), false);
775
776 ag.name = "foo";
777 struct_a.process(&mut ag);
778
779 ag.join_and_ignore_errors_async().await;
780 assert_eq!(*struct_a.flag.lock().unwrap(), true);
781 }
782
783 #[tokio::test]
784 async fn single_fail() {
785 let mut ag = AsyncGroup::new();
786
787 let struct_a = StructA::new(true);
788 assert_eq!(*struct_a.flag.lock().unwrap(), false);
789
790 ag.name = "foo";
791 struct_a.process(&mut ag);
792
793 ag.join_and_ignore_errors_async().await;
794 assert_eq!(*struct_a.flag.lock().unwrap(), false);
795 }
796
797 #[tokio::test]
798 async fn multiple_ok() {
799 let mut ag = AsyncGroup::new();
800
801 let struct_a = StructA::new(false);
802 assert_eq!(*struct_a.flag.lock().unwrap(), false);
803
804 let struct_b = StructB::new(false);
805 assert_eq!(*struct_b.flag.lock().unwrap(), false);
806 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
807
808 let struct_c = StructC::new(false);
809 assert_eq!(*struct_c.number.lock().unwrap(), 123);
810
811 ag.name = "foo";
812 struct_a.process(&mut ag);
813
814 ag.name = "bar";
815 struct_b.process(&mut ag);
816
817 ag.name = "baz";
818 struct_c.process(&mut ag);
819
820 ag.join_and_ignore_errors_async().await;
821
822 assert_eq!(*struct_a.flag.lock().unwrap(), true);
823 assert_eq!(*struct_b.flag.lock().unwrap(), true);
824 assert_eq!(*struct_b.string.lock().unwrap(), "hello".to_string());
825 assert_eq!(*struct_c.number.lock().unwrap(), 987);
826 }
827
828 #[tokio::test]
829 async fn multiple_processes_and_single_fail() {
830 let mut ag = AsyncGroup::new();
831
832 let struct_a = StructA::new(false);
833 assert_eq!(*struct_a.flag.lock().unwrap(), false);
834
835 let struct_b = StructB::new(true);
836 assert_eq!(*struct_b.flag.lock().unwrap(), false);
837 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
838
839 let struct_c = StructC::new(false);
840 assert_eq!(*struct_c.number.lock().unwrap(), 123);
841
842 ag.name = "foo";
843 struct_a.process(&mut ag);
844
845 ag.name = "bar";
846 struct_b.process(&mut ag);
847
848 ag.name = "baz";
849 struct_c.process(&mut ag);
850
851 ag.join_and_ignore_errors_async().await;
852
853 assert_eq!(*struct_a.flag.lock().unwrap(), true);
854 assert_eq!(*struct_b.flag.lock().unwrap(), false);
855 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
856 assert_eq!(*struct_c.number.lock().unwrap(), 987);
857 }
858
859 #[tokio::test]
860 async fn multiple_fail() {
861 let mut ag = AsyncGroup::new();
862
863 let struct_a = StructA::new(true);
864 assert_eq!(*struct_a.flag.lock().unwrap(), false);
865
866 let struct_b = StructB::new(true);
867 assert_eq!(*struct_b.flag.lock().unwrap(), false);
868 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
869
870 let struct_c = StructC::new(true);
871 assert_eq!(*struct_c.number.lock().unwrap(), 123);
872
873 ag.name = "foo";
874 struct_a.process(&mut ag);
875
876 ag.name = "bar";
877 struct_b.process(&mut ag);
878
879 ag.name = "baz";
880 struct_c.process(&mut ag);
881
882 ag.join_and_ignore_errors_async().await;
883
884 assert_eq!(*struct_a.flag.lock().unwrap(), false);
885 assert_eq!(*struct_b.flag.lock().unwrap(), false);
886 assert_eq!(*struct_b.string.lock().unwrap(), "-".to_string());
887 assert_eq!(*struct_c.number.lock().unwrap(), 123);
888 }
889 }
890}