aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Walters <rwalters@digitalstirling.com>2020-10-14 23:56:26 -0700
committerRichard Walters <rwalters@digitalstirling.com>2020-10-14 23:56:26 -0700
commit4bb39345ab9cfcaecf9a5aae7dda1b08a6ab490e (patch)
tree5a6b4c287452782861632438174eafedb5891bb2
parent03b82171f70815e43fbc64d120a20e7a1eebd0bc (diff)
Distribute tests closer to the code they test
-rw-r--r--src/authority.rs146
-rw-r--r--src/parse_host_port.rs91
-rw-r--r--src/uri.rs330
-rw-r--r--src/validate_ipv4_address.rs53
-rw-r--r--src/validate_ipv6_address.rs65
5 files changed, 374 insertions, 311 deletions
diff --git a/src/authority.rs b/src/authority.rs
index 955816c..18d86fa 100644
--- a/src/authority.rs
+++ b/src/authority.rs
@@ -151,3 +151,149 @@ impl std::fmt::Display for Authority {
Ok(())
}
}
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn userinfo() {
+ named_tuple!(
+ struct TestVector {
+ authority_string: &'static str,
+ userinfo: Option<&'static str>,
+ }
+ );
+ let test_vectors: &[TestVector] = &[
+ ("www.example.com", None).into(),
+ ("joe@www.example.com", Some("joe")).into(),
+ ("pepe:feelsbadman@www.example.com", Some("pepe:feelsbadman")).into(),
+ ];
+ for test_vector in test_vectors {
+ let authority = Authority::parse(test_vector.authority_string());
+ assert!(authority.is_ok());
+ let authority = authority.unwrap();
+ assert_eq!(
+ test_vector.userinfo().map(str::as_bytes),
+ authority.userinfo.as_ref().map(|v| &v[..])
+ );
+ }
+ }
+
+ #[test]
+ fn userinfo_illegal_characters() {
+ let test_vectors = [
+ "%X@www.example.com",
+ "{@www.example.com",
+ ];
+ for test_vector in &test_vectors {
+ let authority = Authority::parse(test_vector);
+ assert!(authority.is_err());
+ }
+ }
+
+ #[test]
+ fn userinfo_barely_legal() {
+ named_tuple!(
+ struct TestVector {
+ uri_string: &'static str,
+ userinfo: &'static str
+ }
+ );
+ let test_vectors: &[TestVector] = &[
+ ("%41@www.example.com", "A").into(),
+ ("@www.example.com", "").into(),
+ ("!@www.example.com", "!").into(),
+ ("'@www.example.com", "'").into(),
+ ("(@www.example.com", "(").into(),
+ (";@www.example.com", ";").into(),
+ (":@www.example.com", ":").into(),
+ ];
+ for test_vector in test_vectors {
+ let authority = Authority::parse(test_vector.uri_string());
+ assert!(authority.is_ok());
+ let authority = authority.unwrap();
+ assert_eq!(
+ Some(test_vector.userinfo().as_bytes()),
+ authority.userinfo.as_ref().map(|v| &v[..])
+ );
+ }
+ }
+
+ #[test]
+ fn host_illegal_characters() {
+ let test_vectors = [
+ "%X@www.example.com",
+ "@www:example.com",
+ "[vX.:]",
+ ];
+ for test_vector in &test_vectors {
+ let authority = Authority::parse(test_vector);
+ assert!(authority.is_err());
+ }
+ }
+
+ #[test]
+ fn host_barely_legal() {
+ named_tuple!(
+ struct TestVector {
+ authority_string: &'static str,
+ host: &'static str
+ }
+ );
+ let test_vectors: &[TestVector] = &[
+ ("%41", "a").into(),
+ ("", "").into(),
+ ("!", "!").into(),
+ ("'", "'").into(),
+ ("(", "(").into(),
+ (";", ";").into(),
+ ("1.2.3.4", "1.2.3.4").into(),
+ ("[v7.:]", "v7.:").into(),
+ ("[v7.aB]", "v7.aB").into(),
+ ];
+ for test_vector in test_vectors {
+ let authority = Authority::parse(test_vector.authority_string());
+ assert!(authority.is_ok());
+ let authority = authority.unwrap();
+ assert_eq!(
+ test_vector.host().as_bytes(),
+ authority.host()
+ );
+ }
+ }
+
+ #[test]
+ fn host_ends_in_dot() {
+ let authority = Authority::parse("example.com.");
+ assert!(authority.is_ok());
+ let authority = authority.unwrap();
+ assert_eq!(
+ b"example.com.",
+ authority.host()
+ );
+ }
+
+ #[test]
+ fn host_mixed_case() {
+ let test_vectors = [
+ "www.example.com",
+ "www.EXAMPLE.com",
+ "www.exAMple.com",
+ "www.example.cOM",
+ "wWw.exampLe.Com",
+ ];
+ let normalized_host = "www.example.com";
+ for test_vector in &test_vectors {
+ let authority = Authority::parse(*test_vector);
+ assert!(authority.is_ok());
+ let authority = authority.unwrap();
+ assert_eq!(
+ normalized_host.as_bytes(),
+ authority.host()
+ );
+ }
+ }
+
+}
diff --git a/src/parse_host_port.rs b/src/parse_host_port.rs
index ae4a278..abb34e1 100644
--- a/src/parse_host_port.rs
+++ b/src/parse_host_port.rs
@@ -203,3 +203,94 @@ pub fn parse_host_port<T>(host_port_string: T) -> Result<(Vec<u8>, Option<u16>),
})?
.finalize()
}
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn non_empty_port_number() {
+ let result = parse_host_port("www.example.com:8080");
+ assert!(result.is_ok());
+ let (host, port) = result.unwrap();
+ assert_eq!(b"www.example.com", &host[..]);
+ assert_eq!(Some(8080), port);
+ }
+
+ #[test]
+ fn empty_port_number() {
+ let result = parse_host_port("www.example.com:");
+ assert!(result.is_ok());
+ let (host, port) = result.unwrap();
+ assert_eq!(b"www.example.com", &host[..]);
+ assert_eq!(None, port);
+ }
+
+ #[test]
+ fn no_port_number() {
+ let result = parse_host_port("www.example.com");
+ assert!(result.is_ok());
+ let (host, port) = result.unwrap();
+ assert_eq!(b"www.example.com", &host[..]);
+ assert_eq!(None, port);
+ }
+
+ #[test]
+ fn bad_port_number_purly_alphabetic() {
+ let result = parse_host_port("www.example.com:spam");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn bad_port_number_starts_numeric_ends_alphabetic() {
+ let result = parse_host_port("www.example.com:8080spam");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn largest_valid_port_number() {
+ let result = parse_host_port("www.example.com:65535");
+ assert!(result.is_ok());
+ let (_, port) = result.unwrap();
+ assert_eq!(Some(65535), port);
+ }
+
+ #[test]
+ fn bad_port_number_too_big() {
+ let result = parse_host_port("www.example.com:65536");
+ assert!(matches!(result, Err(Error::IllegalPortNumber(_))));
+ }
+
+ #[test]
+ fn bad_port_number_negative() {
+ let result = parse_host_port("www.example.com:-1234");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn truncated_host() {
+ let test_vectors = [
+ "[::ffff:1.2.3.4/",
+ "[:]/",
+ "[v]/",
+ ];
+ for test_vector in &test_vectors {
+ assert_eq!(
+ Err(Error::TruncatedHost),
+ parse_host_port(test_vector),
+ "{}",
+ test_vector
+ );
+ }
+ }
+
+ #[test]
+ fn ipv6_address_with_ipv4_part_missing_bracket() {
+ assert!(matches!(
+ parse_host_port("::ffff:1.2.3.4]"),
+ Err(Error::IllegalPortNumber(_))
+ ));
+ }
+
+}
diff --git a/src/uri.rs b/src/uri.rs
index 3cb235b..b9e7266 100644
--- a/src/uri.rs
+++ b/src/uri.rs
@@ -748,7 +748,7 @@ mod tests {
use super::*;
#[test]
- fn parse_from_string_no_scheme() {
+ fn no_scheme() {
let uri = Uri::parse("foo/bar");
assert!(uri.is_ok());
let uri = uri.unwrap();
@@ -758,7 +758,7 @@ mod tests {
}
#[test]
- fn parse_from_string_url() {
+ fn url() {
let uri = Uri::parse("http://www.example.com/foo/bar");
assert!(uri.is_ok());
let uri = uri.unwrap();
@@ -769,7 +769,7 @@ mod tests {
}
#[test]
- fn parse_from_string_urn_default_path_delimiter() {
+ fn urn_default_path_delimiter() {
let uri = Uri::parse("urn:book:fantasy:Hobbit");
assert!(uri.is_ok());
let uri = uri.unwrap();
@@ -779,7 +779,7 @@ mod tests {
}
#[test]
- fn parse_from_string_path_corner_cases() {
+ fn path_corner_cases() {
named_tuple!(
struct TestVector {
path_in: &'static str,
@@ -801,82 +801,13 @@ mod tests {
}
#[test]
- fn parse_from_string_has_a_non_empty_port_number() {
- let uri = Uri::parse("http://www.example.com:8080/foo/bar");
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(Some("www.example.com"), uri.host_to_string().unwrap().as_deref());
- assert_eq!(Some(8080), uri.port());
- }
-
- #[test]
- fn parse_from_string_has_an_empty_port_number() {
- let uri = Uri::parse("http://www.example.com:/foo/bar");
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(Some("www.example.com"), uri.host_to_string().unwrap().as_deref());
- assert_eq!(None, uri.port());
- }
-
- #[test]
- fn parse_from_string_does_not_have_a_port_number() {
- let uri = Uri::parse("http://www.example.com/foo/bar");
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(Some("www.example.com"), uri.host_to_string().unwrap().as_deref());
- assert_eq!(None, uri.port());
- }
-
- #[test]
- fn parse_from_string_twice_first_with_port_number_then_without() {
- let uri = Uri::parse("http://www.example.com:8080/foo/bar");
- assert!(uri.is_ok());
- let uri = Uri::parse("http://www.example.com/foo/bar");
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(None, uri.port());
- }
-
- #[test]
- fn parse_from_string_bad_port_number_purly_alphabetic() {
- let uri = Uri::parse("http://www.example.com:spam/foo/bar");
- assert!(uri.is_err());
- }
-
- #[test]
- fn parse_from_string_bad_port_number_starts_numeric_ends_alphabetic() {
- let uri = Uri::parse("http://www.example.com:8080spam/foo/bar");
- assert!(uri.is_err());
- }
-
- #[test]
- fn parse_from_string_largest_valid_port_number() {
- let uri = Uri::parse("http://www.example.com:65535/foo/bar");
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(Some(65535), uri.port());
- }
-
- #[test]
- fn parse_from_string_bad_port_number_too_big() {
- let uri = Uri::parse("http://www.example.com:65536/foo/bar");
- assert!(matches!(uri, Err(Error::IllegalPortNumber(_))));
- }
-
- #[test]
- fn parse_from_string_bad_port_number_negative() {
- let uri = Uri::parse("http://www.example.com:-1234/foo/bar");
- assert!(uri.is_err());
- }
-
- #[test]
- fn parse_from_string_ends_after_authority() {
+ fn uri_ends_after_authority() {
let uri = Uri::parse("http://www.example.com");
assert!(uri.is_ok());
}
#[test]
- fn parse_from_string_relative_vs_non_relative_references() {
+ fn relative_vs_non_relative_references() {
named_tuple!(
struct TestVector {
uri_string: &'static str,
@@ -901,7 +832,7 @@ mod tests {
}
#[test]
- fn parse_from_string_relative_vs_non_relative_paths() {
+ fn relative_vs_non_relative_paths() {
named_tuple!(
struct TestVector {
uri_string: &'static str,
@@ -932,7 +863,7 @@ mod tests {
}
#[test]
- fn parse_from_string_query_and_fragment_elements() {
+ fn query_and_fragment_elements() {
named_tuple!(
struct TestVector {
uri_string: &'static str,
@@ -968,45 +899,7 @@ mod tests {
}
#[test]
- fn parse_from_string_user_info() {
- named_tuple!(
- struct TestVector {
- uri_string: &'static str,
- userinfo: Option<&'static str>,
- }
- );
- let test_vectors: &[TestVector] = &[
- ("http://www.example.com/", None).into(),
- ("http://joe@www.example.com", Some("joe")).into(),
- ("http://pepe:feelsbadman@www.example.com", Some("pepe:feelsbadman")).into(),
- ("//www.example.com", None).into(),
- ("//bob@www.example.com", Some("bob")).into(),
- ("/", None).into(),
- ("foo", None).into(),
- ];
- for test_vector in test_vectors {
- let uri = Uri::parse(test_vector.uri_string());
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(
- *test_vector.userinfo(),
- uri.userinfo_to_string().unwrap().as_deref()
- );
- }
- }
-
- #[test]
- fn parse_from_string_twice_first_user_info_then_without() {
- let uri = Uri::parse("http://joe@www.example.com/foo/bar");
- assert!(uri.is_ok());
- let uri = Uri::parse("/foo/bar");
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(None, uri.userinfo());
- }
-
- #[test]
- fn parse_from_string_scheme_illegal_characters() {
+ fn scheme_illegal_characters() {
let test_vectors = [
"://www.example.com/",
"0://www.example.com/",
@@ -1022,7 +915,7 @@ mod tests {
}
#[test]
- fn parse_from_string_scheme_barely_legal() {
+ fn scheme_barely_legal() {
named_tuple!(
struct TestVector {
uri_string: &'static str,
@@ -1046,7 +939,7 @@ mod tests {
}
#[test]
- fn parse_from_string_scheme_mixed_case () {
+ fn scheme_mixed_case () {
let test_vectors = [
"http://www.example.com/",
"hTtp://www.example.com/",
@@ -1063,116 +956,7 @@ mod tests {
}
#[test]
- fn parse_from_string_user_info_illegal_characters() {
- let test_vectors = [
- "//%X@www.example.com/",
- "//{@www.example.com/",
- ];
- for test_vector in &test_vectors {
- let uri = Uri::parse(test_vector);
- assert!(uri.is_err());
- }
- }
-
- #[test]
- fn parse_from_string_user_info_barely_legal() {
- named_tuple!(
- struct TestVector {
- uri_string: &'static str,
- userinfo: &'static str
- }
- );
- let test_vectors: &[TestVector] = &[
- ("//%41@www.example.com/", "A").into(),
- ("//@www.example.com/", "").into(),
- ("//!@www.example.com/", "!").into(),
- ("//'@www.example.com/", "'").into(),
- ("//(@www.example.com/", "(").into(),
- ("//;@www.example.com/", ";").into(),
- ("http://:@www.example.com/", ":").into(),
- ];
- for test_vector in test_vectors {
- let uri = Uri::parse(test_vector.uri_string());
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(
- Some(*test_vector.userinfo()),
- uri.userinfo_to_string().unwrap().as_deref()
- );
- }
- }
-
- #[test]
- fn parse_from_string_host_illegal_characters() {
- let test_vectors = [
- "//%X@www.example.com/",
- "//@www:example.com/",
- "//[vX.:]/",
- ];
- for test_vector in &test_vectors {
- let uri = Uri::parse(test_vector);
- assert!(uri.is_err());
- }
- }
-
- #[test]
- fn parse_from_string_host_barely_legal() {
- named_tuple!(
- struct TestVector {
- uri_string: &'static str,
- host: &'static str
- }
- );
- let test_vectors: &[TestVector] = &[
- ("//%41/", "a").into(),
- ("///", "").into(),
- ("//!/", "!").into(),
- ("//'/", "'").into(),
- ("//(/", "(").into(),
- ("//;/", ";").into(),
- ("//1.2.3.4/", "1.2.3.4").into(),
- ("//[v7.:]/", "v7.:").into(),
- ("//[v7.aB]/", "v7.aB").into(),
- ];
- for test_vector in test_vectors {
- let uri = Uri::parse(test_vector.uri_string());
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(Some(*test_vector.host()), uri.host_to_string().unwrap().as_deref());
- }
- }
-
- #[test]
- fn parse_from_string_host_mixed_case() {
- let test_vectors = [
- "http://www.example.com/",
- "http://www.EXAMPLE.com/",
- "http://www.exAMple.com/",
- "http://www.example.cOM/",
- "http://wWw.exampLe.Com/",
- ];
- let normalized_host = "www.example.com";
- for test_vector in &test_vectors {
- let uri = Uri::parse(*test_vector);
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(
- Some(normalized_host),
- uri.host_to_string().unwrap().as_deref()
- );
- }
- }
-
- #[test]
- fn parse_from_string_host_ends_in_dot() {
- let uri = Uri::parse("http://example.com./foo");
- assert!(uri.is_ok());
- let uri = uri.unwrap();
- assert_eq!(Some("example.com."), uri.host_to_string().unwrap().as_deref());
- }
-
- #[test]
- fn parse_from_string_dont_misinterpret_colon_in_other_places_as_scheme_delimiter() {
+ fn dont_misinterpret_colon_in_other_places_as_scheme_delimiter() {
let test_vectors = [
"//foo:bar@www.example.com/",
"//www.example.com/a:b",
@@ -1190,7 +974,7 @@ mod tests {
}
#[test]
- fn parse_from_string_path_illegal_characters() {
+ fn path_illegal_characters() {
let test_vectors = [
"http://www.example.com/foo[bar",
"http://www.example.com/]bar",
@@ -1220,7 +1004,7 @@ mod tests {
}
#[test]
- fn parse_from_string_path_barely_legal() {
+ fn path_barely_legal() {
named_tuple!(
struct TestVector {
uri_string: &'static str,
@@ -1243,7 +1027,7 @@ mod tests {
}
#[test]
- fn parse_from_string_query_illegal_characters() {
+ fn query_illegal_characters() {
let test_vectors = [
"http://www.example.com/?foo[bar",
"http://www.example.com/?]bar",
@@ -1273,7 +1057,7 @@ mod tests {
}
#[test]
- fn parse_from_string_query_barely_legal() {
+ fn query_barely_legal() {
named_tuple!(
struct TestVector {
uri_string: &'static str,
@@ -1301,7 +1085,7 @@ mod tests {
}
#[test]
- fn parse_from_string_fragment_illegal_characters() {
+ fn fragment_illegal_characters() {
let test_vectors = [
"http://www.example.com/#foo[bar",
"http://www.example.com/#]bar",
@@ -1331,7 +1115,7 @@ mod tests {
}
#[test]
- fn parse_from_string_fragment_barely_legal() {
+ fn fragment_barely_legal() {
named_tuple!(
struct TestVector {
uri_string: &'static str,
@@ -1358,7 +1142,7 @@ mod tests {
}
#[test]
- fn parse_from_string_paths_with_percent_encoded_characters() {
+ fn paths_with_percent_encoded_characters() {
named_tuple!(
struct TestVector {
uri_string: &'static str,
@@ -1540,82 +1324,6 @@ mod tests {
}
#[test]
- fn ipv6_address_good() {
- named_tuple!(
- struct TestVector {
- uri_string: &'static str,
- expected_host: &'static str,
- }
- );
- let test_vectors: &[TestVector] = &[
- ("http://[::1]/", "::1").into(),
- ("http://[::ffff:1.2.3.4]/", "::ffff:1.2.3.4").into(),
- ("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/", "2001:db8:85a3:8d3:1319:8a2e:370:7348").into(),
- ("http://[2001:db8:85a3:8d3:1319:8a2e:370::]/", "2001:db8:85a3:8d3:1319:8a2e:370::").into(),
- ("http://[2001:db8:85a3:8d3:1319:8a2e::1]/", "2001:db8:85a3:8d3:1319:8a2e::1").into(),
- ("http://[fFfF::1]", "fFfF::1").into(),
- ("http://[1234::1]", "1234::1").into(),
- ("http://[fFfF:1:2:3:4:5:6:a]", "fFfF:1:2:3:4:5:6:a").into(),
- ("http://[2001:db8:85a3::8a2e:0]/", "2001:db8:85a3::8a2e:0").into(),
- ("http://[2001:db8:85a3:8a2e::]/", "2001:db8:85a3:8a2e::").into(),
- ];
- for test_vector in test_vectors {
- let uri = Uri::parse(test_vector.uri_string());
- assert!(uri.is_ok());
- assert_eq!(
- Some(*test_vector.expected_host()),
- uri.unwrap().host_to_string().unwrap().as_deref()
- );
- }
- }
-
- #[test]
- fn ipv6_address_bad() {
- named_tuple!(
- struct TestVector {
- uri_string: &'static str,
- expected_error: Error,
- }
- );
- let test_vectors: &[TestVector] = &[
- ("http://[::fFfF::1]", Error::TooManyDoubleColons).into(),
- ("http://[::ffff:1.2.x.4]/", Error::IllegalCharacter(Context::Ipv4Address)).into(),
- ("http://[::ffff:1.2.3.4.8]/", Error::TooManyAddressParts).into(),
- ("http://[::ffff:1.2.3]/", Error::TooFewAddressParts).into(),
- ("http://[::ffff:1.2.3.]/", Error::TruncatedHost).into(),
- ("http://[::ffff:1.2.3.256]/", Error::InvalidDecimalOctet).into(),
- ("http://[::fxff:1.2.3.4]/", Error::IllegalCharacter(Context::Ipv6Address)).into(),
- ("http://[::ffff:1.2.3.-4]/", Error::IllegalCharacter(Context::Ipv4Address)).into(),
- ("http://[::ffff:1.2.3. 4]/", Error::IllegalCharacter(Context::Ipv4Address)).into(),
- ("http://[::ffff:1.2.3.4 ]/", Error::IllegalCharacter(Context::Ipv4Address)).into(),
- ("http://[::ffff:1.2.3.4/", Error::TruncatedHost).into(),
- ("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348:0000]/", Error::TooManyAddressParts).into(),
- ("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348::1]/", Error::TooManyAddressParts).into(),
- ("http://[2001:db8:85a3:8d3:1319:8a2e:370::1]/", Error::TooManyAddressParts).into(),
- ("http://[2001:db8:85a3::8a2e:0:]/", Error::TruncatedHost).into(),
- ("http://[2001:db8:85a3::8a2e::]/", Error::TooManyDoubleColons).into(),
- ("http://[20001:db8:85a3::1]/", Error::TooManyDigits).into(),
- ("http://[]/", Error::TooFewAddressParts).into(),
- ("http://[:]/", Error::TruncatedHost).into(),
- ("http://[v]/", Error::TruncatedHost).into(),
- ];
- for test_vector in test_vectors {
- let uri = Uri::parse(test_vector.uri_string());
- assert_eq!(
- *test_vector.expected_error(),
- uri.unwrap_err(),
- "{}",
- test_vector.uri_string()
- );
- }
-
- // This is a special case because std::num doesn't trust that we're
- // good enough to make our own ParseIntError values. FeelsBadMan
- let uri = Uri::parse("http://::ffff:1.2.3.4]/");
- assert!(matches!(uri, Err(Error::IllegalPortNumber(_))));
- }
-
- #[test]
// NOTE: `clippy::too_many_arguments` lint has to be disabled at the
// test level because it's triggered inside the `named_tuple!` macro
// expansion.
diff --git a/src/validate_ipv4_address.rs b/src/validate_ipv4_address.rs
index 1b9f7b2..98254df 100644
--- a/src/validate_ipv4_address.rs
+++ b/src/validate_ipv4_address.rs
@@ -94,3 +94,56 @@ pub fn validate_ipv4_address<T>(address: T) -> Result<(), Error>
})?
.finalize()
}
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn good() {
+ let test_vectors = [
+ "0.0.0.0",
+ "1.2.3.0",
+ "1.2.3.4",
+ "1.2.3.255",
+ "1.2.255.4",
+ "1.255.3.4",
+ "255.2.3.4",
+ "255.255.255.255",
+ ];
+ for test_vector in &test_vectors {
+ assert!(validate_ipv4_address(*test_vector).is_ok());
+ }
+ }
+
+ #[test]
+ fn bad() {
+ named_tuple!(
+ struct TestVector {
+ address_string: &'static str,
+ expected_error: Error,
+ }
+ );
+ let test_vectors: &[TestVector] = &[
+ ("1.2.x.4", Error::IllegalCharacter(Context::Ipv4Address)).into(),
+ ("1.2.3.4.8", Error::TooManyAddressParts).into(),
+ ("1.2.3", Error::TooFewAddressParts).into(),
+ ("1.2.3.", Error::TruncatedHost).into(),
+ ("1.2.3.256", Error::InvalidDecimalOctet).into(),
+ ("1.2.3.-4", Error::IllegalCharacter(Context::Ipv4Address)).into(),
+ ("1.2.3. 4", Error::IllegalCharacter(Context::Ipv4Address)).into(),
+ ("1.2.3.4 ", Error::IllegalCharacter(Context::Ipv4Address)).into(),
+ ];
+ for test_vector in test_vectors {
+ let result = validate_ipv4_address(test_vector.address_string());
+ assert!(result.is_err(), "{}", test_vector.address_string());
+ assert_eq!(
+ *test_vector.expected_error(),
+ result.unwrap_err(),
+ "{}",
+ test_vector.address_string()
+ );
+ }
+ }
+}
diff --git a/src/validate_ipv6_address.rs b/src/validate_ipv6_address.rs
index eb3900d..502da65 100644
--- a/src/validate_ipv6_address.rs
+++ b/src/validate_ipv6_address.rs
@@ -210,3 +210,68 @@ pub fn validate_ipv6_address<T>(address: T) -> Result<(), Error>
})?
.finalize()
}
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn good() {
+ let test_vectors = [
+ "::1",
+ "::ffff:1.2.3.4",
+ "2001:db8:85a3:8d3:1319:8a2e:370:7348",
+ "2001:db8:85a3:8d3:1319:8a2e:370::",
+ "2001:db8:85a3:8d3:1319:8a2e::1",
+ "fFfF::1",
+ "1234::1",
+ "fFfF:1:2:3:4:5:6:a",
+ "2001:db8:85a3::8a2e:0",
+ "2001:db8:85a3:8a2e::",
+ ];
+ for test_vector in &test_vectors {
+ assert!(validate_ipv6_address(*test_vector).is_ok());
+ }
+ }
+
+ #[test]
+ fn bad() {
+ named_tuple!(
+ struct TestVector {
+ address_string: &'static str,
+ expected_error: Error,
+ }
+ );
+ let test_vectors: &[TestVector] = &[
+ ("::fFfF::1", Error::TooManyDoubleColons).into(),
+ ("::ffff:1.2.x.4", Error::IllegalCharacter(Context::Ipv4Address)).into(),
+ ("::ffff:1.2.3.4.8", Error::TooManyAddressParts).into(),
+ ("::ffff:1.2.3", Error::TooFewAddressParts).into(),
+ ("::ffff:1.2.3.", Error::TruncatedHost).into(),
+ ("::ffff:1.2.3.256", Error::InvalidDecimalOctet).into(),
+ ("::fxff:1.2.3.4", Error::IllegalCharacter(Context::Ipv6Address)).into(),
+ ("::ffff:1.2.3.-4", Error::IllegalCharacter(Context::Ipv4Address)).into(),
+ ("::ffff:1.2.3. 4", Error::IllegalCharacter(Context::Ipv4Address)).into(),
+ ("::ffff:1.2.3.4 ", Error::IllegalCharacter(Context::Ipv4Address)).into(),
+ ("2001:db8:85a3:8d3:1319:8a2e:370:7348:0000", Error::TooManyAddressParts).into(),
+ ("2001:db8:85a3:8d3:1319:8a2e:370:7348::1", Error::TooManyAddressParts).into(),
+ ("2001:db8:85a3:8d3:1319:8a2e:370::1", Error::TooManyAddressParts).into(),
+ ("2001:db8:85a3::8a2e:0:", Error::TruncatedHost).into(),
+ ("2001:db8:85a3::8a2e::", Error::TooManyDoubleColons).into(),
+ ("20001:db8:85a3::1", Error::TooManyDigits).into(),
+ ("", Error::TooFewAddressParts).into(),
+ ];
+ for test_vector in test_vectors {
+ let result = validate_ipv6_address(test_vector.address_string());
+ assert!(result.is_err(), "{}", test_vector.address_string());
+ assert_eq!(
+ *test_vector.expected_error(),
+ result.unwrap_err(),
+ "{}",
+ test_vector.address_string()
+ );
+ }
+ }
+
+}