This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch branch-1.11
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/branch-1.11 by this push:
     new 93941e3  AVRO-3433: Rust: The canonical form should preserve schema 
references (#1580)
93941e3 is described below

commit 93941e323c467b6381c4157c9ff9ebb02d64a5f8
Author: Martin Grigorov <[email protected]>
AuthorDate: Mon Mar 7 14:47:50 2022 +0200

    AVRO-3433: Rust: The canonical form should preserve schema references 
(#1580)
    
    * AVRO-3433: Rust: The canonical form should preserve schema references
    
    Do not resolve Schema::Ref when printing as JSON.
    The Java SDK complains that a type is redefined if it is not a Ref the
    second time
    
    Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
    
    * AVRO-3433: Use Name as a key for parsed/resolving/input schemata
    
    This is needed to have the fullname (namespace + '.' + name) for lookups
    
    Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
    
    * AVRO-3433: Name::new("...") should parse the optional namespace
    
    This is a breaking change but a bug fix to properly implement the Avro 
specification
    
    Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
    (cherry picked from commit 44b8cd23756b752bf9d0976574453c712dcd44d9)
---
 lang/rust/avro/src/schema.rs   | 266 ++++++++++++++++++++++++++++++++---------
 lang/rust/avro/tests/schema.rs | 158 ++++--------------------
 2 files changed, 236 insertions(+), 188 deletions(-)

diff --git a/lang/rust/avro/src/schema.rs b/lang/rust/avro/src/schema.rs
index 28b34f8..4474ffa 100644
--- a/lang/rust/avro/src/schema.rs
+++ b/lang/rust/avro/src/schema.rs
@@ -30,6 +30,7 @@ use std::{
     collections::{HashMap, HashSet},
     convert::TryInto,
     fmt,
+    hash::{Hash, Hasher},
     str::FromStr,
 };
 use strum_macros::{EnumDiscriminants, EnumString};
@@ -175,7 +176,7 @@ impl SchemaKind {
     pub fn is_named(self) -> bool {
         matches!(
             self,
-            SchemaKind::Record | SchemaKind::Enum | SchemaKind::Fixed
+            SchemaKind::Record | SchemaKind::Enum | SchemaKind::Fixed | 
SchemaKind::Ref
         )
     }
 }
@@ -220,7 +221,7 @@ impl<'a> From<&'a types::Value> for SchemaKind {
 ///
 /// More information about schema names can be found in the
 /// [Avro specification](https://avro.apache.org/docs/current/spec.html#names)
-#[derive(Clone, Debug, PartialEq, Deserialize)]
+#[derive(Clone, Debug, Deserialize)]
 pub struct Name {
     pub name: String,
     pub namespace: Option<String>,
@@ -232,26 +233,40 @@ pub type Documentation = Option<String>;
 
 impl Name {
     /// Create a new `Name`.
-    /// No `namespace` nor `aliases` will be defined.
+    /// Parses the optional `namespace` from the `name` string.
+    /// `aliases` will not be defined.
     pub fn new(name: &str) -> Name {
+        let (name, namespace) = Name::get_name_and_namespace(name);
         Name {
-            name: name.to_owned(),
-            namespace: None,
+            name,
+            namespace,
             aliases: None,
         }
     }
 
+    fn get_name_and_namespace(name: &str) -> (String, Option<String>) {
+        if let Some(idx) = name.rfind('.') {
+            let namespace_from_name = name[..idx].to_owned();
+            let name_from_name = name[idx + 1..].to_owned();
+            (name_from_name, Some(namespace_from_name))
+        } else {
+            (name.to_owned(), None)
+        }
+    }
+
     /// Parse a `serde_json::Value` into a `Name`.
     fn parse(complex: &Map<String, Value>) -> AvroResult<Self> {
-        let name = complex.name().ok_or(Error::GetNameField)?;
+        let (name, namespace_from_name) = complex
+            .name()
+            .map(|name| Name::get_name_and_namespace(name.as_str()))
+            .ok_or(Error::GetNameField)?;
 
+        // FIXME Reading name from the type is wrong ! The name there is just 
a metadata (AVRO-3430)
         let type_name = match complex.get("type") {
             Some(Value::Object(complex_type)) => complex_type.name().or(None),
             _ => None,
         };
 
-        let namespace = complex.string("namespace");
-
         let aliases: Option<Vec<String>> = complex
             .get("aliases")
             .and_then(|aliases| aliases.as_array())
@@ -265,7 +280,7 @@ impl Name {
 
         Ok(Name {
             name: type_name.unwrap_or(name),
-            namespace,
+            namespace: namespace_from_name.or_else(|| 
complex.string("namespace")),
             aliases,
         })
     }
@@ -292,6 +307,26 @@ impl Name {
     }
 }
 
+impl From<&str> for Name {
+    fn from(name: &str) -> Self {
+        Name::new(name)
+    }
+}
+
+impl Hash for Name {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.fullname(None).hash(state);
+    }
+}
+
+impl Eq for Name {}
+
+impl PartialEq for Name {
+    fn eq(&self, other: &Name) -> bool {
+        self.fullname(None).eq(&other.fullname(None))
+    }
+}
+
 /// Represents a `field` in a `record` Avro schema.
 #[derive(Clone, Debug, PartialEq)]
 pub struct RecordField {
@@ -435,15 +470,15 @@ fn parse_json_integer_for_decimal(value: 
&serde_json::Number) -> Result<DecimalM
 
 #[derive(Default)]
 struct Parser {
-    input_schemas: HashMap<String, Value>,
+    input_schemas: HashMap<Name, Value>,
     // A map of name -> Schema::Ref
     // Used to resolve cyclic references, i.e. when a
     // field's type is a reference to its record's type
-    resolving_schemas: HashMap<String, Schema>,
-    input_order: Vec<String>,
+    resolving_schemas: HashMap<Name, Schema>,
+    input_order: Vec<Name>,
     // A map of name -> fully parsed Schema
     // Used to avoid parsing the same schema twice
-    parsed_schemas: HashMap<String, Schema>,
+    parsed_schemas: HashMap<Name, Schema>,
 }
 
 impl Schema {
@@ -485,17 +520,17 @@ impl Schema {
     ///
     /// If two of the input schemas have the same fullname, an Error will be 
returned.
     pub fn parse_list(input: &[&str]) -> Result<Vec<Schema>, Error> {
-        let mut input_schemas: HashMap<String, Value> = 
HashMap::with_capacity(input.len());
-        let mut input_order: Vec<String> = Vec::with_capacity(input.len());
+        let mut input_schemas: HashMap<Name, Value> = 
HashMap::with_capacity(input.len());
+        let mut input_order: Vec<Name> = Vec::with_capacity(input.len());
         for js in input {
             let schema: Value = 
serde_json::from_str(js).map_err(Error::ParseSchemaJson)?;
             if let Value::Object(inner) = &schema {
-                let fullname = Name::parse(inner)?.fullname(None);
-                let previous_value = input_schemas.insert(fullname.clone(), 
schema);
+                let name = Name::parse(inner)?;
+                let previous_value = input_schemas.insert(name.clone(), 
schema);
                 if previous_value.is_some() {
-                    return Err(Error::NameCollision(fullname));
+                    return Err(Error::NameCollision(name.fullname(None)));
                 }
-                input_order.push(fullname);
+                input_order.push(name);
             } else {
                 return Err(Error::GetNameField);
             }
@@ -577,7 +612,7 @@ impl Parser {
             "float" => Ok(Schema::Float),
             "bytes" => Ok(Schema::Bytes),
             "string" => Ok(Schema::String),
-            _ => self.fetch_schema(name),
+            _ => self.fetch_schema_ref(name),
         }
     }
 
@@ -590,25 +625,35 @@ impl Parser {
     ///
     /// This method allows schemas definitions that depend on other types to
     /// parse their dependencies (or look them up if already parsed).
-    fn fetch_schema(&mut self, name: &str) -> AvroResult<Schema> {
-        if let Some(parsed) = self.parsed_schemas.get(name) {
-            return Ok(parsed.clone());
+    fn fetch_schema_ref(&mut self, name: &str) -> AvroResult<Schema> {
+        fn get_schema_ref(parsed: &Schema) -> Schema {
+            match &parsed {
+                Schema::Record { ref name, .. }
+                | Schema::Enum { ref name, .. }
+                | Schema::Fixed { ref name, .. } => Schema::Ref { name: 
name.clone() },
+                _ => parsed.clone(),
+            }
         }
-        if let Some(resolving_schema) = self.resolving_schemas.get(name) {
+
+        let name = Name::new(name);
+
+        if let Some(parsed) = self.parsed_schemas.get(&name) {
+            return Ok(get_schema_ref(parsed));
+        }
+        if let Some(resolving_schema) = self.resolving_schemas.get(&name) {
             return Ok(resolving_schema.clone());
         }
 
         let value = self
             .input_schemas
-            .remove(name)
-            .ok_or_else(|| Error::ParsePrimitive(name.into()))?;
+            .remove(&name)
+            .ok_or_else(|| Error::ParsePrimitive(name.fullname(None)))?;
 
         let parsed = self.parse(&value)?;
-        self.parsed_schemas.insert(
-            get_schema_type_name(name.to_string(), value),
-            parsed.clone(),
-        );
-        Ok(parsed)
+        self.parsed_schemas
+            .insert(get_schema_type_name(name, value), parsed.clone());
+
+        Ok(get_schema_ref(&parsed))
     }
 
     fn parse_precision_and_scale(
@@ -802,7 +847,7 @@ impl Parser {
     fn register_resolving_schema(&mut self, name: &Name) {
         let resolving_schema = Schema::Ref { name: name.clone() };
         self.resolving_schemas
-            .insert(name.fullname(None), resolving_schema.clone());
+            .insert(name.clone(), resolving_schema.clone());
 
         let namespace = &name.namespace;
 
@@ -812,16 +857,16 @@ impl Parser {
                     Some(ref ns) => format!("{}.{}", ns, alias),
                     None => alias.clone(),
                 };
+                let alias_name = Name::new(alias_fullname.as_str());
                 self.resolving_schemas
-                    .insert(alias_fullname, resolving_schema.clone());
+                    .insert(alias_name, resolving_schema.clone());
             });
         }
     }
 
     fn register_parsed_schema(&mut self, name: &Name, schema: &Schema) {
-        self.parsed_schemas
-            .insert(name.fullname(None), schema.clone());
-        self.resolving_schemas.remove(name.fullname(None).as_str());
+        self.parsed_schemas.insert(name.clone(), schema.clone());
+        self.resolving_schemas.remove(name);
 
         let namespace = &name.namespace;
 
@@ -831,9 +876,9 @@ impl Parser {
                     Some(ref ns) => format!("{}.{}", ns, alias),
                     None => alias.clone(),
                 };
-                self.parsed_schemas
-                    .insert(alias_fullname.clone(), schema.clone());
-                self.resolving_schemas.remove(alias_fullname.as_str());
+                let alias_name = Name::new(alias_fullname.as_str());
+                self.resolving_schemas.remove(&alias_name);
+                self.parsed_schemas.insert(alias_name, schema.clone());
             });
         }
     }
@@ -841,10 +886,12 @@ impl Parser {
     /// Returns already parsed schema or a schema that is currently being 
resolved.
     fn get_already_seen_schema(&self, complex: &Map<String, Value>) -> 
Option<&Schema> {
         match complex.get("type") {
-            Some(Value::String(ref typ)) => self
-                .resolving_schemas
-                .get(typ)
-                .or_else(|| self.parsed_schemas.get(typ)),
+            Some(Value::String(ref typ)) => {
+                let name = Name::new(typ.as_str());
+                self.resolving_schemas
+                    .get(&name)
+                    .or_else(|| self.parsed_schemas.get(&name))
+            }
             _ => None,
         }
     }
@@ -1006,10 +1053,10 @@ impl Parser {
     }
 }
 
-fn get_schema_type_name(name: String, value: Value) -> String {
+fn get_schema_type_name(name: Name, value: Value) -> Name {
     match value.get("type") {
         Some(Value::Object(complex_type)) => match complex_type.name() {
-            Some(name) => name,
+            Some(name) => Name::new(name.as_str()),
             _ => name,
         },
         _ => name,
@@ -1022,7 +1069,7 @@ impl Serialize for Schema {
         S: Serializer,
     {
         match *self {
-            Schema::Ref { ref name } => serializer.serialize_str(&name.name),
+            Schema::Ref { ref name } => 
serializer.serialize_str(&name.fullname(None)),
             Schema::Null => serializer.serialize_str("null"),
             Schema::Boolean => serializer.serialize_str("boolean"),
             Schema::Int => serializer.serialize_str("int"),
@@ -1393,9 +1440,6 @@ mod tests {
             ]
         }"#;
 
-        let schema_a = Schema::parse_str(schema_str_a).unwrap();
-        let schema_b = Schema::parse_str(schema_str_b).unwrap();
-
         let schema_c = Schema::parse_list(&[schema_str_a, schema_str_b, 
schema_str_c])
             .unwrap()
             .last()
@@ -1409,7 +1453,17 @@ mod tests {
                 name: "field_one".to_string(),
                 doc: None,
                 default: None,
-                schema: Schema::Union(UnionSchema::new(vec![schema_a, 
schema_b]).unwrap()),
+                schema: Schema::Union(
+                    UnionSchema::new(vec![
+                        Schema::Ref {
+                            name: Name::new("A"),
+                        },
+                        Schema::Ref {
+                            name: Name::new("B"),
+                        },
+                    ])
+                    .unwrap(),
+                ),
                 order: RecordFieldOrder::Ignore,
                 position: 0,
             }],
@@ -1441,8 +1495,6 @@ mod tests {
             ]
         }"#;
 
-        let schema_a = Schema::parse_str(schema_str_a).unwrap();
-
         let schema_option_a = Schema::parse_list(&[schema_str_a, 
schema_str_option_a])
             .unwrap()
             .last()
@@ -1455,8 +1507,16 @@ mod tests {
             fields: vec![RecordField {
                 name: "field_one".to_string(),
                 doc: None,
-                default: Some(Value::Null),
-                schema: Schema::Union(UnionSchema::new(vec![Schema::Null, 
schema_a]).unwrap()),
+                default: Some(Value::String("null".to_string())),
+                schema: Schema::Union(
+                    UnionSchema::new(vec![
+                        Schema::Null,
+                        Schema::Ref {
+                            name: Name::new("A"),
+                        },
+                    ])
+                    .unwrap(),
+                ),
                 order: RecordFieldOrder::Ignore,
                 position: 0,
             }],
@@ -1636,7 +1696,7 @@ mod tests {
 
         let schema = Schema::parse_str(schema).unwrap();
         let schema_str = schema.canonical_form();
-        let expected = 
r#"{"name":"office.User","type":"record","fields":[{"name":"details","type":[{"name":"Employee","type":"record","fields":[{"name":"gender","type":{"name":"Gender","type":"enum","symbols":["male","female"]}}]},{"name":"Manager","type":"record","fields":[{"name":"gender","type":{"name":"Gender","type":"enum","symbols":["male","female"]}}]}]}]}"#;
+        let expected = 
r#"{"name":"office.User","type":"record","fields":[{"name":"details","type":[{"name":"Employee","type":"record","fields":[{"name":"gender","type":{"name":"Gender","type":"enum","symbols":["male","female"]}}]},{"name":"Manager","type":"record","fields":[{"name":"gender","type":"Gender"}]}]}]}"#;
         assert_eq!(schema_str, expected);
     }
 
@@ -1684,7 +1744,7 @@ mod tests {
 
         let schema = Schema::parse_str(schema).unwrap();
         let schema_str = schema.canonical_form();
-        let expected = 
r#"{"name":"office.User","type":"record","fields":[{"name":"details","type":[{"name":"Employee","type":"record","fields":[{"name":"id","type":{"name":"EmployeeId","type":"fixed","size":16}}]},{"name":"Manager","type":"record","fields":[{"name":"id","type":{"name":"EmployeeId","type":"fixed","size":16}}]}]}]}"#;
+        let expected = 
r#"{"name":"office.User","type":"record","fields":[{"name":"details","type":[{"name":"Employee","type":"record","fields":[{"name":"id","type":{"name":"EmployeeId","type":"fixed","size":16}}]},{"name":"Manager","type":"record","fields":[{"name":"id","type":"EmployeeId"}]}]}]}"#;
         assert_eq!(schema_str, expected);
     }
 
@@ -2180,4 +2240,98 @@ mod tests {
             
r#"{"name":"ns.int","type":"record","fields":[{"name":"value","type":"int"},{"name":"next","type":["null","ns.int"]}]}"#
         );
     }
+
+    #[test]
+    fn test_avro_3433_preserve_schema_refs_in_json() {
+        let schema = r#"
+    {
+      "name": "test.test",
+      "type": "record",
+      "fields": [
+        {
+          "name": "bar",
+          "type": { "name": "test.foo", "type": "record", "fields": [{ "name": 
"id", "type": "long" }] }
+        },
+        { "name": "baz", "type": "test.foo" }
+      ]
+    }
+    "#;
+
+        let schema = Schema::parse_str(schema).unwrap();
+
+        let expected = 
r#"{"name":"test.test","type":"record","fields":[{"name":"bar","type":{"name":"test.foo","type":"record","fields":[{"name":"id","type":"long"}]}},{"name":"baz","type":"test.foo"}]}"#;
+        assert_eq!(schema.canonical_form(), expected);
+    }
+
+    #[test]
+    fn test_read_namespace_from_name() {
+        let schema = r#"
+    {
+      "name": "space.name",
+      "type": "record",
+      "fields": [
+        {
+          "name": "num",
+          "type": "int"
+        }
+      ]
+    }
+    "#;
+
+        let schema = Schema::parse_str(schema).unwrap();
+        if let Schema::Record { name, .. } = schema {
+            assert_eq!(name.name, "name");
+            assert_eq!(name.namespace, Some("space".to_string()));
+        } else {
+            panic!("Expected a record schema!");
+        }
+    }
+
+    #[test]
+    fn test_namespace_from_name_has_priority_over_from_field() {
+        let schema = r#"
+    {
+      "name": "space1.name",
+      "namespace": "space2",
+      "type": "record",
+      "fields": [
+        {
+          "name": "num",
+          "type": "int"
+        }
+      ]
+    }
+    "#;
+
+        let schema = Schema::parse_str(schema).unwrap();
+        if let Schema::Record { name, .. } = schema {
+            assert_eq!(name.namespace, Some("space1".to_string()));
+        } else {
+            panic!("Expected a record schema!");
+        }
+    }
+
+    #[test]
+    fn test_namespace_from_field() {
+        let schema = r#"
+    {
+      "name": "name",
+      "namespace": "space2",
+      "type": "record",
+      "fields": [
+        {
+          "name": "num",
+          "type": "int"
+        }
+      ]
+    }
+    "#;
+
+        let schema = Schema::parse_str(schema).unwrap();
+        if let Schema::Record { name, .. } = schema {
+            assert_eq!(name.namespace, Some("space2".to_string()));
+        } else {
+            panic!("Expected a record schema!");
+        }
+    }
 }
diff --git a/lang/rust/avro/tests/schema.rs b/lang/rust/avro/tests/schema.rs
index d7ff3e4..be2d9a8 100644
--- a/lang/rust/avro/tests/schema.rs
+++ b/lang/rust/avro/tests/schema.rs
@@ -699,45 +699,28 @@ fn test_parse_list_without_cross_deps() {
 /// However, the output order is guaranteed to be the same as the input order.
 fn test_parse_list_with_cross_deps_basic() {
     init();
-    let schema_str_1 = r#"{
+    let schema_a_str = r#"{
         "name": "A",
         "type": "record",
         "fields": [
             {"name": "field_one", "type": "float"}
         ]
     }"#;
-    let schema_str_2 = r#"{
+    let schema_b_str = r#"{
         "name": "B",
         "type": "record",
         "fields": [
             {"name": "field_one", "type": "A"}
         ]
     }"#;
-    let schema_composite = r#"{
-        "name": "B",
-        "type": "record",
-        "fields": [
-            { "name": "field_one",
-            "type": {
-                "name": "A",
-                "type": "record",
-                "fields": [
-                    {"name": "field_one", "type": "float"}
-                    ]
-                }
-            }
-        ]
 
-    }"#;
-    let schema_strs_first = [schema_str_1, schema_str_2];
-    let schema_strs_second = [schema_str_2, schema_str_1];
+    let schema_strs_first = [schema_a_str, schema_b_str];
+    let schema_strs_second = [schema_b_str, schema_a_str];
     let schemas_first = Schema::parse_list(&schema_strs_first).expect("Test 
failed");
     let schemas_second = Schema::parse_list(&schema_strs_second).expect("Test 
failed");
 
-    let parsed_1 = Schema::parse_str(schema_str_1).expect("Test failed");
-    let parsed_2 = Schema::parse_str(schema_composite).expect("Test failed");
-    assert_eq!(schemas_first, vec!(parsed_1.clone(), parsed_2.clone()));
-    assert_eq!(schemas_second, vec!(parsed_2, parsed_1));
+    assert_eq!(schemas_first[0], schemas_second[1]);
+    assert_eq!(schemas_first[1], schemas_second[0]);
 }
 
 #[test]
@@ -769,7 +752,7 @@ fn test_parse_list_recursive_type() {
 /// Test that schema composition resolves namespaces.
 fn test_parse_list_with_cross_deps_and_namespaces() {
     init();
-    let schema_str_1 = r#"{
+    let schema_a_str = r#"{
         "name": "A",
         "type": "record",
         "namespace": "namespace",
@@ -777,38 +760,19 @@ fn test_parse_list_with_cross_deps_and_namespaces() {
             {"name": "field_one", "type": "float"}
         ]
     }"#;
-    let schema_str_2 = r#"{
+    let schema_b_str = r#"{
         "name": "B",
         "type": "record",
         "fields": [
             {"name": "field_one", "type": "namespace.A"}
         ]
     }"#;
-    let schema_composite = r#"{
-        "name": "B",
-        "type": "record",
-        "fields": [
-            { "name": "field_one",
-            "type": {
-                "name": "A",
-                "type": "record",
-                "namespace": "namespace",
-                "fields": [
-                    {"name": "field_one", "type": "float"}
-                    ]
-                }
-            }
-        ]
-    }"#;
-    let schema_strs_first = [schema_str_1, schema_str_2];
-    let schema_strs_second = [schema_str_2, schema_str_1];
-    let schemas_first = Schema::parse_list(&schema_strs_first).expect("Test 
failed");
-    let schemas_second = Schema::parse_list(&schema_strs_second).expect("Test 
failed");
 
-    let parsed_1 = Schema::parse_str(schema_str_1).expect("Test failed");
-    let parsed_2 = Schema::parse_str(schema_composite).expect("Test failed");
-    assert_eq!(schemas_first, vec!(parsed_1.clone(), parsed_2.clone()));
-    assert_eq!(schemas_second, vec!(parsed_2, parsed_1));
+    let schemas_first = Schema::parse_list(&[schema_a_str, 
schema_b_str]).expect("Test failed");
+    let schemas_second = Schema::parse_list(&[schema_b_str, 
schema_a_str]).expect("Test failed");
+
+    assert_eq!(schemas_first[0], schemas_second[1]);
+    assert_eq!(schemas_first[1], schemas_second[0]);
 }
 
 #[test]
@@ -901,14 +865,8 @@ fn test_parse_reused_record_schema_by_fullname() {
             assert_eq!(name, "min_temp");
 
             match schema {
-                Schema::Record {
-                    ref name,
-                    doc: _,
-                    ref fields,
-                    lookup: _,
-                } => {
+                Schema::Ref { ref name } => {
                     assert_eq!(name.fullname(None), "prefix.Temp", "Name does 
not match!");
-                    assert_eq!(fields.len(), 1, "The number of the fields is 
not correct!");
                 }
                 unexpected => unreachable!("Unexpected schema type: {:?}", 
unexpected),
             }
@@ -959,56 +917,29 @@ fn permutation_indices(indices: Vec<usize>) -> 
Vec<Vec<usize>> {
 /// definitions are passed in as a list. This should work regardless of the 
ordering of the list.
 fn test_parse_list_multiple_dependencies() {
     init();
-    let schema_str_1 = r#"{
+    let schema_a_str = r#"{
         "name": "A",
         "type": "record",
         "fields": [
             {"name": "field_one", "type": ["null", "B", "C"]}
         ]
     }"#;
-    let schema_str_2 = r#"{
+    let schema_b_str = r#"{
         "name": "B",
         "type": "fixed",
         "size": 16
     }"#;
-    let schema_str_3 = r#"{
+    let schema_c_str = r#"{
         "name": "C",
         "type": "record",
         "fields": [
             {"name": "field_one", "type": "string"}
         ]
     }"#;
-    let schema_composite = r#"{
-        "name": "A",
-        "type": "record",
-        "fields": [
-            {
-                "name": "field_one",
-                "type":  [
-                    "null",
-                    {
-                        "name": "B",
-                        "type": "fixed",
-                        "size": 16
-                    },
-                    {
-                        "name": "C",
-                        "type": "record",
-                        "fields": [
-                            {"name": "field_one", "type": "string"}
-                        ]
-                    }
-                ]
-            }
-        ]
-    }"#;
 
-    let parsed = vec![
-        Schema::parse_str(schema_str_2).expect("Test failed"),
-        Schema::parse_str(schema_str_3).expect("Test failed"),
-        Schema::parse_str(schema_composite).expect("Test failed"),
-    ];
-    let schema_strs = vec![schema_str_1, schema_str_2, schema_str_3];
+    let parsed =
+        Schema::parse_list(&[schema_a_str, schema_b_str, 
schema_c_str]).expect("Test failed");
+    let schema_strs = vec![schema_a_str, schema_b_str, schema_c_str];
     for schema_str_perm in permutations(&schema_strs) {
         let schema_str_perm: Vec<&str> = schema_str_perm.iter().map(|s| 
**s).collect();
         let schemas = Schema::parse_list(&schema_str_perm).expect("Test 
failed");
@@ -1024,68 +955,31 @@ fn test_parse_list_multiple_dependencies() {
 /// definitions are passed in as a list. This should work regardless of the 
ordering of the list.
 fn test_parse_list_shared_dependency() {
     init();
-    let schema_str_1 = r#"{
+    let schema_a_str = r#"{
         "name": "A",
         "type": "record",
         "fields": [
             {"name": "field_one", "type": {"type": "array", "items": "C"}}
         ]
     }"#;
-    let schema_str_2 = r#"{
+    let schema_b_str = r#"{
         "name": "B",
         "type": "record",
         "fields": [
             {"name": "field_one", "type": {"type": "map", "values": "C"}}
         ]
     }"#;
-    let schema_str_3 = r#"{
+    let schema_c_str = r#"{
         "name": "C",
         "type": "record",
         "fields": [
             {"name": "field_one", "type": "string"}
         ]
     }"#;
-    let schema_composite_1 = r#"{
-        "name": "A",
-        "type": "record",
-        "fields": [
-            { "name": "field_one",
-              "type": {"type": "array",
-                       "items": {
-                            "name": "C",
-                            "type": "record",
-                            "fields": [
-                                {"name": "field_one", "type": "string"}
-                                ]
-                            }
-                      }
-            }
-        ]
-    }"#;
-    let schema_composite_2 = r#"{
-        "name": "B",
-        "type": "record",
-        "fields": [
-            { "name": "field_one",
-              "type": {"type": "map",
-                       "values": {
-                            "name": "C",
-                            "type":  "record",
-                            "fields": [
-                                {"name": "field_one", "type": "string"}
-                                ]
-                            }
-                      }
-                 }
-            ]
-    }"#;
 
-    let parsed = vec![
-        Schema::parse_str(schema_str_3).expect("Test failed"),
-        Schema::parse_str(schema_composite_1).expect("Test failed"),
-        Schema::parse_str(schema_composite_2).expect("Test failed"),
-    ];
-    let schema_strs = vec![schema_str_1, schema_str_2, schema_str_3];
+    let parsed =
+        Schema::parse_list(&[schema_a_str, schema_b_str, 
schema_c_str]).expect("Test failed");
+    let schema_strs = vec![schema_a_str, schema_b_str, schema_c_str];
     for schema_str_perm in permutations(&schema_strs) {
         let schema_str_perm: Vec<&str> = schema_str_perm.iter().map(|s| 
**s).collect();
         let schemas = Schema::parse_list(&schema_str_perm).expect("Test 
failed");

Reply via email to