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

RyanSkraba pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/main by this push:
     new c5f66c7cb5 AVRO-2825: [csharp] Resolve: C# Logical Types throw 
exception on unknown (#3727)
c5f66c7cb5 is described below

commit c5f66c7cb5f522f7c6fa7ce68e640e3833525d8a
Author: RawScape <[email protected]>
AuthorDate: Sun May 10 14:23:20 2026 +0200

    AVRO-2825: [csharp] Resolve: C# Logical Types throw exception on unknown 
(#3727)
    
    * AVRO-2825: [csharp] Resolve: C# Logical Types throw exception on unknown 
logical type
    
    (cherry picked from commit ad61af02da435652ba0662d34205f60fa88537cb)
    
    * [AVRO-3941] CSharp Resolve missing namespace issue
    
    (cherry picked from commit e5a7dedf9959687637f621bfdecbe478a5a89cc4)
    
    * Resolve requested changes on PR 2751
    
    (cherry picked from commit 89095295036d0dbd180fa4265205f0d666b3c0d9)
    
    * uncomment testcase after testing
    
    (cherry picked from commit 235d329118764005c2ace77bc7b26e472bcd5e14)
    
    * savepoint remove local setting files
    
    (cherry picked from commit f7b4872a347938d090193a55beba3ff2a31bcefa)
    
    * backout chags for a different pr, adjust unit test
    
    (cherry picked from commit 60463b5da7c885ce4e90ff9cf2d81c7682d59b0b)
    
    * changes from code review
    
    (cherry picked from commit 42b0fbd0a665cf409b85e329151f5b5d3e2a07e8)
    
    * Resolve remaining feedback for AVRO-2825 and fix complex logical type 
parsing
    
    * Fix CodeQL warning: Use pattern matching to assert logicalSchema type 
safely
    
    * Remove accidentally tracked launchSettings.json
    
    ---------
    
    Co-authored-by: Tom Bruns <[email protected]>
---
 .../csharp/src/apache/main/Schema/LogicalSchema.cs |  18 +-
 .../src/apache/main/Util/LogicalTypeFactory.cs     |  20 +--
 .../src/apache/main/Util/UnknownLogicalType.cs     | 145 ++++++++++++++++
 .../src/apache/test/AvroGen/AvroGenSchemaTests.cs  |  10 +-
 lang/csharp/src/apache/test/File/FileTests.cs      |  33 ++++
 lang/csharp/src/apache/test/Schema/SchemaTests.cs  |  73 +++++++-
 .../apache/test/Util/UnknownLogicalTypeTests.cs    | 188 +++++++++++++++++++++
 7 files changed, 469 insertions(+), 18 deletions(-)

diff --git a/lang/csharp/src/apache/main/Schema/LogicalSchema.cs 
b/lang/csharp/src/apache/main/Schema/LogicalSchema.cs
index 181260f2ca..49d04875d5 100644
--- a/lang/csharp/src/apache/main/Schema/LogicalSchema.cs
+++ b/lang/csharp/src/apache/main/Schema/LogicalSchema.cs
@@ -47,14 +47,27 @@ namespace Avro
             JToken jtype = jtok["type"];
             if (null == jtype) throw new AvroTypeException("Logical Type does 
not have 'type'");
 
-            return new LogicalSchema(Schema.ParseJson(jtype, names, encspace), 
JsonHelper.GetRequiredString(jtok, "logicalType"),  props);
+            JToken baseSchemaToken = jtype;
+
+            if (jtok is JObject jo && jtype.Type == JTokenType.String)
+            {
+                string typeStr = (string)jtype;
+                if (typeStr == "record" || typeStr == "enum" || typeStr == 
"array" || typeStr == "map" || typeStr == "fixed")
+                {
+                    var clone = (JObject)jo.DeepClone();
+                    clone.Property("logicalType")?.Remove();
+                    baseSchemaToken = clone;
+                }
+            }
+
+            return new LogicalSchema(Schema.ParseJson(baseSchemaToken, names, 
encspace), JsonHelper.GetRequiredString(jtok, "logicalType"), props);
         }
 
         private LogicalSchema(Schema baseSchema, string logicalTypeName,  
PropertyMap props) : base(Type.Logical, props)
         {
             BaseSchema = baseSchema ?? throw new 
ArgumentNullException(nameof(baseSchema));
             LogicalTypeName = logicalTypeName;
-            LogicalType = 
LogicalTypeFactory.Instance.GetFromLogicalSchema(this);
+            LogicalType = 
LogicalTypeFactory.Instance.GetFromLogicalSchema(this, true);
         }
 
         /// <summary>
@@ -97,6 +110,7 @@ namespace Avro
             if (writerSchema.Tag != Tag) return false;
 
             LogicalSchema that = writerSchema as LogicalSchema;
+
             return BaseSchema.CanRead(that.BaseSchema);
         }
 
diff --git a/lang/csharp/src/apache/main/Util/LogicalTypeFactory.cs 
b/lang/csharp/src/apache/main/Util/LogicalTypeFactory.cs
index f4086ab5a2..e92d48ff7a 100644
--- a/lang/csharp/src/apache/main/Util/LogicalTypeFactory.cs
+++ b/lang/csharp/src/apache/main/Util/LogicalTypeFactory.cs
@@ -67,22 +67,22 @@ namespace Avro.Util
         /// <returns>A <see cref="LogicalType" />.</returns>
         public LogicalType GetFromLogicalSchema(LogicalSchema schema, bool 
ignoreInvalidOrUnknown = false)
         {
-            try
-            {
-                if (!_logicalTypes.TryGetValue(schema.LogicalTypeName, out 
LogicalType logicalType))
-                    throw new AvroTypeException("Logical type '" + 
schema.LogicalTypeName + "' is not supported.");
+            LogicalType logicalType = null;
 
+            if (_logicalTypes.TryGetValue(schema.LogicalTypeName, out 
logicalType))
+            {
                 logicalType.ValidateSchema(schema);
-
-                return logicalType;
             }
-            catch (AvroTypeException)
+            else if (ignoreInvalidOrUnknown)
+            {
+                logicalType = new UnknownLogicalType(schema);
+            }
+            else
             {
-                if (!ignoreInvalidOrUnknown)
-                    throw;
+                throw new AvroTypeException("Logical type '" + 
schema.LogicalTypeName + "' is not supported.");
             }
 
-            return null;
+            return logicalType;
         }
     }
 }
