blob: 807acbda92a6e56e465ef1ea2e1fc3080bc6b253 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using NUnit.Framework;
using Avro.Specific;
namespace Avro.Test.AvroGen
{
[TestFixture]
class AvroGenSchemaTests
{
private const string _customConversionWithLogicalTypes = @"
{
""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""CustomConversionWithLogicalTypes"",
""doc"" : ""Test custom conversion and logical types in generated Java classes"",
""fields"": [
{
""name"": ""customEnum"",
""type"": [""null"", {
""namespace"": ""org.apache.avro.codegentest.testdata"",
""name"": ""CustomAvroEnum"",
""type"": ""enum"",
""logicalType"": ""custom-enum"",
""symbols"": [""ONE"", ""TWO"", ""THREE""]
}]
}]
}
";
private const string _logicalTypesWithCustomConversion = @"
{
""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""LogicalTypesWithCustomConversion"",
""doc"" : ""Test unions with logical types in generated Java classes"",
""fields"": [
{""name"": ""nullableCustomField"", ""type"": [""null"", {""type"": ""bytes"", ""logicalType"": ""decimal"", ""precision"": 9, ""scale"": 2}], ""default"": null},
{ ""name"": ""nonNullCustomField"", ""type"": { ""type"": ""bytes"", ""logicalType"": ""decimal"", ""precision"": 9, ""scale"": 2} },
{ ""name"": ""nullableFixedSizeString"", ""type"": [""null"", { ""type"": ""bytes"", ""logicalType"": ""fixed-size-string"", ""minLength"": 1, ""maxLength"": 50}], ""default"": null},
{ ""name"": ""nonNullFixedSizeString"", ""type"": { ""type"": ""bytes"", ""logicalType"": ""fixed-size-string"", ""minLength"": 1, ""maxLength"": 50} }
]
}
";
private const string _logicalTypesWithDefaults = @"
{
""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""LogicalTypesWithDefaults"",
""doc"" : ""Test logical types and default values in generated Java classes"",
""fields"": [
{""name"": ""nullableDate"", ""type"": [{""type"": ""int"", ""logicalType"": ""date""}, ""null""], ""default"": 1234},
{ ""name"": ""nonNullDate"", ""type"": { ""type"": ""int"", ""logicalType"": ""date""}, ""default"": 1234}
]
}";
private const string _nestedLogicalTypesArray = @"
{""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""NestedLogicalTypesArray"",
""doc"" : ""Test nested types with logical types in generated Java classes"",
""fields"": [
{
""name"": ""arrayOfRecords"",
""type"": {
""type"": ""array"",
""items"": {
""namespace"": ""org.apache.avro.codegentest.testdata"",
""name"": ""RecordInArray"",
""type"": ""record"",
""fields"": [
{
""name"": ""nullableDateField"",
""type"": [""null"", {""type"": ""int"", ""logicalType"": ""date""}]
}
]
}
}
}]
}
";
private const string _nestedLogicalTypesMap = @"
{""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""NestedLogicalTypesMap"",
""doc"" : ""Test nested types with logical types in generated Java classes"",
""fields"": [
{
""name"": ""mapOfRecords"",
""type"": {
""type"": ""map"",
""values"": {
""namespace"": ""org.apache.avro.codegentest.testdata"",
""name"": ""RecordInMap"",
""type"": ""record"",
""fields"": [
{
""name"": ""nullableDateField"",
""type"": [""null"", {""type"": ""int"", ""logicalType"": ""date""}]
}
]
}
}
}]
}";
private const string _nestedLogicalTypesRecord = @"
{""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""NestedLogicalTypesRecord"",
""doc"" : ""Test nested types with logical types in generated Java classes"",
""fields"": [
{
""name"": ""nestedRecord"",
""type"": {
""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""NestedRecord"",
""fields"": [
{
""name"": ""nullableDateField"",
""type"": [""null"", {""type"": ""int"", ""logicalType"": ""date""}]
}
]
}
}]
}";
private const string _nestedLogicalTypesUnionFixedDecimal = @"
{""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""NestedLogicalTypesUnionFixedDecimal"",
""doc"" : ""Test nested types with logical types in generated Java classes"",
""fields"": [
{
""name"": ""unionOfFixedDecimal"",
""type"": [""null"", {
""namespace"": ""org.apache.avro.codegentest.testdata"",
""name"": ""FixedInUnion"",
""type"": {
""type"": ""fixed"",
""size"": 12,
""name"": ""FixedName"",
},
""logicalType"": ""decimal"",
""precision"": 28,
""scale"": 15
}]
}]
}";
private const string _nestedLogicalTypesUnion = @"
{""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""NestedLogicalTypesUnion"",
""doc"" : ""Test nested types with logical types in generated Java classes"",
""fields"": [
{
""name"": ""unionOfRecords"",
""type"": [""null"", {
""namespace"": ""org.apache.avro.codegentest.testdata"",
""name"": ""RecordInUnion"",
""type"": ""record"",
""fields"": [
{
""name"": ""nullableDateField"",
""type"": [""null"", {""type"": ""int"", ""logicalType"": ""date""}]
}
]
}]
}]
}";
private const string _nestedSomeNamespaceRecord = @"
{""namespace"": ""org.apache.avro.codegentest.some"",
""type"": ""record"",
""name"": ""NestedSomeNamespaceRecord"",
""doc"" : ""Test nested types with different namespace than the outer type"",
""fields"": [
{
""name"": ""nestedRecord"",
""type"": {
""namespace"": ""org.apache.avro.codegentest.other"",
""type"": ""record"",
""name"": ""NestedOtherNamespaceRecord"",
""fields"": [
{
""name"": ""someField"",
""type"": ""int""
}
]
}
}]
}";
private const string _nullableLogicalTypesArray = @"
{""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""NullableLogicalTypesArray"",
""doc"" : ""Test nested types with logical types in generated Java classes"",
""fields"": [
{
""name"": ""arrayOfLogicalType"",
""type"": {
""type"": ""array"",
""items"": [""null"", {""type"": ""int"", ""logicalType"": ""date""}]
}
}]
}";
private const string _nullableLogicalTypes = @"
{""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""NullableLogicalTypes"",
""doc"" : ""Test unions with logical types in generated Java classes"",
""fields"": [
{""name"": ""nullableDate"", ""type"": [""null"", {""type"": ""int"", ""logicalType"": ""date""}], ""default"": null}
]
}";
private const string _stringLogicalType = @"
{
""namespace"": ""org.apache.avro.codegentest.testdata"",
""type"": ""record"",
""name"": ""StringLogicalType"",
""doc"": ""Test logical type applied to field of type string"",
""fields"": [
{
""name"": ""someIdentifier"",
""type"": {
""type"": ""string"",
""logicalType"": ""uuid""
}
},
{
""name"": ""someJavaString"",
""type"": ""string"",
""doc"": ""Just to ensure no one removed <stringType>String</stringType> because this is the basis of this test""
}
]
}";
// https://issues.apache.org/jira/browse/AVRO-2883
private const string _schema_avro_2883 = @"
{
""type"" : ""record"",
""name"" : ""TestModel"",
""namespace"" : ""my.avro.ns"",
""fields"" : [ {
""name"" : ""eventType"",
""type"" : {
""type"" : ""enum"",
""name"" : ""EventType"",
""symbols"" : [ ""CREATE"", ""UPDATE"", ""DELETE"" ]
}
} ]
}";
// https://issues.apache.org/jira/browse/AVRO-3046
private const string _schema_avro_3046 = @"
{
""type"": ""record"",
""name"": ""ExampleRecord"",
""namespace"": ""com.example"",
""fields"": [
{
""name"": ""Id"",
""type"": ""string"",
""logicalType"": ""UUID""
},
{
""name"": ""InnerRecord"",
""type"": {
""type"": ""record"",
""name"": ""InnerRecord"",
""fields"": [
{
""name"": ""Id"",
""type"": ""string"",
""logicalType"": ""UUID""
}
]
}
}
]
}";
private Assembly TestSchema(
string schema,
IEnumerable<string> typeNamesToCheck = null,
IEnumerable<KeyValuePair<string, string>> namespaceMapping = null,
IEnumerable<string> generatedFilesToCheck = null)
{
// Create temp folder
string outputDir = AvroGenHelper.CreateEmptyTemporaryFolder(out string uniqueId);
try
{
// Save schema
string schemaFileName = Path.Combine(outputDir, $"{uniqueId}.avsc");
System.IO.File.WriteAllText(schemaFileName, schema);
// Generate from schema file
Assert.That(AvroGenTool.GenSchema(schemaFileName, outputDir, namespaceMapping ?? new Dictionary<string, string>(), false), Is.EqualTo(0));
// Check if all generated files exist
if (generatedFilesToCheck != null)
{
foreach (string generatedFile in generatedFilesToCheck)
{
Assert.That(new FileInfo(Path.Combine(outputDir, generatedFile)), Does.Exist);
}
}
// Compile into netstandard library and load assembly
Assembly assembly = AvroGenHelper.CompileCSharpFilesIntoLibrary(
new DirectoryInfo(outputDir)
.EnumerateFiles("*.cs", SearchOption.AllDirectories)
.Select(fi => fi.FullName),
uniqueId);
if (typeNamesToCheck != null)
{
// Check if the compiled code has the same number of types defined as the check list
Assert.That(typeNamesToCheck.Count(), Is.EqualTo(assembly.DefinedTypes.Count()));
// Check if types available in compiled assembly
foreach (string typeName in typeNamesToCheck)
{
Type type = assembly.GetType(typeName);
Assert.That(type, Is.Not.Null);
// Instantiate
object obj = Activator.CreateInstance(type);
Assert.That(obj, Is.Not.Null);
}
}
// Verify GeneratedCodeAttribute
foreach(System.Reflection.TypeInfo definedType in assembly.DefinedTypes)
{
var generatedAttributes = definedType.CustomAttributes.Where(x => x.AttributeType.FullName == "System.CodeDom.Compiler.GeneratedCodeAttribute");
Assert.That(generatedAttributes, Is.Not.Null);
}
return assembly;
}
finally
{
Directory.Delete(outputDir, true);
}
}
[TestCase(
_logicalTypesWithDefaults,
new string[]
{
"org.apache.avro.codegentest.testdata.LogicalTypesWithDefaults"
},
new string[]
{
"org/apache/avro/codegentest/testdata/LogicalTypesWithDefaults.cs"
})]
[TestCase(
_nestedLogicalTypesArray,
new string[]
{
"org.apache.avro.codegentest.testdata.NestedLogicalTypesArray",
"org.apache.avro.codegentest.testdata.RecordInArray"
},
new string[]
{
"org/apache/avro/codegentest/testdata/NestedLogicalTypesArray.cs",
"org/apache/avro/codegentest/testdata/RecordInArray.cs"
})]
[TestCase(
_nestedLogicalTypesMap,
new string[]
{
"org.apache.avro.codegentest.testdata.NestedLogicalTypesMap",
"org.apache.avro.codegentest.testdata.RecordInMap"
},
new string[]
{
"org/apache/avro/codegentest/testdata/NestedLogicalTypesMap.cs",
"org/apache/avro/codegentest/testdata/RecordInMap.cs"
})]
[TestCase(
_nestedLogicalTypesRecord,
new string[]
{
"org.apache.avro.codegentest.testdata.NestedLogicalTypesRecord",
"org.apache.avro.codegentest.testdata.NestedRecord"
},
new string[]
{
"org/apache/avro/codegentest/testdata/NestedLogicalTypesRecord.cs",
"org/apache/avro/codegentest/testdata/NestedRecord.cs"
})]
[TestCase(
_nestedLogicalTypesUnion,
new string[]
{
"org.apache.avro.codegentest.testdata.NestedLogicalTypesUnion",
"org.apache.avro.codegentest.testdata.RecordInUnion"
},
new string[]
{
"org/apache/avro/codegentest/testdata/NestedLogicalTypesUnion.cs",
"org/apache/avro/codegentest/testdata/RecordInUnion.cs"
})]
[TestCase(
_nestedSomeNamespaceRecord,
new string[]
{
"org.apache.avro.codegentest.some.NestedSomeNamespaceRecord",
"org.apache.avro.codegentest.other.NestedOtherNamespaceRecord"
},
new string[]
{
"org/apache/avro/codegentest/some/NestedSomeNamespaceRecord.cs",
"org/apache/avro/codegentest/other/NestedOtherNamespaceRecord.cs"
})]
[TestCase(
_nestedLogicalTypesUnionFixedDecimal,
new string[]
{
"org.apache.avro.codegentest.testdata.NestedLogicalTypesUnionFixedDecimal"
},
new string[]
{
"org/apache/avro/codegentest/testdata/NestedLogicalTypesUnionFixedDecimal.cs"
})]
[TestCase(
_nullableLogicalTypes,
new string[]
{
"org.apache.avro.codegentest.testdata.NullableLogicalTypes"
},
new string[]
{
"org/apache/avro/codegentest/testdata/NullableLogicalTypes.cs"
})]
[TestCase(
_nullableLogicalTypesArray,
new string[]
{
"org.apache.avro.codegentest.testdata.NullableLogicalTypesArray"
},
new string[]
{
"org/apache/avro/codegentest/testdata/NullableLogicalTypesArray.cs"
})]
[TestCase(
_schema_avro_2883,
new string[]
{
"my.avro.ns.TestModel",
"my.avro.ns.EventType",
},
new string[]
{
"my/avro/ns/TestModel.cs",
"my/avro/ns/EventType.cs"
})]
public void GenerateSchema(string schema, IEnumerable<string> typeNamesToCheck, IEnumerable<string> generatedFilesToCheck)
{
AvroGenHelper.TestSchema(schema, typeNamesToCheck, generatedFilesToCheck: generatedFilesToCheck);
}
[TestCase(
_nullableLogicalTypesArray,
"org.apache.avro.codegentest.testdata", "org.apache.csharp.codegentest.testdata",
new string[]
{
"org.apache.csharp.codegentest.testdata.NullableLogicalTypesArray"
},
new string[]
{
"org/apache/csharp/codegentest/testdata/NullableLogicalTypesArray.cs"
})]
[TestCase(
_nestedLogicalTypesUnion,
"org.apache.avro.codegentest.testdata", "org.apache.csharp.codegentest.testdata",
new string[]
{
"org.apache.csharp.codegentest.testdata.NestedLogicalTypesUnion",
"org.apache.csharp.codegentest.testdata.RecordInUnion"
},
new string[]
{
"org/apache/csharp/codegentest/testdata/NestedLogicalTypesUnion.cs",
"org/apache/csharp/codegentest/testdata/RecordInUnion.cs"
})]
[TestCase(
_schema_avro_2883,
"my.avro.ns", "my.csharp.ns",
new string[]
{
"my.csharp.ns.TestModel",
"my.csharp.ns.EventType",
},
new string[]
{
"my/csharp/ns/TestModel.cs",
"my/csharp/ns/EventType.cs"
})]
[TestCase(
_schema_avro_3046,
"com.example", "Example",
new string[]
{
"Example.ExampleRecord",
"Example.InnerRecord",
},
new string[]
{
"Example/ExampleRecord.cs",
"Example/InnerRecord.cs"
})]
[TestCase(
_nullableLogicalTypesArray,
"org.apache.avro.codegentest.testdata", "org.apache.@return.@int", // Reserved keywords in namespace
new string[]
{
"org.apache.return.int.NullableLogicalTypesArray"
},
new string[]
{
"org/apache/return/int/NullableLogicalTypesArray.cs"
})]
[TestCase(
_nullableLogicalTypesArray,
"org.apache.avro.codegentest.testdata", "org.apache.value.partial", // Contextual keywords in namespace
new string[]
{
"org.apache.value.partial.NullableLogicalTypesArray"
},
new string[]
{
"org/apache/value/partial/NullableLogicalTypesArray.cs"
})]
[TestCase(@"
{
""type"": ""fixed"",
""namespace"": ""com.base"",
""name"": ""MD5"",
""size"": 16
}",
"com.base", "SchemaTest",
new string[]
{
"SchemaTest.MD5"
},
new string[]
{
"SchemaTest/MD5.cs"
})]
[TestCase(@"
{
""type"": ""fixed"",
""namespace"": ""com.base"",
""name"": ""MD5"",
""size"": 16
}",
"miss", "SchemaTest",
new string[]
{
"com.base.MD5"
},
new string[]
{
"com/base/MD5.cs"
})]
public void GenerateSchemaWithNamespaceMapping(
string schema,
string namespaceMappingFrom,
string namespaceMappingTo,
IEnumerable<string> typeNamesToCheck,
IEnumerable<string> generatedFilesToCheck)
{
AvroGenHelper.TestSchema(schema, typeNamesToCheck, new Dictionary<string, string> { { namespaceMappingFrom, namespaceMappingTo } }, generatedFilesToCheck);
}
[TestCase(_logicalTypesWithCustomConversion, typeof(AvroTypeException))]
[TestCase(_customConversionWithLogicalTypes, typeof(SchemaParseException))]
public void NotSupportedSchema(string schema, Type expectedException)
{
// Create temp folder
string outputDir = AvroGenHelper.CreateEmptyTemporaryFolder(out string uniqueId);
try
{
// Save schema
string schemaFileName = Path.Combine(outputDir, $"{uniqueId}.avsc");
System.IO.File.WriteAllText(schemaFileName, schema);
Assert.That(AvroGenTool.GenSchema(schemaFileName, outputDir, new Dictionary<string, string>(), false), Is.EqualTo(1));
}
finally
{
Directory.Delete(outputDir, true);
}
}
[TestCase(@"
{
""type"" : ""record"",
""name"" : ""ClassKeywords"",
""namespace"" : ""com.base"",
""fields"" :
[
{ ""name"" : ""int"", ""type"" : ""int"" },
{ ""name"" : ""base"", ""type"" : ""long"" },
{ ""name"" : ""event"", ""type"" : ""boolean"" },
{ ""name"" : ""foreach"", ""type"" : ""double"" },
{ ""name"" : ""bool"", ""type"" : ""float"" },
{ ""name"" : ""internal"", ""type"" : ""bytes"" },
{ ""name"" : ""while"", ""type"" : ""string"" },
{ ""name"" : ""return"", ""type"" : ""null"" },
{ ""name"" : ""enum"", ""type"" : { ""type"" : ""enum"", ""name"" : ""class"", ""symbols"" : [ ""Unknown"", ""A"", ""B"" ], ""default"" : ""Unknown"" } },
{ ""name"" : ""string"", ""type"" : { ""type"": ""fixed"", ""size"": 16, ""name"": ""static"" } }
]
}",
new object[] { "com.base.ClassKeywords", typeof(int), typeof(long), typeof(bool), typeof(double), typeof(float), typeof(byte[]), typeof(string), typeof(object), "com.base.class", "com.base.static" })]
[TestCase(@"
{
""type"" : ""record"",
""name"" : ""AvroNamespaceType"",
""namespace"" : ""My.Avro"",
""fields"" :
[
{ ""name"" : ""justenum"", ""type"" : { ""type"" : ""enum"", ""name"" : ""justenumEnum"", ""symbols"" : [ ""One"", ""Two"" ] } },
]
}",
new object[] { "My.Avro.AvroNamespaceType", "My.Avro.justenumEnum" })]
[TestCase(@"
{
""type"" : ""record"",
""name"" : ""SchemaObject"",
""namespace"" : ""schematest"",
""fields"" :
[
{ ""name"" : ""myobject"", ""type"" :
[
""null"",
{ ""type"" : ""array"", ""items"" :
[
""null"",
{ ""type"" : ""enum"", ""name"" : ""MyEnum"", ""symbols"" : [ ""A"", ""B"" ] },
{ ""type"": ""fixed"", ""size"": 16, ""name"": ""MyFixed"" }
]
}
]
}
]
}",
new object[] { "schematest.SchemaObject", typeof(IList<object>) })]
[TestCase(@"
{
""type"" : ""record"",
""name"" : ""LogicalTypes"",
""namespace"" : ""schematest"",
""fields"" :
[
{ ""name"" : ""nullibleguid"", ""type"" : [""null"", {""type"": ""string"", ""logicalType"": ""uuid"" } ]},
{ ""name"" : ""guid"", ""type"" : {""type"": ""string"", ""logicalType"": ""uuid"" } },
{ ""name"" : ""nullibletimestampmillis"", ""type"" : [""null"", {""type"": ""long"", ""logicalType"": ""timestamp-millis""}] },
{ ""name"" : ""timestampmillis"", ""type"" : {""type"": ""long"", ""logicalType"": ""timestamp-millis""} },
{ ""name"" : ""nullibiletimestampmicros"", ""type"" : [""null"", {""type"": ""long"", ""logicalType"": ""timestamp-micros""}] },
{ ""name"" : ""timestampmicros"", ""type"" : {""type"": ""long"", ""logicalType"": ""timestamp-micros""} },
{ ""name"" : ""nulliblelocaltimestampmillis"", ""type"" : [""null"", {""type"": ""long"", ""logicalType"": ""local-timestamp-millis""}] },
{ ""name"" : ""localtimestampmillis"", ""type"" : {""type"": ""long"", ""logicalType"": ""local-timestamp-millis""} },
{ ""name"" : ""nullibilelocaltimestampmicros"", ""type"" : [""null"", {""type"": ""long"", ""logicalType"": ""local-timestamp-micros""}] },
{ ""name"" : ""locallocaltimestampmicros"", ""type"" : {""type"": ""long"", ""logicalType"": ""local-timestamp-micros""} },
{ ""name"" : ""nullibiletimemicros"", ""type"" : [""null"", {""type"": ""long"", ""logicalType"": ""time-micros""}] },
{ ""name"" : ""timemicros"", ""type"" : {""type"": ""long"", ""logicalType"": ""time-micros""} },
{ ""name"" : ""nullibiletimemillis"", ""type"" : [""null"", {""type"": ""int"", ""logicalType"": ""time-millis""}] },
{ ""name"" : ""timemillis"", ""type"" : {""type"": ""int"", ""logicalType"": ""time-millis""} },
{ ""name"" : ""nullibledecimal"", ""type"" : [""null"", {""type"": ""bytes"", ""logicalType"": ""decimal"", ""precision"": 4, ""scale"": 2}] },
{ ""name"" : ""decimal"", ""type"" : {""type"": ""bytes"", ""logicalType"": ""decimal"", ""precision"": 4, ""scale"": 2} },
{ ""name"" : ""nullibledecimalfixed"", ""type"" : [""null"", {""type"": {""type"" : ""fixed"", ""size"": 16, ""name"": ""ndf""}, ""logicalType"": ""decimal"", ""precision"": 4, ""scale"": 2}] },
{ ""name"" : ""decimalfixed"", ""type"" : {""type"": {""type"" : ""fixed"", ""size"": 16, ""name"": ""df""}, ""logicalType"": ""decimal"", ""precision"": 4, ""scale"": 2} }
]
}",
new object[] { "schematest.LogicalTypes", typeof(Guid?), typeof(Guid), typeof(DateTime?), typeof(DateTime), typeof(DateTime?), typeof(DateTime), typeof(DateTime?), typeof(DateTime), typeof(DateTime?), typeof(DateTime), typeof(TimeSpan?), typeof(TimeSpan), typeof(TimeSpan?), typeof(TimeSpan), typeof(AvroDecimal?), typeof(AvroDecimal), typeof(AvroDecimal?), typeof(AvroDecimal) })]
[TestCase(@"
{
""namespace"": ""enum.base"",
""type"": ""record"",
""name"": ""EnumInDifferentNamespace"",
""doc"": ""Test enum with a default value in a different namespace"",
""fields"": [
{
""name"": ""anEnum"",
""type"": {
""namespace"": ""enum.base.other"",
""type"": ""enum"",
""name"": ""AnEnum"",
""symbols"": [
""A"",
""B""
],
""default"": ""A""
}
}
]
}",
new object[] { "enum.base.EnumInDifferentNamespace", "enum.base.other.AnEnum" })]
public void GenerateSchemaCheckFields(string schema, object[] result)
{
Assembly assembly = AvroGenHelper.TestSchema(schema);
// Instantiate object
Type type = assembly.GetType((string)result[0]);
Assert.That(type, Is.Not.Null);
ISpecificRecord record = Activator.CreateInstance(type) as ISpecificRecord;
Assert.IsNotNull(record);
// test type of each fields
for (int i = 1; i < result.Length; ++i)
{
object field = record.Get(i - 1);
Type stype;
if (result[i].GetType() == typeof(string))
{
Type t = assembly.GetType((string)result[i]);
Assert.That(record, Is.Not.Null);
object obj = Activator.CreateInstance(t);
Assert.That(obj, Is.Not.Null);
stype = obj.GetType();
}
else
{
stype = (Type)result[i];
}
if (!stype.IsValueType)
{
Assert.That(field, Is.Null); // can't test reference type, it will be null
}
else if (stype.IsValueType && field == null)
{
Assert.That(field, Is.Null); // nullable value type, so we can't get the type using GetType
}
else
{
Assert.That(field, Is.Not.Null);
Assert.That(field.GetType(), Is.EqualTo(stype));
}
}
}
[TestCase(
_nullableLogicalTypesArray,
new string[]
{
"org.apache.avro.codegentest.testdata.NullableLogicalTypesArray"
},
new string[]
{
"NullableLogicalTypesArray.cs"
})]
[TestCase(
_nestedSomeNamespaceRecord,
new string[]
{
"org.apache.avro.codegentest.some.NestedSomeNamespaceRecord",
"org.apache.avro.codegentest.other.NestedOtherNamespaceRecord"
},
new string[]
{
"NestedSomeNamespaceRecord.cs",
"NestedOtherNamespaceRecord.cs"
})]
[TestCase(_schema_avro_2883,
new string[]
{
"my.avro.ns.TestModel",
"my.avro.ns.EventType",
},
new string[]
{
"TestModel.cs",
"EventType.cs"
})]
public void GenerateSchemaWithSkipDirectoriesOption(string schema, IEnumerable<string> typeNamesToCheck, IEnumerable<string> generatedFilesToCheck)
{
AvroGenHelper.TestSchema(schema, typeNamesToCheck, generatedFilesToCheck: generatedFilesToCheck, skipDirectories: true);
}
}
}