diff --git a/lang/rust/avro/src/schema.rs b/lang/rust/avro/src/schema.rs index d2858722bd6..47900e46be3 100644 --- a/lang/rust/avro/src/schema.rs +++ b/lang/rust/avro/src/schema.rs @@ -42,7 +42,7 @@ lazy_static! { // An optional namespace (with optional dots) followed by a name without any dots in it. static ref SCHEMA_NAME_R: Regex = - Regex::new(r"^((?P([A-Za-z_][A-Za-z0-9_\.]*)*)\.)?(?P[A-Za-z_][A-Za-z0-9_]*)$").unwrap(); + Regex::new(r"^((?P([A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*)?)\.)?(?P[A-Za-z_][A-Za-z0-9_]*)$").unwrap(); static ref FIELD_NAME_R: Regex = Regex::new(r"^[A-Za-z_][A-Za-z0-9_]*$").unwrap(); @@ -6195,4 +6195,37 @@ mod tests { Ok(()) } + + #[test] + fn test_avro_3897_disallow_invalid_namespaces_in_fully_qualified_name() -> TestResult { + let full_name = "ns.0.record1"; + let name = Name::new(full_name); + assert!(name.is_err()); + let expected = + Error::InvalidSchemaName(full_name.to_string(), SCHEMA_NAME_R.as_str()).to_string(); + let err = name.map_err(|e| e.to_string()).err().unwrap(); + assert_eq!(expected, err); + + let full_name = "ns..record1"; + let name = Name::new(full_name); + assert!(name.is_err()); + let expected = + Error::InvalidSchemaName(full_name.to_string(), SCHEMA_NAME_R.as_str()).to_string(); + let err = name.map_err(|e| e.to_string()).err().unwrap(); + assert_eq!(expected, err); + + Ok(()) + } + + /// A test cases showing that names and namespaces can be constructed + /// entirely by underscores. + #[test] + fn test_avro_3897_funny_valid_names_and_namespaces() -> TestResult { + for funny_name in ["_", "_._", "__._", "_.__", "_._._"] { + let name = Name::new(funny_name); + assert!(name.is_ok()); + } + + Ok(()) + } }