1use std::fmt::{Debug, Display};
27
28use crate::collections::{MapLike, SetLike};
29
30pub const FAILED: &str = "Condition failed";
36
37#[inline(always)]
43pub fn check_predicate_true(predicate: bool, fail_msg: &str) -> anyhow::Result<()> {
44 if !predicate {
45 anyhow::bail!("{fail_msg}")
46 }
47 Ok(())
48}
49
50#[inline(always)]
56pub fn check_predicate_false(predicate: bool, fail_msg: &str) -> anyhow::Result<()> {
57 if predicate {
58 anyhow::bail!("{fail_msg}")
59 }
60 Ok(())
61}
62
63#[inline(always)]
72pub fn check_nonempty_string<T: AsRef<str>>(s: T, param: &str) -> anyhow::Result<()> {
73 if s.as_ref().is_empty() {
74 anyhow::bail!("invalid string for '{param}', was empty");
75 }
76 Ok(())
77}
78
79#[inline(always)]
88pub fn check_valid_string<T: AsRef<str>>(s: T, param: &str) -> anyhow::Result<()> {
89 let s = s.as_ref();
90
91 if s.is_empty() {
92 anyhow::bail!("invalid string for '{param}', was empty");
93 }
94
95 let mut has_non_whitespace = false;
97 for c in s.chars() {
98 if !c.is_whitespace() {
99 has_non_whitespace = true;
100 }
101 if !c.is_ascii() {
102 anyhow::bail!("invalid string for '{param}' contained a non-ASCII char, was '{s}'");
103 }
104 }
105
106 if !has_non_whitespace {
107 anyhow::bail!("invalid string for '{param}', was all whitespace");
108 }
109
110 Ok(())
111}
112
113#[inline(always)]
122pub fn check_valid_string_optional<T: AsRef<str>>(s: Option<T>, param: &str) -> anyhow::Result<()> {
123 if let Some(s) = s {
124 check_valid_string(s, param)?;
125 }
126 Ok(())
127}
128
129#[inline(always)]
135pub fn check_string_contains<T: AsRef<str>>(s: T, pat: &str, param: &str) -> anyhow::Result<()> {
136 let s = s.as_ref();
137 if !s.contains(pat) {
138 anyhow::bail!("invalid string for '{param}' did not contain '{pat}', was '{s}'")
139 }
140 Ok(())
141}
142
143#[inline(always)]
149pub fn check_equal<T: PartialEq + Debug + Display>(
150 lhs: &T,
151 rhs: &T,
152 lhs_param: &str,
153 rhs_param: &str,
154) -> anyhow::Result<()> {
155 if lhs != rhs {
156 anyhow::bail!("'{lhs_param}' value of {lhs} was not equal to '{rhs_param}' value of {rhs}");
157 }
158 Ok(())
159}
160
161#[inline(always)]
167pub fn check_equal_u8(lhs: u8, rhs: u8, lhs_param: &str, rhs_param: &str) -> anyhow::Result<()> {
168 if lhs != rhs {
169 anyhow::bail!("'{lhs_param}' u8 of {lhs} was not equal to '{rhs_param}' u8 of {rhs}")
170 }
171 Ok(())
172}
173
174#[inline(always)]
180pub fn check_equal_usize(
181 lhs: usize,
182 rhs: usize,
183 lhs_param: &str,
184 rhs_param: &str,
185) -> anyhow::Result<()> {
186 if lhs != rhs {
187 anyhow::bail!("'{lhs_param}' usize of {lhs} was not equal to '{rhs_param}' usize of {rhs}")
188 }
189 Ok(())
190}
191
192#[inline(always)]
198pub fn check_positive_u64(value: u64, param: &str) -> anyhow::Result<()> {
199 if value == 0 {
200 anyhow::bail!("invalid u64 for '{param}' not positive, was {value}")
201 }
202 Ok(())
203}
204
205#[inline(always)]
211pub fn check_positive_u128(value: u128, param: &str) -> anyhow::Result<()> {
212 if value == 0 {
213 anyhow::bail!("invalid u128 for '{param}' not positive, was {value}")
214 }
215 Ok(())
216}
217
218#[inline(always)]
224pub fn check_positive_i64(value: i64, param: &str) -> anyhow::Result<()> {
225 if value <= 0 {
226 anyhow::bail!("invalid i64 for '{param}' not positive, was {value}")
227 }
228 Ok(())
229}
230
231#[inline(always)]
237pub fn check_positive_i128(value: i128, param: &str) -> anyhow::Result<()> {
238 if value <= 0 {
239 anyhow::bail!("invalid i128 for '{param}' not positive, was {value}")
240 }
241 Ok(())
242}
243
244#[inline(always)]
250pub fn check_non_negative_f64(value: f64, param: &str) -> anyhow::Result<()> {
251 if value.is_nan() || value.is_infinite() {
252 anyhow::bail!("invalid f64 for '{param}', was {value}")
253 }
254 if value < 0.0 {
255 anyhow::bail!("invalid f64 for '{param}' negative, was {value}")
256 }
257 Ok(())
258}
259
260#[inline(always)]
266pub fn check_in_range_inclusive_u8(value: u8, l: u8, r: u8, param: &str) -> anyhow::Result<()> {
267 if value < l || value > r {
268 anyhow::bail!("invalid u8 for '{param}' not in range [{l}, {r}], was {value}")
269 }
270 Ok(())
271}
272
273#[inline(always)]
279pub fn check_in_range_inclusive_u64(value: u64, l: u64, r: u64, param: &str) -> anyhow::Result<()> {
280 if value < l || value > r {
281 anyhow::bail!("invalid u64 for '{param}' not in range [{l}, {r}], was {value}")
282 }
283 Ok(())
284}
285
286#[inline(always)]
292pub fn check_in_range_inclusive_i64(value: i64, l: i64, r: i64, param: &str) -> anyhow::Result<()> {
293 if value < l || value > r {
294 anyhow::bail!("invalid i64 for '{param}' not in range [{l}, {r}], was {value}")
295 }
296 Ok(())
297}
298
299#[inline(always)]
305pub fn check_in_range_inclusive_f64(value: f64, l: f64, r: f64, param: &str) -> anyhow::Result<()> {
306 const EPSILON: f64 = 1e-15;
312
313 if value.is_nan() || value.is_infinite() {
314 anyhow::bail!("invalid f64 for '{param}', was {value}")
315 }
316 if value < l - EPSILON || value > r + EPSILON {
317 anyhow::bail!("invalid f64 for '{param}' not in range [{l}, {r}], was {value}")
318 }
319 Ok(())
320}
321
322#[inline(always)]
328pub fn check_in_range_inclusive_usize(
329 value: usize,
330 l: usize,
331 r: usize,
332 param: &str,
333) -> anyhow::Result<()> {
334 if value < l || value > r {
335 anyhow::bail!("invalid usize for '{param}' not in range [{l}, {r}], was {value}")
336 }
337 Ok(())
338}
339
340#[inline(always)]
346pub fn check_slice_empty<T>(slice: &[T], param: &str) -> anyhow::Result<()> {
347 if !slice.is_empty() {
348 anyhow::bail!(
349 "the '{param}' slice `&[{}]` was not empty",
350 std::any::type_name::<T>()
351 )
352 }
353 Ok(())
354}
355
356#[inline(always)]
362pub fn check_slice_not_empty<T>(slice: &[T], param: &str) -> anyhow::Result<()> {
363 if slice.is_empty() {
364 anyhow::bail!(
365 "the '{param}' slice `&[{}]` was empty",
366 std::any::type_name::<T>()
367 )
368 }
369 Ok(())
370}
371
372#[inline(always)]
378pub fn check_map_empty<M>(map: &M, param: &str) -> anyhow::Result<()>
379where
380 M: MapLike,
381{
382 if !map.is_empty() {
383 anyhow::bail!(
384 "the '{param}' map `&<{}, {}>` was not empty",
385 std::any::type_name::<M::Key>(),
386 std::any::type_name::<M::Value>(),
387 );
388 }
389 Ok(())
390}
391
392#[inline(always)]
398pub fn check_map_not_empty<M>(map: &M, param: &str) -> anyhow::Result<()>
399where
400 M: MapLike,
401{
402 if map.is_empty() {
403 anyhow::bail!(
404 "the '{param}' map `&<{}, {}>` was empty",
405 std::any::type_name::<M::Key>(),
406 std::any::type_name::<M::Value>(),
407 );
408 }
409 Ok(())
410}
411
412#[inline(always)]
418pub fn check_key_not_in_map<M>(
419 key: &M::Key,
420 map: &M,
421 key_name: &str,
422 map_name: &str,
423) -> anyhow::Result<()>
424where
425 M: MapLike,
426{
427 if map.contains_key(key) {
428 anyhow::bail!(
429 "the '{key_name}' key {key} was already in the '{map_name}' map `&<{}, {}>`",
430 std::any::type_name::<M::Key>(),
431 std::any::type_name::<M::Value>(),
432 );
433 }
434 Ok(())
435}
436
437#[inline(always)]
443pub fn check_key_in_map<M>(
444 key: &M::Key,
445 map: &M,
446 key_name: &str,
447 map_name: &str,
448) -> anyhow::Result<()>
449where
450 M: MapLike,
451{
452 if !map.contains_key(key) {
453 anyhow::bail!(
454 "the '{key_name}' key {key} was not in the '{map_name}' map `&<{}, {}>`",
455 std::any::type_name::<M::Key>(),
456 std::any::type_name::<M::Value>(),
457 );
458 }
459 Ok(())
460}
461
462#[inline(always)]
468pub fn check_member_not_in_set<S>(
469 member: &S::Item,
470 set: &S,
471 member_name: &str,
472 set_name: &str,
473) -> anyhow::Result<()>
474where
475 S: SetLike,
476{
477 if set.contains(member) {
478 anyhow::bail!(
479 "the '{member_name}' member was already in the '{set_name}' set `&<{}>`",
480 std::any::type_name::<S::Item>(),
481 );
482 }
483 Ok(())
484}
485
486#[inline(always)]
492pub fn check_member_in_set<S>(
493 member: &S::Item,
494 set: &S,
495 member_name: &str,
496 set_name: &str,
497) -> anyhow::Result<()>
498where
499 S: SetLike,
500{
501 if !set.contains(member) {
502 anyhow::bail!(
503 "the '{member_name}' member was not in the '{set_name}' set `&<{}>`",
504 std::any::type_name::<S::Item>(),
505 );
506 }
507 Ok(())
508}
509
510#[cfg(test)]
514mod tests {
515 use std::{
516 collections::{HashMap, HashSet},
517 fmt::Display,
518 };
519
520 use rstest::rstest;
521
522 use super::*;
523
524 #[rstest]
525 #[case(false, false)]
526 #[case(true, true)]
527 fn test_check_predicate_true(#[case] predicate: bool, #[case] expected: bool) {
528 let result = check_predicate_true(predicate, "the predicate was false").is_ok();
529 assert_eq!(result, expected);
530 }
531
532 #[rstest]
533 #[case(false, true)]
534 #[case(true, false)]
535 fn test_check_predicate_false(#[case] predicate: bool, #[case] expected: bool) {
536 let result = check_predicate_false(predicate, "the predicate was true").is_ok();
537 assert_eq!(result, expected);
538 }
539
540 #[rstest]
541 #[case("a")]
542 #[case(" ")] #[case(" ")] #[case("🦀")] #[case(" a")]
546 #[case("a ")]
547 #[case("abc")]
548 fn test_check_nonempty_string_with_valid_values(#[case] s: &str) {
549 assert!(check_nonempty_string(s, "value").is_ok());
550 }
551
552 #[rstest]
553 #[case("")] fn test_check_nonempty_string_with_invalid_values(#[case] s: &str) {
555 assert!(check_nonempty_string(s, "value").is_err());
556 }
557
558 #[rstest]
559 #[case(" a")]
560 #[case("a ")]
561 #[case("a a")]
562 #[case(" a ")]
563 #[case("abc")]
564 fn test_check_valid_string_with_valid_value(#[case] s: &str) {
565 assert!(check_valid_string(s, "value").is_ok());
566 }
567
568 #[rstest]
569 #[case("")] #[case(" ")] #[case(" ")] #[case("🦀")] fn test_check_valid_string_with_invalid_values(#[case] s: &str) {
574 assert!(check_valid_string(s, "value").is_err());
575 }
576
577 #[rstest]
578 #[case(None)]
579 #[case(Some(" a"))]
580 #[case(Some("a "))]
581 #[case(Some("a a"))]
582 #[case(Some(" a "))]
583 #[case(Some("abc"))]
584 fn test_check_valid_string_optional_with_valid_value(#[case] s: Option<&str>) {
585 assert!(check_valid_string_optional(s, "value").is_ok());
586 }
587
588 #[rstest]
589 #[case("a", "a")]
590 fn test_check_string_contains_when_does_contain(#[case] s: &str, #[case] pat: &str) {
591 assert!(check_string_contains(s, pat, "value").is_ok());
592 }
593
594 #[rstest]
595 #[case("a", "b")]
596 fn test_check_string_contains_when_does_not_contain(#[case] s: &str, #[case] pat: &str) {
597 assert!(check_string_contains(s, pat, "value").is_err());
598 }
599
600 #[rstest]
601 #[case(0u8, 0u8, "left", "right", true)]
602 #[case(1u8, 1u8, "left", "right", true)]
603 #[case(0u8, 1u8, "left", "right", false)]
604 #[case(1u8, 0u8, "left", "right", false)]
605 #[case(10i32, 10i32, "left", "right", true)]
606 #[case(10i32, 20i32, "left", "right", false)]
607 #[case("hello", "hello", "left", "right", true)]
608 #[case("hello", "world", "left", "right", false)]
609 fn test_check_equal<T: PartialEq + Debug + Display>(
610 #[case] lhs: T,
611 #[case] rhs: T,
612 #[case] lhs_param: &str,
613 #[case] rhs_param: &str,
614 #[case] expected: bool,
615 ) {
616 let result = check_equal(&lhs, &rhs, lhs_param, rhs_param).is_ok();
617 assert_eq!(result, expected);
618 }
619
620 #[rstest]
621 #[case(0, 0, "left", "right", true)]
622 #[case(1, 1, "left", "right", true)]
623 #[case(0, 1, "left", "right", false)]
624 #[case(1, 0, "left", "right", false)]
625 fn test_check_equal_u8_when_equal(
626 #[case] lhs: u8,
627 #[case] rhs: u8,
628 #[case] lhs_param: &str,
629 #[case] rhs_param: &str,
630 #[case] expected: bool,
631 ) {
632 let result = check_equal_u8(lhs, rhs, lhs_param, rhs_param).is_ok();
633 assert_eq!(result, expected);
634 }
635
636 #[rstest]
637 #[case(0, 0, "left", "right", true)]
638 #[case(1, 1, "left", "right", true)]
639 #[case(0, 1, "left", "right", false)]
640 #[case(1, 0, "left", "right", false)]
641 fn test_check_equal_usize_when_equal(
642 #[case] lhs: usize,
643 #[case] rhs: usize,
644 #[case] lhs_param: &str,
645 #[case] rhs_param: &str,
646 #[case] expected: bool,
647 ) {
648 let result = check_equal_usize(lhs, rhs, lhs_param, rhs_param).is_ok();
649 assert_eq!(result, expected);
650 }
651
652 #[rstest]
653 #[case(1, "value")]
654 fn test_check_positive_u64_when_positive(#[case] value: u64, #[case] param: &str) {
655 assert!(check_positive_u64(value, param).is_ok());
656 }
657
658 #[rstest]
659 #[case(0, "value")]
660 fn test_check_positive_u64_when_not_positive(#[case] value: u64, #[case] param: &str) {
661 assert!(check_positive_u64(value, param).is_err());
662 }
663
664 #[rstest]
665 #[case(1, "value")]
666 fn test_check_positive_i64_when_positive(#[case] value: i64, #[case] param: &str) {
667 assert!(check_positive_i64(value, param).is_ok());
668 }
669
670 #[rstest]
671 #[case(0, "value")]
672 #[case(-1, "value")]
673 fn test_check_positive_i64_when_not_positive(#[case] value: i64, #[case] param: &str) {
674 assert!(check_positive_i64(value, param).is_err());
675 }
676
677 #[rstest]
678 #[case(0.0, "value")]
679 #[case(1.0, "value")]
680 fn test_check_non_negative_f64_when_not_negative(#[case] value: f64, #[case] param: &str) {
681 assert!(check_non_negative_f64(value, param).is_ok());
682 }
683
684 #[rstest]
685 #[case(f64::NAN, "value")]
686 #[case(f64::INFINITY, "value")]
687 #[case(f64::NEG_INFINITY, "value")]
688 #[case(-0.1, "value")]
689 fn test_check_non_negative_f64_when_negative(#[case] value: f64, #[case] param: &str) {
690 assert!(check_non_negative_f64(value, param).is_err());
691 }
692
693 #[rstest]
694 #[case(0, 0, 0, "value")]
695 #[case(0, 0, 1, "value")]
696 #[case(1, 0, 1, "value")]
697 fn test_check_in_range_inclusive_u8_when_in_range(
698 #[case] value: u8,
699 #[case] l: u8,
700 #[case] r: u8,
701 #[case] desc: &str,
702 ) {
703 assert!(check_in_range_inclusive_u8(value, l, r, desc).is_ok());
704 }
705
706 #[rstest]
707 #[case(0, 1, 2, "value")]
708 #[case(3, 1, 2, "value")]
709 fn test_check_in_range_inclusive_u8_when_out_of_range(
710 #[case] value: u8,
711 #[case] l: u8,
712 #[case] r: u8,
713 #[case] param: &str,
714 ) {
715 assert!(check_in_range_inclusive_u8(value, l, r, param).is_err());
716 }
717
718 #[rstest]
719 #[case(0, 0, 0, "value")]
720 #[case(0, 0, 1, "value")]
721 #[case(1, 0, 1, "value")]
722 fn test_check_in_range_inclusive_u64_when_in_range(
723 #[case] value: u64,
724 #[case] l: u64,
725 #[case] r: u64,
726 #[case] param: &str,
727 ) {
728 assert!(check_in_range_inclusive_u64(value, l, r, param).is_ok());
729 }
730
731 #[rstest]
732 #[case(0, 1, 2, "value")]
733 #[case(3, 1, 2, "value")]
734 fn test_check_in_range_inclusive_u64_when_out_of_range(
735 #[case] value: u64,
736 #[case] l: u64,
737 #[case] r: u64,
738 #[case] param: &str,
739 ) {
740 assert!(check_in_range_inclusive_u64(value, l, r, param).is_err());
741 }
742
743 #[rstest]
744 #[case(0, 0, 0, "value")]
745 #[case(0, 0, 1, "value")]
746 #[case(1, 0, 1, "value")]
747 fn test_check_in_range_inclusive_i64_when_in_range(
748 #[case] value: i64,
749 #[case] l: i64,
750 #[case] r: i64,
751 #[case] param: &str,
752 ) {
753 assert!(check_in_range_inclusive_i64(value, l, r, param).is_ok());
754 }
755
756 #[rstest]
757 #[case(0.0, 0.0, 0.0, "value")]
758 #[case(0.0, 0.0, 1.0, "value")]
759 #[case(1.0, 0.0, 1.0, "value")]
760 fn test_check_in_range_inclusive_f64_when_in_range(
761 #[case] value: f64,
762 #[case] l: f64,
763 #[case] r: f64,
764 #[case] param: &str,
765 ) {
766 assert!(check_in_range_inclusive_f64(value, l, r, param).is_ok());
767 }
768
769 #[rstest]
770 #[case(-1e16, 0.0, 0.0, "value")]
771 #[case(1.0 + 1e16, 0.0, 1.0, "value")]
772 fn test_check_in_range_inclusive_f64_when_out_of_range(
773 #[case] value: f64,
774 #[case] l: f64,
775 #[case] r: f64,
776 #[case] param: &str,
777 ) {
778 assert!(check_in_range_inclusive_f64(value, l, r, param).is_err());
779 }
780
781 #[rstest]
782 #[case(0, 1, 2, "value")]
783 #[case(3, 1, 2, "value")]
784 fn test_check_in_range_inclusive_i64_when_out_of_range(
785 #[case] value: i64,
786 #[case] l: i64,
787 #[case] r: i64,
788 #[case] param: &str,
789 ) {
790 assert!(check_in_range_inclusive_i64(value, l, r, param).is_err());
791 }
792
793 #[rstest]
794 #[case(0, 0, 0, "value")]
795 #[case(0, 0, 1, "value")]
796 #[case(1, 0, 1, "value")]
797 fn test_check_in_range_inclusive_usize_when_in_range(
798 #[case] value: usize,
799 #[case] l: usize,
800 #[case] r: usize,
801 #[case] param: &str,
802 ) {
803 assert!(check_in_range_inclusive_usize(value, l, r, param).is_ok());
804 }
805
806 #[rstest]
807 #[case(0, 1, 2, "value")]
808 #[case(3, 1, 2, "value")]
809 fn test_check_in_range_inclusive_usize_when_out_of_range(
810 #[case] value: usize,
811 #[case] l: usize,
812 #[case] r: usize,
813 #[case] param: &str,
814 ) {
815 assert!(check_in_range_inclusive_usize(value, l, r, param).is_err());
816 }
817
818 #[rstest]
819 #[case(vec![], true)]
820 #[case(vec![1_u8], false)]
821 fn test_check_slice_empty(#[case] collection: Vec<u8>, #[case] expected: bool) {
822 let result = check_slice_empty(collection.as_slice(), "param").is_ok();
823 assert_eq!(result, expected);
824 }
825
826 #[rstest]
827 #[case(vec![], false)]
828 #[case(vec![1_u8], true)]
829 fn test_check_slice_not_empty(#[case] collection: Vec<u8>, #[case] expected: bool) {
830 let result = check_slice_not_empty(collection.as_slice(), "param").is_ok();
831 assert_eq!(result, expected);
832 }
833
834 #[rstest]
835 #[case(HashMap::new(), true)]
836 #[case(HashMap::from([("A".to_string(), 1_u8)]), false)]
837 fn test_check_map_empty(#[case] map: HashMap<String, u8>, #[case] expected: bool) {
838 let result = check_map_empty(&map, "param").is_ok();
839 assert_eq!(result, expected);
840 }
841
842 #[rstest]
843 #[case(HashMap::new(), false)]
844 #[case(HashMap::from([("A".to_string(), 1_u8)]), true)]
845 fn test_check_map_not_empty(#[case] map: HashMap<String, u8>, #[case] expected: bool) {
846 let result = check_map_not_empty(&map, "param").is_ok();
847 assert_eq!(result, expected);
848 }
849
850 #[rstest]
851 #[case(&HashMap::<u32, u32>::new(), 5, "key", "map", true)] #[case(&HashMap::from([(1, 10), (2, 20)]), 1, "key", "map", false)] #[case(&HashMap::from([(1, 10), (2, 20)]), 5, "key", "map", true)] fn test_check_key_not_in_map(
855 #[case] map: &HashMap<u32, u32>,
856 #[case] key: u32,
857 #[case] key_name: &str,
858 #[case] map_name: &str,
859 #[case] expected: bool,
860 ) {
861 let result = check_key_not_in_map(&key, map, key_name, map_name).is_ok();
862 assert_eq!(result, expected);
863 }
864
865 #[rstest]
866 #[case(&HashMap::<u32, u32>::new(), 5, "key", "map", false)] #[case(&HashMap::from([(1, 10), (2, 20)]), 1, "key", "map", true)] #[case(&HashMap::from([(1, 10), (2, 20)]), 5, "key", "map", false)] fn test_check_key_in_map(
870 #[case] map: &HashMap<u32, u32>,
871 #[case] key: u32,
872 #[case] key_name: &str,
873 #[case] map_name: &str,
874 #[case] expected: bool,
875 ) {
876 let result = check_key_in_map(&key, map, key_name, map_name).is_ok();
877 assert_eq!(result, expected);
878 }
879
880 #[rstest]
881 #[case(&HashSet::<u32>::new(), 5, "member", "set", true)] #[case(&HashSet::from([1, 2]), 1, "member", "set", false)] #[case(&HashSet::from([1, 2]), 5, "member", "set", true)] fn test_check_member_not_in_set(
885 #[case] set: &HashSet<u32>,
886 #[case] member: u32,
887 #[case] member_name: &str,
888 #[case] set_name: &str,
889 #[case] expected: bool,
890 ) {
891 let result = check_member_not_in_set(&member, set, member_name, set_name).is_ok();
892 assert_eq!(result, expected);
893 }
894
895 #[rstest]
896 #[case(&HashSet::<u32>::new(), 5, "member", "set", false)] #[case(&HashSet::from([1, 2]), 1, "member", "set", true)] #[case(&HashSet::from([1, 2]), 5, "member", "set", false)] fn test_check_member_in_set(
900 #[case] set: &HashSet<u32>,
901 #[case] member: u32,
902 #[case] member_name: &str,
903 #[case] set_name: &str,
904 #[case] expected: bool,
905 ) {
906 let result = check_member_in_set(&member, set, member_name, set_name).is_ok();
907 assert_eq!(result, expected);
908 }
909}