diff --git a/lang/csharp/src/apache/main/Util/UnknownLogicalType.cs 
b/lang/csharp/src/apache/main/Util/UnknownLogicalType.cs
new file mode 100644
index 0000000000..5cc03fe289
--- /dev/null
+++ b/lang/csharp/src/apache/main/Util/UnknownLogicalType.cs
@@ -0,0 +1,145 @@
+/*
+ * 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.Collections.Generic;
+using System.Text;
+
+namespace Avro.Util
+{
+    /// <summary>
+    /// Class UnknownLogicalType.
+    /// Implements the <see cref="Avro.Util.LogicalType" />
+    /// </summary>
+    /// <seealso cref="Avro.Util.LogicalType" />
+    public class UnknownLogicalType : LogicalType
+    {
+        /// <summary>
+        /// Gets the schema.
+        /// </summary>
+        /// <value>The schema.</value>
+        public LogicalSchema Schema { get; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="UnknownLogicalType"/> 
class.
+        /// </summary>
+        /// <param name="schema">The schema.</param>
+        public UnknownLogicalType(LogicalSchema schema) : 
base(schema.LogicalTypeName)
+        {
+            this.Schema = schema;
+        }
+
+        /// <summary>
+        /// Converts a logical value to an instance of its base type.
+        /// </summary>
+        /// <param name="logicalValue">The logical value to convert.</param>
+        /// <param name="schema">The schema that represents the target of the 
conversion.</param>
+        /// <returns>An object representing the encoded value of the base 
type.</returns>
+        public override object ConvertToBaseValue(object logicalValue, 
LogicalSchema schema)
+        {
+            return logicalValue;
+        }
+
+        /// <summary>
+        /// Converts a base value to an instance of the logical type.
+        /// </summary>
+        /// <param name="baseValue">The base value to convert.</param>
+        /// <param name="schema">The schema that represents the target of the 
conversion.</param>
+        /// <returns>An object representing the encoded value of the logical 
type.</returns>
+        public override object ConvertToLogicalValue(object baseValue, 
LogicalSchema schema)
+        {
+            switch (schema.Name)
+            {
+                case @"string":
+                    return (System.String)baseValue;
+                case @"boolean":
+                    return (System.Boolean)baseValue;
+                case @"int":
+                    return (System.Int32)baseValue;
+                case @"long":
+                    return (System.Int64)baseValue;
+                case @"float":
+                    return (System.Single)baseValue;
+                case @"double":
+                    return (System.Double)baseValue;
+                case @"bytes":
+                    return (System.Byte[])baseValue;
+                default:
+                    return baseValue;
+            }
+        }
+
+        /// <summary>
+        /// Retrieve the .NET type that is represented by the logical type 
implementation.
+        /// </summary>
+        /// <param name="nullible">A flag indicating whether it should be 
nullible.</param>
+        /// <returns>Type.</returns>
+        public override Type GetCSharpType(bool nullible)
+        {
+            // handle all Primitive Types
+            switch (this.Schema.BaseSchema.Name)
+            {
+                case @"string":
+                    return typeof(System.String);
+                case @"boolean":
+                    return nullible ? typeof(System.Boolean?) : 
typeof(System.Boolean);
+                case @"int":
+                    return nullible ? typeof(System.Int32?) : 
typeof(System.Int32);
+                case @"long":
+                    return nullible ? typeof(System.Int64?) : 
typeof(System.Int64);
+                case @"float":
+                    return nullible ? typeof(System.Single?) : 
typeof(System.Single);
+                case @"double":
+                    return nullible ? typeof(System.Double?) : 
typeof(System.Double);
+                case @"bytes":
+                    return typeof(System.Byte[]);
+                default:
+                    return typeof(System.Object);
+            }
+        }
+
+        /// <summary>
+        /// Determines if a given object is an instance of the logical type.
+        /// </summary>
+        /// <param name="logicalValue">The logical value to test.</param>
+        /// <returns><c>true</c> if [is instance of logical type] [the 
specified logical value]; otherwise, <c>false</c>.</returns>
+        public override bool IsInstanceOfLogicalType(object logicalValue)
+        {
+            // handle all Primitive Types
+            switch (this.Schema.BaseSchema.Name)
+            {
+                case @"string":
+                    return logicalValue is System.String;
+                case @"boolean":
+                    return logicalValue is System.Boolean;
+                case @"int":
+                    return logicalValue is System.Int32;
+                case @"long":
+                    return logicalValue is System.Int64;
+                case @"float":
+                    return logicalValue is System.Single;
+                case @"double":
+                    return logicalValue is System.Double;
+                case @"bytes":
+                    return logicalValue is System.Byte[];
+                default:
+                    return true;
+            }
+        }
+
+    }
+}
diff --git a/lang/csharp/src/apache/test/AvroGen/AvroGenSchemaTests.cs 
b/lang/csharp/src/apache/test/AvroGen/AvroGenSchemaTests.cs
index 807acbda92..2763318c87 100644
--- a/lang/csharp/src/apache/test/AvroGen/AvroGenSchemaTests.cs
+++ b/lang/csharp/src/apache/test/AvroGen/AvroGenSchemaTests.cs
@@ -606,9 +606,9 @@ namespace Avro.Test.AvroGen
             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)
+        [TestCase(_logicalTypesWithCustomConversion)]
+        [TestCase(_customConversionWithLogicalTypes)]
+        public void UnknownLogicalTypesFallbackToBaseType(string schema)
         {
             // Create temp folder
             string outputDir = AvroGenHelper.CreateEmptyTemporaryFolder(out 
string uniqueId);
@@ -619,7 +619,9 @@ namespace Avro.Test.AvroGen
                 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));
+                // Assert that the generator successfully runs (exit code 0)
+                // by ignoring the unknown logical types and using the 
underlying base types
+                Assert.That(AvroGenTool.GenSchema(schemaFileName, outputDir, 
new Dictionary<string, string>(), false), Is.EqualTo(0));
             }
             finally
             {
diff --git a/lang/csharp/src/apache/test/File/FileTests.cs 
b/lang/csharp/src/apache/test/File/FileTests.cs
index 0ef81c9766..abb3f9c607 100644
--- a/lang/csharp/src/apache/test/File/FileTests.cs
+++ b/lang/csharp/src/apache/test/File/FileTests.cs
@@ -35,6 +35,34 @@ namespace Avro.Test.File
         const string specificSchema  = 
"{\"type\":\"record\",\"name\":\"Foo\",\"namespace\":\"Avro.Test.File\",\"fields\":"
                                      + 
"[{\"name\":\"name\",\"type\":[\"null\",\"string\"]},{\"name\":\"age\",\"type\":\"int\"}]}";
 
+        /// <summary>
+        /// This test case added to confirm standalone serialization / 
deserialization behavior of new type UnknownLogicalType
+        /// </summary>
+        const string unknowLogicalTypeSchema = @"
+{
+       ""type"" : ""record"",
+       ""name"" : ""Foo"",
+       ""namespace"" : ""Avro.Test.File"",
+       ""fields"": [
+               {
+                       ""name"" :""name"",
+                       ""type"":  [
+                ""null"",
+                {
+                  ""logicalType"": ""varchar"",
+                  ""maxLength"": 65,
+                  ""type"": ""string""
+                }
+              ]
+               }, 
+               {
+                       ""name"" : ""age"",
+                       ""type"" : ""int""
+               }
+       ]
+}
+";
+
         private static IEnumerable<TestCaseData> TestSpecificDataSource()
         {
             foreach (Codec.Type codecType in 
Enum.GetValues(typeof(Codec.Type)))
@@ -100,6 +128,11 @@ namespace Avro.Test.File
                         new object[] { "Bob", 9 },
                         new object[] { null, 48 }
                     }, codecType).SetName("{m}(Case3,{2})");
+
+                yield return new TestCaseData(unknowLogicalTypeSchema, new 
object[]
+                    {
+                        new object[] { "John", 23 }
+                    }, codecType).SetName("{m}(Case4,{2})");
             }
         }
 
diff --git a/lang/csharp/src/apache/test/Schema/SchemaTests.cs 
b/lang/csharp/src/apache/test/Schema/SchemaTests.cs
index 221f34eec0..309ecf4d60 100644
--- a/lang/csharp/src/apache/test/Schema/SchemaTests.cs
+++ b/lang/csharp/src/apache/test/Schema/SchemaTests.cs
@@ -19,6 +19,7 @@ using System;
 using System.Collections.Generic;
 using NUnit.Framework;
 using System.Linq;
+using Avro.Util;
 
 namespace Avro.Test
 {
@@ -567,12 +568,80 @@ namespace Avro.Test
             testToString(sc);
         }
 
+        // Make sure unknown type is carried thru to LogicalTypeName
         [TestCase("{\"type\": \"int\", \"logicalType\": \"unknown\"}", 
"unknown")]
         public void TestUnknownLogical(string s, string unknownType)
         {
-            var err = Assert.Throws<AvroTypeException>(() => Schema.Parse(s));
+            var schema = Schema.Parse(s);
+            Assert.IsNotNull(schema);
+            Assert.IsInstanceOf(typeof(LogicalSchema), schema);
 
-            Assert.AreEqual("Logical type '" + unknownType + "' is not 
supported.", err.Message);
+            if (schema is LogicalSchema logicalSchema)
+            {
+                Assert.IsInstanceOf(typeof(UnknownLogicalType), 
logicalSchema.LogicalType);
+                Assert.AreEqual(logicalSchema.LogicalTypeName, unknownType);
+            }
+            else
+            {
+                Assert.Fail("Parsed schema was not a LogicalSchema");
+            }
+        }
+
+        /*
+            {
+              "fields": [
+                {
+                  "default": 0,
+                  "name": "firstField",
+                  "type": "int"
+                },
+                {
+                  "default": null,
+                  "name": "secondField",
+                  "type": [
+                    "null",
+                    {
+                      "logicalType": "varchar",
+                      "maxLength": 65,
+                      "type": "string"
+                    }
+                  ]
+                }
+              ],
+              "name": "sample_schema",
+              "type": "record"
+            }
+         */
+
+        // Before Change will throw Avro.AvroTypeException: 'Logical type 
'varchar' is not supported.'
+        // Per AVRO Spec (v1.8.0 - v1.11.1) ... Logical Types Section
+        //  Language implementations must ignore unknown logical types when 
reading, and should use the underlying Avro type.
+        [TestCase("{\"fields\": [{\"default\": 0,\"name\": 
\"firstField\",\"type\": \"int\"},{\"default\": null,\"name\": 
\"secondField\",\"type\": [\"null\",{\"logicalType\": 
\"varchar\",\"maxLength\": 65,\"type\": \"string\"}]}],\"name\": 
\"sample_schema\",\"type\": \"record\"}")]
+        public void TestUnknownLogicalType(string schemaText)
+        {
+            var schema = Avro.Schema.Parse(schemaText);
+            Assert.IsNotNull(schema);
+
+            var secondField = ((RecordSchema)schema).Fields.FirstOrDefault(f 
=> f.Name == @"secondField");
+            Assert.IsNotNull(secondField);
+
+            var secondFieldSchema = (secondField).Schema;
+            Assert.IsNotNull(secondFieldSchema);
+
+            var secondFieldUnionSchema = (UnionSchema)secondFieldSchema;
+            Assert.IsNotNull(secondFieldUnionSchema);
+
+            var props = secondFieldUnionSchema.Schemas.Where(s => s.Props != 
null).ToList();
+            Assert.IsNotNull(props);
+            Assert.IsTrue(props.Count == 1);
+
+            var prop = props[0];
+            // Confirm that the unknown logical type is ignored and the 
underlying AVRO type is used
+            Assert.IsTrue(prop.Name == @"string");
+            var logicalSchema = prop as LogicalSchema;
+            Assert.IsInstanceOf(typeof(UnknownLogicalType), 
logicalSchema.LogicalType);
+
+            Assert.AreEqual(logicalSchema.LogicalTypeName, @"varchar");
         }
 
         [TestCase("{\"type\": \"map\", \"values\": \"long\"}", "long")]
