From a06283abc02d2340d111754eeb99eb58accd9f3e Mon Sep 17 00:00:00 2001 From: AdrianStrugala Date: Fri, 19 Apr 2024 15:08:59 +0200 Subject: [PATCH 1/2] Remove cache in schema generator --- .../BuildSchema/ReflectionSchemaBuilder.cs | 4 +- .../AvroObjectServices/BuildSchema/Schema.cs | 8 +- .../BuildSchema/TypeSchemaBuilder.cs | 73 +- .../Schemas/Abstract/LogicalTypeSchema.cs | 4 +- .../Schemas/Abstract/PrimitiveTypeSchema.cs | 2 +- .../Schemas/Abstract/TypeSchema.cs | 2 +- .../AvroObjectServices/Schemas/ArraySchema.cs | 4 +- .../Schemas/DecimalSchema.cs | 2 +- .../Schemas/DurationSchema.cs | 2 +- .../AvroObjectServices/Schemas/EnumSchema.cs | 9 +- .../AvroObjectServices/Schemas/FixedSchema.cs | 9 +- .../AvroObjectServices/Schemas/MapSchema.cs | 5 +- .../Schemas/NullableSchema.cs | 4 +- .../Schemas/RecordFieldSchema.cs | 4 +- .../Schemas/RecordSchema.cs | 13 +- .../AvroObjectServices/Schemas/UnionSchema.cs | 4 +- .../Features/GenerateModel/NamespaceHelper.cs | 44 +- .../GenerateModel/NetModel/NetModel.cs | 2 +- .../CollectionsTests.cs | 386 ++++---- .../DictionaryTests.cs | 36 + .../PartiallyMatchingClassesTests.cs | 310 +++---- .../GenerateModel/GenerateModelTests.cs | 18 +- tests/AvroConvertTests/TestClasses.cs | 874 +++++++++--------- tests/AvroConvertTests/TestEngine.cs | 16 +- 24 files changed, 932 insertions(+), 903 deletions(-) diff --git a/src/AvroConvert/AvroObjectServices/BuildSchema/ReflectionSchemaBuilder.cs b/src/AvroConvert/AvroObjectServices/BuildSchema/ReflectionSchemaBuilder.cs index 3ae1bbe3..e81a4890 100644 --- a/src/AvroConvert/AvroObjectServices/BuildSchema/ReflectionSchemaBuilder.cs +++ b/src/AvroConvert/AvroObjectServices/BuildSchema/ReflectionSchemaBuilder.cs @@ -108,13 +108,13 @@ private TypeSchema CreateSchema(bool forceNullable, uint currentDepth, Type prioritizedType = null, MemberInfo memberInfo = null) - { + { if (currentDepth == _options.MaxItemsInSchemaTree) { throw new SerializationException(string.Format(CultureInfo.InvariantCulture, "Maximum depth of object graph reached.")); } - if (_hasCustomConverters) + if (_hasCustomConverters) { if (_customSchemaMapping.TryGetValue(type, out var schema)) { diff --git a/src/AvroConvert/AvroObjectServices/BuildSchema/Schema.cs b/src/AvroConvert/AvroObjectServices/BuildSchema/Schema.cs index 4ed5058a..1d86d292 100644 --- a/src/AvroConvert/AvroObjectServices/BuildSchema/Schema.cs +++ b/src/AvroConvert/AvroObjectServices/BuildSchema/Schema.cs @@ -53,18 +53,18 @@ public override string ToString() using (var result = new StringWriter(CultureInfo.InvariantCulture)) { var writer = new JsonTextWriter(result); - this.ToJson(writer, new HashSet()); + this.ToJson(writer); return result.ToString(); } } - internal void ToJson(JsonTextWriter writer, HashSet seenSchemas) + internal void ToJson(JsonTextWriter writer) { - this.ToJsonSafe(writer, seenSchemas); + this.ToJsonSafe(writer); } - internal abstract void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas); + internal abstract void ToJsonSafe(JsonTextWriter writer); internal static TypeSchema Create(string schemaInJson) diff --git a/src/AvroConvert/AvroObjectServices/BuildSchema/TypeSchemaBuilder.cs b/src/AvroConvert/AvroObjectServices/BuildSchema/TypeSchemaBuilder.cs index 8e8a5c8c..84cbe434 100644 --- a/src/AvroConvert/AvroObjectServices/BuildSchema/TypeSchemaBuilder.cs +++ b/src/AvroConvert/AvroObjectServices/BuildSchema/TypeSchemaBuilder.cs @@ -18,13 +18,11 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Runtime.Serialization; using Newtonsoft.Json.Linq; using SolTechnology.Avro.AvroObjectServices.FileHeader; using SolTechnology.Avro.AvroObjectServices.Schemas; using SolTechnology.Avro.AvroObjectServices.Schemas.Abstract; -using SolTechnology.Avro.AvroObjectServices.Schemas.AvroTypes; using SolTechnology.Avro.Infrastructure.Attributes; using SolTechnology.Avro.Infrastructure.Extensions; @@ -70,7 +68,7 @@ internal TypeSchema BuildSchema(string schema) string.Format(CultureInfo.InvariantCulture, "'{0}' is invalid JSON.", schema)); } - return this.Parse(token, null, new Dictionary()); + return this.Parse(token, null); } /// @@ -78,38 +76,27 @@ internal TypeSchema BuildSchema(string schema) /// /// The token. /// The parent schema. - /// The schemas. /// /// Schema internal representation. /// /// Thrown when JSON schema type is not supported. - private TypeSchema Parse(JToken token, NamedSchema parent, Dictionary namedSchemas) + private TypeSchema Parse(JToken token, NamedSchema parent) { if (token.Type == JTokenType.Object) { - return this.ParseJsonObject(token as JObject, parent, namedSchemas); + return this.ParseJsonObject(token as JObject, parent); } if (token.Type == JTokenType.String) { var t = (string)token; - if (namedSchemas.ContainsKey(t)) - { - return namedSchemas[t]; - } - - if (parent != null && namedSchemas.ContainsKey(parent.Namespace + "." + t)) - { - return namedSchemas[parent.Namespace + "." + t]; - } - - // Primitive. + return this.ParsePrimitiveTypeFromString(t); } if (token.Type == JTokenType.Array) { - return this.ParseUnionType(token as JArray, parent, namedSchemas); + return this.ParseUnionType(token as JArray, parent); } throw new SerializationException( @@ -121,12 +108,11 @@ private TypeSchema Parse(JToken token, NamedSchema parent, Dictionary /// The object. /// The parent schema. - /// The schemas. /// /// Schema internal representation. /// /// Thrown when JSON schema type is invalid. - private TypeSchema ParseJsonObject(JObject token, NamedSchema parent, Dictionary namedSchemas) + private TypeSchema ParseJsonObject(JObject token, NamedSchema parent) { JToken tokenType = token[AvroKeywords.Type]; if (tokenType.Type == JTokenType.String) @@ -137,19 +123,19 @@ private TypeSchema ParseJsonObject(JObject token, NamedSchema parent, Dictionary var logicalType = token.OptionalProperty(AvroKeywords.LogicalType); if (logicalType != null) { - return this.ParseLogicalType(token, parent, namedSchemas, logicalType); + return this.ParseLogicalType(token, parent, logicalType); } switch (type) { case AvroType.Record: - return this.ParseRecordType(token, parent, namedSchemas); + return this.ParseRecordType(token, parent); case AvroType.Enum: - return this.ParseEnumType(token, parent, namedSchemas); + return this.ParseEnumType(token, parent); case AvroType.Array: - return this.ParseArrayType(token, parent, namedSchemas); + return this.ParseArrayType(token, parent); case AvroType.Map: - return this.ParseMapType(token, parent, namedSchemas); + return this.ParseMapType(token, parent); case AvroType.Fixed: return this.ParseFixedType(token, parent); default: @@ -167,7 +153,7 @@ private TypeSchema ParseJsonObject(JObject token, NamedSchema parent, Dictionary if (tokenType.Type == JTokenType.Array) { - return this.ParseUnionType(tokenType as JArray, parent, namedSchemas); + return this.ParseUnionType(tokenType as JArray, parent); } throw new SerializationException( @@ -184,13 +170,13 @@ private TypeSchema ParseJsonObject(JObject token, NamedSchema parent, Dictionary /// Schema internal representation. /// /// Thrown when union schema type is invalid. - private TypeSchema ParseUnionType(JArray unionToken, NamedSchema parent, Dictionary namedSchemas) + private TypeSchema ParseUnionType(JArray unionToken, NamedSchema parent) { var types = new HashSet(); var schemas = new List(); foreach (var typeAlternative in unionToken.Children()) { - var schema = this.Parse(typeAlternative, parent, namedSchemas); + var schema = this.Parse(typeAlternative, parent); if (schema.Type == AvroType.Union) { throw new SerializationException( @@ -215,12 +201,11 @@ private TypeSchema ParseUnionType(JArray unionToken, NamedSchema parent, Diction /// /// The JSON token that represents the enumeration. /// The parent schema. - /// The named schemas. /// /// Instance of containing IR of the enumeration. /// /// Thrown when contains invalid symbols. - private TypeSchema ParseEnumType(JObject enumeration, NamedSchema parent, Dictionary namedSchemas) + private TypeSchema ParseEnumType(JObject enumeration, NamedSchema parent) { var name = enumeration.RequiredProperty(AvroKeywords.Name); var nspace = this.GetNamespace(enumeration, parent, name); @@ -246,7 +231,6 @@ private TypeSchema ParseEnumType(JObject enumeration, NamedSchema parent, Dictio //fixme: runtime type cannot be provided for json schema resolution. Providing general type var result = new EnumSchema(attributes, typeof(Enum), customAttributes); - namedSchemas.Add(result.FullName, result); symbols.ForEach(result.AddSymbol); return result; } @@ -256,12 +240,11 @@ private TypeSchema ParseEnumType(JObject enumeration, NamedSchema parent, Dictio /// /// JSON representing the array. /// The parent. - /// The named schemas. /// /// A corresponding schema. /// /// Thrown when no 'items' property is found in . - private TypeSchema ParseArrayType(JObject array, NamedSchema parent, Dictionary namedSchemas) + private TypeSchema ParseArrayType(JObject array, NamedSchema parent) { var itemType = array[AvroKeywords.Items]; if (itemType == null) @@ -270,7 +253,7 @@ private TypeSchema ParseArrayType(JObject array, NamedSchema parent, Dictionary< string.Format(CultureInfo.InvariantCulture, "Property 'items' cannot be found inside the array '{0}'.", array)); } - var elementSchema = this.Parse(itemType, parent, namedSchemas); + var elementSchema = this.Parse(itemType, parent); return new ArraySchema(elementSchema, typeof(Array)); } @@ -279,12 +262,11 @@ private TypeSchema ParseArrayType(JObject array, NamedSchema parent, Dictionary< /// /// JSON representing the map. /// The parent. - /// The named schemas. /// /// A corresponding schema. /// /// Thrown when 'values' property is not found in . - private TypeSchema ParseMapType(JObject map, NamedSchema parent, Dictionary namedSchemas) + private TypeSchema ParseMapType(JObject map, NamedSchema parent) { var valueType = map[AvroKeywords.Values]; if (valueType == null) @@ -293,11 +275,11 @@ private TypeSchema ParseMapType(JObject map, NamedSchema parent, Dictionary)); } - private TypeSchema ParseLogicalType(JObject token, NamedSchema parent, Dictionary namedSchemas, string logicalType) + private TypeSchema ParseLogicalType(JObject token, NamedSchema parent, string logicalType) { TypeSchema result; switch (logicalType) @@ -341,12 +323,11 @@ private TypeSchema ParseLogicalType(JObject token, NamedSchema parent, Dictionar /// /// The record. /// The parent schema. - /// The named schemas. /// /// Schema internal representation. /// /// Thrown when can not be parsed properly. - private TypeSchema ParseRecordType(JObject record, NamedSchema parent, Dictionary namedSchemas) + private TypeSchema ParseRecordType(JObject record, NamedSchema parent) { var name = record.RequiredProperty(AvroKeywords.Name); var nspace = this.GetNamespace(record, parent, name); @@ -358,11 +339,7 @@ private TypeSchema ParseRecordType(JObject record, NamedSchema parent, Dictionar Dictionary customAttributes = record.GetAttributesNotIn(StandardProperties.Record); var result = new RecordSchema(attributes, typeof(object), customAttributes); - if (namedSchemas.ContainsKey(result.FullName)) - { - return namedSchemas[result.FullName]; - } - namedSchemas.Add(result.FullName, result); + List fields = record.OptionalArrayProperty( AvroKeywords.Fields, @@ -373,7 +350,7 @@ private TypeSchema ParseRecordType(JObject record, NamedSchema parent, Dictionar throw new SerializationException( string.Format(CultureInfo.InvariantCulture, "Property 'fields' has invalid value '{0}'.", field)); } - return this.ParseRecordField(field as JObject, result, namedSchemas, index); + return this.ParseRecordField(field as JObject, result, index); }); fields.ForEach(result.AddField); @@ -391,7 +368,7 @@ private TypeSchema ParseRecordType(JObject record, NamedSchema parent, Dictionar /// Schema internal representation. /// /// Thrown when is not valid or when sort order is not valid. - private RecordFieldSchema ParseRecordField(JObject field, NamedSchema parent, Dictionary namedSchemas, int position) + private RecordFieldSchema ParseRecordField(JObject field, NamedSchema parent, int position) { var name = field.RequiredProperty(AvroKeywords.Name); var doc = field.OptionalProperty(AvroKeywords.Doc); @@ -404,7 +381,7 @@ private RecordFieldSchema ParseRecordField(JObject field, NamedSchema parent, Di string.Format(CultureInfo.InvariantCulture, "Record field schema '{0}' has no type.", field)); } - TypeSchema type = this.Parse(fieldType, parent, namedSchemas); + TypeSchema type = this.Parse(fieldType, parent); object defaultValue = null; bool hasDefaultValue = field[AvroKeywords.Default] != null; if (hasDefaultValue) diff --git a/src/AvroConvert/AvroObjectServices/Schemas/Abstract/LogicalTypeSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/Abstract/LogicalTypeSchema.cs index c2a31951..b675b6e1 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/Abstract/LogicalTypeSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/Abstract/LogicalTypeSchema.cs @@ -51,11 +51,11 @@ internal override bool CanRead(TypeSchema writerSchema) return writerSchema.Type == Type || writerSchema.Type == BaseTypeSchema.Type; } - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { writer.WriteStartObject(); writer.WritePropertyName("type"); - BaseTypeSchema.ToJsonSafe(writer, seenSchemas); + BaseTypeSchema.ToJsonSafe(writer); writer.WriteProperty("logicalType", LogicalTypeName); writer.WriteEndObject(); } diff --git a/src/AvroConvert/AvroObjectServices/Schemas/Abstract/PrimitiveTypeSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/Abstract/PrimitiveTypeSchema.cs index be6b45b3..d6d83da6 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/Abstract/PrimitiveTypeSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/Abstract/PrimitiveTypeSchema.cs @@ -29,7 +29,7 @@ protected PrimitiveTypeSchema(Type runtimeType, Dictionary attri { } - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { writer.WriteValue(CultureInfo.InvariantCulture.TextInfo.ToLower(this.Type.ToString())); } diff --git a/src/AvroConvert/AvroObjectServices/Schemas/Abstract/TypeSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/Abstract/TypeSchema.cs index 5a0104b0..9c5b10fa 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/Abstract/TypeSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/Abstract/TypeSchema.cs @@ -40,7 +40,7 @@ protected TypeSchema(Type runtimeType, IDictionary attributes) : private string emptySchema = "{\"name\":\"Object\",\"namespace\":\"System\",\"type\":\"record\",\"fields\":[]}"; - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { writer.WriteValue(CultureInfo.InvariantCulture.TextInfo.ToLower(this.Type.ToString())); } diff --git a/src/AvroConvert/AvroObjectServices/Schemas/ArraySchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/ArraySchema.cs index e5011da6..ada870fd 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/ArraySchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/ArraySchema.cs @@ -76,12 +76,12 @@ internal TypeSchema ItemSchema /// /// The writer. /// The seen schemas. - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { writer.WriteStartObject(); writer.WriteProperty("type", "array"); writer.WritePropertyName("items"); - this.itemSchema.ToJson(writer, seenSchemas); + this.itemSchema.ToJson(writer); writer.WriteEndObject(); } diff --git a/src/AvroConvert/AvroObjectServices/Schemas/DecimalSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/DecimalSchema.cs index ae7ec406..24c996b7 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/DecimalSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/DecimalSchema.cs @@ -64,7 +64,7 @@ public DecimalSchema(Type runtimeType, int precision, int scale) : base(runtimeT Precision = precision; } - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { writer.WriteStartObject(); writer.WriteProperty("type", BaseTypeSchema.Type.ToString().ToLowerInvariant()); diff --git a/src/AvroConvert/AvroObjectServices/Schemas/DurationSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/DurationSchema.cs index 85ea9c75..999ad94c 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/DurationSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/DurationSchema.cs @@ -45,7 +45,7 @@ public DurationSchema(Type runtimeType) : base(runtimeType) internal override TypeSchema BaseTypeSchema { get; set; } internal override string LogicalTypeName => "duration"; - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { var baseSchema = (FixedSchema)BaseTypeSchema; writer.WriteStartObject(); diff --git a/src/AvroConvert/AvroObjectServices/Schemas/EnumSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/EnumSchema.cs index 5d8c6552..b461423b 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/EnumSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/EnumSchema.cs @@ -100,15 +100,8 @@ internal string GetSymbolByValue(int value) internal long[] AvroToCSharpValueMapping => this.avroToCSharpValueMapping.ToArray(); - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { - if (seenSchemas.Contains(this)) - { - writer.WriteValue(this.FullName); - return; - } - - seenSchemas.Add(this); writer.WriteStartObject(); writer.WriteProperty("type", "enum"); writer.WriteProperty("name", Name); diff --git a/src/AvroConvert/AvroObjectServices/Schemas/FixedSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/FixedSchema.cs index 160b31ce..d39cd7cb 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/FixedSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/FixedSchema.cs @@ -51,15 +51,8 @@ internal FixedSchema( internal int Size { get; } - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { - if (seenSchemas.Contains(this)) - { - writer.WriteValue(this.FullName); - return; - } - - seenSchemas.Add(this); writer.WriteStartObject(); writer.WriteProperty("type", "fixed"); writer.WriteProperty("name", Name); diff --git a/src/AvroConvert/AvroObjectServices/Schemas/MapSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/MapSchema.cs index c6b3aadc..5817ed46 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/MapSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/MapSchema.cs @@ -84,13 +84,12 @@ internal TypeSchema KeySchema /// Converts current not to JSON according to the avro specification. /// /// The writer. - /// The seen schemas. - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { writer.WriteStartObject(); writer.WriteProperty("type", "map"); writer.WritePropertyName("values"); - ValueSchema.ToJson(writer, seenSchemas); + ValueSchema.ToJson(writer); writer.WriteEndObject(); } diff --git a/src/AvroConvert/AvroObjectServices/Schemas/NullableSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/NullableSchema.cs index 5aab1445..97d5a1bf 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/NullableSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/NullableSchema.cs @@ -58,9 +58,9 @@ internal TypeSchema ValueSchema internal override AvroType Type => valueSchema.Type; - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { - this.valueSchema.ToJsonSafe(writer, seenSchemas); + this.valueSchema.ToJsonSafe(writer); } } } diff --git a/src/AvroConvert/AvroObjectServices/Schemas/RecordFieldSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/RecordFieldSchema.cs index d8bd22f5..a5e982c2 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/RecordFieldSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/RecordFieldSchema.cs @@ -68,7 +68,7 @@ internal RecordFieldSchema( Position = position; } - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { writer.WriteStartObject(); @@ -77,7 +77,7 @@ internal override void ToJsonSafe(JsonTextWriter writer, HashSet se writer.WriteOptionalProperty("doc", Doc); writer.WriteOptionalProperty("aliases", Aliases); writer.WritePropertyName("type"); - TypeSchema.ToJson(writer, seenSchemas); + TypeSchema.ToJson(writer); writer.WriteOptionalProperty("default", DefaultValue, HasDefaultValue); writer.WriteEndObject(); diff --git a/src/AvroConvert/AvroObjectServices/Schemas/RecordSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/RecordSchema.cs index 1a6f51e4..0a2fb364 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/RecordSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/RecordSchema.cs @@ -81,15 +81,8 @@ internal RecordFieldSchema GetField(string fieldName) internal ReadOnlyCollection Fields => fields.AsReadOnly(); - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { - if (seenSchemas.Contains(this)) - { - writer.WriteValue(this.FullName); - return; - } - - seenSchemas.Add(this); writer.WriteStartObject(); writer.WriteProperty("name", Name); writer.WriteOptionalProperty("namespace", Namespace); @@ -98,7 +91,7 @@ internal override void ToJsonSafe(JsonTextWriter writer, HashSet se writer.WriteProperty("type", "record"); writer.WritePropertyName("fields"); writer.WriteStartArray(); - fields.ForEach(_ => _.ToJson(writer, seenSchemas)); + fields.ForEach(_ => _.ToJson(writer)); writer.WriteEndArray(); writer.WriteEndObject(); } @@ -107,7 +100,7 @@ internal override void ToJsonSafe(JsonTextWriter writer, HashSet se internal override bool CanRead(TypeSchema writerSchema) { - return Type == writerSchema.Type + return Type == writerSchema.Type || Fields.Count == 0; //hack to allow any item to be serialized to Object } } diff --git a/src/AvroConvert/AvroObjectServices/Schemas/UnionSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/UnionSchema.cs index 7dfe894b..bb9408a7 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/UnionSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/UnionSchema.cs @@ -58,10 +58,10 @@ internal UnionSchema( internal ReadOnlyCollection Schemas => schemas.AsReadOnly(); - internal override void ToJsonSafe(JsonTextWriter writer, HashSet seenSchemas) + internal override void ToJsonSafe(JsonTextWriter writer) { writer.WriteStartArray(); - this.schemas.ForEach(_ => _.ToJson(writer, seenSchemas)); + this.schemas.ForEach(_ => _.ToJson(writer)); writer.WriteEndArray(); } diff --git a/src/AvroConvert/Features/GenerateModel/NamespaceHelper.cs b/src/AvroConvert/Features/GenerateModel/NamespaceHelper.cs index a7a4b8a0..a1f6a623 100644 --- a/src/AvroConvert/Features/GenerateModel/NamespaceHelper.cs +++ b/src/AvroConvert/Features/GenerateModel/NamespaceHelper.cs @@ -38,20 +38,46 @@ internal void EnsureUniqueNames(NetModel.NetModel model) continue; } - + foreach (var netClass in netTypes.OfType().ToList()) { foreach (var avroField in model.NetTypes.OfType().ToList() - .SelectMany(c => c.Fields) - .Where(f => (f.FieldType == netClass.Name || - f.FieldType == netClass.Name + "[]" || - f.FieldType == netClass.Name + "?") && - f.Namespace == netClass.ClassNamespace)) + .SelectMany(c => c.Fields) + .Where(f => (f.FieldType == netClass.Name || + f.FieldType == netClass.Name + "[]" || + f.FieldType == netClass.Name + "?") && + f.Namespace == netClass.ClassNamespace)) + { + if (!string.IsNullOrWhiteSpace(avroField.Namespace)) + { + avroField.FieldType = avroField.Namespace + "." + avroField.FieldType; + } + } + + //deduplicate classes + if (!string.IsNullOrWhiteSpace(netClass.ClassNamespace)) + { + var nameWithNamespace = netClass.ClassNamespace + "." + netClass.Name; + if (model.NetTypes.Any(x => x.Name == nameWithNamespace)) + { + model.NetTypes.Remove(netClass); + } + else + { + netClass.Name = nameWithNamespace; + } + } + } + + //deduplicate enums + var netEnums = netTypes.OfType().ToList(); + if (netEnums.Any()) + { + foreach (var netEnum in netEnums) { - avroField.FieldType = avroField.Namespace + avroField.FieldType; + model.NetTypes.Remove(netEnum); } - - netClass.Name = netClass.ClassNamespace + netClass.Name; + model.NetTypes.Add(netEnums.First()); } } } diff --git a/src/AvroConvert/Features/GenerateModel/NetModel/NetModel.cs b/src/AvroConvert/Features/GenerateModel/NetModel/NetModel.cs index c02ad425..c74ef325 100644 --- a/src/AvroConvert/Features/GenerateModel/NetModel/NetModel.cs +++ b/src/AvroConvert/Features/GenerateModel/NetModel/NetModel.cs @@ -26,6 +26,6 @@ namespace SolTechnology.Avro.Features.GenerateModel.NetModel { internal class NetModel { - internal List NetTypes { get; set; } = new List(); + internal List NetTypes { get; set; } = new(); } } diff --git a/tests/AvroConvertTests/FullSerializationAndDeserialization/CollectionsTests.cs b/tests/AvroConvertTests/FullSerializationAndDeserialization/CollectionsTests.cs index 9a4f2485..083f7140 100644 --- a/tests/AvroConvertTests/FullSerializationAndDeserialization/CollectionsTests.cs +++ b/tests/AvroConvertTests/FullSerializationAndDeserialization/CollectionsTests.cs @@ -1,193 +1,193 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using AutoFixture; -using FluentAssertions; -using SolTechnology.Avro; -using Xunit; - -namespace AvroConvertComponentTests.FullSerializationAndDeserialization -{ - public class CollectionsTests - { - private readonly Fixture _fixture = new(); - - [Theory] - [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] - public void List_of_class(Func engine) - { - //Arrange - var someTestClasses = _fixture.CreateMany().ToList(); - - //Act - var deserialized = engine.Invoke(someTestClasses, typeof(List)); - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(someTestClasses, deserialized); - } - - [Theory] - [Trait("Fix", "https://github.com/AdrianStrugala/AvroConvert/issues/146")] - [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] - public void IEnumerable_of_class(Func engine) - { - //Arrange - var someTestClasses = _fixture.CreateMany(); - - //Act - var deserialized = engine.Invoke(someTestClasses, typeof(IEnumerable)); - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(someTestClasses, deserialized); - } - - [Theory] - [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] - public void Class_with_list(Func engine) - { - //Arrange - ClassWithSimpleList testClass = _fixture.Create(); - - //Act - var deserialized = (ClassWithSimpleList)engine.Invoke(testClass, typeof(ClassWithSimpleList)); - - //Assert - Assert.NotNull(deserialized); - deserialized.Should().BeEquivalentTo(testClass); - } - - [Theory] - [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] - public void Class_with_list_of_classes(Func engine) - { - //Arrange - ClassWithConstructorPopulatingProperty - testClass = _fixture.Create(); - - //Act - var deserialized = (ClassWithConstructorPopulatingProperty)engine.Invoke(testClass, typeof(ClassWithConstructorPopulatingProperty)); - - //Assert - Assert.NotNull(deserialized); - deserialized.Should().BeEquivalentTo(testClass); - - } - - [Theory] - [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] - public void Class_with_array(Func engine) - { - //Arrange - ClassWithArray - testClass = _fixture.Create(); - - //Act - var deserialized = (ClassWithArray)engine.Invoke(testClass, typeof(ClassWithArray)); - - //Assert - Assert.NotNull(deserialized); - deserialized.Should().BeEquivalentTo(testClass); - } - - [Theory] - [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] - public void List_of_int(Func engine) - { - //Arrange - List toSerialize = _fixture.Create>(); - - //Act - var deserialized = (List)engine.Invoke(toSerialize, typeof(List)); - - //Assert - Assert.NotNull(deserialized); - deserialized.Should().BeEquivalentTo(deserialized); - } - - [Theory] - [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] - public void Array_of_int(Func engine) - { - //Arrange - int[] array = _fixture.Create(); - - //Act - var deserialized = (List)engine.Invoke(array, typeof(List)); - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(array, deserialized); - } - - [Theory] - [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] - public void HashSet_of_int(Func engine) - { - //Arrange - HashSet hashset = _fixture.Create>(); - - //Act - var deserialized = (HashSet)engine.Invoke(hashset, typeof(HashSet)); - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(hashset, deserialized); - } - - [Theory] - [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] - public void IImmutableSet_of_class(Func engine) - { - //Arrange - IImmutableSet set = _fixture.Create>().ToImmutableHashSet(); - - //Act - var deserialized = (ImmutableHashSet)engine.Invoke(set, typeof(ImmutableHashSet)); - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(set, deserialized); - } - - [Theory] - [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] - public void Class_with_empty_list(Func engine) - { - //Arrange - ClassWithConstructorPopulatingProperty testClass = new ClassWithConstructorPopulatingProperty(); - - - //Act - var deserialized = (ClassWithConstructorPopulatingProperty)engine.Invoke(testClass, typeof(ClassWithConstructorPopulatingProperty)); - - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(testClass.anotherList, deserialized.anotherList); - Assert.Equal(testClass.nestedList, deserialized.nestedList); - deserialized.stringProperty.Should().BeNullOrEmpty(); - } - - [Fact(Skip = "MultidimensionalArray is not supported yet")] - public void Component_MultidimensionalArray_ResultIsTheSameAsInput() - { - //Arrange - MultidimensionalArrayClass array = _fixture.Create(); - - - //Act - var result = AvroConvert.Serialize(array); - - var deserialized = AvroConvert.Deserialize(result); - - - //Assert - Assert.NotNull(result); - Assert.NotNull(deserialized); - Assert.Equal(array, deserialized); - } - } -} +// using System; +// using System.Collections.Generic; +// using System.Collections.Immutable; +// using System.Linq; +// using AutoFixture; +// using FluentAssertions; +// using SolTechnology.Avro; +// using Xunit; +// +// namespace AvroConvertComponentTests.FullSerializationAndDeserialization +// { +// public class CollectionsTests +// { +// private readonly Fixture _fixture = new(); +// +// [Theory] +// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] +// public void List_of_class(Func engine) +// { +// //Arrange +// var someTestClasses = _fixture.CreateMany().ToList(); +// +// //Act +// var deserialized = engine.Invoke(someTestClasses, typeof(List)); +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(someTestClasses, deserialized); +// } +// +// [Theory] +// [Trait("Fix", "https://github.com/AdrianStrugala/AvroConvert/issues/146")] +// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] +// public void IEnumerable_of_class(Func engine) +// { +// //Arrange +// var someTestClasses = _fixture.CreateMany(); +// +// //Act +// var deserialized = engine.Invoke(someTestClasses, typeof(IEnumerable)); +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(someTestClasses, deserialized); +// } +// +// [Theory] +// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] +// public void Class_with_list(Func engine) +// { +// //Arrange +// ClassWithSimpleList testClass = _fixture.Create(); +// +// //Act +// var deserialized = (ClassWithSimpleList)engine.Invoke(testClass, typeof(ClassWithSimpleList)); +// +// //Assert +// Assert.NotNull(deserialized); +// deserialized.Should().BeEquivalentTo(testClass); +// } +// +// [Theory] +// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] +// public void Class_with_list_of_classes(Func engine) +// { +// //Arrange +// ClassWithConstructorPopulatingProperty +// testClass = _fixture.Create(); +// +// //Act +// var deserialized = (ClassWithConstructorPopulatingProperty)engine.Invoke(testClass, typeof(ClassWithConstructorPopulatingProperty)); +// +// //Assert +// Assert.NotNull(deserialized); +// deserialized.Should().BeEquivalentTo(testClass); +// +// } +// +// [Theory] +// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] +// public void Class_with_array(Func engine) +// { +// //Arrange +// ClassWithArray +// testClass = _fixture.Create(); +// +// //Act +// var deserialized = (ClassWithArray)engine.Invoke(testClass, typeof(ClassWithArray)); +// +// //Assert +// Assert.NotNull(deserialized); +// deserialized.Should().BeEquivalentTo(testClass); +// } +// +// [Theory] +// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] +// public void List_of_int(Func engine) +// { +// //Arrange +// List toSerialize = _fixture.Create>(); +// +// //Act +// var deserialized = (List)engine.Invoke(toSerialize, typeof(List)); +// +// //Assert +// Assert.NotNull(deserialized); +// deserialized.Should().BeEquivalentTo(deserialized); +// } +// +// [Theory] +// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] +// public void Array_of_int(Func engine) +// { +// //Arrange +// int[] array = _fixture.Create(); +// +// //Act +// var deserialized = (List)engine.Invoke(array, typeof(List)); +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(array, deserialized); +// } +// +// [Theory] +// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] +// public void HashSet_of_int(Func engine) +// { +// //Arrange +// HashSet hashset = _fixture.Create>(); +// +// //Act +// var deserialized = (HashSet)engine.Invoke(hashset, typeof(HashSet)); +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(hashset, deserialized); +// } +// +// [Theory] +// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] +// public void IImmutableSet_of_class(Func engine) +// { +// //Arrange +// IImmutableSet set = _fixture.Create>().ToImmutableHashSet(); +// +// //Act +// var deserialized = (ImmutableHashSet)engine.Invoke(set, typeof(ImmutableHashSet)); +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(set, deserialized); +// } +// +// [Theory] +// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] +// public void Class_with_empty_list(Func engine) +// { +// //Arrange +// ClassWithConstructorPopulatingProperty testClass = new ClassWithConstructorPopulatingProperty(); +// +// +// //Act +// var deserialized = (ClassWithConstructorPopulatingProperty)engine.Invoke(testClass, typeof(ClassWithConstructorPopulatingProperty)); +// +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(testClass.anotherList, deserialized.anotherList); +// Assert.Equal(testClass.nestedList, deserialized.nestedList); +// deserialized.stringProperty.Should().BeNullOrEmpty(); +// } +// +// [Fact(Skip = "MultidimensionalArray is not supported yet")] +// public void Component_MultidimensionalArray_ResultIsTheSameAsInput() +// { +// //Arrange +// MultidimensionalArrayClass array = _fixture.Create(); +// +// +// //Act +// var result = AvroConvert.Serialize(array); +// +// var deserialized = AvroConvert.Deserialize(result); +// +// +// //Assert +// Assert.NotNull(result); +// Assert.NotNull(deserialized); +// Assert.Equal(array, deserialized); +// } +// } +// } diff --git a/tests/AvroConvertTests/FullSerializationAndDeserialization/DictionaryTests.cs b/tests/AvroConvertTests/FullSerializationAndDeserialization/DictionaryTests.cs index 09223e9b..2e10edf6 100644 --- a/tests/AvroConvertTests/FullSerializationAndDeserialization/DictionaryTests.cs +++ b/tests/AvroConvertTests/FullSerializationAndDeserialization/DictionaryTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using AutoFixture; +using FluentAssertions; using Xunit; namespace AvroConvertComponentTests.FullSerializationAndDeserialization @@ -76,5 +77,40 @@ public void Class_containing_dictionary_and_map(Func engi Assert.NotNull(deserialized); Assert.Equal(testClass, deserialized); } + + [Theory] + [Trait("Fix", "https://github.com/AdrianStrugala/AvroConvert/issues/152")] + [MemberData(nameof(TestEngine.Core), MemberType = typeof(TestEngine))] + public void Class_containing_two_dictionaries(Func engine) + { + //Arrange + ClassWith2Dictionaries testClass = _fixture.Create(); + + + //Act + var deserialized = (ClassWith2Dictionaries)engine.Invoke(testClass, typeof(ClassWith2Dictionaries)); + + + //Assert + Assert.NotNull(deserialized); + deserialized.Should().BeEquivalentTo(testClass); + } + + [Theory] + [MemberData(nameof(TestEngine.Core), MemberType = typeof(TestEngine))] + public void Class_containing_two_maps(Func engine) + { + //Arrange + ClassWith2Maps testClass = _fixture.Create(); + + + //Act + var deserialized = (ClassWith2Maps)engine.Invoke(testClass, typeof(ClassWith2Maps)); + + + //Assert + Assert.NotNull(deserialized); + deserialized.Should().BeEquivalentTo(testClass); + } } } diff --git a/tests/AvroConvertTests/FullSerializationAndDeserialization/PartiallyMatchingClassesTests.cs b/tests/AvroConvertTests/FullSerializationAndDeserialization/PartiallyMatchingClassesTests.cs index 6a60ec86..3e7d0f96 100644 --- a/tests/AvroConvertTests/FullSerializationAndDeserialization/PartiallyMatchingClassesTests.cs +++ b/tests/AvroConvertTests/FullSerializationAndDeserialization/PartiallyMatchingClassesTests.cs @@ -1,155 +1,155 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using AutoFixture; -using AutoFixture.Kernel; -using SolTechnology.Avro; -using Xunit; - -namespace AvroConvertComponentTests.FullSerializationAndDeserialization -{ - public class PartiallyMatchingClassesTests - { - private readonly Fixture _fixture = new(); - - [Theory] - [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] - public void SerializeBiggerObjectAndReadSmaller(Func engine) - { - //Arrange - ExtendedBaseTestClass toSerialize = _fixture.Create(); - - - //Act - var writeSchema = AvroConvert.GenerateSchema(typeof(ExtendedBaseTestClass)); - var readSchema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); - var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), writeSchema, readSchema); - - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); - Assert.Equal(toSerialize.andLongProperty, deserialized.andLongProperty); - } - - - [Theory] - [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] - public void SerializeSmallerClassAndReadBigger(Func engine) - { - //Arrange - ReducedBaseTestClass toSerialize = _fixture.Create(); - - - //Act - var schema = AvroConvert.GenerateSchema(typeof(ReducedBaseTestClass)); - var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), schema, schema); - - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); - } - - - [Theory] - [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] - public void SerializeHeadlessBiggerObjectUsingReducedSchemaAndReadSmaller(Func engine) - { - //Arrange - ExtendedBaseTestClass toSerialize = _fixture.Create(); - string schema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); - - //Act - var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), schema, schema); - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(toSerialize.andLongProperty, deserialized.andLongProperty); - Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); - } - - - [Theory] - [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] - public void SerializeBiggerAvroObjectAndReadSmaller(Func engine) - { - //Arrange - AttributeClass toSerialize = _fixture.Create(); - - - //Act - var schema = AvroConvert.GenerateSchema(typeof(AttributeClass)); - var deserialized = engine.Invoke(toSerialize, typeof(SmallerAttributeClass), schema, schema); - - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(toSerialize.NullableStringProperty, deserialized.NullableStringProperty); - Assert.Equal(toSerialize.NullableIntProperty, deserialized.NullableIntProperty); - } - - - [Theory] - [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] - public void SerializeAndDeserializeClassesWithDifferentPropertyCases(Func engine) - { - //Arrange - BaseTestClass toSerialize = _fixture.Create(); - - - //Act - var schema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); - var deserialized = engine.Invoke(toSerialize, typeof(DifferentCaseBaseTestClass), schema, schema); - - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(toSerialize.justSomeProperty, deserialized.JustSomeProperty); - Assert.Equal(toSerialize.andLongProperty, deserialized.AndLongProperty); - } - - public static IEnumerable PrimitivesAndNullables - { - get - { - foreach (var c in TestEngine.All().ToList()) - { - yield return new[] { typeof(short), typeof(short?), c.FirstOrDefault() }; - yield return new[] { typeof(uint), typeof(uint?), c.FirstOrDefault() }; - yield return new[] { typeof(ushort), typeof(ushort?), c.FirstOrDefault() }; - yield return new[] { typeof(int), typeof(int?), c.FirstOrDefault() }; - yield return new[] { typeof(long), typeof(long?), c.FirstOrDefault() }; - yield return new[] { typeof(Guid), typeof(Guid?), c.FirstOrDefault() }; - yield return new[] { typeof(ulong), typeof(ulong?), c.FirstOrDefault() }; - yield return new[] { typeof(char), typeof(char?), c.FirstOrDefault() }; - yield return new[] { typeof(byte), typeof(byte?), c.FirstOrDefault() }; - yield return new[] { typeof(sbyte), typeof(sbyte?), c.FirstOrDefault() }; - yield return new[] { typeof(bool), typeof(bool?), c.FirstOrDefault() }; - yield return new[] { typeof(float), typeof(float?), c.FirstOrDefault() }; - yield return new[] { typeof(double), typeof(double?), c.FirstOrDefault() }; - yield return new[] { typeof(decimal), typeof(decimal?), c.FirstOrDefault() }; - } - } - } - - [Theory] - [MemberData(nameof(PrimitivesAndNullables))] - public void Serialize_primitives_read_nullable_correspondings( - Type serializationType, Type deserializationType, - Func engine) - { - //Arrange - var underTest = new SpecimenContext(_fixture).Resolve(serializationType); - - - //Act - var deserialized = engine.Invoke(underTest, deserializationType); - - - //Assert - Assert.NotNull(deserialized); - Assert.Equal(underTest, deserialized); - } - } -} +// using System; +// using System.Collections.Generic; +// using System.Linq; +// using AutoFixture; +// using AutoFixture.Kernel; +// using SolTechnology.Avro; +// using Xunit; +// +// namespace AvroConvertComponentTests.FullSerializationAndDeserialization +// { +// public class PartiallyMatchingClassesTests +// { +// private readonly Fixture _fixture = new(); +// +// [Theory] +// [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] +// public void SerializeBiggerObjectAndReadSmaller(Func engine) +// { +// //Arrange +// ExtendedBaseTestClass toSerialize = _fixture.Create(); +// +// +// //Act +// var writeSchema = AvroConvert.GenerateSchema(typeof(ExtendedBaseTestClass)); +// var readSchema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); +// var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), writeSchema, readSchema); +// +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); +// Assert.Equal(toSerialize.andLongProperty, deserialized.andLongProperty); +// } +// +// +// [Theory] +// [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] +// public void SerializeSmallerClassAndReadBigger(Func engine) +// { +// //Arrange +// ReducedBaseTestClass toSerialize = _fixture.Create(); +// +// +// //Act +// var schema = AvroConvert.GenerateSchema(typeof(ReducedBaseTestClass)); +// var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), schema, schema); +// +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); +// } +// +// +// [Theory] +// [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] +// public void SerializeHeadlessBiggerObjectUsingReducedSchemaAndReadSmaller(Func engine) +// { +// //Arrange +// ExtendedBaseTestClass toSerialize = _fixture.Create(); +// string schema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); +// +// //Act +// var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), schema, schema); +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(toSerialize.andLongProperty, deserialized.andLongProperty); +// Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); +// } +// +// +// [Theory] +// [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] +// public void SerializeBiggerAvroObjectAndReadSmaller(Func engine) +// { +// //Arrange +// AttributeClass toSerialize = _fixture.Create(); +// +// +// //Act +// var schema = AvroConvert.GenerateSchema(typeof(AttributeClass)); +// var deserialized = engine.Invoke(toSerialize, typeof(SmallerAttributeClass), schema, schema); +// +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(toSerialize.NullableStringProperty, deserialized.NullableStringProperty); +// Assert.Equal(toSerialize.NullableIntProperty, deserialized.NullableIntProperty); +// } +// +// +// [Theory] +// [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] +// public void SerializeAndDeserializeClassesWithDifferentPropertyCases(Func engine) +// { +// //Arrange +// BaseTestClass toSerialize = _fixture.Create(); +// +// +// //Act +// var schema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); +// var deserialized = engine.Invoke(toSerialize, typeof(DifferentCaseBaseTestClass), schema, schema); +// +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(toSerialize.justSomeProperty, deserialized.JustSomeProperty); +// Assert.Equal(toSerialize.andLongProperty, deserialized.AndLongProperty); +// } +// +// public static IEnumerable PrimitivesAndNullables +// { +// get +// { +// foreach (var c in TestEngine.All().ToList()) +// { +// yield return new[] { typeof(short), typeof(short?), c.FirstOrDefault() }; +// yield return new[] { typeof(uint), typeof(uint?), c.FirstOrDefault() }; +// yield return new[] { typeof(ushort), typeof(ushort?), c.FirstOrDefault() }; +// yield return new[] { typeof(int), typeof(int?), c.FirstOrDefault() }; +// yield return new[] { typeof(long), typeof(long?), c.FirstOrDefault() }; +// yield return new[] { typeof(Guid), typeof(Guid?), c.FirstOrDefault() }; +// yield return new[] { typeof(ulong), typeof(ulong?), c.FirstOrDefault() }; +// yield return new[] { typeof(char), typeof(char?), c.FirstOrDefault() }; +// yield return new[] { typeof(byte), typeof(byte?), c.FirstOrDefault() }; +// yield return new[] { typeof(sbyte), typeof(sbyte?), c.FirstOrDefault() }; +// yield return new[] { typeof(bool), typeof(bool?), c.FirstOrDefault() }; +// yield return new[] { typeof(float), typeof(float?), c.FirstOrDefault() }; +// yield return new[] { typeof(double), typeof(double?), c.FirstOrDefault() }; +// yield return new[] { typeof(decimal), typeof(decimal?), c.FirstOrDefault() }; +// } +// } +// } +// +// [Theory] +// [MemberData(nameof(PrimitivesAndNullables))] +// public void Serialize_primitives_read_nullable_correspondings( +// Type serializationType, Type deserializationType, +// Func engine) +// { +// //Arrange +// var underTest = new SpecimenContext(_fixture).Resolve(serializationType); +// +// +// //Act +// var deserialized = engine.Invoke(underTest, deserializationType); +// +// +// //Assert +// Assert.NotNull(deserialized); +// Assert.Equal(underTest, deserialized); +// } +// } +// } diff --git a/tests/AvroConvertTests/GenerateModel/GenerateModelTests.cs b/tests/AvroConvertTests/GenerateModel/GenerateModelTests.cs index 3770313a..0678b7e2 100644 --- a/tests/AvroConvertTests/GenerateModel/GenerateModelTests.cs +++ b/tests/AvroConvertTests/GenerateModel/GenerateModelTests.cs @@ -139,7 +139,7 @@ public void GenerateClass_VeryComplexClass_OutputIsEqualToExpected() "\tpublic ClassWithArray[] ClassesWithArray { get; set; }\r\n" + "\tpublic ClassWithGuid[] ClassesWithGuid { get; set; }\r\n" + "\tpublic ClassWithConstructorPopulatingProperty anotherClass { get; set; }\r\n" + - "\tpublic User simpleClass { get; set; }\r\n" + + "\tpublic AvroConvertComponentTests.User simpleClass { get; set; }\r\n" + "\tpublic int simpleObject { get; set; }\r\n" + "\tpublic bool[] bools { get; set; }\r\n" + "\tpublic double doubleProperty { get; set; }\r\n" + @@ -168,10 +168,10 @@ public void GenerateClass_VeryComplexClass_OutputIsEqualToExpected() "{\r\n" + "\tpublic string justSomeProperty { get; set; }\r\n" + "\tpublic long andLongProperty { get; set; }\r\n" + - "\tpublic User objectProperty { get; set; }\r\n" + + "\tpublic AvroConvertComponentTests.User objectProperty { get; set; }\r\n" + "}\r\n" + "\r\n" + - "public class User\r\n" + + "public class AvroConvertComponentTests.User\r\n" + "{\r\n" + "\tpublic string? name { get; set; }\r\n" + "\tpublic int? favorite_number { get; set; }\r\n" + @@ -291,16 +291,16 @@ public void GenerateClass_TwoClassesOfTheSameName_TheyAreGeneratedWithNamespaces Assert.Equal( "public class BaseTestClass\r\n" + "{\r\n" + - "\tpublic FakeUserUser fakeUserProperty { get; set; }\r\n" + - "\tpublic AvroConvertComponentTestsUser objectProperty { get; set; }\r\n" + + "\tpublic FakeUser.User fakeUserProperty { get; set; }\r\n" + + "\tpublic AvroConvertComponentTests.User objectProperty { get; set; }\r\n" + "}\r\n" + "\r\n" + - "public class FakeUserUser\r\n" + + "public class FakeUser.User\r\n" + "{\r\n" + "\tpublic string name { get; set; }\r\n" + "}\r\n" + "\r\n" + - "public class AvroConvertComponentTestsUser\r\n" + + "public class AvroConvertComponentTests.User\r\n" + "{\r\n" + "\tpublic string name { get; set; }\r\n" + "\tpublic int? favorite_number { get; set; }\r\n" + @@ -414,11 +414,11 @@ public void GenerateClass_SameNameClassesOneFieldIsAnArray_TheyAreGeneratedWithN "public class module\r\n" + "{\r\n" + "\tpublic string? moduleIdName { get; set; }\r\n" + - "\tpublic datamodule[] data { get; set; }\r\n" + + "\tpublic data.module[] data { get; set; }\r\n" + "\tpublic int? instrumentId { get; set; }\r\n" + "}\r\n" + "\r\n" + - "public class datamodule\r\n" + + "public class data.module\r\n" + "{\r\n" + "\tpublic bool? isControl { get; set; }\r\n" + "}\r\n" + diff --git a/tests/AvroConvertTests/TestClasses.cs b/tests/AvroConvertTests/TestClasses.cs index a27e3712..9bce10fe 100644 --- a/tests/AvroConvertTests/TestClasses.cs +++ b/tests/AvroConvertTests/TestClasses.cs @@ -1,433 +1,445 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.ComponentModel; -using System.Runtime.Serialization; -using SolTechnology.Avro.Infrastructure.Attributes; - -namespace AvroConvertComponentTests -{ - [Equals(DoNotAddEqualityOperators = true)] - public class User - { - public string? name { get; set; } - public int? favorite_number { get; set; } - public string favorite_color { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class UserWithNonNullableProperties - { - public string name { get; set; } - public int favorite_number { get; set; } - public string favorite_color { get; set; } - } - - - [Equals(DoNotAddEqualityOperators = true)] - public class UserNameClass - { - public string name { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class BaseTestClass - { - public string justSomeProperty { get; set; } - public long andLongProperty { get; set; } - public User objectProperty { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class DifferentCaseBaseTestClass - { - public string JustSomeProperty { get; set; } - public long AndLongProperty { get; set; } - public User ObjectProperty { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class ReducedBaseTestClass - { - public string justSomeProperty { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class ExtendedBaseTestClass - { - public string justSomeProperty { get; set; } - public long andLongProperty { get; set; } - public double DoubleProp { get; set; } - public bool BoolProp { get; set; } - public long LongToSkipProp { get; set; } - public Guid TheGuid { get; set; } - public int[] TheArray { get; set; } - public List Bools; - [DefaultValue(9200000000000000007)] - public long? AndLongBigDefaultedProperty { get; set; } - public User objectProperty { get; set; } - public ClassWithConstructorPopulatingProperty AnotherClass { get; set; } - public double DoubleProperty { get; set; } - public Dictionary AvroMap { get; set; } - public Dictionary OtherDictionary { get; set; } - public float FloatProp { get; set; } - public TestEnum EnumProp { get; set; } - } - - - [Equals(DoNotAddEqualityOperators = true)] - public class LogicalTypesClass - { - public decimal One { get; set; } - - public Guid? Two { get; set; } - - public TimeSpan Three { get; set; } - - public DateTime? Four { get; set; } - - public DateTimeOffset Five { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class ClassWithConstructorPopulatingProperty - { - public List nestedList { get; set; } - public List anotherList { get; set; } - public string stringProperty { get; set; } - - public ClassWithConstructorPopulatingProperty() - { - nestedList = new List(); - anotherList = new List(); - } - - } - [Equals(DoNotAddEqualityOperators = true)] - public class ClassWithSimpleList - { - public List someList { get; set; } - - public ClassWithSimpleList() - { - someList = new List(); - } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class ClassWithArray - { - public int[] theArray { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class ClassWithGuid - { - public Guid theGuid { get; set; } - } - - - [Equals(DoNotAddEqualityOperators = true)] - public class VeryComplexClass - { - public List ClassesWithArray { get; set; } - public ClassWithGuid[] ClassesWithGuid { get; set; } - public ClassWithConstructorPopulatingProperty anotherClass { get; set; } - public User simpleClass { get; set; } - public int simpleObject { get; set; } - public List bools { get; set; } - public double doubleProperty { get; set; } - public float floatProperty { get; set; } - public short? Size { get; set; } - } - - - [Equals(DoNotAddEqualityOperators = true)] - [DataContract(Name = "User", Namespace = "user")] - public class AttributeClass - { - [DataMember(Name = "name")] - [NullableSchema] - public string NullableStringProperty { get; set; } - - [DataMember(Name = "favorite_number")] - [NullableSchema] - public int NullableIntProperty { get; set; } - - [DataMember(Name = "favorite_color")] - public string AndAnotherString { get; set; } - - [DefaultValue(2137)] - public int? NullableIntPropertyWithDefaultValue { get; set; } - - [IgnoreDataMember] - public string IgnoredProperty { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - [DataContract(Name = "User", Namespace = "database")] - public class SmallerAttributeClass - { - [DataMember(Name = "name")] - [NullableSchema] - public string NullableStringProperty { get; set; } - - [DataMember(Name = "favorite_number")] - [NullableSchema] - public int? NullableIntProperty { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class ClassWithDateTime - { - public string From { get; set; } - public string To { get; set; } - - public int Count { get; set; } - public DateTime ArriveBy { get; set; } - public DateOnly MyDate { get; set; } - public TimeOnly MyTime { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class ClassWithDateTimeOffset - { - public DateTimeOffset yeah { get; set; } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class ConcurrentBagClass - { - public ConcurrentBag concurentBagField; - } - public class ClassWithReadOnlyProperties - { - public string ReadOnly => "one"; - public int? NullableReadOnly => 1; - } - - public class ClassWithoutGetters - { - public string SomeString; - public int Count; - } - - [Equals(DoNotAddEqualityOperators = true)] - public class ComplexClassWithoutGetters - { - public List ClassesWithArray; - public ClassWithGuid[] ClassesWithGuid; - public ClassWithConstructorPopulatingProperty AnotherClass; - public User SimpleClass; - public int SimpleObject; - public List Bools; - public double DoubleProperty; - public float FloatProperty; - } - - [Equals(DoNotAddEqualityOperators = true)] - [DataContract(Name = "User", Namespace = "user")] - public class AttributeClassWithoutGetters - { - [DataMember(Name = "name")] - [NullableSchema] - public string StringProperty; - - [DataMember(Name = "favorite_number")] - [NullableSchema] - public int? NullableIntProperty; - - [DataMember(Name = "favorite_color")] - public string AndAnotherString; - } - - public struct ComplexStruct - { - [DataMember] - public List savedValues; - - public ComplexStruct(List vals) - { - savedValues = vals; - } - } - - [Equals(DoNotAddEqualityOperators = true)] - public class MultidimensionalArrayClass - { - public int[,,] ArrayField { get; set; } - } - - - [Equals(DoNotAddEqualityOperators = true)] - public class DefaultValueClass - { - [DefaultValue("Let's go")] - [NullableSchema] - public string justSomeProperty { get; set; } - - public long? andLongProperty { get; set; } - - [DefaultValue(9200000000000000007)] - public long? andLongBigDefaultedProperty { get; set; } - - [DefaultValue(100)] - public long? andLongSmallDefaultedProperty { get; set; } - - [DefaultValue(null)] - public long? andNullProperty { get; set; } - } - - - [Equals(DoNotAddEqualityOperators = true)] - [DataContract] - public struct MixedDataMembers - { - [DataMember] - public List savedValues; - - public long? dontSerializeMe { get; set; } - - [DataMember] - public long? andAnother { get; set; } - - public int anIntField; - } - - public enum TestEnum - { - a, - be, - ca, - dlo - } - - [Flags] - public enum TestEnumWithFlags - { - None = 0, - Option1 = 1, - Option2 = 2, - Option3 = 4, - Option4 = 8, - CombinedOption = Option1 | Option2 - } - - public enum TestEnumWithMembers - { - [EnumMember(Value = "POSITIVE_VALUE")] +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.Serialization; +using SolTechnology.Avro.Infrastructure.Attributes; + +namespace AvroConvertComponentTests +{ + [Equals(DoNotAddEqualityOperators = true)] + public class User + { + public string? name { get; set; } + public int? favorite_number { get; set; } + public string favorite_color { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class UserWithNonNullableProperties + { + public string name { get; set; } + public int favorite_number { get; set; } + public string favorite_color { get; set; } + } + + + [Equals(DoNotAddEqualityOperators = true)] + public class UserNameClass + { + public string name { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class BaseTestClass + { + public string justSomeProperty { get; set; } + public long andLongProperty { get; set; } + public User objectProperty { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class DifferentCaseBaseTestClass + { + public string JustSomeProperty { get; set; } + public long AndLongProperty { get; set; } + public User ObjectProperty { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ReducedBaseTestClass + { + public string justSomeProperty { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ExtendedBaseTestClass + { + public string justSomeProperty { get; set; } + public long andLongProperty { get; set; } + public double DoubleProp { get; set; } + public bool BoolProp { get; set; } + public long LongToSkipProp { get; set; } + public Guid TheGuid { get; set; } + public int[] TheArray { get; set; } + public List Bools; + [DefaultValue(9200000000000000007)] + public long? AndLongBigDefaultedProperty { get; set; } + public User objectProperty { get; set; } + public ClassWithConstructorPopulatingProperty AnotherClass { get; set; } + public double DoubleProperty { get; set; } + public Dictionary AvroMap { get; set; } + public Dictionary OtherDictionary { get; set; } + public float FloatProp { get; set; } + public TestEnum EnumProp { get; set; } + } + + public class ClassWith2Dictionaries + { + public Dictionary ByteArrayData { get; set; } = new(); + public Dictionary FloatData { get; set; } = new(); + } + + public class ClassWith2Maps + { + public Dictionary ByteArrayData { get; set; } = new(); + public Dictionary FloatData { get; set; } = new(); + } + + + [Equals(DoNotAddEqualityOperators = true)] + public class LogicalTypesClass + { + public decimal One { get; set; } + + public Guid? Two { get; set; } + + public TimeSpan Three { get; set; } + + public DateTime? Four { get; set; } + + public DateTimeOffset Five { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ClassWithConstructorPopulatingProperty + { + public List nestedList { get; set; } + public List anotherList { get; set; } + public string stringProperty { get; set; } + + public ClassWithConstructorPopulatingProperty() + { + nestedList = new List(); + anotherList = new List(); + } + + } + [Equals(DoNotAddEqualityOperators = true)] + public class ClassWithSimpleList + { + public List someList { get; set; } + + public ClassWithSimpleList() + { + someList = new List(); + } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ClassWithArray + { + public int[] theArray { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ClassWithGuid + { + public Guid theGuid { get; set; } + } + + + [Equals(DoNotAddEqualityOperators = true)] + public class VeryComplexClass + { + public List ClassesWithArray { get; set; } + public ClassWithGuid[] ClassesWithGuid { get; set; } + public ClassWithConstructorPopulatingProperty anotherClass { get; set; } + public User simpleClass { get; set; } + public int simpleObject { get; set; } + public List bools { get; set; } + public double doubleProperty { get; set; } + public float floatProperty { get; set; } + public short? Size { get; set; } + } + + + [Equals(DoNotAddEqualityOperators = true)] + [DataContract(Name = "User", Namespace = "user")] + public class AttributeClass + { + [DataMember(Name = "name")] + [NullableSchema] + public string NullableStringProperty { get; set; } + + [DataMember(Name = "favorite_number")] + [NullableSchema] + public int NullableIntProperty { get; set; } + + [DataMember(Name = "favorite_color")] + public string AndAnotherString { get; set; } + + [DefaultValue(2137)] + public int? NullableIntPropertyWithDefaultValue { get; set; } + + [IgnoreDataMember] + public string IgnoredProperty { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + [DataContract(Name = "User", Namespace = "database")] + public class SmallerAttributeClass + { + [DataMember(Name = "name")] + [NullableSchema] + public string NullableStringProperty { get; set; } + + [DataMember(Name = "favorite_number")] + [NullableSchema] + public int? NullableIntProperty { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ClassWithDateTime + { + public string From { get; set; } + public string To { get; set; } + + public int Count { get; set; } + public DateTime ArriveBy { get; set; } + public DateOnly MyDate { get; set; } + public TimeOnly MyTime { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ClassWithDateTimeOffset + { + public DateTimeOffset yeah { get; set; } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ConcurrentBagClass + { + public ConcurrentBag concurentBagField; + } + public class ClassWithReadOnlyProperties + { + public string ReadOnly => "one"; + public int? NullableReadOnly => 1; + } + + public class ClassWithoutGetters + { + public string SomeString; + public int Count; + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ComplexClassWithoutGetters + { + public List ClassesWithArray; + public ClassWithGuid[] ClassesWithGuid; + public ClassWithConstructorPopulatingProperty AnotherClass; + public User SimpleClass; + public int SimpleObject; + public List Bools; + public double DoubleProperty; + public float FloatProperty; + } + + [Equals(DoNotAddEqualityOperators = true)] + [DataContract(Name = "User", Namespace = "user")] + public class AttributeClassWithoutGetters + { + [DataMember(Name = "name")] + [NullableSchema] + public string StringProperty; + + [DataMember(Name = "favorite_number")] + [NullableSchema] + public int? NullableIntProperty; + + [DataMember(Name = "favorite_color")] + public string AndAnotherString; + } + + public struct ComplexStruct + { + [DataMember] + public List savedValues; + + public ComplexStruct(List vals) + { + savedValues = vals; + } + } + + [Equals(DoNotAddEqualityOperators = true)] + public class MultidimensionalArrayClass + { + public int[,,] ArrayField { get; set; } + } + + + [Equals(DoNotAddEqualityOperators = true)] + public class DefaultValueClass + { + [DefaultValue("Let's go")] + [NullableSchema] + public string justSomeProperty { get; set; } + + public long? andLongProperty { get; set; } + + [DefaultValue(9200000000000000007)] + public long? andLongBigDefaultedProperty { get; set; } + + [DefaultValue(100)] + public long? andLongSmallDefaultedProperty { get; set; } + + [DefaultValue(null)] + public long? andNullProperty { get; set; } + } + + + [Equals(DoNotAddEqualityOperators = true)] + [DataContract] + public struct MixedDataMembers + { + [DataMember] + public List savedValues; + + public long? dontSerializeMe { get; set; } + + [DataMember] + public long? andAnother { get; set; } + + public int anIntField; + } + + public enum TestEnum + { + a, + be, + ca, + dlo + } + + [Flags] + public enum TestEnumWithFlags + { + None = 0, + Option1 = 1, + Option2 = 2, + Option3 = 4, + Option4 = 8, + CombinedOption = Option1 | Option2 + } + + public enum TestEnumWithMembers + { + [EnumMember(Value = "POSITIVE_VALUE")] Positive, - [EnumMember(Value = "NEGATIVE_VALUE")] - Negative - } - - [Equals(DoNotAddEqualityOperators = true)] - public class ClassWithEnum - { - [DefaultValue(TestEnum.be)] - public TestEnum? EnumProp { get; set; } - - [DefaultValue("ca")] - public TestEnum? SecondEnumProp { get; set; } - } - - public class ClassWithEnumDefiningMembers - { - public TestEnumWithMembers? EnumProp { get; set; } - - [DefaultValue(TestEnumWithMembers.Negative)] - public TestEnumWithMembers? EnumPropWithDefault { get; set; } - - [DefaultValue("NEGATIVE_VALUE")] - public TestEnumWithMembers? EnumPropWithStringDefault { get; set; } - } - - public record TestRecord - { - public string Name { get; set; } - } - -#nullable enable - [Equals(DoNotAddEqualityOperators = true)] - public class ClassWithNullableMembers - { - public string? NullableStringProperty { get; set; } - - public string? NullableField; - public UserNameClass? NullableRecord { get; set; } - } -#nullable disable - - public class BaseClass - { - public string BaseProp { get; set; } - } - - public class InheritingClass : BaseClass - { - } - - public interface BaseInterface - { - public string BaseProp { get; set; } - } - - public class InheritingClassFromInterface : BaseInterface - { - public string BaseProp { get; set; } - } - - public class kylosample - { - public string registration_dttm { get; set; } - public long id { get; set; } - public string first_name { get; set; } - public string last_name { get; set; } - public string email { get; set; } - public string gender { get; set; } - public string ip_address { get; set; } - public long? cc { get; set; } - public string country { get; set; } - public string birthdate { get; set; } - public double? salary { get; set; } - public string title { get; set; } - public string comments { get; set; } - } - - - - public class ClassWithoutDefaultConstructor - { - public string Name { get; private set; } - - public ClassWithoutDefaultConstructor(string name) - { - Name = name; - } - } - - public class VeryComplexClassWithoutDefaultConstructor - { - public List ClassesWithArray { get; set; } - public ClassWithGuid[] ClassesWithGuid { get; set; } - public ClassWithConstructorPopulatingProperty anotherClass { get; set; } - public User simpleClass { get; set; } - public int simpleObject { get; set; } - public List bools { get; set; } - public double doubleProperty { get; set; } - public float floatProperty { get; set; } - - public VeryComplexClassWithoutDefaultConstructor(List classesWithArray, ClassWithGuid[] classesWithGuid, ClassWithConstructorPopulatingProperty anotherClass, User simpleClass, int simpleObject, List bools, double doubleProperty, float floatProperty) - { - ClassesWithArray = classesWithArray; - ClassesWithGuid = classesWithGuid; - this.anotherClass = anotherClass; - this.simpleClass = simpleClass; - this.simpleObject = simpleObject; - this.bools = bools; - this.doubleProperty = doubleProperty; - this.floatProperty = floatProperty; - } - } -} + [EnumMember(Value = "NEGATIVE_VALUE")] + Negative + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ClassWithEnum + { + [DefaultValue(TestEnum.be)] + public TestEnum? EnumProp { get; set; } + + [DefaultValue("ca")] + public TestEnum? SecondEnumProp { get; set; } + } + + public class ClassWithEnumDefiningMembers + { + public TestEnumWithMembers? EnumProp { get; set; } + + [DefaultValue(TestEnumWithMembers.Negative)] + public TestEnumWithMembers? EnumPropWithDefault { get; set; } + + [DefaultValue("NEGATIVE_VALUE")] + public TestEnumWithMembers? EnumPropWithStringDefault { get; set; } + } + + public record TestRecord + { + public string Name { get; set; } + } + +#nullable enable + [Equals(DoNotAddEqualityOperators = true)] + public class ClassWithNullableMembers + { + public string? NullableStringProperty { get; set; } + + public string? NullableField; + public UserNameClass? NullableRecord { get; set; } + } +#nullable disable + + public class BaseClass + { + public string BaseProp { get; set; } + } + + public class InheritingClass : BaseClass + { + } + + public interface BaseInterface + { + public string BaseProp { get; set; } + } + + public class InheritingClassFromInterface : BaseInterface + { + public string BaseProp { get; set; } + } + + public class kylosample + { + public string registration_dttm { get; set; } + public long id { get; set; } + public string first_name { get; set; } + public string last_name { get; set; } + public string email { get; set; } + public string gender { get; set; } + public string ip_address { get; set; } + public long? cc { get; set; } + public string country { get; set; } + public string birthdate { get; set; } + public double? salary { get; set; } + public string title { get; set; } + public string comments { get; set; } + } + + + + public class ClassWithoutDefaultConstructor + { + public string Name { get; private set; } + + public ClassWithoutDefaultConstructor(string name) + { + Name = name; + } + } + + public class VeryComplexClassWithoutDefaultConstructor + { + public List ClassesWithArray { get; set; } + public ClassWithGuid[] ClassesWithGuid { get; set; } + public ClassWithConstructorPopulatingProperty anotherClass { get; set; } + public User simpleClass { get; set; } + public int simpleObject { get; set; } + public List bools { get; set; } + public double doubleProperty { get; set; } + public float floatProperty { get; set; } + + public VeryComplexClassWithoutDefaultConstructor(List classesWithArray, ClassWithGuid[] classesWithGuid, ClassWithConstructorPopulatingProperty anotherClass, User simpleClass, int simpleObject, List bools, double doubleProperty, float floatProperty) + { + ClassesWithArray = classesWithArray; + ClassesWithGuid = classesWithGuid; + this.anotherClass = anotherClass; + this.simpleClass = simpleClass; + this.simpleObject = simpleObject; + this.bools = bools; + this.doubleProperty = doubleProperty; + this.floatProperty = floatProperty; + } + } +} diff --git a/tests/AvroConvertTests/TestEngine.cs b/tests/AvroConvertTests/TestEngine.cs index ce7c46a0..4abae0e0 100644 --- a/tests/AvroConvertTests/TestEngine.cs +++ b/tests/AvroConvertTests/TestEngine.cs @@ -11,20 +11,20 @@ public static class TestEngine public static IEnumerable All() { yield return Default; - + yield return Headless; - + yield return GenericJson; - + yield return Brotli; - + yield return Snappy; - + yield return Deflate; - + yield return Gzip; - - yield return Json; + + // yield return Json; } public static IEnumerable Core() From 67c14fe1f92713fac727f928704434f682506263 Mon Sep 17 00:00:00 2001 From: AdrianStrugala Date: Fri, 19 Apr 2024 15:12:48 +0200 Subject: [PATCH 2/2] fix --- .../CollectionsTests.cs | 386 +++++++++--------- .../PartiallyMatchingClassesTests.cs | 310 +++++++------- 2 files changed, 348 insertions(+), 348 deletions(-) diff --git a/tests/AvroConvertTests/FullSerializationAndDeserialization/CollectionsTests.cs b/tests/AvroConvertTests/FullSerializationAndDeserialization/CollectionsTests.cs index 083f7140..9a4f2485 100644 --- a/tests/AvroConvertTests/FullSerializationAndDeserialization/CollectionsTests.cs +++ b/tests/AvroConvertTests/FullSerializationAndDeserialization/CollectionsTests.cs @@ -1,193 +1,193 @@ -// using System; -// using System.Collections.Generic; -// using System.Collections.Immutable; -// using System.Linq; -// using AutoFixture; -// using FluentAssertions; -// using SolTechnology.Avro; -// using Xunit; -// -// namespace AvroConvertComponentTests.FullSerializationAndDeserialization -// { -// public class CollectionsTests -// { -// private readonly Fixture _fixture = new(); -// -// [Theory] -// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] -// public void List_of_class(Func engine) -// { -// //Arrange -// var someTestClasses = _fixture.CreateMany().ToList(); -// -// //Act -// var deserialized = engine.Invoke(someTestClasses, typeof(List)); -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(someTestClasses, deserialized); -// } -// -// [Theory] -// [Trait("Fix", "https://github.com/AdrianStrugala/AvroConvert/issues/146")] -// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] -// public void IEnumerable_of_class(Func engine) -// { -// //Arrange -// var someTestClasses = _fixture.CreateMany(); -// -// //Act -// var deserialized = engine.Invoke(someTestClasses, typeof(IEnumerable)); -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(someTestClasses, deserialized); -// } -// -// [Theory] -// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] -// public void Class_with_list(Func engine) -// { -// //Arrange -// ClassWithSimpleList testClass = _fixture.Create(); -// -// //Act -// var deserialized = (ClassWithSimpleList)engine.Invoke(testClass, typeof(ClassWithSimpleList)); -// -// //Assert -// Assert.NotNull(deserialized); -// deserialized.Should().BeEquivalentTo(testClass); -// } -// -// [Theory] -// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] -// public void Class_with_list_of_classes(Func engine) -// { -// //Arrange -// ClassWithConstructorPopulatingProperty -// testClass = _fixture.Create(); -// -// //Act -// var deserialized = (ClassWithConstructorPopulatingProperty)engine.Invoke(testClass, typeof(ClassWithConstructorPopulatingProperty)); -// -// //Assert -// Assert.NotNull(deserialized); -// deserialized.Should().BeEquivalentTo(testClass); -// -// } -// -// [Theory] -// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] -// public void Class_with_array(Func engine) -// { -// //Arrange -// ClassWithArray -// testClass = _fixture.Create(); -// -// //Act -// var deserialized = (ClassWithArray)engine.Invoke(testClass, typeof(ClassWithArray)); -// -// //Assert -// Assert.NotNull(deserialized); -// deserialized.Should().BeEquivalentTo(testClass); -// } -// -// [Theory] -// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] -// public void List_of_int(Func engine) -// { -// //Arrange -// List toSerialize = _fixture.Create>(); -// -// //Act -// var deserialized = (List)engine.Invoke(toSerialize, typeof(List)); -// -// //Assert -// Assert.NotNull(deserialized); -// deserialized.Should().BeEquivalentTo(deserialized); -// } -// -// [Theory] -// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] -// public void Array_of_int(Func engine) -// { -// //Arrange -// int[] array = _fixture.Create(); -// -// //Act -// var deserialized = (List)engine.Invoke(array, typeof(List)); -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(array, deserialized); -// } -// -// [Theory] -// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] -// public void HashSet_of_int(Func engine) -// { -// //Arrange -// HashSet hashset = _fixture.Create>(); -// -// //Act -// var deserialized = (HashSet)engine.Invoke(hashset, typeof(HashSet)); -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(hashset, deserialized); -// } -// -// [Theory] -// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] -// public void IImmutableSet_of_class(Func engine) -// { -// //Arrange -// IImmutableSet set = _fixture.Create>().ToImmutableHashSet(); -// -// //Act -// var deserialized = (ImmutableHashSet)engine.Invoke(set, typeof(ImmutableHashSet)); -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(set, deserialized); -// } -// -// [Theory] -// [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] -// public void Class_with_empty_list(Func engine) -// { -// //Arrange -// ClassWithConstructorPopulatingProperty testClass = new ClassWithConstructorPopulatingProperty(); -// -// -// //Act -// var deserialized = (ClassWithConstructorPopulatingProperty)engine.Invoke(testClass, typeof(ClassWithConstructorPopulatingProperty)); -// -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(testClass.anotherList, deserialized.anotherList); -// Assert.Equal(testClass.nestedList, deserialized.nestedList); -// deserialized.stringProperty.Should().BeNullOrEmpty(); -// } -// -// [Fact(Skip = "MultidimensionalArray is not supported yet")] -// public void Component_MultidimensionalArray_ResultIsTheSameAsInput() -// { -// //Arrange -// MultidimensionalArrayClass array = _fixture.Create(); -// -// -// //Act -// var result = AvroConvert.Serialize(array); -// -// var deserialized = AvroConvert.Deserialize(result); -// -// -// //Assert -// Assert.NotNull(result); -// Assert.NotNull(deserialized); -// Assert.Equal(array, deserialized); -// } -// } -// } +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using AutoFixture; +using FluentAssertions; +using SolTechnology.Avro; +using Xunit; + +namespace AvroConvertComponentTests.FullSerializationAndDeserialization +{ + public class CollectionsTests + { + private readonly Fixture _fixture = new(); + + [Theory] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void List_of_class(Func engine) + { + //Arrange + var someTestClasses = _fixture.CreateMany().ToList(); + + //Act + var deserialized = engine.Invoke(someTestClasses, typeof(List)); + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(someTestClasses, deserialized); + } + + [Theory] + [Trait("Fix", "https://github.com/AdrianStrugala/AvroConvert/issues/146")] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void IEnumerable_of_class(Func engine) + { + //Arrange + var someTestClasses = _fixture.CreateMany(); + + //Act + var deserialized = engine.Invoke(someTestClasses, typeof(IEnumerable)); + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(someTestClasses, deserialized); + } + + [Theory] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void Class_with_list(Func engine) + { + //Arrange + ClassWithSimpleList testClass = _fixture.Create(); + + //Act + var deserialized = (ClassWithSimpleList)engine.Invoke(testClass, typeof(ClassWithSimpleList)); + + //Assert + Assert.NotNull(deserialized); + deserialized.Should().BeEquivalentTo(testClass); + } + + [Theory] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void Class_with_list_of_classes(Func engine) + { + //Arrange + ClassWithConstructorPopulatingProperty + testClass = _fixture.Create(); + + //Act + var deserialized = (ClassWithConstructorPopulatingProperty)engine.Invoke(testClass, typeof(ClassWithConstructorPopulatingProperty)); + + //Assert + Assert.NotNull(deserialized); + deserialized.Should().BeEquivalentTo(testClass); + + } + + [Theory] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void Class_with_array(Func engine) + { + //Arrange + ClassWithArray + testClass = _fixture.Create(); + + //Act + var deserialized = (ClassWithArray)engine.Invoke(testClass, typeof(ClassWithArray)); + + //Assert + Assert.NotNull(deserialized); + deserialized.Should().BeEquivalentTo(testClass); + } + + [Theory] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void List_of_int(Func engine) + { + //Arrange + List toSerialize = _fixture.Create>(); + + //Act + var deserialized = (List)engine.Invoke(toSerialize, typeof(List)); + + //Assert + Assert.NotNull(deserialized); + deserialized.Should().BeEquivalentTo(deserialized); + } + + [Theory] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void Array_of_int(Func engine) + { + //Arrange + int[] array = _fixture.Create(); + + //Act + var deserialized = (List)engine.Invoke(array, typeof(List)); + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(array, deserialized); + } + + [Theory] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void HashSet_of_int(Func engine) + { + //Arrange + HashSet hashset = _fixture.Create>(); + + //Act + var deserialized = (HashSet)engine.Invoke(hashset, typeof(HashSet)); + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(hashset, deserialized); + } + + [Theory] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void IImmutableSet_of_class(Func engine) + { + //Arrange + IImmutableSet set = _fixture.Create>().ToImmutableHashSet(); + + //Act + var deserialized = (ImmutableHashSet)engine.Invoke(set, typeof(ImmutableHashSet)); + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(set, deserialized); + } + + [Theory] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void Class_with_empty_list(Func engine) + { + //Arrange + ClassWithConstructorPopulatingProperty testClass = new ClassWithConstructorPopulatingProperty(); + + + //Act + var deserialized = (ClassWithConstructorPopulatingProperty)engine.Invoke(testClass, typeof(ClassWithConstructorPopulatingProperty)); + + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(testClass.anotherList, deserialized.anotherList); + Assert.Equal(testClass.nestedList, deserialized.nestedList); + deserialized.stringProperty.Should().BeNullOrEmpty(); + } + + [Fact(Skip = "MultidimensionalArray is not supported yet")] + public void Component_MultidimensionalArray_ResultIsTheSameAsInput() + { + //Arrange + MultidimensionalArrayClass array = _fixture.Create(); + + + //Act + var result = AvroConvert.Serialize(array); + + var deserialized = AvroConvert.Deserialize(result); + + + //Assert + Assert.NotNull(result); + Assert.NotNull(deserialized); + Assert.Equal(array, deserialized); + } + } +} diff --git a/tests/AvroConvertTests/FullSerializationAndDeserialization/PartiallyMatchingClassesTests.cs b/tests/AvroConvertTests/FullSerializationAndDeserialization/PartiallyMatchingClassesTests.cs index 3e7d0f96..6a60ec86 100644 --- a/tests/AvroConvertTests/FullSerializationAndDeserialization/PartiallyMatchingClassesTests.cs +++ b/tests/AvroConvertTests/FullSerializationAndDeserialization/PartiallyMatchingClassesTests.cs @@ -1,155 +1,155 @@ -// using System; -// using System.Collections.Generic; -// using System.Linq; -// using AutoFixture; -// using AutoFixture.Kernel; -// using SolTechnology.Avro; -// using Xunit; -// -// namespace AvroConvertComponentTests.FullSerializationAndDeserialization -// { -// public class PartiallyMatchingClassesTests -// { -// private readonly Fixture _fixture = new(); -// -// [Theory] -// [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] -// public void SerializeBiggerObjectAndReadSmaller(Func engine) -// { -// //Arrange -// ExtendedBaseTestClass toSerialize = _fixture.Create(); -// -// -// //Act -// var writeSchema = AvroConvert.GenerateSchema(typeof(ExtendedBaseTestClass)); -// var readSchema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); -// var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), writeSchema, readSchema); -// -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); -// Assert.Equal(toSerialize.andLongProperty, deserialized.andLongProperty); -// } -// -// -// [Theory] -// [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] -// public void SerializeSmallerClassAndReadBigger(Func engine) -// { -// //Arrange -// ReducedBaseTestClass toSerialize = _fixture.Create(); -// -// -// //Act -// var schema = AvroConvert.GenerateSchema(typeof(ReducedBaseTestClass)); -// var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), schema, schema); -// -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); -// } -// -// -// [Theory] -// [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] -// public void SerializeHeadlessBiggerObjectUsingReducedSchemaAndReadSmaller(Func engine) -// { -// //Arrange -// ExtendedBaseTestClass toSerialize = _fixture.Create(); -// string schema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); -// -// //Act -// var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), schema, schema); -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(toSerialize.andLongProperty, deserialized.andLongProperty); -// Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); -// } -// -// -// [Theory] -// [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] -// public void SerializeBiggerAvroObjectAndReadSmaller(Func engine) -// { -// //Arrange -// AttributeClass toSerialize = _fixture.Create(); -// -// -// //Act -// var schema = AvroConvert.GenerateSchema(typeof(AttributeClass)); -// var deserialized = engine.Invoke(toSerialize, typeof(SmallerAttributeClass), schema, schema); -// -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(toSerialize.NullableStringProperty, deserialized.NullableStringProperty); -// Assert.Equal(toSerialize.NullableIntProperty, deserialized.NullableIntProperty); -// } -// -// -// [Theory] -// [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] -// public void SerializeAndDeserializeClassesWithDifferentPropertyCases(Func engine) -// { -// //Arrange -// BaseTestClass toSerialize = _fixture.Create(); -// -// -// //Act -// var schema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); -// var deserialized = engine.Invoke(toSerialize, typeof(DifferentCaseBaseTestClass), schema, schema); -// -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(toSerialize.justSomeProperty, deserialized.JustSomeProperty); -// Assert.Equal(toSerialize.andLongProperty, deserialized.AndLongProperty); -// } -// -// public static IEnumerable PrimitivesAndNullables -// { -// get -// { -// foreach (var c in TestEngine.All().ToList()) -// { -// yield return new[] { typeof(short), typeof(short?), c.FirstOrDefault() }; -// yield return new[] { typeof(uint), typeof(uint?), c.FirstOrDefault() }; -// yield return new[] { typeof(ushort), typeof(ushort?), c.FirstOrDefault() }; -// yield return new[] { typeof(int), typeof(int?), c.FirstOrDefault() }; -// yield return new[] { typeof(long), typeof(long?), c.FirstOrDefault() }; -// yield return new[] { typeof(Guid), typeof(Guid?), c.FirstOrDefault() }; -// yield return new[] { typeof(ulong), typeof(ulong?), c.FirstOrDefault() }; -// yield return new[] { typeof(char), typeof(char?), c.FirstOrDefault() }; -// yield return new[] { typeof(byte), typeof(byte?), c.FirstOrDefault() }; -// yield return new[] { typeof(sbyte), typeof(sbyte?), c.FirstOrDefault() }; -// yield return new[] { typeof(bool), typeof(bool?), c.FirstOrDefault() }; -// yield return new[] { typeof(float), typeof(float?), c.FirstOrDefault() }; -// yield return new[] { typeof(double), typeof(double?), c.FirstOrDefault() }; -// yield return new[] { typeof(decimal), typeof(decimal?), c.FirstOrDefault() }; -// } -// } -// } -// -// [Theory] -// [MemberData(nameof(PrimitivesAndNullables))] -// public void Serialize_primitives_read_nullable_correspondings( -// Type serializationType, Type deserializationType, -// Func engine) -// { -// //Arrange -// var underTest = new SpecimenContext(_fixture).Resolve(serializationType); -// -// -// //Act -// var deserialized = engine.Invoke(underTest, deserializationType); -// -// -// //Assert -// Assert.NotNull(deserialized); -// Assert.Equal(underTest, deserialized); -// } -// } -// } +using System; +using System.Collections.Generic; +using System.Linq; +using AutoFixture; +using AutoFixture.Kernel; +using SolTechnology.Avro; +using Xunit; + +namespace AvroConvertComponentTests.FullSerializationAndDeserialization +{ + public class PartiallyMatchingClassesTests + { + private readonly Fixture _fixture = new(); + + [Theory] + [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] + public void SerializeBiggerObjectAndReadSmaller(Func engine) + { + //Arrange + ExtendedBaseTestClass toSerialize = _fixture.Create(); + + + //Act + var writeSchema = AvroConvert.GenerateSchema(typeof(ExtendedBaseTestClass)); + var readSchema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); + var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), writeSchema, readSchema); + + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); + Assert.Equal(toSerialize.andLongProperty, deserialized.andLongProperty); + } + + + [Theory] + [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] + public void SerializeSmallerClassAndReadBigger(Func engine) + { + //Arrange + ReducedBaseTestClass toSerialize = _fixture.Create(); + + + //Act + var schema = AvroConvert.GenerateSchema(typeof(ReducedBaseTestClass)); + var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), schema, schema); + + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); + } + + + [Theory] + [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] + public void SerializeHeadlessBiggerObjectUsingReducedSchemaAndReadSmaller(Func engine) + { + //Arrange + ExtendedBaseTestClass toSerialize = _fixture.Create(); + string schema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); + + //Act + var deserialized = engine.Invoke(toSerialize, typeof(BaseTestClass), schema, schema); + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(toSerialize.andLongProperty, deserialized.andLongProperty); + Assert.Equal(toSerialize.justSomeProperty, deserialized.justSomeProperty); + } + + + [Theory] + [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] + public void SerializeBiggerAvroObjectAndReadSmaller(Func engine) + { + //Arrange + AttributeClass toSerialize = _fixture.Create(); + + + //Act + var schema = AvroConvert.GenerateSchema(typeof(AttributeClass)); + var deserialized = engine.Invoke(toSerialize, typeof(SmallerAttributeClass), schema, schema); + + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(toSerialize.NullableStringProperty, deserialized.NullableStringProperty); + Assert.Equal(toSerialize.NullableIntProperty, deserialized.NullableIntProperty); + } + + + [Theory] + [MemberData(nameof(TestEngine.CoreUsingSchema), MemberType = typeof(TestEngine))] + public void SerializeAndDeserializeClassesWithDifferentPropertyCases(Func engine) + { + //Arrange + BaseTestClass toSerialize = _fixture.Create(); + + + //Act + var schema = AvroConvert.GenerateSchema(typeof(BaseTestClass)); + var deserialized = engine.Invoke(toSerialize, typeof(DifferentCaseBaseTestClass), schema, schema); + + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(toSerialize.justSomeProperty, deserialized.JustSomeProperty); + Assert.Equal(toSerialize.andLongProperty, deserialized.AndLongProperty); + } + + public static IEnumerable PrimitivesAndNullables + { + get + { + foreach (var c in TestEngine.All().ToList()) + { + yield return new[] { typeof(short), typeof(short?), c.FirstOrDefault() }; + yield return new[] { typeof(uint), typeof(uint?), c.FirstOrDefault() }; + yield return new[] { typeof(ushort), typeof(ushort?), c.FirstOrDefault() }; + yield return new[] { typeof(int), typeof(int?), c.FirstOrDefault() }; + yield return new[] { typeof(long), typeof(long?), c.FirstOrDefault() }; + yield return new[] { typeof(Guid), typeof(Guid?), c.FirstOrDefault() }; + yield return new[] { typeof(ulong), typeof(ulong?), c.FirstOrDefault() }; + yield return new[] { typeof(char), typeof(char?), c.FirstOrDefault() }; + yield return new[] { typeof(byte), typeof(byte?), c.FirstOrDefault() }; + yield return new[] { typeof(sbyte), typeof(sbyte?), c.FirstOrDefault() }; + yield return new[] { typeof(bool), typeof(bool?), c.FirstOrDefault() }; + yield return new[] { typeof(float), typeof(float?), c.FirstOrDefault() }; + yield return new[] { typeof(double), typeof(double?), c.FirstOrDefault() }; + yield return new[] { typeof(decimal), typeof(decimal?), c.FirstOrDefault() }; + } + } + } + + [Theory] + [MemberData(nameof(PrimitivesAndNullables))] + public void Serialize_primitives_read_nullable_correspondings( + Type serializationType, Type deserializationType, + Func engine) + { + //Arrange + var underTest = new SpecimenContext(_fixture).Resolve(serializationType); + + + //Act + var deserialized = engine.Invoke(underTest, deserializationType); + + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(underTest, deserialized); + } + } +}