Skip to content

Commit 1efdadb

Browse files
committed
functora-tagged tests
1 parent dc575c3 commit 1efdadb

File tree

5 files changed

+557
-0
lines changed

5 files changed

+557
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use functora_tagged::infallible::InfallibleInto;
2+
use std::convert::Infallible;
3+
4+
#[test]
5+
fn test_infallible_into() {
6+
let result_ok: Result<i32, Infallible> = Ok(10);
7+
assert_eq!(result_ok.infallible(), 10);
8+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
use derive_more::Display;
2+
use functora_tagged::parse_error::ParseError;
3+
use functora_tagged::refine::Refine;
4+
use std::error::Error;
5+
use std::fmt::Debug;
6+
7+
#[derive(Debug, Display, PartialEq, Eq, Clone)]
8+
struct MyRefineError;
9+
10+
impl Error for MyRefineError {}
11+
12+
#[derive(Debug, Display)]
13+
struct MyTag;
14+
15+
impl Refine<i32> for MyTag {
16+
type RefineError = MyRefineError;
17+
18+
fn refine(rep: i32) -> Result<i32, Self::RefineError> {
19+
if rep > 0 { Ok(rep) } else { Err(MyRefineError) }
20+
}
21+
}
22+
23+
type TestParseError = ParseError<i32, MyTag>;
24+
25+
#[test]
26+
fn test_parse_error_decode() {
27+
let decode_err = "abc".parse::<i32>().unwrap_err();
28+
let parse_error =
29+
TestParseError::Decode(decode_err.clone());
30+
31+
let formatted_error = format!("{}", parse_error);
32+
assert!(
33+
formatted_error.contains(&decode_err.to_string())
34+
);
35+
36+
let debug_formatted_error =
37+
format!("{:?}", parse_error);
38+
assert_eq!(
39+
debug_formatted_error,
40+
"Decode(ParseIntError { kind: InvalidDigit })"
41+
);
42+
43+
assert_eq!(
44+
parse_error,
45+
TestParseError::Decode(decode_err)
46+
);
47+
assert_ne!(
48+
parse_error,
49+
TestParseError::Refine(MyRefineError)
50+
);
51+
assert_eq!(parse_error.clone(), parse_error);
52+
}
53+
54+
#[test]
55+
fn test_parse_error_refine() {
56+
let refine_err = MyRefineError;
57+
let parse_error =
58+
TestParseError::Refine(refine_err.clone());
59+
60+
let formatted_error = format!("{}", parse_error);
61+
assert!(
62+
formatted_error.contains(&refine_err.to_string())
63+
);
64+
65+
let debug_formatted_error =
66+
format!("{:?}", parse_error);
67+
assert_eq!(
68+
debug_formatted_error,
69+
"Refine(MyRefineError)"
70+
);
71+
72+
assert_eq!(
73+
parse_error,
74+
TestParseError::Refine(refine_err)
75+
);
76+
let decode_err_for_neq =
77+
"abc".parse::<i32>().unwrap_err();
78+
assert_ne!(
79+
parse_error,
80+
TestParseError::Decode(decode_err_for_neq)
81+
);
82+
assert_eq!(parse_error.clone(), parse_error);
83+
}
84+
85+
#[test]
86+
fn test_parse_error_eq() {
87+
let decode_err1 = "abc".parse::<i32>().unwrap_err();
88+
let decode_err2 = "abc".parse::<i32>().unwrap_err();
89+
let refine_err1 = MyRefineError;
90+
91+
let err_decode1 =
92+
TestParseError::Decode(decode_err1.clone());
93+
let err_decode2 =
94+
TestParseError::Decode(decode_err2.clone());
95+
96+
let err_refine1 =
97+
TestParseError::Refine(refine_err1.clone());
98+
let err_refine2 =
99+
TestParseError::Refine(refine_err1.clone());
100+
101+
assert_eq!(err_decode1, err_decode2);
102+
assert_eq!(err_refine1, err_refine2);
103+
assert_ne!(err_decode1, err_refine1);
104+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use derive_more::Display;
2+
use functora_tagged::refine::Refine;
3+
use std::error::Error;
4+
use std::fmt::Debug;
5+
6+
#[derive(Debug, Display, PartialEq, Eq, Clone)]
7+
struct MyRefineError;
8+
9+
impl Error for MyRefineError {}
10+
11+
#[derive(Debug)]
12+
struct MyTag;
13+
14+
impl Refine<String> for MyTag {
15+
type RefineError = MyRefineError;
16+
17+
fn refine(
18+
rep: String,
19+
) -> Result<String, Self::RefineError> {
20+
Ok(rep)
21+
}
22+
}
23+
24+
#[test]
25+
fn test_refine_default_implementation() {
26+
let rep_value = String::from("test_string");
27+
let refined_rep = MyTag::refine(rep_value.clone());
28+
29+
assert!(refined_rep.is_ok());
30+
assert_eq!(refined_rep.unwrap(), rep_value);
31+
}
32+
33+
struct StrictTag;
34+
35+
impl Refine<String> for StrictTag {
36+
type RefineError = String;
37+
38+
fn refine(
39+
rep: String,
40+
) -> Result<String, Self::RefineError> {
41+
if rep.starts_with("strict_") {
42+
Ok(rep)
43+
} else {
44+
Err(format!(
45+
"String must start with 'strict_': {}",
46+
rep
47+
))
48+
}
49+
}
50+
}
51+
52+
#[test]
53+
fn test_refine_custom_implementation() {
54+
let strict_value = String::from("strict_value");
55+
let refined_strict =
56+
StrictTag::refine(strict_value.clone());
57+
assert!(refined_strict.is_ok());
58+
assert_eq!(refined_strict.unwrap(), strict_value);
59+
60+
let non_strict_value = String::from("non_strict_value");
61+
let refined_non_strict =
62+
StrictTag::refine(non_strict_value.clone());
63+
assert!(refined_non_strict.is_err());
64+
assert_eq!(
65+
refined_non_strict.unwrap_err(),
66+
format!(
67+
"String must start with 'strict_': {}",
68+
non_strict_value
69+
)
70+
);
71+
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
use derive_more::Display;
2+
use functora_tagged::parse_error::ParseError;
3+
use functora_tagged::refine::Refine;
4+
use functora_tagged::tagged::Tagged;
5+
use std::fmt::Debug;
6+
use std::hash::{Hash, Hasher};
7+
use std::str::FromStr;
8+
9+
#[derive(Debug, Display, PartialEq, Eq, Clone)]
10+
struct MyRefineError;
11+
12+
impl std::error::Error for MyRefineError {}
13+
14+
#[derive(Debug)]
15+
struct MyTag;
16+
17+
impl Refine<i32> for MyTag {
18+
type RefineError = MyRefineError;
19+
20+
fn refine(rep: i32) -> Result<i32, Self::RefineError> {
21+
if rep >= 0 {
22+
Ok(rep)
23+
} else {
24+
Err(MyRefineError)
25+
}
26+
}
27+
}
28+
29+
type TestTagged = Tagged<i32, MyTag>;
30+
type TestParseError = ParseError<i32, MyTag>;
31+
32+
#[test]
33+
fn test_tagged_new() {
34+
let rep_value = 10;
35+
let tagged_instance = TestTagged::new(rep_value);
36+
assert!(tagged_instance.is_ok());
37+
assert_eq!(tagged_instance.unwrap().rep(), &rep_value);
38+
39+
let negative_rep_value = -5;
40+
let tagged_instance_err =
41+
TestTagged::new(negative_rep_value);
42+
assert!(tagged_instance_err.is_err());
43+
assert_eq!(
44+
tagged_instance_err.unwrap_err(),
45+
MyRefineError
46+
);
47+
}
48+
49+
#[test]
50+
fn test_tagged_rep() {
51+
let rep_value = 20;
52+
let tagged_instance =
53+
TestTagged::new(rep_value).unwrap();
54+
assert_eq!(tagged_instance.rep(), &rep_value);
55+
}
56+
57+
#[test]
58+
fn test_tagged_eq_partial_eq() {
59+
let tagged1 = TestTagged::new(30).unwrap();
60+
let tagged2 = TestTagged::new(30).unwrap();
61+
let tagged3 = TestTagged::new(40).unwrap();
62+
63+
assert_eq!(tagged1, tagged2);
64+
assert_ne!(tagged1, tagged3);
65+
}
66+
67+
#[test]
68+
fn test_tagged_ord_partial_ord() {
69+
let tagged1 = TestTagged::new(50).unwrap();
70+
let tagged2 = TestTagged::new(50).unwrap();
71+
let tagged3 = TestTagged::new(60).unwrap();
72+
let tagged4 = TestTagged::new(40).unwrap();
73+
74+
assert_eq!(
75+
tagged1.cmp(&tagged2),
76+
std::cmp::Ordering::Equal
77+
);
78+
assert_eq!(
79+
tagged1.partial_cmp(&tagged2),
80+
Some(std::cmp::Ordering::Equal)
81+
);
82+
83+
assert_eq!(
84+
tagged1.cmp(&tagged3),
85+
std::cmp::Ordering::Less
86+
);
87+
assert_eq!(
88+
tagged1.partial_cmp(&tagged3),
89+
Some(std::cmp::Ordering::Less)
90+
);
91+
92+
assert_eq!(
93+
tagged1.cmp(&tagged4),
94+
std::cmp::Ordering::Greater
95+
);
96+
assert_eq!(
97+
tagged1.partial_cmp(&tagged4),
98+
Some(std::cmp::Ordering::Greater)
99+
);
100+
}
101+
102+
#[test]
103+
fn test_tagged_clone() {
104+
let tagged1 = TestTagged::new(70).unwrap();
105+
let tagged2 = tagged1.clone();
106+
107+
assert_eq!(tagged1, tagged2);
108+
assert_eq!(tagged1.rep(), tagged2.rep());
109+
}
110+
111+
#[test]
112+
fn test_tagged_display() {
113+
let tagged_instance = TestTagged::new(80).unwrap();
114+
assert_eq!(tagged_instance.to_string(), "80");
115+
}
116+
117+
#[test]
118+
fn test_tagged_hash() {
119+
let tagged1 = TestTagged::new(90).unwrap();
120+
let tagged2 = TestTagged::new(90).unwrap();
121+
let tagged3 = TestTagged::new(100).unwrap();
122+
123+
let mut hasher1 =
124+
std::collections::hash_map::DefaultHasher::new();
125+
tagged1.hash(&mut hasher1);
126+
let hash1 = hasher1.finish();
127+
128+
let mut hasher2 =
129+
std::collections::hash_map::DefaultHasher::new();
130+
tagged2.hash(&mut hasher2);
131+
let hash2 = hasher2.finish();
132+
133+
let mut hasher3 =
134+
std::collections::hash_map::DefaultHasher::new();
135+
tagged3.hash(&mut hasher3);
136+
let hash3 = hasher3.finish();
137+
138+
assert_eq!(hash1, hash2);
139+
assert_ne!(hash1, hash3);
140+
}
141+
142+
#[test]
143+
fn test_tagged_deref() {
144+
let rep_value = 110;
145+
let tagged_instance =
146+
TestTagged::new(rep_value).unwrap();
147+
assert_eq!(*tagged_instance, rep_value);
148+
assert_eq!(tagged_instance.abs(), rep_value.abs());
149+
}
150+
151+
#[test]
152+
fn test_tagged_from_str() {
153+
let s_ok = "120";
154+
let tagged_ok = TestTagged::from_str(s_ok).unwrap();
155+
assert_eq!(tagged_ok.rep(), &120);
156+
157+
let s_decode_err = "abc";
158+
let parse_result_decode: Result<
159+
TestTagged,
160+
TestParseError,
161+
> = FromStr::from_str(s_decode_err);
162+
assert!(parse_result_decode.is_err());
163+
match parse_result_decode.unwrap_err() {
164+
TestParseError::Decode(_) => {}
165+
_ => panic!("Expected Decode error"),
166+
}
167+
168+
let s_refine_err = "-10";
169+
let parse_result_refine: Result<
170+
TestTagged,
171+
TestParseError,
172+
> = FromStr::from_str(s_refine_err);
173+
assert!(parse_result_refine.is_err());
174+
match parse_result_refine.unwrap_err() {
175+
TestParseError::Refine(_) => {}
176+
_ => panic!("Expected Refine error"),
177+
}
178+
}

0 commit comments

Comments
 (0)