diff --git a/test/EFCore.Jet.FunctionalTests/BuiltInDataTypesJetTest.cs b/test/EFCore.Jet.FunctionalTests/BuiltInDataTypesJetTest.cs index 4d90917..3481650 100644 --- a/test/EFCore.Jet.FunctionalTests/BuiltInDataTypesJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/BuiltInDataTypesJetTest.cs @@ -6,10 +6,12 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Globalization; using System.Linq; +using System.Linq.Expressions; using System.Text; using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities; using EntityFrameworkCore.Jet.Infrastructure; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; @@ -4413,5 +4415,1237 @@ UnicodeDataTypes.StringUnicode ---> [nullable varchar] [MaxLength = 255] public int? NumericScale { get; set; } public int? DateTimePrecision { get; set; } } + + public override void Can_insert_and_read_back_all_non_nullable_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new BuiltInDataTypes + { + Id = 1, + PartitionId = 1, + TestInt16 = -1234, + TestInt32 = -123456789, + TestInt64 = -1234567890123456789L, + TestDouble = -1.23456789, + TestDecimal = -1234567890.01M, + TestDateTime = DateTime.Parse("01/01/2000 12:34:56", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal), + TestDateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TestTimeSpan = new TimeSpan(0, 10, 9, 8, 0), + TestDateOnly = new DateOnly(2020, 3, 1), + TestTimeOnly = new TimeOnly(12, 30, 45, 0), + TestSingle = -1.234F, + TestBoolean = true, + TestByte = 255, + TestUnsignedInt16 = 1234, + TestUnsignedInt32 = 1234565789U, + TestUnsignedInt64 = 1234567890123456789UL, + TestCharacter = 'a', + TestSignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(e => e.Id == 1).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(BuiltInDataTypes)); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.TestInt16); + AssertEqualIfMapped(entityType, -123456789, () => dt.TestInt32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.TestInt64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.TestDouble); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.TestDecimal); + AssertEqualIfMapped( + entityType, DateTime.Parse("01/01/2000 12:34:56", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal), + () => dt.TestDateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.TestDateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TestTimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.TestDateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TestTimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.TestSingle); + AssertEqualIfMapped(entityType, true, () => dt.TestBoolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.TestByte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.TestUnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.TestUnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.TestUnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.TestCharacter); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.TestSignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_insert_and_read_back_all_nullable_data_types_with_values_set_to_non_null() + { + using (var context = CreateContext()) + { + context.Set().Add( + new BuiltInNullableDataTypes + { + Id = 101, + PartitionId = 101, + TestString = "TestString", + TestByteArray = new byte[] { 10, 9, 8, 7, 6 }, + TestNullableInt16 = -1234, + TestNullableInt32 = -123456789, + TestNullableInt64 = -1234567890123456789L, + TestNullableDouble = -1.23456789, + TestNullableDecimal = -1234567890.01M, + TestNullableDateTime = DateTime.Parse("01/01/2000 12:34:56").ToUniversalTime(), + TestNullableDateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TestNullableDateOnly = new DateOnly(2020, 3, 1), + TestNullableTimeOnly = new TimeOnly(12, 30, 45, 0), + TestNullableTimeSpan = new TimeSpan(0, 10, 9, 8, 0), + TestNullableSingle = -1.234F, + TestNullableBoolean = false, + TestNullableByte = 255, + TestNullableUnsignedInt16 = 1234, + TestNullableUnsignedInt32 = 1234565789U, + TestNullableUnsignedInt64 = 1234567890123456789UL, + TestNullableCharacter = 'a', + TestNullableSignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(BuiltInNullableDataTypes)); + AssertEqualIfMapped(entityType, "TestString", () => dt.TestString); + AssertEqualIfMapped(entityType, new byte[] { 10, 9, 8, 7, 6 }, () => dt.TestByteArray); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.TestNullableInt16); + AssertEqualIfMapped(entityType, -123456789, () => dt.TestNullableInt32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.TestNullableInt64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.TestNullableDouble); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.TestNullableDecimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56").ToUniversalTime(), () => dt.TestNullableDateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.TestNullableDateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TestNullableTimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.TestNullableDateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TestNullableTimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.TestNullableSingle); + AssertEqualIfMapped(entityType, false, () => dt.TestNullableBoolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.TestNullableByte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.TestNullableUnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.TestNullableUnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.TestNullableUnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.TestNullableCharacter); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.TestNullableSignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_insert_and_read_back_object_backed_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new ObjectBackedDataTypes + { + Id = 101, + PartitionId = 101, + String = "TestString", + Bytes = new byte[] { 10, 9, 8, 7, 6 }, + Int16 = -1234, + Int32 = -123456789, + Int64 = -1234567890123456789L, + Double = -1.23456789, + Decimal = -1234567890.01M, + DateTime = DateTime.Parse("01/01/2000 12:34:56"), + DateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TimeSpan = new TimeSpan(0, 10, 9, 8, 0), + DateOnly = new DateOnly(2020, 3, 1), + TimeOnly = new TimeOnly(12, 30, 45, 0), + Single = -1.234F, + Boolean = false, + Byte = 255, + UnsignedInt16 = 1234, + UnsignedInt32 = 1234565789U, + UnsignedInt64 = 1234567890123456789UL, + Character = 'a', + SignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(ObjectBackedDataTypes)); + AssertEqualIfMapped(entityType, "TestString", () => dt.String); + AssertEqualIfMapped(entityType, new byte[] { 10, 9, 8, 7, 6 }, () => dt.Bytes); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.Int16); + AssertEqualIfMapped(entityType, -123456789, () => dt.Int32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.Double); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.Decimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56"), () => dt.DateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.DateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.DateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.Single); + AssertEqualIfMapped(entityType, false, () => dt.Boolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.Byte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.UnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.UnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.UnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.Character); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.SignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_insert_and_read_back_nullable_backed_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new NullableBackedDataTypes + { + Id = 101, + PartitionId = 101, + Int16 = -1234, + Int32 = -123456789, + Int64 = -1234567890123456789L, + Double = -1.23456789, + Decimal = -1234567890.01M, + DateTime = DateTime.Parse("01/01/2000 12:34:56"), + DateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TimeSpan = new TimeSpan(0, 10, 9, 8, 0), + DateOnly = new DateOnly(2020, 3, 1), + TimeOnly = new TimeOnly(12, 30, 45, 0), + Single = -1.234F, + Boolean = false, + Byte = 255, + UnsignedInt16 = 1234, + UnsignedInt32 = 1234565789U, + UnsignedInt64 = 1234567890123456789UL, + Character = 'a', + SignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(NullableBackedDataTypes)); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.Int16); + AssertEqualIfMapped(entityType, -123456789, () => dt.Int32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.Double); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.Decimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56"), () => dt.DateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.DateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.DateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.Single); + AssertEqualIfMapped(entityType, false, () => dt.Boolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.Byte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.UnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.UnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.UnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.Character); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.SignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_insert_and_read_back_non_nullable_backed_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new NonNullableBackedDataTypes + { + Id = 101, + PartitionId = 101, + Int16 = -1234, + Int32 = -123456789, + Int64 = -1234567890123456789L, + Double = -1.23456789, + Decimal = -1234567890.01M, + DateTime = DateTime.Parse("01/01/2000 12:34:56"), + DateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TimeSpan = new TimeSpan(0, 10, 9, 8, 0), + DateOnly = new DateOnly(2020, 3, 1), + TimeOnly = new TimeOnly(12, 30, 45, 0), + Single = -1.234F, + Boolean = true, + Byte = 255, + UnsignedInt16 = 1234, + UnsignedInt32 = 1234565789U, + UnsignedInt64 = 1234567890123456789UL, + Character = 'a', + SignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(NonNullableBackedDataTypes)); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.Int16); + AssertEqualIfMapped(entityType, -123456789, () => dt.Int32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.Double); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.Decimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56"), () => dt.DateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.DateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.DateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.Single); + AssertEqualIfMapped(entityType, true, () => dt.Boolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.Byte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.UnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.UnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.UnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.Character); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.SignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_query_using_any_data_type() + { + using var context = CreateContext(); + var source = AddTestBuiltInDataTypes(context.Set()); + + Assert.Equal(1, context.SaveChanges()); + + QueryBuiltInDataTypesTest(source); + } + + public override void Can_query_using_any_data_type_shadow() + { + using var context = CreateContext(); + var source = AddTestBuiltInDataTypes(context.Set()); + + Assert.Equal(1, context.SaveChanges()); + + QueryBuiltInDataTypesTest(source); + } + + private void QueryBuiltInDataTypesTest(EntityEntry source) + where TEntity : BuiltInDataTypesBase + { + using var context = CreateContext(); + var set = context.Set(); + var entity = set.Where(e => e.Id == 11).ToList().Single(); + var entityType = context.Model.FindEntityType(typeof(TEntity)); + + var param1 = (short)-1234; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestInt16)) == param1).ToList().Single()); + + var param2 = -123456789; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestInt32)) == param2).ToList().Single()); + + var param3 = -1234567890123456789L; + if (Fixture.IntegerPrecision == 64) + { + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestInt64)) == param3).ToList().Single()); + } + + double? param4 = -1.23456789; + if (Fixture.StrictEquality) + { + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInDataTypes.TestDouble)) == param4).ToList().Single()); + } + else if (Fixture.SupportsDecimalComparisons) + { + double? param4l = -1.234567891; + double? param4h = -1.234567889; + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && (EF.Property(e, nameof(BuiltInDataTypes.TestDouble)) == param4 + || (EF.Property(e, nameof(BuiltInDataTypes.TestDouble)) > param4l + && EF.Property(e, nameof(BuiltInDataTypes.TestDouble)) < param4h))) + .ToList().Single()); + } + + var param5 = -1234567890.01M; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestDecimal)) == param5).ToList() + .Single()); + + var param6 = Fixture.DefaultDateTime; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestDateTime)) == param6).ToList() + .Single()); + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestDateTimeOffset)) != null) + { + var param7 = new DateTimeOffset(new DateTime(), TimeSpan.FromHours(-8.0)); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestDateTimeOffset)) == param7) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestTimeSpan)) != null) + { + var param8 = new TimeSpan(0, 10, 9, 8, 7); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestTimeSpan)) == param8).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestDateOnly)) != null) + { + var param9 = new DateOnly(2020, 3, 1); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestDateOnly)) == param9).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestTimeOnly)) != null) + { + var param10 = new TimeOnly(12, 30, 45, 0); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestTimeOnly)) == param10).ToList() + .Single()); + } + + var param11 = -1.234F; + if (Fixture.StrictEquality) + { + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInDataTypes.TestSingle)) == param11).ToList().Single()); + } + else if (Fixture.SupportsDecimalComparisons) + { + var param11l = -1.2341F; + var param11h = -1.2339F; + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && (EF.Property(e, nameof(BuiltInDataTypes.TestSingle)) == param11 + || (EF.Property(e, nameof(BuiltInDataTypes.TestSingle)) > param11l + && EF.Property(e, nameof(BuiltInDataTypes.TestSingle)) < param11h))).ToList().Single()); + } + + var param12 = true; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestBoolean)) == param12).ToList().Single()); + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestByte)) != null) + { + var param13 = (byte)255; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestByte)) == param13).ToList().Single()); + } + + var param14 = Enum64.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum64)) == param14).ToList().Single()); + + var param15 = Enum32.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum32)) == param15).ToList().Single()); + + var param16 = Enum16.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum16)) == param16).ToList().Single()); + + if (entityType.FindProperty(nameof(BuiltInDataTypes.Enum8)) != null) + { + var param17 = Enum8.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum8)) == param17).ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestUnsignedInt16)) != null) + { + var param18 = (ushort)1234; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestUnsignedInt16)) == param18).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestUnsignedInt32)) != null) + { + var param19 = 1234565789U; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestUnsignedInt32)) == param19).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestUnsignedInt64)) != null) + { + var param20 = 1234567890123456789UL; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestUnsignedInt64)) == param20).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestCharacter)) != null) + { + var param21 = 'a'; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestCharacter)) == param21).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestSignedByte)) != null) + { + var param22 = (sbyte)-128; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestSignedByte)) == param22).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.EnumU64)) != null) + { + var param23 = EnumU64.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.EnumU64)) == param23).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.EnumU32)) != null) + { + var param24 = EnumU32.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.EnumU32)) == param24).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.EnumU16)) != null) + { + var param25 = EnumU16.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.EnumU16)) == param25).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.EnumS8)) != null) + { + var param26 = EnumS8.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.EnumS8)) == param26).ToList().Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInDataTypes.Enum64))?.GetProviderClrType()) == typeof(long)) + { + var param27 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum64)) == (Enum64)param27).ToList() + .Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInDataTypes.Enum64)) == param27).ToList() + .Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInDataTypes.Enum32))?.GetProviderClrType()) == typeof(int)) + { + var param28 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum32)) == (Enum32)param28).ToList() + .Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInDataTypes.Enum32)) == param28).ToList() + .Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInDataTypes.Enum16))?.GetProviderClrType()) == typeof(short)) + { + var param29 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum16)) == (Enum16)param29).ToList() + .Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInDataTypes.Enum16)) == param29).ToList() + .Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInDataTypes.Enum8))?.GetProviderClrType()) == typeof(byte)) + { + var param30 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum8)) == (Enum8)param30).ToList() + .Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInDataTypes.Enum8)) == param30).ToList() + .Single()); + } + + foreach (var propertyEntry in context.Entry(entity).Properties) + { + if (propertyEntry.Metadata.ValueGenerated != ValueGenerated.Never) + { + continue; + } + + Assert.Equal( + source.Property(propertyEntry.Metadata).CurrentValue, + propertyEntry.CurrentValue); + } + } + + protected new EntityEntry AddTestBuiltInDataTypes(DbSet set) + where TEntity : BuiltInDataTypesBase, new() + { + var entityEntry = set.Add( + new TEntity { Id = 11 }); + + entityEntry.CurrentValues.SetValues( + new BuiltInDataTypes + { + Id = 11, + PartitionId = 1, + TestInt16 = -1234, + TestInt32 = -123456789, + TestInt64 = -1234567890123456789L, + TestDouble = -1.23456789, + TestDecimal = -1234567890.01M, + TestDateTime = Fixture.DefaultDateTime, + TestDateTimeOffset = new DateTimeOffset(new DateTime(), TimeSpan.FromHours(-8.0)), + TestTimeSpan = new TimeSpan(0, 10, 9, 8, 7), + TestDateOnly = new DateOnly(2020, 3, 1), + TestTimeOnly = new TimeOnly(12, 30, 45, 0), + TestSingle = -1.234F, + TestBoolean = true, + TestByte = 255, + TestUnsignedInt16 = 1234, + TestUnsignedInt32 = 1234565789U, + TestUnsignedInt64 = 1234567890123456789UL, + TestCharacter = 'a', + TestSignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + return entityEntry; + } + + public override void Can_query_using_any_nullable_data_type() + { + using var context = CreateContext(); + var source = AddTestBuiltInNullableDataTypes(context.Set()); + + Assert.Equal(1, context.SaveChanges()); + + QueryBuiltInNullableDataTypesTest(source); + } + + public override void Can_query_using_any_data_type_nullable_shadow() + { + using var context = CreateContext(); + var source = AddTestBuiltInNullableDataTypes(context.Set()); + + Assert.Equal(1, context.SaveChanges()); + + QueryBuiltInNullableDataTypesTest(source); + } + + private void QueryBuiltInNullableDataTypesTest(EntityEntry source) + where TEntity : BuiltInNullableDataTypesBase + { + using var context = CreateContext(); + var set = context.Set(); + var entity = set.Where(e => e.Id == 11).ToList().Single(); + var entityType = context.Model.FindEntityType(typeof(TEntity)); + + short? param1 = -1234; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableInt16)) == param1) + .ToList().Single()); + + int? param2 = -123456789; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableInt32)) == param2) + .ToList().Single()); + + long? param3 = -1234567890123456789L; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableInt64)) == param3) + .ToList().Single()); + + double? param4 = -1.23456789; + if (Fixture.StrictEquality) + { + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDouble)) == param4).ToList() + .Single()); + } + else if (Fixture.SupportsDecimalComparisons) + { + double? param4l = -1.234567891; + double? param4h = -1.234567889; + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && (EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDouble)) == param4 + || (EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDouble)) > param4l + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDouble)) < param4h))) + .ToList().Single()); + } + + decimal? param5 = -1234567890.01M; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDecimal)) == param5) + .ToList().Single()); + + DateTime? param6 = Fixture.DefaultDateTime; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDateTime)) == param6) + .ToList().Single()); + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableDateTimeOffset)) != null) + { + DateTimeOffset? param7 = new DateTimeOffset(new DateTime(), TimeSpan.FromHours(-8.0)); + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDateTimeOffset)) + == param7).ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableTimeSpan)) != null) + { + TimeSpan? param8 = new TimeSpan(0, 10, 9, 8, 7); + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableTimeSpan)) + == param8) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableDateOnly)) != null) + { + DateOnly? param9 = new DateOnly(2020, 3, 1); + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDateOnly)) + == param9) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableTimeOnly)) != null) + { + TimeOnly? param10 = new TimeOnly(12, 30, 45, 0); + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableTimeOnly)) + == param10) + .ToList().Single()); + } + + float? param11 = -1.234F; + if (Fixture.StrictEquality) + { + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableSingle)) == param11).ToList() + .Single()); + } + else if (Fixture.SupportsDecimalComparisons) + { + float? param11l = -1.2341F; + float? param11h = -1.2339F; + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && (EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableSingle)) == param11 + || (EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableSingle)) > param11l + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableSingle)) < param11h))) + .ToList().Single()); + } + + bool? param12 = true; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableBoolean)) == param12) + .ToList().Single()); + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableByte)) != null) + { + byte? param13 = 255; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableByte)) == param13) + .ToList().Single()); + } + + Enum64? param14 = Enum64.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum64)) == param14).ToList() + .Single()); + + Enum32? param15 = Enum32.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum32)) == param15).ToList() + .Single()); + + Enum16? param16 = Enum16.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum16)) == param16).ToList() + .Single()); + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.Enum8)) != null) + { + Enum8? param17 = Enum8.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum8)) == param17).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt16)) != null) + { + ushort? param18 = 1234; + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt16)) + == param18).ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt32)) != null) + { + uint? param19 = 1234565789U; + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt32)) + == param19) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt64)) != null) + { + ulong? param20 = 1234567890123456789UL; + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property( + e, nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt64)) + == param20).ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableCharacter)) != null) + { + char? param21 = 'a'; + Assert.Same( + entity, + set.Where( + e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableCharacter)) == param21) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableSignedByte)) != null) + { + sbyte? param22 = -128; + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableSignedByte)) + == param22) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.EnumU64)) != null) + { + var param23 = EnumU64.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.EnumU64)) == param23).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.EnumU32)) != null) + { + var param24 = EnumU32.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.EnumU32)) == param24).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.EnumU16)) != null) + { + var param25 = EnumU16.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.EnumU16)) == param25).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.EnumS8)) != null) + { + var param26 = EnumS8.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.EnumS8)) == param26).ToList() + .Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInNullableDataTypes.Enum64))?.GetProviderClrType()) + == typeof(long)) + { + int? param27 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum64)) == (Enum64)param27) + .ToList().Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInNullableDataTypes.Enum64)) == param27) + .ToList().Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInNullableDataTypes.Enum32))?.GetProviderClrType()) + == typeof(int)) + { + int? param28 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum32)) == (Enum32)param28) + .ToList().Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInNullableDataTypes.Enum32)) == param28) + .ToList().Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInNullableDataTypes.Enum16))?.GetProviderClrType()) + == typeof(short)) + { + int? param29 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum16)) == (Enum16)param29) + .ToList().Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInNullableDataTypes.Enum16)) == param29) + .ToList().Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInNullableDataTypes.Enum8))?.GetProviderClrType()) + == typeof(byte)) + { + int? param30 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum8)) == (Enum8)param30) + .ToList().Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInNullableDataTypes.Enum8)) == param30) + .ToList().Single()); + } + + foreach (var propertyEntry in context.Entry(entity).Properties) + { + if (propertyEntry.Metadata.ValueGenerated != ValueGenerated.Never) + { + continue; + } + + Assert.Equal( + source.Property(propertyEntry.Metadata).CurrentValue, + propertyEntry.CurrentValue); + } + } + + protected new virtual EntityEntry AddTestBuiltInNullableDataTypes(DbSet set) + where TEntity : BuiltInNullableDataTypesBase, new() + { + var entityEntry = set.Add( + new TEntity { Id = 11 }); + + entityEntry.CurrentValues.SetValues( + new BuiltInNullableDataTypes + { + Id = 11, + PartitionId = 1, + TestNullableInt16 = -1234, + TestNullableInt32 = -123456789, + TestNullableInt64 = -1234567890123456789L, + TestNullableDouble = -1.23456789, + TestNullableDecimal = -1234567890.01M, + TestNullableDateTime = Fixture.DefaultDateTime, + TestNullableDateTimeOffset = new DateTimeOffset(new DateTime(), TimeSpan.FromHours(-8.0)), + TestNullableTimeSpan = new TimeSpan(0, 10, 9, 8, 7), + TestNullableDateOnly = new DateOnly(2020, 3, 1), + TestNullableTimeOnly = new TimeOnly(12, 30, 45, 0), + TestNullableSingle = -1.234F, + TestNullableBoolean = true, + TestNullableByte = 255, + TestNullableUnsignedInt16 = 1234, + TestNullableUnsignedInt32 = 1234565789U, + TestNullableUnsignedInt64 = 1234567890123456789UL, + TestNullableCharacter = 'a', + TestNullableSignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + return entityEntry; + } + + + + private void AssertEqualIfMapped(IEntityType entityType, T expected, Expression> actualExpression) + { + if (entityType.FindProperty(((MemberExpression)actualExpression.Body).Member.Name) != null) + { + var actual = actualExpression.Compile()(); + var type = UnwrapNullableEnumType(typeof(T)); + if (IsSignedInteger(type)) + { + Assert.True(Equal(Convert.ToInt64(expected), Convert.ToInt64(actual)), $"Expected:\t{expected}\r\nActual:\t{actual}"); + } + else if (IsUnsignedInteger(type)) + { + Assert.True(Equal(Convert.ToUInt64(expected), Convert.ToUInt64(actual)), $"Expected:\t{expected}\r\nActual:\t{actual}"); + } + else if (type == typeof(DateTime)) + { + Assert.True( + Equal((DateTime)(object)expected, (DateTime)(object)actual), $"Expected:\t{expected:O}\r\nActual:\t{actual:O}"); + } + else if (type == typeof(DateTimeOffset)) + { + Assert.True( + Equal((DateTimeOffset)(object)expected, (DateTimeOffset)(object)actual), + $"Expected:\t{expected:O}\r\nActual:\t{actual:O}"); + } + else + { + Assert.Equal(expected, actual); + } + } + } + + private bool Equal(long left, long right) + { + if (left >= 0 + && right >= 0) + { + return Equal((ulong)left, (ulong)right); + } + + if (left < 0 + && right < 0) + { + return Equal((ulong)-left, (ulong)-right); + } + + return false; + } + + private bool Equal(ulong left, ulong right) + { + if (Fixture.IntegerPrecision < 64) + { + var largestPrecise = 1ul << Fixture.IntegerPrecision; + while (left > largestPrecise) + { + left >>= 1; + right >>= 1; + } + } + + return left == right; + } + + private bool Equal(DateTime left, DateTime right) + => left.Equals(right) && (!Fixture.PreservesDateTimeKind || left.Kind == right.Kind); + + private bool Equal(DateTimeOffset left, DateTimeOffset right) + => left.EqualsExact(right); + + private static Type UnwrapNullableType(Type type) + => type == null ? null : Nullable.GetUnderlyingType(type) ?? type; + + private static bool IsSignedInteger(Type type) + => type == typeof(int) + || type == typeof(long) + || type == typeof(short) + || type == typeof(sbyte); + + private static bool IsUnsignedInteger(Type type) + => type == typeof(byte) + || type == typeof(uint) + || type == typeof(ulong) + || type == typeof(ushort) + || type == typeof(char); } } diff --git a/test/EFCore.Jet.FunctionalTests/ConvertToProviderTypesJetTest.cs b/test/EFCore.Jet.FunctionalTests/ConvertToProviderTypesJetTest.cs index dd01a0a..2dd644c 100644 --- a/test/EFCore.Jet.FunctionalTests/ConvertToProviderTypesJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/ConvertToProviderTypesJetTest.cs @@ -1,11 +1,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq; +using System.Linq.Expressions; using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -180,6 +183,1238 @@ UnicodeDataTypes.StringUnicode ---> [nullable varchar] [MaxLength = 255] Assert.Equal(expected, actual, ignoreLineEndingDifferences: true); } + public override void Can_insert_and_read_back_all_non_nullable_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new BuiltInDataTypes + { + Id = 1, + PartitionId = 1, + TestInt16 = -1234, + TestInt32 = -123456789, + TestInt64 = -1234567890123456789L, + TestDouble = -1.23456789, + TestDecimal = -1234567890.01M, + TestDateTime = DateTime.Parse("01/01/2000 12:34:56", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal), + TestDateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TestTimeSpan = new TimeSpan(0, 10, 9, 8, 0), + TestDateOnly = new DateOnly(2020, 3, 1), + TestTimeOnly = new TimeOnly(12, 30, 45, 0), + TestSingle = -1.234F, + TestBoolean = true, + TestByte = 255, + TestUnsignedInt16 = 1234, + TestUnsignedInt32 = 1234565789U, + TestUnsignedInt64 = 1234567890123456789UL, + TestCharacter = 'a', + TestSignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(e => e.Id == 1).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(BuiltInDataTypes)); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.TestInt16); + AssertEqualIfMapped(entityType, -123456789, () => dt.TestInt32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.TestInt64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.TestDouble); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.TestDecimal); + AssertEqualIfMapped( + entityType, DateTime.Parse("01/01/2000 12:34:56", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal), + () => dt.TestDateTime); + AssertEqualIfMapped( + entityType, new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + () => dt.TestDateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TestTimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.TestDateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TestTimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.TestSingle); + AssertEqualIfMapped(entityType, true, () => dt.TestBoolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.TestByte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.TestUnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.TestUnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.TestUnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.TestCharacter); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.TestSignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_insert_and_read_back_all_nullable_data_types_with_values_set_to_non_null() + { + using (var context = CreateContext()) + { + context.Set().Add( + new BuiltInNullableDataTypes + { + Id = 101, + PartitionId = 101, + TestString = "TestString", + TestByteArray = new byte[] { 10, 9, 8, 7, 6 }, + TestNullableInt16 = -1234, + TestNullableInt32 = -123456789, + TestNullableInt64 = -1234567890123456789L, + TestNullableDouble = -1.23456789, + TestNullableDecimal = -1234567890.01M, + TestNullableDateTime = DateTime.Parse("01/01/2000 12:34:56").ToUniversalTime(), + TestNullableDateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TestNullableDateOnly = new DateOnly(2020, 3, 1), + TestNullableTimeOnly = new TimeOnly(12, 30, 45, 0), + TestNullableTimeSpan = new TimeSpan(0, 10, 9, 8, 0), + TestNullableSingle = -1.234F, + TestNullableBoolean = false, + TestNullableByte = 255, + TestNullableUnsignedInt16 = 1234, + TestNullableUnsignedInt32 = 1234565789U, + TestNullableUnsignedInt64 = 1234567890123456789UL, + TestNullableCharacter = 'a', + TestNullableSignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(BuiltInNullableDataTypes)); + AssertEqualIfMapped(entityType, "TestString", () => dt.TestString); + AssertEqualIfMapped(entityType, new byte[] { 10, 9, 8, 7, 6 }, () => dt.TestByteArray); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.TestNullableInt16); + AssertEqualIfMapped(entityType, -123456789, () => dt.TestNullableInt32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.TestNullableInt64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.TestNullableDouble); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.TestNullableDecimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56").ToUniversalTime(), () => dt.TestNullableDateTime); + AssertEqualIfMapped( + entityType, new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + () => dt.TestNullableDateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TestNullableTimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.TestNullableDateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TestNullableTimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.TestNullableSingle); + AssertEqualIfMapped(entityType, false, () => dt.TestNullableBoolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.TestNullableByte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.TestNullableUnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.TestNullableUnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.TestNullableUnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.TestNullableCharacter); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.TestNullableSignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_insert_and_read_back_object_backed_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new ObjectBackedDataTypes + { + Id = 101, + PartitionId = 101, + String = "TestString", + Bytes = new byte[] { 10, 9, 8, 7, 6 }, + Int16 = -1234, + Int32 = -123456789, + Int64 = -1234567890123456789L, + Double = -1.23456789, + Decimal = -1234567890.01M, + DateTime = DateTime.Parse("01/01/2000 12:34:56"), + DateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TimeSpan = new TimeSpan(0, 10, 9, 8, 0), + DateOnly = new DateOnly(2020, 3, 1), + TimeOnly = new TimeOnly(12, 30, 45, 0), + Single = -1.234F, + Boolean = false, + Byte = 255, + UnsignedInt16 = 1234, + UnsignedInt32 = 1234565789U, + UnsignedInt64 = 1234567890123456789UL, + Character = 'a', + SignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(ObjectBackedDataTypes)); + AssertEqualIfMapped(entityType, "TestString", () => dt.String); + AssertEqualIfMapped(entityType, new byte[] { 10, 9, 8, 7, 6 }, () => dt.Bytes); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.Int16); + AssertEqualIfMapped(entityType, -123456789, () => dt.Int32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.Double); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.Decimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56"), () => dt.DateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.DateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.DateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.Single); + AssertEqualIfMapped(entityType, false, () => dt.Boolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.Byte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.UnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.UnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.UnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.Character); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.SignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_insert_and_read_back_nullable_backed_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new NullableBackedDataTypes + { + Id = 101, + PartitionId = 101, + Int16 = -1234, + Int32 = -123456789, + Int64 = -1234567890123456789L, + Double = -1.23456789, + Decimal = -1234567890.01M, + DateTime = DateTime.Parse("01/01/2000 12:34:56"), + DateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TimeSpan = new TimeSpan(0, 10, 9, 8, 0), + DateOnly = new DateOnly(2020, 3, 1), + TimeOnly = new TimeOnly(12, 30, 45, 0), + Single = -1.234F, + Boolean = false, + Byte = 255, + UnsignedInt16 = 1234, + UnsignedInt32 = 1234565789U, + UnsignedInt64 = 1234567890123456789UL, + Character = 'a', + SignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(NullableBackedDataTypes)); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.Int16); + AssertEqualIfMapped(entityType, -123456789, () => dt.Int32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.Double); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.Decimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56"), () => dt.DateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.DateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.DateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.Single); + AssertEqualIfMapped(entityType, false, () => dt.Boolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.Byte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.UnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.UnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.UnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.Character); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.SignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_insert_and_read_back_non_nullable_backed_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new NonNullableBackedDataTypes + { + Id = 101, + PartitionId = 101, + Int16 = -1234, + Int32 = -123456789, + Int64 = -1234567890123456789L, + Double = -1.23456789, + Decimal = -1234567890.01M, + DateTime = DateTime.Parse("01/01/2000 12:34:56"), + DateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TimeSpan = new TimeSpan(0, 10, 9, 8, 0), + DateOnly = new DateOnly(2020, 3, 1), + TimeOnly = new TimeOnly(12, 30, 45, 0), + Single = -1.234F, + Boolean = true, + Byte = 255, + UnsignedInt16 = 1234, + UnsignedInt32 = 1234565789U, + UnsignedInt64 = 1234567890123456789UL, + Character = 'a', + SignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(NonNullableBackedDataTypes)); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.Int16); + AssertEqualIfMapped(entityType, -123456789, () => dt.Int32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.Double); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.Decimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56"), () => dt.DateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.DateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.DateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.Single); + AssertEqualIfMapped(entityType, true, () => dt.Boolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.Byte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.UnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.UnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.UnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.Character); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.SignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_query_using_any_data_type() + { + using var context = CreateContext(); + var source = AddTestBuiltInDataTypes(context.Set()); + + Assert.Equal(1, context.SaveChanges()); + + QueryBuiltInDataTypesTest(source); + } + + public override void Can_query_using_any_data_type_shadow() + { + using var context = CreateContext(); + var source = AddTestBuiltInDataTypes(context.Set()); + + Assert.Equal(1, context.SaveChanges()); + + QueryBuiltInDataTypesTest(source); + } + + private void QueryBuiltInDataTypesTest(EntityEntry source) + where TEntity : BuiltInDataTypesBase + { + using var context = CreateContext(); + var set = context.Set(); + var entity = set.Where(e => e.Id == 11).ToList().Single(); + var entityType = context.Model.FindEntityType(typeof(TEntity)); + + var param1 = (short)-1234; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestInt16)) == param1).ToList().Single()); + + var param2 = -123456789; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestInt32)) == param2).ToList().Single()); + + var param3 = -1234567890123456789L; + if (Fixture.IntegerPrecision == 64) + { + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestInt64)) == param3).ToList().Single()); + } + + double? param4 = -1.23456789; + if (Fixture.StrictEquality) + { + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInDataTypes.TestDouble)) == param4).ToList().Single()); + } + else if (Fixture.SupportsDecimalComparisons) + { + double? param4l = -1.234567891; + double? param4h = -1.234567889; + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && (EF.Property(e, nameof(BuiltInDataTypes.TestDouble)) == param4 + || (EF.Property(e, nameof(BuiltInDataTypes.TestDouble)) > param4l + && EF.Property(e, nameof(BuiltInDataTypes.TestDouble)) < param4h))) + .ToList().Single()); + } + + var param5 = -1234567890.01M; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestDecimal)) == param5).ToList() + .Single()); + + var param6 = Fixture.DefaultDateTime; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestDateTime)) == param6).ToList() + .Single()); + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestDateTimeOffset)) != null) + { + var param7 = new DateTimeOffset(new DateTime(), TimeSpan.FromHours(-8.0)); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestDateTimeOffset)) == param7) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestTimeSpan)) != null) + { + var param8 = new TimeSpan(0, 10, 9, 8, 7); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestTimeSpan)) == param8).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestDateOnly)) != null) + { + var param9 = new DateOnly(2020, 3, 1); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestDateOnly)) == param9).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestTimeOnly)) != null) + { + var param10 = new TimeOnly(12, 30, 45, 0); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestTimeOnly)) == param10).ToList() + .Single()); + } + + var param11 = -1.234F; + if (Fixture.StrictEquality) + { + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInDataTypes.TestSingle)) == param11).ToList().Single()); + } + else if (Fixture.SupportsDecimalComparisons) + { + var param11l = -1.2341F; + var param11h = -1.2339F; + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && (EF.Property(e, nameof(BuiltInDataTypes.TestSingle)) == param11 + || (EF.Property(e, nameof(BuiltInDataTypes.TestSingle)) > param11l + && EF.Property(e, nameof(BuiltInDataTypes.TestSingle)) < param11h))).ToList().Single()); + } + + var param12 = true; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestBoolean)) == param12).ToList().Single()); + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestByte)) != null) + { + var param13 = (byte)255; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestByte)) == param13).ToList().Single()); + } + + var param14 = Enum64.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum64)) == param14).ToList().Single()); + + var param15 = Enum32.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum32)) == param15).ToList().Single()); + + var param16 = Enum16.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum16)) == param16).ToList().Single()); + + if (entityType.FindProperty(nameof(BuiltInDataTypes.Enum8)) != null) + { + var param17 = Enum8.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum8)) == param17).ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestUnsignedInt16)) != null) + { + var param18 = (ushort)1234; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestUnsignedInt16)) == param18).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestUnsignedInt32)) != null) + { + var param19 = 1234565789U; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestUnsignedInt32)) == param19).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestUnsignedInt64)) != null) + { + var param20 = 1234567890123456789UL; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestUnsignedInt64)) == param20).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestCharacter)) != null) + { + var param21 = 'a'; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestCharacter)) == param21).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.TestSignedByte)) != null) + { + var param22 = (sbyte)-128; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.TestSignedByte)) == param22).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.EnumU64)) != null) + { + var param23 = EnumU64.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.EnumU64)) == param23).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.EnumU32)) != null) + { + var param24 = EnumU32.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.EnumU32)) == param24).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.EnumU16)) != null) + { + var param25 = EnumU16.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.EnumU16)) == param25).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInDataTypes.EnumS8)) != null) + { + var param26 = EnumS8.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.EnumS8)) == param26).ToList().Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInDataTypes.Enum64))?.GetProviderClrType()) == typeof(long)) + { + var param27 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum64)) == (Enum64)param27).ToList() + .Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInDataTypes.Enum64)) == param27).ToList() + .Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInDataTypes.Enum32))?.GetProviderClrType()) == typeof(int)) + { + var param28 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum32)) == (Enum32)param28).ToList() + .Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInDataTypes.Enum32)) == param28).ToList() + .Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInDataTypes.Enum16))?.GetProviderClrType()) == typeof(short)) + { + var param29 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum16)) == (Enum16)param29).ToList() + .Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInDataTypes.Enum16)) == param29).ToList() + .Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInDataTypes.Enum8))?.GetProviderClrType()) == typeof(byte)) + { + var param30 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInDataTypes.Enum8)) == (Enum8)param30).ToList() + .Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInDataTypes.Enum8)) == param30).ToList() + .Single()); + } + + foreach (var propertyEntry in context.Entry(entity).Properties) + { + if (propertyEntry.Metadata.ValueGenerated != ValueGenerated.Never) + { + continue; + } + + Assert.Equal( + source.Property(propertyEntry.Metadata).CurrentValue, + propertyEntry.CurrentValue); + } + } + + protected new EntityEntry AddTestBuiltInDataTypes(DbSet set) + where TEntity : BuiltInDataTypesBase, new() + { + var entityEntry = set.Add( + new TEntity { Id = 11 }); + + entityEntry.CurrentValues.SetValues( + new BuiltInDataTypes + { + Id = 11, + PartitionId = 1, + TestInt16 = -1234, + TestInt32 = -123456789, + TestInt64 = -1234567890123456789L, + TestDouble = -1.23456789, + TestDecimal = -1234567890.01M, + TestDateTime = Fixture.DefaultDateTime, + TestDateTimeOffset = new DateTimeOffset(new DateTime(), TimeSpan.FromHours(-8.0)), + TestTimeSpan = new TimeSpan(0, 10, 9, 8, 7), + TestDateOnly = new DateOnly(2020, 3, 1), + TestTimeOnly = new TimeOnly(12, 30, 45, 0), + TestSingle = -1.234F, + TestBoolean = true, + TestByte = 255, + TestUnsignedInt16 = 1234, + TestUnsignedInt32 = 1234565789U, + TestUnsignedInt64 = 1234567890123456789UL, + TestCharacter = 'a', + TestSignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + return entityEntry; + } + + public override void Can_query_using_any_nullable_data_type() + { + using var context = CreateContext(); + var source = AddTestBuiltInNullableDataTypes(context.Set()); + + Assert.Equal(1, context.SaveChanges()); + + QueryBuiltInNullableDataTypesTest(source); + } + + public override void Can_query_using_any_data_type_nullable_shadow() + { + using var context = CreateContext(); + var source = AddTestBuiltInNullableDataTypes(context.Set()); + + Assert.Equal(1, context.SaveChanges()); + + QueryBuiltInNullableDataTypesTest(source); + } + + private void QueryBuiltInNullableDataTypesTest(EntityEntry source) + where TEntity : BuiltInNullableDataTypesBase + { + using var context = CreateContext(); + var set = context.Set(); + var entity = set.Where(e => e.Id == 11).ToList().Single(); + var entityType = context.Model.FindEntityType(typeof(TEntity)); + + short? param1 = -1234; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableInt16)) == param1) + .ToList().Single()); + + int? param2 = -123456789; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableInt32)) == param2) + .ToList().Single()); + + long? param3 = -1234567890123456789L; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableInt64)) == param3) + .ToList().Single()); + + double? param4 = -1.23456789; + if (Fixture.StrictEquality) + { + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDouble)) == param4).ToList() + .Single()); + } + else if (Fixture.SupportsDecimalComparisons) + { + double? param4l = -1.234567891; + double? param4h = -1.234567889; + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && (EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDouble)) == param4 + || (EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDouble)) > param4l + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDouble)) < param4h))) + .ToList().Single()); + } + + decimal? param5 = -1234567890.01M; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDecimal)) == param5) + .ToList().Single()); + + DateTime? param6 = Fixture.DefaultDateTime; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDateTime)) == param6) + .ToList().Single()); + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableDateTimeOffset)) != null) + { + DateTimeOffset? param7 = new DateTimeOffset(new DateTime(), TimeSpan.FromHours(-8.0)); + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDateTimeOffset)) + == param7).ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableTimeSpan)) != null) + { + TimeSpan? param8 = new TimeSpan(0, 10, 9, 8, 7); + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableTimeSpan)) + == param8) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableDateOnly)) != null) + { + DateOnly? param9 = new DateOnly(2020, 3, 1); + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableDateOnly)) + == param9) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableTimeOnly)) != null) + { + TimeOnly? param10 = new TimeOnly(12, 30, 45, 0); + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableTimeOnly)) + == param10) + .ToList().Single()); + } + + float? param11 = -1.234F; + if (Fixture.StrictEquality) + { + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableSingle)) == param11).ToList() + .Single()); + } + else if (Fixture.SupportsDecimalComparisons) + { + float? param11l = -1.2341F; + float? param11h = -1.2339F; + Assert.Same( + entity, set.Where( + e => e.Id == 11 + && (EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableSingle)) == param11 + || (EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableSingle)) > param11l + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableSingle)) < param11h))) + .ToList().Single()); + } + + bool? param12 = true; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableBoolean)) == param12) + .ToList().Single()); + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableByte)) != null) + { + byte? param13 = 255; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableByte)) == param13) + .ToList().Single()); + } + + Enum64? param14 = Enum64.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum64)) == param14).ToList() + .Single()); + + Enum32? param15 = Enum32.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum32)) == param15).ToList() + .Single()); + + Enum16? param16 = Enum16.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum16)) == param16).ToList() + .Single()); + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.Enum8)) != null) + { + Enum8? param17 = Enum8.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum8)) == param17).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt16)) != null) + { + ushort? param18 = 1234; + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt16)) + == param18).ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt32)) != null) + { + uint? param19 = 1234565789U; + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt32)) + == param19) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt64)) != null) + { + ulong? param20 = 1234567890123456789UL; + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property( + e, nameof(BuiltInNullableDataTypes.TestNullableUnsignedInt64)) + == param20).ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableCharacter)) != null) + { + char? param21 = 'a'; + Assert.Same( + entity, + set.Where( + e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableCharacter)) == param21) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.TestNullableSignedByte)) != null) + { + sbyte? param22 = -128; + Assert.Same( + entity, + set.Where( + e => e.Id == 11 + && EF.Property(e, nameof(BuiltInNullableDataTypes.TestNullableSignedByte)) + == param22) + .ToList().Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.EnumU64)) != null) + { + var param23 = EnumU64.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.EnumU64)) == param23).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.EnumU32)) != null) + { + var param24 = EnumU32.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.EnumU32)) == param24).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.EnumU16)) != null) + { + var param25 = EnumU16.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.EnumU16)) == param25).ToList() + .Single()); + } + + if (entityType.FindProperty(nameof(BuiltInNullableDataTypes.EnumS8)) != null) + { + var param26 = EnumS8.SomeValue; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.EnumS8)) == param26).ToList() + .Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInNullableDataTypes.Enum64))?.GetProviderClrType()) + == typeof(long)) + { + int? param27 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum64)) == (Enum64)param27) + .ToList().Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInNullableDataTypes.Enum64)) == param27) + .ToList().Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInNullableDataTypes.Enum32))?.GetProviderClrType()) + == typeof(int)) + { + int? param28 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum32)) == (Enum32)param28) + .ToList().Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInNullableDataTypes.Enum32)) == param28) + .ToList().Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInNullableDataTypes.Enum16))?.GetProviderClrType()) + == typeof(short)) + { + int? param29 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum16)) == (Enum16)param29) + .ToList().Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInNullableDataTypes.Enum16)) == param29) + .ToList().Single()); + } + + if (UnwrapNullableType(entityType.FindProperty(nameof(BuiltInNullableDataTypes.Enum8))?.GetProviderClrType()) + == typeof(byte)) + { + int? param30 = 1; + Assert.Same( + entity, + set.Where(e => e.Id == 11 && EF.Property(e, nameof(BuiltInNullableDataTypes.Enum8)) == (Enum8)param30) + .ToList().Single()); + Assert.Same( + entity, + set.Where(e => e.Id == 11 && (int)EF.Property(e, nameof(BuiltInNullableDataTypes.Enum8)) == param30) + .ToList().Single()); + } + + foreach (var propertyEntry in context.Entry(entity).Properties) + { + if (propertyEntry.Metadata.ValueGenerated != ValueGenerated.Never) + { + continue; + } + + Assert.Equal( + source.Property(propertyEntry.Metadata).CurrentValue, + propertyEntry.CurrentValue); + } + } + + protected new virtual EntityEntry AddTestBuiltInNullableDataTypes(DbSet set) + where TEntity : BuiltInNullableDataTypesBase, new() + { + var entityEntry = set.Add( + new TEntity { Id = 11 }); + + entityEntry.CurrentValues.SetValues( + new BuiltInNullableDataTypes + { + Id = 11, + PartitionId = 1, + TestNullableInt16 = -1234, + TestNullableInt32 = -123456789, + TestNullableInt64 = -1234567890123456789L, + TestNullableDouble = -1.23456789, + TestNullableDecimal = -1234567890.01M, + TestNullableDateTime = Fixture.DefaultDateTime, + TestNullableDateTimeOffset = new DateTimeOffset(new DateTime(), TimeSpan.FromHours(-8.0)), + TestNullableTimeSpan = new TimeSpan(0, 10, 9, 8, 7), + TestNullableDateOnly = new DateOnly(2020, 3, 1), + TestNullableTimeOnly = new TimeOnly(12, 30, 45, 0), + TestNullableSingle = -1.234F, + TestNullableBoolean = true, + TestNullableByte = 255, + TestNullableUnsignedInt16 = 1234, + TestNullableUnsignedInt32 = 1234565789U, + TestNullableUnsignedInt64 = 1234567890123456789UL, + TestNullableCharacter = 'a', + TestNullableSignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + return entityEntry; + } + + + + private void AssertEqualIfMapped(IEntityType entityType, T expected, Expression> actualExpression) + { + if (entityType.FindProperty(((MemberExpression)actualExpression.Body).Member.Name) != null) + { + var actual = actualExpression.Compile()(); + var type = UnwrapNullableEnumType(typeof(T)); + if (IsSignedInteger(type)) + { + Assert.True(Equal(Convert.ToInt64(expected), Convert.ToInt64(actual)), $"Expected:\t{expected}\r\nActual:\t{actual}"); + } + else if (IsUnsignedInteger(type)) + { + Assert.True(Equal(Convert.ToUInt64(expected), Convert.ToUInt64(actual)), $"Expected:\t{expected}\r\nActual:\t{actual}"); + } + else if (type == typeof(DateTime)) + { + Assert.True( + Equal((DateTime)(object)expected, (DateTime)(object)actual), $"Expected:\t{expected:O}\r\nActual:\t{actual:O}"); + } + else if (type == typeof(DateTimeOffset)) + { + Assert.True( + Equal((DateTimeOffset)(object)expected, (DateTimeOffset)(object)actual), + $"Expected:\t{expected:O}\r\nActual:\t{actual:O}"); + } + else + { + Assert.Equal(expected, actual); + } + } + } + + private bool Equal(long left, long right) + { + if (left >= 0 + && right >= 0) + { + return Equal((ulong)left, (ulong)right); + } + + if (left < 0 + && right < 0) + { + return Equal((ulong)-left, (ulong)-right); + } + + return false; + } + + private bool Equal(ulong left, ulong right) + { + if (Fixture.IntegerPrecision < 64) + { + var largestPrecise = 1ul << Fixture.IntegerPrecision; + while (left > largestPrecise) + { + left >>= 1; + right >>= 1; + } + } + + return left == right; + } + + private bool Equal(DateTime left, DateTime right) + => left.Equals(right) && (!Fixture.PreservesDateTimeKind || left.Kind == right.Kind); + + private bool Equal(DateTimeOffset left, DateTimeOffset right) + => left.EqualsExact(right); + + private static Type UnwrapNullableType(Type type) + => type == null ? null : Nullable.GetUnderlyingType(type) ?? type; + + private static bool IsSignedInteger(Type type) + => type == typeof(int) + || type == typeof(long) + || type == typeof(short) + || type == typeof(sbyte); + + private static bool IsUnsignedInteger(Type type) + => type == typeof(byte) + || type == typeof(uint) + || type == typeof(ulong) + || type == typeof(ushort) + || type == typeof(char); + public class ConvertToProviderTypesJetFixture : ConvertToProviderTypesFixtureBase { public override bool StrictEquality => true; diff --git a/test/EFCore.Jet.FunctionalTests/CustomConvertersJetTest.cs b/test/EFCore.Jet.FunctionalTests/CustomConvertersJetTest.cs index ed8a30c..4573915 100644 --- a/test/EFCore.Jet.FunctionalTests/CustomConvertersJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/CustomConvertersJetTest.cs @@ -2,9 +2,11 @@ using System; using System.Linq; +using System.Linq.Expressions; using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -224,6 +226,325 @@ User23059.MessageGroups ---> [nullable varchar] [MaxLength = 255] Assert.Equal(expected, actual, ignoreLineEndingDifferences: true); } + public override void Can_insert_and_read_back_object_backed_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new ObjectBackedDataTypes + { + Id = 101, + PartitionId = 101, + String = "TestString", + Bytes = new byte[] { 10, 9, 8, 7, 6 }, + Int16 = -1234, + Int32 = -123456789, + Int64 = -1234567890123456789L, + Double = -1.23456789, + Decimal = -1234567890.01M, + DateTime = DateTime.Parse("01/01/2000 12:34:56"), + DateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TimeSpan = new TimeSpan(0, 10, 9, 8, 0), + DateOnly = new DateOnly(2020, 3, 1), + TimeOnly = new TimeOnly(12, 30, 45, 0), + Single = -1.234F, + Boolean = false, + Byte = 255, + UnsignedInt16 = 1234, + UnsignedInt32 = 1234565789U, + UnsignedInt64 = 1234567890123456789UL, + Character = 'a', + SignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(ObjectBackedDataTypes)); + AssertEqualIfMapped(entityType, "TestString", () => dt.String); + AssertEqualIfMapped(entityType, new byte[] { 10, 9, 8, 7, 6 }, () => dt.Bytes); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.Int16); + AssertEqualIfMapped(entityType, -123456789, () => dt.Int32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.Double); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.Decimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56"), () => dt.DateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.DateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.DateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.Single); + AssertEqualIfMapped(entityType, false, () => dt.Boolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.Byte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.UnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.UnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.UnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.Character); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.SignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_insert_and_read_back_nullable_backed_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new NullableBackedDataTypes + { + Id = 101, + PartitionId = 101, + Int16 = -1234, + Int32 = -123456789, + Int64 = -1234567890123456789L, + Double = -1.23456789, + Decimal = -1234567890.01M, + DateTime = DateTime.Parse("01/01/2000 12:34:56"), + DateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TimeSpan = new TimeSpan(0, 10, 9, 8, 0), + DateOnly = new DateOnly(2020, 3, 1), + TimeOnly = new TimeOnly(12, 30, 45, 0), + Single = -1.234F, + Boolean = false, + Byte = 255, + UnsignedInt16 = 1234, + UnsignedInt32 = 1234565789U, + UnsignedInt64 = 1234567890123456789UL, + Character = 'a', + SignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(NullableBackedDataTypes)); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.Int16); + AssertEqualIfMapped(entityType, -123456789, () => dt.Int32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.Double); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.Decimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56"), () => dt.DateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.DateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.DateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.Single); + AssertEqualIfMapped(entityType, false, () => dt.Boolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.Byte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.UnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.UnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.UnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.Character); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.SignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + public override void Can_insert_and_read_back_non_nullable_backed_data_types() + { + using (var context = CreateContext()) + { + context.Set().Add( + new NonNullableBackedDataTypes + { + Id = 101, + PartitionId = 101, + Int16 = -1234, + Int32 = -123456789, + Int64 = -1234567890123456789L, + Double = -1.23456789, + Decimal = -1234567890.01M, + DateTime = DateTime.Parse("01/01/2000 12:34:56"), + DateTimeOffset = new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0)), + TimeSpan = new TimeSpan(0, 10, 9, 8, 0), + DateOnly = new DateOnly(2020, 3, 1), + TimeOnly = new TimeOnly(12, 30, 45, 0), + Single = -1.234F, + Boolean = true, + Byte = 255, + UnsignedInt16 = 1234, + UnsignedInt32 = 1234565789U, + UnsignedInt64 = 1234567890123456789UL, + Character = 'a', + SignedByte = -128, + Enum64 = Enum64.SomeValue, + Enum32 = Enum32.SomeValue, + Enum16 = Enum16.SomeValue, + Enum8 = Enum8.SomeValue, + EnumU64 = EnumU64.SomeValue, + EnumU32 = EnumU32.SomeValue, + EnumU16 = EnumU16.SomeValue, + EnumS8 = EnumS8.SomeValue + }); + + Assert.Equal(1, context.SaveChanges()); + } + + using (var context = CreateContext()) + { + var dt = context.Set().Where(ndt => ndt.Id == 101).ToList().Single(); + + var entityType = context.Model.FindEntityType(typeof(NonNullableBackedDataTypes)); + AssertEqualIfMapped(entityType, (short)-1234, () => dt.Int16); + AssertEqualIfMapped(entityType, -123456789, () => dt.Int32); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1234567890123456789L, () => dt.Int64); + AssertEqualIfMapped(entityType, -1.23456789, () => dt.Double); + AssertEqualIfMapped(entityType, -1234567890.01M, () => dt.Decimal); + AssertEqualIfMapped(entityType, DateTime.Parse("01/01/2000 12:34:56"), () => dt.DateTime); + AssertEqualIfMapped( + entityType, JetTestHelpers.GetExpectedValue(new DateTimeOffset(DateTime.Parse("01/01/2000 12:34:56"), TimeSpan.FromHours(-8.0))), + () => dt.DateTimeOffset); + AssertEqualIfMapped(entityType, new TimeSpan(0, 10, 9, 8, 0), () => dt.TimeSpan); + AssertEqualIfMapped(entityType, new DateOnly(2020, 3, 1), () => dt.DateOnly); + AssertEqualIfMapped(entityType, new TimeOnly(12, 30, 45, 0), () => dt.TimeOnly); + AssertEqualIfMapped(entityType, -1.234F, () => dt.Single); + AssertEqualIfMapped(entityType, true, () => dt.Boolean); + AssertEqualIfMapped(entityType, (byte)255, () => dt.Byte); + AssertEqualIfMapped(entityType, Enum64.SomeValue, () => dt.Enum64); + AssertEqualIfMapped(entityType, Enum32.SomeValue, () => dt.Enum32); + AssertEqualIfMapped(entityType, Enum16.SomeValue, () => dt.Enum16); + AssertEqualIfMapped(entityType, Enum8.SomeValue, () => dt.Enum8); + AssertEqualIfMapped(entityType, (ushort)1234, () => dt.UnsignedInt16); + AssertEqualIfMapped(entityType, 1234565789U, () => dt.UnsignedInt32); + AssertEqualIfMapped(entityType, 1234567890123456789UL, () => dt.UnsignedInt64); + AssertEqualIfMapped(entityType, 'a', () => dt.Character); + AssertEqualIfMapped(entityType, (sbyte)-128, () => dt.SignedByte); + AssertEqualIfMapped(entityType, EnumU64.SomeValue, () => dt.EnumU64); + AssertEqualIfMapped(entityType, EnumU32.SomeValue, () => dt.EnumU32); + AssertEqualIfMapped(entityType, EnumU16.SomeValue, () => dt.EnumU16); + AssertEqualIfMapped(entityType, EnumS8.SomeValue, () => dt.EnumS8); + } + } + + private void AssertEqualIfMapped(IEntityType entityType, T expected, Expression> actualExpression) + { + if (entityType.FindProperty(((MemberExpression)actualExpression.Body).Member.Name) != null) + { + var actual = actualExpression.Compile()(); + var type = UnwrapNullableEnumType(typeof(T)); + if (IsSignedInteger(type)) + { + Assert.True(Equal(Convert.ToInt64(expected), Convert.ToInt64(actual)), $"Expected:\t{expected}\r\nActual:\t{actual}"); + } + else if (IsUnsignedInteger(type)) + { + Assert.True(Equal(Convert.ToUInt64(expected), Convert.ToUInt64(actual)), $"Expected:\t{expected}\r\nActual:\t{actual}"); + } + else if (type == typeof(DateTime)) + { + Assert.True( + Equal((DateTime)(object)expected, (DateTime)(object)actual), $"Expected:\t{expected:O}\r\nActual:\t{actual:O}"); + } + else if (type == typeof(DateTimeOffset)) + { + Assert.True( + Equal((DateTimeOffset)(object)expected, (DateTimeOffset)(object)actual), + $"Expected:\t{expected:O}\r\nActual:\t{actual:O}"); + } + else + { + Assert.Equal(expected, actual); + } + } + } + + private bool Equal(long left, long right) + { + if (left >= 0 + && right >= 0) + { + return Equal((ulong)left, (ulong)right); + } + + if (left < 0 + && right < 0) + { + return Equal((ulong)-left, (ulong)-right); + } + + return false; + } + + private bool Equal(ulong left, ulong right) + { + if (Fixture.IntegerPrecision < 64) + { + var largestPrecise = 1ul << Fixture.IntegerPrecision; + while (left > largestPrecise) + { + left >>= 1; + right >>= 1; + } + } + + return left == right; + } + + private bool Equal(DateTime left, DateTime right) + => left.Equals(right) && (!Fixture.PreservesDateTimeKind || left.Kind == right.Kind); + + private bool Equal(DateTimeOffset left, DateTimeOffset right) + => left.EqualsExact(right); + + private static Type UnwrapNullableType(Type type) + => type == null ? null : Nullable.GetUnderlyingType(type) ?? type; + + private static bool IsSignedInteger(Type type) + => type == typeof(int) + || type == typeof(long) + || type == typeof(short) + || type == typeof(sbyte); + + private static bool IsUnsignedInteger(Type type) + => type == typeof(byte) + || type == typeof(uint) + || type == typeof(ulong) + || type == typeof(ushort) + || type == typeof(char); + public class CustomConvertersJetFixture : CustomConvertersFixtureBase { public override bool StrictEquality => true;