diff --git a/lang/csharp/src/apache/test/Util/UnknownLogicalTypeTests.cs 
b/lang/csharp/src/apache/test/Util/UnknownLogicalTypeTests.cs
new file mode 100644
index 0000000000..43cc2f3a46
--- /dev/null
+++ b/lang/csharp/src/apache/test/Util/UnknownLogicalTypeTests.cs
@@ -0,0 +1,188 @@
+/*
+ * 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.Data.SqlTypes;
+using System.Globalization;
+using System.Net.Sockets;
+using System.Numerics;
+using Avro.Util;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+
+namespace Avro.test.Util
+{
+    /// <summary>
+    /// This tests added to confirm standalone operation of new type 
UnknownLogicalType that implements LogicalType
+    /// </summary>
+    [TestFixture]
+    class UnknownLogicalTypeTests
+    {
+        [TestCase(typeof(System.String), "", "{\"type\": \"string\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Boolean), true, "{\"type\": \"boolean\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int32), Int32.MinValue, "{\"type\": \"int\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int64), Int64.MinValue, "{\"type\": \"long\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Single), Single.MinValue, "{\"type\": 
\"float\", \"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Double), Double.MinValue, "{\"type\": 
\"double\", \"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Byte[]), new byte[] { }, "{\"type\": 
\"bytes\", \"logicalType\": \"unknown\"}")]
+        public void TestConvertToBaseValue_IsTrue(Type baseType, object 
logicalValue, string schemaText)
+        {
+            var schema = (LogicalSchema)Schema.Parse(schemaText);
+
+            var logicalType = new UnknownLogicalType(schema);
+
+            var baseValue = logicalType.ConvertToBaseValue(logicalValue, 
schema);
+
+            Assert.AreEqual(baseValue, Convert.ChangeType(logicalValue, 
baseType));
+        }
+
+        [TestCase(typeof(System.Byte[]), "", "{\"type\": \"string\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Double), true, "{\"type\": \"boolean\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Single), Int32.MinValue, "{\"type\": \"int\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Boolean), Int64.MinValue, "{\"type\": 
\"long\", \"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int32), Single.MinValue, "{\"type\": 
\"float\", \"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int64), Double.MinValue, "{\"type\": 
\"double\", \"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.String), new byte[] { }, "{\"type\": 
\"bytes\", \"logicalType\": \"unknown\"}")]
+        public void TestConvertToBaseValue_IsFalse(Type baseType, object 
logicalValue, string schemaText)
+        {
+            var schema = (LogicalSchema)Schema.Parse(schemaText);
+
+            var logicalType = new UnknownLogicalType(schema);
+
+            var baseValue = logicalType.ConvertToBaseValue(logicalValue, 
schema);
+
+            Assert.AreNotEqual(baseValue.GetType(), baseType);
+        }
+
+        [TestCase(typeof(System.String), "", "{\"type\": \"string\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Boolean), true, "{\"type\": \"boolean\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int32), Int32.MinValue, "{\"type\": \"int\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int64), Int64.MinValue, "{\"type\": \"long\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Single), Single.MinValue, "{\"type\": 
\"float\", \"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Double), Double.MinValue, "{\"type\": 
\"double\", \"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Byte[]), new byte[] { }, "{\"type\": 
\"bytes\", \"logicalType\": \"unknown\"}")]
+        public void TestConvertToLogicalValue_IsTrue(Type baseType, object 
logicalValue, string schemaText)
+        {
+            var schema = (LogicalSchema)Schema.Parse(schemaText);
+
+            var logicalType = new UnknownLogicalType(schema);
+
+            var baseValue = logicalType.ConvertToLogicalValue(logicalValue, 
schema);
+
+            Assert.AreEqual(baseValue, Convert.ChangeType(logicalValue, 
baseType));
+        }
+
+        [TestCase(typeof(System.Byte[]), "", "{\"type\": \"string\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Double), true, "{\"type\": \"boolean\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Single), Int32.MinValue, "{\"type\": \"int\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Boolean), Int64.MinValue, "{\"type\": 
\"long\", \"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int32), Single.MinValue, "{\"type\": 
\"float\", \"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int64), Double.MinValue, "{\"type\": 
\"double\", \"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.String), new byte[] { }, "{\"type\": 
\"bytes\", \"logicalType\": \"unknown\"}")]
+        public void TestConvertToLogicalValue_IsFalse(Type baseType, object 
logicalValue, string schemaText)
+        {
+            var schema = (LogicalSchema)Schema.Parse(schemaText);
+
+            var logicalType = new UnknownLogicalType(schema);
+
+            var baseValue = logicalType.ConvertToLogicalValue(logicalValue, 
schema);
+
+            Assert.AreNotEqual(baseValue.GetType(), baseType);
+        }
+
+        [TestCase(typeof(System.String), false, "{\"type\": \"string\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Boolean), false, "{\"type\": \"boolean\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int32), false, "{\"type\": \"int\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int64), false, "{\"type\": \"long\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Single), false, "{\"type\": \"float\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Double), false, "{\"type\": \"double\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Byte[]), false, "{\"type\": \"bytes\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.String), true, "{\"type\": \"string\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Boolean?), true, "{\"type\": \"boolean\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int32?), true, "{\"type\": \"int\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int64?), true, "{\"type\": \"long\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Single?), true, "{\"type\": \"float\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Double?), true, "{\"type\": \"double\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Byte[]), true, "{\"type\": \"bytes\", 
\"logicalType\": \"unknown\"}")]
+        public void TestGetCSharpType_IsTrue(Type type, bool isNullable, 
string schemaText)
+        {
+            var schema = (LogicalSchema)Schema.Parse(schemaText);
+
+            var logicalType = new UnknownLogicalType(schema);
+
+            Assert.AreEqual(logicalType.GetCSharpType(isNullable), type);
+        }
+
+        //[TestCase(typeof(System.String), true, "{\"type\": \"string\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Boolean), true, "{\"type\": \"boolean\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int32), true, "{\"type\": \"int\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int64), true, "{\"type\": \"long\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Single), true, "{\"type\": \"float\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Double), true, "{\"type\": \"double\", 
\"logicalType\": \"unknown\"}")]
+        //[TestCase(typeof(System.Byte[]), true, "{\"type\": \"bytes\", 
\"logicalType\": \"unknown\"}")]
+        //[TestCase(typeof(System.String), false, "{\"type\": \"string\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Boolean?), false, "{\"type\": \"boolean\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int32?), false, "{\"type\": \"int\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Int64?), false, "{\"type\": \"long\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Single?), false, "{\"type\": \"float\", 
\"logicalType\": \"unknown\"}")]
+        [TestCase(typeof(System.Double?), false, "{\"type\": \"double\", 
\"logicalType\": \"unknown\"}")]
+        //[TestCase(typeof(System.Byte?[]), false, "{\"type\": \"bytes\", 
\"logicalType\": \"unknown\"}")]
+        public void TestGetCSharpType_IsFalse(Type type, bool isNullable, 
string schemaText)
+        {
+            var schema = (LogicalSchema)Schema.Parse(schemaText);
+
+            var logicalType = new UnknownLogicalType(schema);
+
+            Assert.AreNotEqual(logicalType.GetCSharpType(isNullable), type);
+        }
+
+        [TestCase("", "{\"type\": \"string\", \"logicalType\": \"unknown\"}")]
+        [TestCase(true, "{\"type\": \"boolean\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase(Int32.MinValue, "{\"type\": \"int\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase(Int64.MinValue, "{\"type\": \"long\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase(Single.MinValue, "{\"type\": \"float\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase(Double.MinValue, "{\"type\": \"double\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase(new byte[] { } , "{\"type\": \"bytes\", \"logicalType\": 
\"unknown\"}")]
+        public void TestIsInstanceOfLogicalType_IsTrue(object logicalValue, 
string schemaText)
+        {
+            var schema = (LogicalSchema)Schema.Parse(schemaText);
+
+            var logicalType = new UnknownLogicalType(schema);
+
+            Assert.IsTrue(logicalType.IsInstanceOfLogicalType(logicalValue));
+        }
+
+        [TestCase(Int32.MinValue, "{\"type\": \"string\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase(new byte[] { }, "{\"type\": \"boolean\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase(Int64.MinValue, "{\"type\": \"int\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase(Single.MinValue, "{\"type\": \"long\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase(Double.MinValue, "{\"type\": \"float\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase(new byte[] { }, "{\"type\": \"double\", \"logicalType\": 
\"unknown\"}")]
+        [TestCase("", "{\"type\": \"bytes\", \"logicalType\": \"unknown\"}")]
+        public void TestIsInstanceOfLogicalType_IsFalse(object logicalValue, 
string schemaText)
+        {
+            var schema = (LogicalSchema)Schema.Parse(schemaText);
+
+            var logicalType = new UnknownLogicalType(schema);
+
+            Assert.IsFalse(logicalType.IsInstanceOfLogicalType(logicalValue));
+        }
+
+        // See also a new test in Avro.Tests.File in TestSpecificDataSource 
using unknowLogicalTypeSchema
+    }
+}

Reply via email to