From 5d5b1f12594e72400c2fd83a58971da8e27dcf1e Mon Sep 17 00:00:00 2001 From: maumar Date: Wed, 31 Jul 2024 02:02:13 -0700 Subject: [PATCH] Promote Json tests to Core so that they can be utilized for Cosmos. --- .../Query/JsonQueryCosmosFixture.cs | 575 ++++ .../Query/JsonQueryCosmosTest.cs | 2336 +++++++++++++++++ .../InMemoryComplianceTest.cs | 1 + .../Query/JsonQueryRelationalFixture.cs | 50 + .../Query/JsonQueryRelationalTestBase.cs | 605 +++++ .../Query/JsonQueryFixtureBase.cs | 46 +- .../Query/JsonQueryTestBase.cs | 648 +---- .../TestModels/JsonQuery/EntityBasic.cs | 0 .../JsonQuery/JsonEntityAllTypes.cs | 0 .../TestModels/JsonQuery/JsonEntityBasic.cs | 0 .../JsonQuery/JsonEntityBasicForCollection.cs | 0 .../JsonQuery/JsonEntityBasicForReference.cs | 0 .../JsonQuery/JsonEntityConverters.cs | 0 .../JsonQuery/JsonEntityCustomNaming.cs | 0 .../JsonQuery/JsonEntityInheritanceBase.cs | 0 .../JsonQuery/JsonEntityInheritanceDerived.cs | 0 .../JsonQuery/JsonEntitySingleOwned.cs | 0 .../TestModels/JsonQuery/JsonEnum.cs | 0 .../TestModels/JsonQuery/JsonOwnedAllTypes.cs | 0 .../TestModels/JsonQuery/JsonOwnedBranch.cs | 0 .../JsonQuery/JsonOwnedConverters.cs | 0 .../JsonQuery/JsonOwnedCustomNameBranch.cs | 0 .../JsonQuery/JsonOwnedCustomNameRoot.cs | 0 .../TestModels/JsonQuery/JsonOwnedLeaf.cs | 0 .../TestModels/JsonQuery/JsonOwnedRoot.cs | 0 .../TestModels/JsonQuery/JsonQueryContext.cs | 0 .../TestModels/JsonQuery/JsonQueryData.cs | 0 .../Query/JsonQuerySqlServerFixture.cs | 2 +- .../Query/JsonQuerySqlServerTest.cs | 2 +- .../Query/JsonQuerySqliteFixture.cs | 2 +- .../Query/JsonQuerySqliteTest.cs | 2 +- 31 files changed, 3623 insertions(+), 646 deletions(-) create mode 100644 test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosFixture.cs create mode 100644 test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosTest.cs create mode 100644 test/EFCore.Relational.Specification.Tests/Query/JsonQueryRelationalFixture.cs create mode 100644 test/EFCore.Relational.Specification.Tests/Query/JsonQueryRelationalTestBase.cs rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/Query/JsonQueryFixtureBase.cs (97%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/Query/JsonQueryTestBase.cs (80%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/EntityBasic.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonEntityAllTypes.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonEntityBasic.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonEntityBasicForCollection.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonEntityBasicForReference.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonEntityConverters.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonEntityCustomNaming.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonEntityInheritanceBase.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonEntityInheritanceDerived.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonEntitySingleOwned.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonEnum.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonOwnedAllTypes.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonOwnedBranch.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonOwnedConverters.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonOwnedCustomNameBranch.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonOwnedCustomNameRoot.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonOwnedLeaf.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonOwnedRoot.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonQueryContext.cs (100%) rename test/{EFCore.Relational.Specification.Tests => EFCore.Specification.Tests}/TestModels/JsonQuery/JsonQueryData.cs (100%) diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosFixture.cs b/test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosFixture.cs new file mode 100644 index 00000000000..8ac39ba8e6c --- /dev/null +++ b/test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosFixture.cs @@ -0,0 +1,575 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.EntityFrameworkCore.TestModels.JsonQuery; + +namespace Microsoft.EntityFrameworkCore.Query; + +#nullable disable + +public class JsonQueryCosmosFixture : JsonQueryFixtureBase +{ + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + + protected override ITestStoreFactory TestStoreFactory + => CosmosTestStoreFactory.Instance; + + public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) + => base.AddOptions(builder.ConfigureWarnings( + w => w.Ignore(CosmosEventId.NoPartitionKeyDefined))); + + public Task NoSyncTest(bool async, Func testCode) + => CosmosTestHelpers.Instance.NoSyncTest(async, testCode); + + public void NoSyncTest(Action testCode) + => CosmosTestHelpers.Instance.NoSyncTest(testCode); + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder.Entity() + .ToContainer("JsonEntities") + .IncludeDiscriminatorInJsonId() + .HasDiscriminator("Discriminator").HasValue("Basic"); + + modelBuilder.Entity().ToContainer("EntitiesBasic"); + + modelBuilder.Entity().ToContainer("EntitiesBasicForReference"); + + modelBuilder.Entity().ToContainer("EntitiesBasicForCollection"); + modelBuilder.Entity().OwnsOne( + x => x.OwnedReferenceRoot, b => + { + b.OwnsOne( + x => x.OwnedReferenceBranch, bb => + { + //issue #34026 + bb.Ignore(x => x.Enums); + bb.Ignore(x => x.NullableEnums); + }); + + b.OwnsMany( + x => x.OwnedCollectionBranch, bb => + { + //issue #34026 + bb.Ignore(x => x.Enums); + bb.Ignore(x => x.NullableEnums); + }); + }); + + modelBuilder.Entity().OwnsMany( + x => x.OwnedCollectionRoot, b => + { + b.OwnsOne( + x => x.OwnedReferenceBranch, bb => + { + //issue #34026 + bb.Ignore(x => x.Enums); + bb.Ignore(x => x.NullableEnums); + }); + + b.OwnsMany( + x => x.OwnedCollectionBranch, bb => + { + //issue #34026 + bb.Ignore(x => x.Enums); + bb.Ignore(x => x.NullableEnums); + }); + }); + + modelBuilder.Entity() + .ToContainer("JsonEntities") + .IncludeDiscriminatorInJsonId() + .HasDiscriminator("Discriminator").HasValue("CustomNaming"); + + modelBuilder.Entity() + .ToContainer("JsonEntities") + .IncludeDiscriminatorInJsonId() + .HasDiscriminator("Discriminator").HasValue("SingleOwned"); + + modelBuilder.Entity().OwnsMany( + x => x.OwnedCollection, b => + { + b.Ignore(x => x.Parent); + }); + + modelBuilder.Entity().ToContainer("JsonEntitiesInheritance"); + + modelBuilder.Entity( + b => + { + b.OwnsOne( + x => x.ReferenceOnBase, bb => + { + //issue #34026 + bb.Ignore(x => x.Enums); + bb.Ignore(x => x.NullableEnums); + }); + + b.OwnsMany( + x => x.CollectionOnBase, bb => + { + //issue #34026 + bb.Ignore(x => x.Enums); + bb.Ignore(x => x.NullableEnums); + }); + }); + + modelBuilder.Entity( + b => + { + b.OwnsOne( + x => x.ReferenceOnDerived, bb => + { + //issue #34026 + bb.Ignore(x => x.Enums); + bb.Ignore(x => x.NullableEnums); + }); + + b.OwnsMany( + x => x.CollectionOnDerived, bb => + { + //issue #34026 + bb.Ignore(x => x.Enums); + bb.Ignore(x => x.NullableEnums); + }); + }); + + modelBuilder.Entity() + .ToContainer("JsonEntities") + .IncludeDiscriminatorInJsonId() + .HasDiscriminator("Discriminator").HasValue("AllTypes"); + + modelBuilder.Entity().OwnsOne( + x => x.Reference, b => + { + //issue #34026 + b.Ignore(x => x.TestEnumCollection); + b.Ignore(x => x.TestEnumWithIntConverterCollection); + b.Ignore(x => x.TestGuidCollection); + b.Ignore(x => x.TestNullableEnumCollection); + b.Ignore(x => x.TestNullableEnumCollectionCollection); + b.Ignore(x => x.TestNullableEnumWithConverterThatHandlesNullsCollection); + b.Ignore(x => x.TestNullableEnumWithIntConverterCollection); + b.Ignore(x => x.TestNullableEnumWithIntConverterCollectionCollection); + }); + modelBuilder.Entity().OwnsMany( + x => x.Collection, b => + { + //issue #34026 + b.Ignore(x => x.TestEnumCollection); + b.Ignore(x => x.TestEnumWithIntConverterCollection); + b.Ignore(x => x.TestGuidCollection); + b.Ignore(x => x.TestNullableEnumCollection); + b.Ignore(x => x.TestNullableEnumCollectionCollection); + b.Ignore(x => x.TestNullableEnumWithConverterThatHandlesNullsCollection); + b.Ignore(x => x.TestNullableEnumWithIntConverterCollection); + b.Ignore(x => x.TestNullableEnumWithIntConverterCollectionCollection); + }); + + //issue #34026 + modelBuilder.Entity().Ignore(x => x.TestEnumCollection); + modelBuilder.Entity().Ignore(x => x.TestEnumWithIntConverterCollection); + modelBuilder.Entity().Ignore(x => x.TestGuidCollection); + modelBuilder.Entity().Ignore(x => x.TestNullableEnumCollection); + modelBuilder.Entity().Ignore(x => x.TestNullableEnumCollectionCollection); + modelBuilder.Entity().Ignore(x => x.TestNullableEnumWithConverterThatHandlesNullsCollection); + modelBuilder.Entity().Ignore(x => x.TestNullableEnumWithIntConverterCollection); + modelBuilder.Entity().Ignore(x => x.TestNullableEnumWithIntConverterCollectionCollection); + + modelBuilder.Entity() + .ToContainer("JsonEntities") + .IncludeDiscriminatorInJsonId() + .HasDiscriminator("Discriminator").HasValue("Converters"); + } + + // TODO: remove all this infra once we support converters on cosmos + // also undo virtual on base + // issue #34026 + public override IReadOnlyDictionary EntityAsserters { get; } = new Dictionary> + { + { + typeof(EntityBasic), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (EntityBasic)e; + var aa = (EntityBasic)a; + + Assert.Equal(ee.Id, aa.Id); + Assert.Equal(ee.Name, aa.Name); + } + } + }, + { + typeof(JsonEntityBasic), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonEntityBasic)e; + var aa = (JsonEntityBasic)a; + + Assert.Equal(ee.Id, aa.Id); + Assert.Equal(ee.Name, aa.Name); + + if (ee.OwnedReferenceRoot is not null || aa.OwnedReferenceRoot is not null) + { + AssertCosmosOwnedRoot(ee.OwnedReferenceRoot, aa.OwnedReferenceRoot); + + Assert.Equal(ee.OwnedCollectionRoot.Count, aa.OwnedCollectionRoot.Count); + for (var i = 0; i < ee.OwnedCollectionRoot.Count; i++) + { + AssertCosmosOwnedRoot(ee.OwnedCollectionRoot[i], aa.OwnedCollectionRoot[i]); + } + } + } + } + }, + { + typeof(JsonEntityBasicForReference), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonEntityBasicForReference)e; + var aa = (JsonEntityBasicForReference)a; + + Assert.Equal(ee.Id, aa.Id); + Assert.Equal(ee.Name, aa.Name); + Assert.Equal(ee.ParentId, aa.ParentId); + } + } + }, + { + typeof(JsonEntityBasicForCollection), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonEntityBasicForCollection)e; + var aa = (JsonEntityBasicForCollection)a; + + Assert.Equal(ee.Id, aa.Id); + Assert.Equal(ee.Name, aa.Name); + Assert.Equal(ee.ParentId, aa.ParentId); + } + } + }, + { + typeof(JsonOwnedRoot), (e, a) => + { + if (a != null) + { + var ee = (JsonOwnedRoot)e; + var aa = (JsonOwnedRoot)a; + + AssertCosmosOwnedRoot(ee, aa); + } + } + }, + { + typeof(JsonOwnedBranch), (e, a) => + { + if (a != null) + { + var ee = (JsonOwnedBranch)e; + var aa = (JsonOwnedBranch)a; + + AssertCosmosOwnedBranch(ee, aa); + } + } + }, + { + typeof(JsonOwnedLeaf), (e, a) => + { + if (a != null) + { + var ee = (JsonOwnedLeaf)e; + var aa = (JsonOwnedLeaf)a; + + AssertOwnedLeaf(ee, aa); + } + } + }, + { + typeof(JsonEntityCustomNaming), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonEntityCustomNaming)e; + var aa = (JsonEntityCustomNaming)a; + + Assert.Equal(ee.Id, aa.Id); + Assert.Equal(ee.Title, aa.Title); + + AssertCustomNameRoot(ee.OwnedReferenceRoot, aa.OwnedReferenceRoot); + + Assert.Equal(ee.OwnedCollectionRoot.Count, aa.OwnedCollectionRoot.Count); + for (var i = 0; i < ee.OwnedCollectionRoot.Count; i++) + { + AssertCustomNameRoot(ee.OwnedCollectionRoot[i], aa.OwnedCollectionRoot[i]); + } + } + } + }, + { + typeof(JsonOwnedCustomNameRoot), (e, a) => + { + if (a != null) + { + var ee = (JsonOwnedCustomNameRoot)e; + var aa = (JsonOwnedCustomNameRoot)a; + + AssertCustomNameRoot(ee, aa); + } + } + }, + { + typeof(JsonOwnedCustomNameBranch), (e, a) => + { + if (a != null) + { + var ee = (JsonOwnedCustomNameBranch)e; + var aa = (JsonOwnedCustomNameBranch)a; + + AssertCustomNameBranch(ee, aa); + } + } + }, + { + typeof(JsonEntitySingleOwned), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonEntitySingleOwned)e; + var aa = (JsonEntitySingleOwned)a; + + Assert.Equal(ee.Id, aa.Id); + Assert.Equal(ee.Name, aa.Name); + + Assert.Equal(ee.OwnedCollection?.Count ?? 0, aa.OwnedCollection?.Count ?? 0); + for (var i = 0; i < ee.OwnedCollection.Count; i++) + { + AssertOwnedLeaf(ee.OwnedCollection[i], aa.OwnedCollection[i]); + } + } + } + }, + { + typeof(JsonEntityInheritanceBase), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonEntityInheritanceBase)e; + var aa = (JsonEntityInheritanceBase)a; + + Assert.Equal(ee.Id, aa.Id); + Assert.Equal(ee.Name, aa.Name); + + AssertCosmosOwnedBranch(ee.ReferenceOnBase, aa.ReferenceOnBase); + Assert.Equal(ee.CollectionOnBase?.Count ?? 0, aa.CollectionOnBase?.Count ?? 0); + for (var i = 0; i < ee.CollectionOnBase.Count; i++) + { + AssertCosmosOwnedBranch(ee.CollectionOnBase[i], aa.CollectionOnBase[i]); + } + } + } + }, + { + typeof(JsonEntityInheritanceDerived), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonEntityInheritanceDerived)e; + var aa = (JsonEntityInheritanceDerived)a; + + Assert.Equal(ee.Id, aa.Id); + Assert.Equal(ee.Name, aa.Name); + Assert.Equal(ee.Fraction, aa.Fraction); + + AssertCosmosOwnedBranch(ee.ReferenceOnBase, aa.ReferenceOnBase); + AssertCosmosOwnedBranch(ee.ReferenceOnDerived, aa.ReferenceOnDerived); + + Assert.Equal(ee.CollectionOnBase?.Count ?? 0, aa.CollectionOnBase?.Count ?? 0); + for (var i = 0; i < ee.CollectionOnBase.Count; i++) + { + AssertCosmosOwnedBranch(ee.CollectionOnBase[i], aa.CollectionOnBase[i]); + } + + Assert.Equal(ee.CollectionOnDerived?.Count ?? 0, aa.CollectionOnDerived?.Count ?? 0); + for (var i = 0; i < ee.CollectionOnDerived.Count; i++) + { + AssertCosmosOwnedBranch(ee.CollectionOnDerived[i], aa.CollectionOnDerived[i]); + } + } + } + }, + { + typeof(JsonEntityAllTypes), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonEntityAllTypes)e; + var aa = (JsonEntityAllTypes)a; + + Assert.Equal(ee.Id, aa.Id); + + AssertCosmosAllTypes(ee.Reference, aa.Reference); + + Assert.Equal(ee.Collection?.Count ?? 0, aa.Collection?.Count ?? 0); + for (var i = 0; i < ee.Collection.Count; i++) + { + AssertCosmosAllTypes(ee.Collection[i], aa.Collection[i]); + } + } + } + }, + { + typeof(JsonOwnedAllTypes), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonOwnedAllTypes)e; + var aa = (JsonOwnedAllTypes)a; + + AssertCosmosAllTypes(ee, aa); + } + } + }, + { + typeof(JsonEntityConverters), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonEntityConverters)e; + var aa = (JsonEntityConverters)a; + + Assert.Equal(ee.Id, aa.Id); + + AssertCosmosConverters(ee.Reference, aa.Reference); + } + } + }, + { + typeof(JsonOwnedConverters), (e, a) => + { + Assert.Equal(e == null, a == null); + if (a != null) + { + var ee = (JsonOwnedConverters)e; + var aa = (JsonOwnedConverters)a; + + AssertCosmosConverters(ee, aa); + } + } + }, + }.ToDictionary(e => e.Key, e => (object)e.Value); + + public static void AssertCosmosOwnedRoot(JsonOwnedRoot expected, JsonOwnedRoot actual) + { + Assert.Equal(expected.Name, actual.Name); + Assert.Equal(expected.Number, actual.Number); + Assert.Equal(expected.Names, actual.Names); + Assert.Equal(expected.Numbers, actual.Numbers); + + AssertCosmosOwnedBranch(expected.OwnedReferenceBranch, actual.OwnedReferenceBranch); + Assert.Equal(expected.OwnedCollectionBranch.Count, actual.OwnedCollectionBranch.Count); + for (var i = 0; i < expected.OwnedCollectionBranch.Count; i++) + { + AssertCosmosOwnedBranch(expected.OwnedCollectionBranch[i], actual.OwnedCollectionBranch[i]); + } + } + + public static void AssertCosmosOwnedBranch(JsonOwnedBranch expected, JsonOwnedBranch actual) + { + Assert.Equal(expected.Date, actual.Date); + Assert.Equal(expected.Fraction, actual.Fraction); + Assert.Equal(expected.Enum, actual.Enum); + Assert.Equal(expected.NullableEnum, actual.NullableEnum); + + AssertOwnedLeaf(expected.OwnedReferenceLeaf, actual.OwnedReferenceLeaf); + Assert.Equal(expected.OwnedCollectionLeaf.Count, actual.OwnedCollectionLeaf.Count); + for (var i = 0; i < expected.OwnedCollectionLeaf.Count; i++) + { + AssertOwnedLeaf(expected.OwnedCollectionLeaf[i], actual.OwnedCollectionLeaf[i]); + } + } + + public static void AssertCosmosAllTypes(JsonOwnedAllTypes expected, JsonOwnedAllTypes actual) + { + Assert.Equal(expected.TestDefaultString, actual.TestDefaultString); + Assert.Equal(expected.TestMaxLengthString, actual.TestMaxLengthString); + Assert.Equal(expected.TestBoolean, actual.TestBoolean); + Assert.Equal(expected.TestCharacter, actual.TestCharacter); + Assert.Equal(expected.TestDateTime, actual.TestDateTime); + Assert.Equal(expected.TestDateTimeOffset, actual.TestDateTimeOffset); + Assert.Equal(expected.TestDouble, actual.TestDouble); + Assert.Equal(expected.TestGuid, actual.TestGuid); + Assert.Equal(expected.TestInt16, actual.TestInt16); + Assert.Equal(expected.TestInt32, actual.TestInt32); + Assert.Equal(expected.TestInt64, actual.TestInt64); + Assert.Equal(expected.TestSignedByte, actual.TestSignedByte); + Assert.Equal(expected.TestSingle, actual.TestSingle); + Assert.Equal(expected.TestTimeSpan, actual.TestTimeSpan); + Assert.Equal(expected.TestDateOnly, actual.TestDateOnly); + Assert.Equal(expected.TestTimeOnly, actual.TestTimeOnly); + Assert.Equal(expected.TestUnsignedInt16, actual.TestUnsignedInt16); + Assert.Equal(expected.TestUnsignedInt32, actual.TestUnsignedInt32); + Assert.Equal(expected.TestUnsignedInt64, actual.TestUnsignedInt64); + Assert.Equal(expected.TestNullableInt32, actual.TestNullableInt32); + Assert.Equal(expected.TestEnum, actual.TestEnum); + Assert.Equal(expected.TestEnumWithIntConverter, actual.TestEnumWithIntConverter); + Assert.Equal(expected.TestNullableEnum, actual.TestNullableEnum); + Assert.Equal(expected.TestNullableEnumWithIntConverter, actual.TestNullableEnumWithIntConverter); + Assert.Equal(expected.TestNullableEnumWithConverterThatHandlesNulls, actual.TestNullableEnumWithConverterThatHandlesNulls); + + AssertPrimitiveCollection(expected.TestDefaultStringCollection, actual.TestDefaultStringCollection); + AssertPrimitiveCollection(expected.TestMaxLengthStringCollection, actual.TestMaxLengthStringCollection); + AssertPrimitiveCollection(expected.TestBooleanCollection, actual.TestBooleanCollection); + AssertPrimitiveCollection(expected.TestCharacterCollection, actual.TestCharacterCollection); + AssertPrimitiveCollection(expected.TestDateTimeCollection, actual.TestDateTimeCollection); + AssertPrimitiveCollection(expected.TestDateTimeOffsetCollection, actual.TestDateTimeOffsetCollection); + AssertPrimitiveCollection(expected.TestDoubleCollection, actual.TestDoubleCollection); + //AssertPrimitiveCollection(expected.TestGuidCollection, actual.TestGuidCollection); + AssertPrimitiveCollection((IList)expected.TestInt16Collection, (IList)actual.TestInt16Collection); + AssertPrimitiveCollection(expected.TestInt32Collection, actual.TestInt32Collection); + AssertPrimitiveCollection(expected.TestInt64Collection, actual.TestInt64Collection); + AssertPrimitiveCollection(expected.TestSignedByteCollection, actual.TestSignedByteCollection); + AssertPrimitiveCollection(expected.TestSingleCollection, actual.TestSingleCollection); + AssertPrimitiveCollection(expected.TestTimeSpanCollection, actual.TestTimeSpanCollection); + AssertPrimitiveCollection(expected.TestDateOnlyCollection, actual.TestDateOnlyCollection); + AssertPrimitiveCollection(expected.TestTimeOnlyCollection, actual.TestTimeOnlyCollection); + AssertPrimitiveCollection(expected.TestUnsignedInt16Collection, actual.TestUnsignedInt16Collection); + AssertPrimitiveCollection(expected.TestUnsignedInt32Collection, actual.TestUnsignedInt32Collection); + AssertPrimitiveCollection(expected.TestUnsignedInt64Collection, actual.TestUnsignedInt64Collection); + AssertPrimitiveCollection(expected.TestNullableInt32Collection, actual.TestNullableInt32Collection); + //AssertPrimitiveCollection(expected.TestEnumCollection, actual.TestEnumCollection); + //AssertPrimitiveCollection(expected.TestEnumWithIntConverterCollection, actual.TestEnumWithIntConverterCollection); + //AssertPrimitiveCollection(expected.TestNullableEnumCollection, actual.TestNullableEnumCollection); + //AssertPrimitiveCollection(expected.TestNullableEnumWithIntConverterCollection, actual.TestNullableEnumWithIntConverterCollection); + //AssertPrimitiveCollection( + // expected.TestNullableEnumWithConverterThatHandlesNullsCollection, + // actual.TestNullableEnumWithConverterThatHandlesNullsCollection); + } + + public static void AssertCosmosConverters(JsonOwnedConverters expected, JsonOwnedConverters actual) + { + Assert.Equal(expected.BoolConvertedToIntZeroOne, actual.BoolConvertedToIntZeroOne); + Assert.Equal(expected.BoolConvertedToStringTrueFalse, actual.BoolConvertedToStringTrueFalse); + Assert.Equal(expected.BoolConvertedToStringYN, actual.BoolConvertedToStringYN); + Assert.Equal(expected.IntZeroOneConvertedToBool, actual.IntZeroOneConvertedToBool); + Assert.Equal(expected.StringTrueFalseConvertedToBool, actual.StringTrueFalseConvertedToBool); + Assert.Equal(expected.StringYNConvertedToBool, actual.StringYNConvertedToBool); + } +} diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosTest.cs new file mode 100644 index 00000000000..715478c8027 --- /dev/null +++ b/test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosTest.cs @@ -0,0 +1,2336 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Azure.Cosmos; +using Microsoft.EntityFrameworkCore.Cosmos.Internal; +using Microsoft.EntityFrameworkCore.TestModels.JsonQuery; + +namespace Microsoft.EntityFrameworkCore.Query; + +public class JsonQueryCosmosTest : JsonQueryTestBase +{ + private const string NotImplementedBindPropertyMessage + = "Bind property on structural type coming out of scalar subquery"; + + public JsonQueryCosmosTest(JsonQueryCosmosFixture fixture, ITestOutputHelper testOutputHelper) + : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); + } + + public override Task Basic_json_projection_enum_inside_json_entity(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_enum_inside_json_entity(a); + + AssertSql( + """ +SELECT c["Id"], c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["Enum"] +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + [ConditionalTheory] + public override async Task Basic_json_projection_owned_collection_branch(bool async) + { + // Always throws for sync. + if (async) + { + //issue #31696 + await Assert.ThrowsAsync( + () => base.Basic_json_projection_owned_collection_branch(async)); + } + } + + [ConditionalTheory] + public override async Task Basic_json_projection_owned_collection_branch_NoTrackingWithIdentityResolution(bool async) + { + // Always throws for sync. + if (async) + { + //issue #31696 + await Assert.ThrowsAsync( + () => base.Basic_json_projection_owned_collection_branch_NoTrackingWithIdentityResolution(async)); + } + } + + [ConditionalTheory] + public override async Task Basic_json_projection_owned_collection_leaf(bool async) + { + // Always throws for sync. + if (async) + { + //issue #31696 + await Assert.ThrowsAsync( + () => base.Basic_json_projection_owned_collection_leaf(async)); + } + } + + public override Task Basic_json_projection_owned_collection_root(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_collection_root(a); + + // TODO: issue #34067 (?) + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_owned_collection_root_NoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_collection_root_NoTrackingWithIdentityResolution(a); + + // TODO: issue #34067 (?) + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + [ConditionalTheory] + public override Task Basic_json_projection_owned_reference_branch(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_reference_branch(async); + + AssertSql( +""" +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + [ConditionalTheory] + public override Task Basic_json_projection_owned_reference_branch_NoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_reference_branch_NoTrackingWithIdentityResolution(async); + + AssertSql( +""" +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + [ConditionalTheory] + public override Task Basic_json_projection_owned_reference_duplicated(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_reference_duplicated(async); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +ORDER BY c["Id"] +"""); + }); + + [ConditionalTheory] + public override Task Basic_json_projection_owned_reference_duplicated2(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_reference_duplicated2(async); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +ORDER BY c["Id"] +"""); + }); + + [ConditionalTheory] + public override Task Basic_json_projection_owned_reference_duplicated2_NoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_reference_duplicated2_NoTrackingWithIdentityResolution(async); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +ORDER BY c["Id"] +"""); + }); + + [ConditionalTheory] + public override Task Basic_json_projection_owned_reference_duplicated_NoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_reference_duplicated_NoTrackingWithIdentityResolution(async); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +ORDER BY c["Id"] +"""); + }); + + [ConditionalTheory] + public override Task Basic_json_projection_owned_reference_leaf(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_reference_leaf(async); + + AssertSql( +""" +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_owned_reference_root(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_reference_root(a); + + // TODO: issue #34067 (?) + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_owned_reference_root_NoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owned_reference_root_NoTrackingWithIdentityResolution(a); + + // TODO: issue #34067 (?) + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_owner_entity(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owner_entity(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_owner_entity_duplicated(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owner_entity_duplicated(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_owner_entity_duplicated_NoTracking(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owner_entity_duplicated_NoTracking(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "SingleOwned") +"""); + }); + + public override Task Basic_json_projection_owner_entity_duplicated_NoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owner_entity_duplicated_NoTrackingWithIdentityResolution(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "SingleOwned") +"""); + }); + + public override Task Basic_json_projection_owner_entity_NoTracking(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owner_entity_NoTracking(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_owner_entity_NoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owner_entity_NoTrackingWithIdentityResolution(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_owner_entity_twice(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owner_entity_twice(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_owner_entity_twice_NoTracking(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owner_entity_twice_NoTracking(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_owner_entity_twice_NoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_owner_entity_twice_NoTrackingWithIdentityResolution(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Basic_json_projection_scalar(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Basic_json_projection_scalar(a); + + AssertSql( + """ +SELECT VALUE c["OwnedReferenceRoot"]["Name"] +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + [ConditionalTheory(Skip = "issue #34350")] + public override Task Custom_naming_projection_everything(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Custom_naming_projection_everything(a); + + AssertSql(""); + }); + + public override Task Custom_naming_projection_owned_collection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Custom_naming_projection_owned_collection(a); + + // TODO: issue #34067 (?) + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "CustomNaming") +ORDER BY c["Id"] +"""); + }); + + [ConditionalTheory] + public override Task Custom_naming_projection_owned_reference(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Custom_naming_projection_owned_reference(async); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "CustomNaming") +"""); + }); + + public override Task Custom_naming_projection_owned_scalar(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Custom_naming_projection_owned_scalar(a); + + AssertSql( + """ +SELECT VALUE c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["Fraction"] +FROM root c +WHERE (c["Discriminator"] = "CustomNaming") +"""); + }); + + public override Task Custom_naming_projection_owner_entity(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Custom_naming_projection_owner_entity(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "CustomNaming") +"""); + }); + + public override async Task Entity_including_collection_with_json(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Entity_including_collection_with_json(async))).Message; + + Assert.Equal( + CosmosStrings.NonEmbeddedIncludeNotSupported("Navigation: EntityBasic.JsonEntityBasics (List) Collection ToDependent JsonEntityBasic"), + message); + } + + [ConditionalTheory(Skip = "issue #17313")] + public override Task Group_by_FirstOrDefault_on_json_scalar(bool async) + => base.Group_by_FirstOrDefault_on_json_scalar(async); + + [ConditionalTheory(Skip = "issue #17313")] + public override Task Group_by_First_on_json_scalar(bool async) + => base.Group_by_First_on_json_scalar(async); + + [ConditionalTheory(Skip = "issue #17313")] + public override Task Group_by_json_scalar_Orderby_json_scalar_FirstOrDefault(bool async) + => base.Group_by_json_scalar_Orderby_json_scalar_FirstOrDefault(async); + + [ConditionalTheory(Skip = "issue #17313")] + public override Task Group_by_json_scalar_Skip_First_project_json_scalar(bool async) + => base.Group_by_json_scalar_Skip_First_project_json_scalar(async); + + [ConditionalTheory(Skip = "issue #17313")] + public override Task Group_by_on_json_scalar(bool async) + => base.Group_by_on_json_scalar(async); + + [ConditionalTheory(Skip = "issue #17313")] + public override Task Group_by_on_json_scalar_using_collection_indexer(bool async) + => base.Group_by_on_json_scalar_using_collection_indexer(async); + + [ConditionalTheory(Skip = "issue #17313")] + public override Task Group_by_Skip_Take_on_json_scalar(bool async) + => base.Group_by_Skip_Take_on_json_scalar(async); + + public override Task Json_all_types_entity_projection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_all_types_entity_projection(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "AllTypes") +"""); + }); + + public override Task Json_all_types_projection_from_owned_entity_reference(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_all_types_projection_from_owned_entity_reference(a); + + // TODO: issue #34067 (?) + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "AllTypes") +"""); + }); + + public override Task Json_all_types_projection_individual_properties(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_all_types_projection_individual_properties(a); + + AssertSql( + """ +SELECT c["Reference"]["TestDefaultString"], c["Reference"]["TestMaxLengthString"], c["Reference"]["TestBoolean"], c["Reference"]["TestByte"], c["Reference"]["TestCharacter"], c["Reference"]["TestDateTime"], c["Reference"]["TestDateTimeOffset"], c["Reference"]["TestDecimal"], c["Reference"]["TestDouble"], c["Reference"]["TestGuid"], c["Reference"]["TestInt16"], c["Reference"]["TestInt32"], c["Reference"]["TestInt64"], c["Reference"]["TestSignedByte"], c["Reference"]["TestSingle"], c["Reference"]["TestTimeSpan"], c["Reference"]["TestDateOnly"], c["Reference"]["TestTimeOnly"], c["Reference"]["TestUnsignedInt16"], c["Reference"]["TestUnsignedInt32"], c["Reference"]["TestUnsignedInt64"], c["Reference"]["TestEnum"], c["Reference"]["TestEnumWithIntConverter"], c["Reference"]["TestNullableEnum"], c["Reference"]["TestNullableEnumWithIntConverter"], c["Reference"]["TestNullableEnumWithConverterThatHandlesNulls"] +FROM root c +WHERE (c["Discriminator"] = "AllTypes") +"""); + }); + public override Task Json_boolean_predicate(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_boolean_predicate(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND c["Reference"]["TestBoolean"]) +"""); + }); + + public override Task Json_boolean_predicate_negated(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_boolean_predicate_negated(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND NOT(c["Reference"]["TestBoolean"])) +"""); + }); + + public override Task Json_boolean_projection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_boolean_projection(a); + + AssertSql( + """ +SELECT VALUE c["Reference"]["TestBoolean"] +FROM root c +WHERE (c["Discriminator"] = "AllTypes") +"""); + }); + + public override Task Json_boolean_projection_negated(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_boolean_projection_negated(a); + + AssertSql( + """ +SELECT VALUE NOT(c["Reference"]["TestBoolean"]) +FROM root c +WHERE (c["Discriminator"] = "AllTypes") +"""); + }); + + public override Task Json_branch_collection_distinct_and_other_collection(bool async) + => AssertTranslationFailed( + () => base.Json_branch_collection_distinct_and_other_collection(async)); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_after_collection_index_in_projection_using_constant_when_owner_is_not_present(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_after_collection_index_in_projection_using_constant_when_owner_is_not_present(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_after_collection_index_in_projection_using_constant_when_owner_is_present(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_after_collection_index_in_projection_using_constant_when_owner_is_present(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_after_collection_index_in_projection_using_parameter_when_owner_is_not_present(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_after_collection_index_in_projection_using_parameter_when_owner_is_not_present(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_after_collection_index_in_projection_using_parameter_when_owner_is_present(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_after_collection_index_in_projection_using_parameter_when_owner_is_present(a); + + AssertSql(""); + }); + + public override Task Json_collection_anonymous_projection_distinct_in_projection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_anonymous_projection_distinct_in_projection(a); + + AssertSql(""); + }); + + public override Task Json_collection_Any_with_predicate(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_Any_with_predicate(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND EXISTS ( + SELECT 1 + FROM o IN c["OwnedReferenceRoot"]["OwnedCollectionBranch"] + WHERE (o["OwnedReferenceLeaf"]["SomethingSomething"] = "e1_r_c1_r"))) +"""); + }); + + public override Task Json_collection_Distinct_Count_with_predicate(bool async) + => AssertTranslationFailed( + () => base.Json_collection_Distinct_Count_with_predicate(async)); + + public override Task Json_collection_distinct_in_projection(bool async) + => AssertTranslationFailed( + () => base.Json_collection_distinct_in_projection(async)); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_ElementAtOrDefault_in_projection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_ElementAtOrDefault_in_projection(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_ElementAtOrDefault_project_collection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_ElementAtOrDefault_project_collection(a); + + AssertSql(""); + }); + + public override Task Json_collection_ElementAt_and_pushdown(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_ElementAt_and_pushdown(a); + + AssertSql( + """ +SELECT VALUE +{ + "Id" : c["Id"], + "CollectionElement" : c["OwnedCollectionRoot"][0]["Number"] +} +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Json_collection_ElementAt_in_predicate(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_ElementAt_in_predicate(a); + + AssertSql( + """ +SELECT VALUE c["Id"] +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedCollectionRoot"][1]["Name"] != "Foo")) +"""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_ElementAt_in_projection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_ElementAt_in_projection(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_ElementAt_project_collection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_ElementAt_project_collection(a); + + AssertSql(""); + }); + + public override Task Json_collection_filter_in_projection(bool async) + => AssertTranslationFailed( + () => base.Json_collection_filter_in_projection(async)); + + [ConditionalTheory] + public override async Task Json_collection_index_in_predicate_nested_mix(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_predicate_nested_mix(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + public override async Task Json_collection_index_in_predicate_using_column(bool async) + { + // Always throws for sync. + if (async) + { + var exception = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_predicate_using_column(async))); + + Assert.Contains( + "The specified query includes 'member indexer' which is currently not supported.", + exception.InnerException?.Message); + } + } + + public override async Task Json_collection_index_in_predicate_using_complex_expression1(bool async) + { + // Always throws for sync. + if (async) + { + var exception = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_predicate_using_complex_expression1(async))); + + Assert.Contains( + "The specified query includes 'member indexer' which is currently not supported.", + exception.InnerException?.Message); + } + } + + public override Task Json_collection_index_in_predicate_using_complex_expression2(bool async) + => AssertTranslationFailed( + () => base.Json_collection_index_in_predicate_using_complex_expression2(async)); + + public override Task Json_collection_index_in_predicate_using_constant(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_predicate_using_constant(a); + + AssertSql( + """ +SELECT VALUE c["Id"] +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedCollectionRoot"][0]["Name"] != "Foo")) +"""); + }); + + public override Task Json_collection_index_in_predicate_using_variable(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_predicate_using_variable(a); + + AssertSql( + """ +@__prm_0='1' + +SELECT VALUE c["Id"] +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedCollectionRoot"][@__prm_0]["Name"] != "Foo")) +"""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_index_in_projection_basic(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_projection_basic(a); + + AssertSql(""); + }); + + [ConditionalTheory] + public override async Task Json_collection_index_in_projection_nested(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_projection_nested(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory] + public override async Task Json_collection_index_in_projection_nested_project_collection(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_projection_nested_project_collection(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory] + public override async Task Json_collection_index_in_projection_nested_project_collection_anonymous_projection(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_projection_nested_project_collection_anonymous_projection(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory] + public override async Task Json_collection_index_in_projection_nested_project_reference(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_projection_nested_project_reference(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory] + public override async Task Json_collection_index_in_projection_nested_project_scalar(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_projection_nested_project_scalar(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_index_in_projection_project_collection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_projection_project_collection(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_index_in_projection_using_column(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_projection_using_column(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_index_in_projection_using_constant_when_owner_is_not_present(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_projection_using_constant_when_owner_is_not_present(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_index_in_projection_using_constant_when_owner_is_present(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_projection_using_constant_when_owner_is_present(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_index_in_projection_using_parameter(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_projection_using_parameter(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_index_in_projection_using_parameter_when_owner_is_not_present(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_projection_using_parameter_when_owner_is_not_present(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_index_in_projection_using_parameter_when_owner_is_present(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_projection_using_parameter_when_owner_is_present(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_index_in_projection_using_untranslatable_client_method(bool async) + => base.Json_collection_index_in_projection_using_untranslatable_client_method(async); + + public override Task Json_collection_index_in_projection_using_untranslatable_client_method2(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_collection_index_in_projection_using_untranslatable_client_method2(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override async Task Json_collection_index_in_projection_when_owner_is_not_present_misc1(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_projection_when_owner_is_not_present_misc1(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory(Skip = "issue #34350")] + public override Task Json_collection_index_in_projection_when_owner_is_not_present_misc2(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_projection_when_owner_is_not_present_misc2(a); + + AssertSql(""); + }); + + [ConditionalTheory] + public override async Task Json_collection_index_in_projection_when_owner_is_not_present_multiple(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_projection_when_owner_is_not_present_multiple(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory] + public override async Task Json_collection_index_in_projection_when_owner_is_present_misc1(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_projection_when_owner_is_present_misc1(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory(Skip = "issue #34350")] + public override Task Json_collection_index_in_projection_when_owner_is_present_misc2(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_in_projection_when_owner_is_present_misc2(a); + + AssertSql(""); + }); + + [ConditionalTheory] + public override async Task Json_collection_index_in_projection_when_owner_is_present_multiple(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_in_projection_when_owner_is_present_multiple(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_index_outside_bounds(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_outside_bounds(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34350")] + public override Task Json_collection_index_outside_bounds2(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_index_outside_bounds2(a); + + AssertSql(""); + }); + + // returns "wrong" results by design - see #34351 for more context + [ConditionalTheory] + public override Task Json_collection_index_outside_bounds_with_property_access(bool async) + => Task.CompletedTask; + + [ConditionalTheory] + public override async Task Json_collection_index_with_expression_Select_ElementAt(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_with_expression_Select_ElementAt(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory] + public override async Task Json_collection_index_with_parameter_Select_ElementAt(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_collection_index_with_parameter_Select_ElementAt(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory(Skip = "issue #34004")] // anonymous projection + public override Task Json_collection_in_projection_with_anonymous_projection_of_scalars(bool async) + => base.Json_collection_in_projection_with_anonymous_projection_of_scalars(async); + + public override Task Json_collection_in_projection_with_composition_count(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_in_projection_with_composition_count(a); + + AssertSql( + """ +SELECT VALUE ARRAY_LENGTH(c["OwnedCollectionRoot"]) +FROM root c +WHERE (c["Discriminator"] = "Basic") +ORDER BY c["Id"] +"""); + }); + + [ConditionalTheory(Skip = "issue #34004")] // anonymous projection + public override Task Json_collection_in_projection_with_composition_where_and_anonymous_projection_of_primitive_arrays(bool async) + => base.Json_collection_in_projection_with_composition_where_and_anonymous_projection_of_primitive_arrays(async); + + [ConditionalTheory(Skip = "issue #34004")] // anonymous projection + public override Task Json_collection_in_projection_with_composition_where_and_anonymous_projection_of_scalars(bool async) + => base.Json_collection_in_projection_with_composition_where_and_anonymous_projection_of_scalars(async); + + public override Task Json_collection_leaf_filter_in_projection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_leaf_filter_in_projection(a); + + AssertSql( + """ +SELECT VALUE ARRAY( + SELECT VALUE o + FROM o IN c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["OwnedCollectionLeaf"] + WHERE (o["SomethingSomething"] != "Baz")) +FROM root c +WHERE (c["Discriminator"] = "Basic") +ORDER BY c["Id"] +"""); + }); + + + public override Task Json_collection_of_primitives_contains_in_predicate(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_of_primitives_contains_in_predicate(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND ARRAY_CONTAINS(c["OwnedReferenceRoot"]["Names"], "e1_r1")) +"""); + }); + + public override Task Json_collection_of_primitives_index_used_in_orderby(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_of_primitives_index_used_in_orderby(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +ORDER BY c["OwnedReferenceRoot"]["Numbers"][0] +"""); + }); + + public override Task Json_collection_of_primitives_index_used_in_predicate(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_of_primitives_index_used_in_predicate(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedReferenceRoot"]["Names"][0] = "e1_r1")) +"""); + }); + + [ConditionalTheory(Skip = "issue #34026")] //enums property is ignored + public override Task Json_collection_of_primitives_index_used_in_projection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_of_primitives_index_used_in_projection(a); + + AssertSql( + """ +SELECT VALUE c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["Enums"][0] +FROM root c +WHERE (c["Discriminator"] = "JsonEntityBasic") +ORDER BY c["Id"] +"""); + }); + + public override Task Json_collection_of_primitives_SelectMany(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_of_primitives_SelectMany(a); + + AssertSql( + """ +SELECT VALUE n +FROM root c +JOIN n IN c["OwnedReferenceRoot"]["Names"] +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Json_collection_OrderByDescending_Skip_ElementAt(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_collection_OrderByDescending_Skip_ElementAt(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries + + Environment.NewLine + + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + [ConditionalTheory(Skip = "issue #34349")] + public override Task Json_collection_SelectMany(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_SelectMany(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34335")] + public override Task Json_collection_Select_entity_collection_ElementAt(bool async) => base.Json_collection_Select_entity_collection_ElementAt(async); + + public override Task Json_collection_Select_entity_ElementAt(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_collection_Select_entity_ElementAt(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_collection_Select_entity_in_anonymous_object_ElementAt(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_collection_Select_entity_in_anonymous_object_ElementAt(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_collection_Select_entity_with_initializer_ElementAt(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_collection_Select_entity_with_initializer_ElementAt(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_collection_Skip(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_Skip(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND (ARRAY( + SELECT VALUE o["OwnedReferenceLeaf"]["SomethingSomething"] + FROM o IN (SELECT VALUE ARRAY_SLICE(c["OwnedReferenceRoot"]["OwnedCollectionBranch"], 1)))[0] = "e1_r_c2_r")) +"""); + }); + + public override Task Json_collection_skip_take_in_projection(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_collection_skip_take_in_projection(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_collection_skip_take_in_projection_project_into_anonymous_type(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_collection_skip_take_in_projection_project_into_anonymous_type(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_collection_skip_take_in_projection_with_json_reference_access_as_final_operation(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_collection_skip_take_in_projection_with_json_reference_access_as_final_operation(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_collection_Where_ElementAt(bool async) + => Fixture.NoSyncTest( + async, async a => + { + // TODO: note the enum value -3 + await base.Json_collection_Where_ElementAt(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND (ARRAY( + SELECT VALUE o["OwnedReferenceLeaf"]["SomethingSomething"] + FROM o IN c["OwnedReferenceRoot"]["OwnedCollectionBranch"] + WHERE (o["Enum"] = -3))[0] = "e1_r_c2_r")) +"""); + }); + + public override Task Json_collection_within_collection_Count(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_collection_within_collection_Count(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND EXISTS ( + SELECT 1 + FROM o IN c["OwnedCollectionRoot"] + WHERE (ARRAY_LENGTH(o["OwnedCollectionBranch"]) = 2))) +"""); + }); + + public override Task Json_entity_backtracking(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_entity_backtracking(a); + + AssertSql(""); + }); + + public override Task Json_entity_with_inheritance_basic_projection(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_entity_with_inheritance_basic_projection(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE c["Discriminator"] IN ("JsonEntityInheritanceBase", "JsonEntityInheritanceDerived") +"""); + }); + + public override Task Json_entity_with_inheritance_project_derived(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_entity_with_inheritance_project_derived(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] IN ("JsonEntityInheritanceBase", "JsonEntityInheritanceDerived") AND (c["Discriminator"] = "JsonEntityInheritanceDerived")) +"""); + }); + + [ConditionalTheory(Skip = "issue #34350")] + public override Task Json_entity_with_inheritance_project_navigations(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_entity_with_inheritance_project_navigations(a); + + AssertSql(""); + }); + + [ConditionalTheory(Skip = "issue #34350")] + public override Task Json_entity_with_inheritance_project_navigations_on_derived(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_entity_with_inheritance_project_navigations_on_derived(a); + + AssertSql(""); + }); + + public override Task Json_leaf_collection_distinct_and_other_collection(bool async) + => AssertTranslationFailed( + () => base.Json_leaf_collection_distinct_and_other_collection(async)); + + public override Task Json_multiple_collection_projections(bool async) + => AssertTranslationFailed( + () => base.Json_multiple_collection_projections(async)); + + public override Task Json_nested_collection_anonymous_projection_in_projection(bool async) + => AssertTranslationFailed( + () => base.Json_nested_collection_anonymous_projection_in_projection(async)); + + public override Task Json_nested_collection_anonymous_projection_of_primitives_in_projection_NoTrackingWithIdentityResolution(bool async) + => AssertTranslationFailed( + () => base.Json_nested_collection_anonymous_projection_of_primitives_in_projection_NoTrackingWithIdentityResolution(async)); + + public override Task Json_nested_collection_filter_in_projection(bool async) + => AssertTranslationFailed( + () => base.Json_nested_collection_filter_in_projection(async)); + + [ConditionalTheory(Skip = "issue #34349")] + public override Task Json_nested_collection_SelectMany(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_nested_collection_SelectMany(a); + + AssertSql(""); + }); + + public override Task Json_predicate_on_bool_converted_to_int_zero_one(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_bool_converted_to_int_zero_one(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToIntZeroOne"] = 1)) +"""); + }); + + public override Task Json_predicate_on_bool_converted_to_int_zero_one_with_explicit_comparison(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_bool_converted_to_int_zero_one_with_explicit_comparison(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToIntZeroOne"] = 0)) +"""); + }); + + public override Task Json_predicate_on_bool_converted_to_string_True_False(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_bool_converted_to_string_True_False(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToStringTrueFalse"] = "True")) +"""); + }); + + public override Task Json_predicate_on_bool_converted_to_string_True_False_with_explicit_comparison(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_bool_converted_to_string_True_False_with_explicit_comparison(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToStringTrueFalse"] = "True")) +"""); + }); + + public override Task Json_predicate_on_bool_converted_to_string_Y_N(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_bool_converted_to_string_Y_N(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToStringYN"] = "Y")) +"""); + }); + + public override Task Json_predicate_on_bool_converted_to_string_Y_N_with_explicit_comparison(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_bool_converted_to_string_Y_N_with_explicit_comparison(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToStringYN"] = "N")) +"""); + }); + + public override Task Json_predicate_on_byte(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_byte(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestByte"] != 3)) +"""); + }); + + public override Task Json_predicate_on_byte_array(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_byte_array(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestByteArray"] != "AQID")) +"""); + }); + + public override Task Json_predicate_on_character(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_character(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestCharacter"] != "z")) +"""); + }); + + public override Task Json_predicate_on_dateonly(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_dateonly(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDateOnly"] != "0003-02-01")) +"""); + }); + + public override Task Json_predicate_on_datetime(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_datetime(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDateTime"] != "2000-01-03T00:00:00")) +"""); + }); + + public override Task Json_predicate_on_datetimeoffset(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_datetimeoffset(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDateTimeOffset"] != "2000-01-04T00:00:00+03:02")) +"""); + }); + + public override Task Json_predicate_on_decimal(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_decimal(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDecimal"] != 1.35)) +"""); + }); + + public override Task Json_predicate_on_default_string(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_default_string(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDefaultString"] != "MyDefaultStringInReference1")) +"""); + }); + + public override Task Json_predicate_on_double(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_double(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDouble"] != 33.25)) +"""); + }); + + public override Task Json_predicate_on_enum(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_enum(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestEnum"] != 2)) +"""); + }); + + public override Task Json_predicate_on_enumwithintconverter(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_enumwithintconverter(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestEnumWithIntConverter"] != -3)) +"""); + }); + + public override Task Json_predicate_on_guid(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_guid(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestGuid"] != "00000000-0000-0000-0000-000000000000")) +"""); + }); + + public override Task Json_predicate_on_int16(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_int16(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestInt16"] != 3)) +"""); + }); + + public override Task Json_predicate_on_int32(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_int32(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestInt32"] != 33)) +"""); + }); + + public override Task Json_predicate_on_int64(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_int64(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestInt64"] != 333)) +"""); + }); + + public override Task Json_predicate_on_int_zero_one_converted_to_bool(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_int_zero_one_converted_to_bool(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["IntZeroOneConvertedToBool"] = true)) +"""); + }); + + public override Task Json_predicate_on_max_length_string(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_max_length_string(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestMaxLengthString"] != "Foo")) +"""); + }); + + public override Task Json_predicate_on_nullableenum1(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_nullableenum1(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableEnum"] != -1)) +"""); + }); + + public override Task Json_predicate_on_nullableenum2(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_nullableenum2(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableEnum"] != null)) +"""); + }); + + public override Task Json_predicate_on_nullableenumwithconverter1(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_nullableenumwithconverter1(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableEnumWithIntConverter"] != 2)) +"""); + }); + + public override Task Json_predicate_on_nullableenumwithconverter2(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_nullableenumwithconverter2(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableEnumWithIntConverter"] != null)) +"""); + }); + + public override Task Json_predicate_on_nullableenumwithconverterthathandlesnulls1(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_nullableenumwithconverterthathandlesnulls1(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableEnumWithConverterThatHandlesNulls"] != "One")) +"""); + }); + + public override Task Json_predicate_on_nullableenumwithconverterthathandlesnulls2(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_nullableenumwithconverterthathandlesnulls2(a); + + AssertSql(""); + }); + + public override Task Json_predicate_on_nullableint321(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_nullableint321(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableInt32"] != 100)) +"""); + }); + + public override Task Json_predicate_on_nullableint322(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_nullableint322(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableInt32"] != null)) +"""); + }); + + public override Task Json_predicate_on_signedbyte(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_signedbyte(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestSignedByte"] != 100)) +"""); + }); + + public override Task Json_predicate_on_single(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_single(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestSingle"] != 10.4)) +"""); + }); + + public override Task Json_predicate_on_string_condition(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_string_condition(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND ((NOT(c["Reference"]["TestBoolean"]) ? c["Reference"]["TestMaxLengthString"] : c["Reference"]["TestDefaultString"]) = "MyDefaultStringInReference1")) +"""); + }); + + public override Task Json_predicate_on_string_True_False_converted_to_bool(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_string_True_False_converted_to_bool(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["StringTrueFalseConvertedToBool"] = false)) +"""); + }); + + public override Task Json_predicate_on_string_Y_N_converted_to_bool(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_string_Y_N_converted_to_bool(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["StringYNConvertedToBool"] = false)) +"""); + }); + + public override Task Json_predicate_on_timeonly(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_timeonly(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestTimeOnly"] != "03:02:00")) +"""); + }); + + public override Task Json_predicate_on_timespan(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_timespan(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestTimeSpan"] != "03:02:00")) +"""); + }); + + public override Task Json_predicate_on_unisgnedint16(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_unisgnedint16(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestUnsignedInt16"] != 100)) +"""); + }); + + public override Task Json_predicate_on_unsignedint32(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_unsignedint32(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestUnsignedInt32"] != 1000)) +"""); + }); + + public override Task Json_predicate_on_unsignedint64(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_predicate_on_unsignedint64(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestUnsignedInt64"] != 10000)) +"""); + }); + + public override Task Json_projection_collection_element_and_reference_AsNoTrackingWithIdentityResolution(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_projection_collection_element_and_reference_AsNoTrackingWithIdentityResolution(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_projection_deduplication_with_collection_indexer_in_original(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_projection_deduplication_with_collection_indexer_in_original(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_projection_deduplication_with_collection_indexer_in_target(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_projection_deduplication_with_collection_indexer_in_target(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + [ConditionalTheory] + public override async Task Json_projection_deduplication_with_collection_in_original_and_collection_indexer_in_target(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_projection_deduplication_with_collection_in_original_and_collection_indexer_in_target(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + public override Task Json_projection_enum_with_custom_conversion(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_projection_enum_with_custom_conversion(a); + + AssertSql( + """ +SELECT c["Id"], c["OwnedReferenceRoot"]["Enum"] +FROM root c +WHERE (c["Discriminator"] = "CustomNaming") +"""); + }); + + public override Task Json_projection_nested_collection_and_element_correct_order_AsNoTrackingWithIdentityResolution(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_projection_nested_collection_and_element_correct_order_AsNoTrackingWithIdentityResolution(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + [ConditionalTheory] + public override async Task Json_projection_nested_collection_element_using_parameter_and_the_owner_in_correct_order_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_projection_nested_collection_element_using_parameter_and_the_owner_in_correct_order_AsNoTrackingWithIdentityResolution(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + public override Task Json_projection_nothing_interesting_AsNoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_projection_nothing_interesting_AsNoTrackingWithIdentityResolution(a); + + AssertSql( + """ +SELECT c["Id"], c["Name"] +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + [ConditionalTheory] + public override async Task Json_projection_only_second_element_through_collection_element_constant_projected_nested_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_projection_only_second_element_through_collection_element_constant_projected_nested_AsNoTrackingWithIdentityResolution(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + [ConditionalTheory] + public override async Task Json_projection_only_second_element_through_collection_element_parameter_projected_nested_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_projection_only_second_element_through_collection_element_parameter_projected_nested_AsNoTrackingWithIdentityResolution(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + public override Task Json_projection_owner_entity_AsNoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_projection_owner_entity_AsNoTrackingWithIdentityResolution(a); + + AssertSql( + """ +SELECT c["Id"], c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Json_projection_reference_collection_and_collection_element_nested_AsNoTrackingWithIdentityResolution(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_projection_reference_collection_and_collection_element_nested_AsNoTrackingWithIdentityResolution(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_projection_second_element_projected_before_owner_as_well_as_root_AsNoTrackingWithIdentityResolution(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_projection_second_element_projected_before_owner_as_well_as_root_AsNoTrackingWithIdentityResolution(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + [ConditionalTheory(Skip = "issue #34350")] + public override Task Json_projection_second_element_projected_before_owner_nested_as_well_as_root_AsNoTrackingWithIdentityResolution(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_projection_second_element_projected_before_owner_nested_as_well_as_root_AsNoTrackingWithIdentityResolution(a); + + AssertSql(""); + }); + + [ConditionalTheory] + public override async Task Json_projection_second_element_through_collection_element_constant_different_values_projected_before_owner_nested_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_projection_second_element_through_collection_element_constant_different_values_projected_before_owner_nested_AsNoTrackingWithIdentityResolution(async))).Message; + + // issue #34348 + Assert.Equal(NotImplementedBindPropertyMessage, message); + } + + public override Task Json_projection_second_element_through_collection_element_constant_projected_after_owner_nested_AsNoTrackingWithIdentityResolution(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_projection_second_element_through_collection_element_constant_projected_after_owner_nested_AsNoTrackingWithIdentityResolution(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_projection_second_element_through_collection_element_parameter_correctly_projected_after_owner_nested_AsNoTrackingWithIdentityResolution(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_projection_second_element_through_collection_element_parameter_correctly_projected_after_owner_nested_AsNoTrackingWithIdentityResolution(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + [ConditionalTheory(Skip = "issue #34350")] + public override Task Json_projection_with_deduplication(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_projection_with_deduplication(a); + + AssertSql(""); + }); + + [ConditionalTheory] + public override Task Json_projection_with_deduplication_reverse_order(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_projection_with_deduplication_reverse_order(async); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Json_property_in_predicate(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_property_in_predicate(a); + + AssertSql( + """ +SELECT VALUE c["Id"] +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["Fraction"] < 20.5)) +"""); + }); + + public override Task Json_scalar_length(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_scalar_length(a); + + AssertSql( + """ +SELECT VALUE c["Name"] +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND (LENGTH(c["OwnedReferenceRoot"]["Name"]) > 2)) +"""); + }); + + public override Task Json_scalar_optional_null_semantics(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_scalar_optional_null_semantics(a); + + AssertSql( + """ +SELECT VALUE c["Name"] +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedReferenceRoot"]["Name"] != c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["OwnedReferenceLeaf"]["SomethingSomething"])) +"""); + }); + + public override Task Json_scalar_required_null_semantics(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_scalar_required_null_semantics(a); + + AssertSql( + """ +SELECT VALUE c["Name"] +FROM root c +WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedReferenceRoot"]["Number"] != LENGTH(c["OwnedReferenceRoot"]["Name"]))) +"""); + }); + + public override Task Json_subquery_property_pushdown_length(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_subquery_property_pushdown_length(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_subquery_reference_pushdown_property(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_subquery_reference_pushdown_property(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_subquery_reference_pushdown_reference(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_subquery_reference_pushdown_reference(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_subquery_reference_pushdown_reference_anonymous_projection(bool async) + => base.Json_subquery_reference_pushdown_reference_anonymous_projection(async); + + public override Task Json_subquery_reference_pushdown_reference_pushdown_anonymous_projection(bool async) + => base.Json_subquery_reference_pushdown_reference_pushdown_anonymous_projection(async); + + public override Task Json_subquery_reference_pushdown_reference_pushdown_collection(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_subquery_reference_pushdown_reference_pushdown_collection(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Json_subquery_reference_pushdown_reference_pushdown_reference(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_subquery_reference_pushdown_reference_pushdown_reference(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override async Task Json_with_include_on_entity_collection(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Json_with_include_on_entity_collection(async))).Message; + + Assert.Equal( + CosmosStrings.NonEmbeddedIncludeNotSupported("Navigation: JsonEntityBasic.EntityCollection (List) Collection ToDependent JsonEntityBasicForCollection Inverse: Parent"), + message); + } + + public override Task Json_with_include_on_entity_collection_and_reference(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_with_include_on_entity_collection_and_reference(async), + CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(JsonEntityBasicForReference), nameof(JsonEntityBasic))); + + public override Task Json_with_include_on_entity_reference(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_with_include_on_entity_reference(async), + CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(JsonEntityBasicForReference), nameof(JsonEntityBasic))); + + public override Task Json_with_include_on_json_entity(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Json_with_include_on_json_entity(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "Basic") +"""); + }); + + public override Task Json_with_projection_of_json_collection_and_entity_collection(bool async) + => AssertTranslationFailed( + () => base.Json_with_projection_of_json_collection_and_entity_collection(async)); + + public override Task Json_with_projection_of_json_collection_element_and_entity_collection(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_with_projection_of_json_collection_element_and_entity_collection(async), + CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(JsonEntityBasicForReference), nameof(JsonEntityBasic))); + + public override Task Json_with_projection_of_json_collection_leaf_and_entity_collection(bool async) + => AssertTranslationFailed( + () => base.Json_with_projection_of_json_collection_leaf_and_entity_collection(async)); + + public override Task Json_with_projection_of_json_reference_and_entity_collection(bool async) + => AssertTranslationFailed( + () => base.Json_with_projection_of_json_reference_and_entity_collection(async)); + + public override Task Json_with_projection_of_json_reference_leaf_and_entity_collection(bool async) + => AssertTranslationFailed( + () => base.Json_with_projection_of_json_reference_leaf_and_entity_collection(async)); + + public override Task Json_with_projection_of_mix_of_json_collections_json_references_and_entity_collection(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_with_projection_of_mix_of_json_collections_json_references_and_entity_collection(async), + CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(JsonEntityBasicForReference), nameof(JsonEntityBasic))); + + public override Task Json_with_projection_of_multiple_json_references_and_entity_collection(bool async) + => AssertTranslationFailedWithDetails( + () => base.Json_with_projection_of_multiple_json_references_and_entity_collection(async), + CosmosStrings.LimitOffsetNotSupportedInSubqueries); + + public override Task Left_join_json_entities(bool async) + => AssertTranslationFailedWithDetails( + () => base.Left_join_json_entities(async), + CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(JsonEntityBasic), nameof(JsonEntitySingleOwned))); + + public override Task Left_join_json_entities_complex_projection(bool async) + => AssertTranslationFailedWithDetails( + () => base.Left_join_json_entities_complex_projection(async), + CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(JsonEntityBasic), nameof(JsonEntitySingleOwned))); + + public override Task Left_join_json_entities_complex_projection_json_being_inner(bool async) + => AssertTranslationFailedWithDetails( + () => base.Left_join_json_entities_complex_projection_json_being_inner(async), + CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(JsonEntitySingleOwned), nameof(JsonEntityBasic))); + + public override Task Left_join_json_entities_json_being_inner(bool async) + => AssertTranslationFailedWithDetails( + () => base.Left_join_json_entities_json_being_inner(async), + CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(JsonEntitySingleOwned), nameof(JsonEntityBasic))); + + public override Task Project_entity_with_single_owned(bool async) + => Fixture.NoSyncTest( + async, async a => + { + await base.Project_entity_with_single_owned(a); + + AssertSql( + """ +SELECT VALUE c +FROM root c +WHERE (c["Discriminator"] = "SingleOwned") +"""); + }); + + public override Task Project_json_entity_FirstOrDefault_subquery(bool async) + => AssertTranslationFailed( + () => base.Project_json_entity_FirstOrDefault_subquery(async)); + + public override Task Project_json_entity_FirstOrDefault_subquery_deduplication(bool async) + => AssertTranslationFailed( + () => base.Project_json_entity_FirstOrDefault_subquery_deduplication(async)); + + public override Task Project_json_entity_FirstOrDefault_subquery_deduplication_and_outer_reference(bool async) + => AssertTranslationFailed( + () => base.Project_json_entity_FirstOrDefault_subquery_deduplication_and_outer_reference(async)); + + public override Task Project_json_entity_FirstOrDefault_subquery_deduplication_outer_reference_and_pruning(bool async) + => AssertTranslationFailed( + () => base.Project_json_entity_FirstOrDefault_subquery_deduplication_outer_reference_and_pruning(async)); + + public override Task Project_json_entity_FirstOrDefault_subquery_with_binding_on_top(bool async) + => AssertTranslationFailed( + () => base.Project_json_entity_FirstOrDefault_subquery_with_binding_on_top(async)); + + public override Task Project_json_entity_FirstOrDefault_subquery_with_entity_comparison_on_top(bool async) + => AssertTranslationFailed( + () => base.Project_json_entity_FirstOrDefault_subquery_with_entity_comparison_on_top(async)); + + public override async Task Project_json_reference_in_tracking_query_fails(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Project_json_reference_in_tracking_query_fails(async))).Message; + + Assert.Equal(CoreStrings.OwnedEntitiesCannotBeTrackedWithoutTheirOwner, message); + } + + public override async Task Project_json_collection_in_tracking_query_fails(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Project_json_collection_in_tracking_query_fails(async))).Message; + + Assert.Equal(CoreStrings.OwnedEntitiesCannotBeTrackedWithoutTheirOwner, message); + } + + [ConditionalTheory(Skip = "issue #34350")] + public override async Task Project_json_entity_in_tracking_query_fails_even_when_owner_is_present(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Project_json_entity_in_tracking_query_fails_even_when_owner_is_present(async))).Message; + + Assert.Equal(CoreStrings.OwnedEntitiesCannotBeTrackedWithoutTheirOwner, message); + } + + private void AssertSql(params string[] expected) + => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); +} diff --git a/test/EFCore.InMemory.FunctionalTests/InMemoryComplianceTest.cs b/test/EFCore.InMemory.FunctionalTests/InMemoryComplianceTest.cs index 51e6af0b2ad..dccb622b444 100644 --- a/test/EFCore.InMemory.FunctionalTests/InMemoryComplianceTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/InMemoryComplianceTest.cs @@ -24,6 +24,7 @@ public class InMemoryComplianceTest : ComplianceTestBase typeof(InheritanceBulkUpdatesTestBase<>), typeof(NonSharedModelBulkUpdatesTestBase), typeof(NorthwindBulkUpdatesTestBase<>), + typeof(JsonQueryTestBase<>), }; protected override Assembly TargetAssembly { get; } = typeof(InMemoryComplianceTest).Assembly; diff --git a/test/EFCore.Relational.Specification.Tests/Query/JsonQueryRelationalFixture.cs b/test/EFCore.Relational.Specification.Tests/Query/JsonQueryRelationalFixture.cs new file mode 100644 index 00000000000..7004dac0a80 --- /dev/null +++ b/test/EFCore.Relational.Specification.Tests/Query/JsonQueryRelationalFixture.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.EntityFrameworkCore.TestModels.JsonQuery; + +namespace Microsoft.EntityFrameworkCore.Query; + +#nullable disable + +public abstract class JsonQueryRelationalFixture: JsonQueryFixtureBase, ITestSqlLoggerFactory +{ + public new RelationalTestStore TestStore + => (RelationalTestStore)base.TestStore; + + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder.Entity().OwnsOne(x => x.OwnedReferenceRoot).ToJson(); + modelBuilder.Entity().OwnsMany(x => x.OwnedCollectionRoot).ToJson(); + + modelBuilder.Entity().OwnsOne(x => x.OwnedReferenceRoot).ToJson("json_reference_custom_naming"); + modelBuilder.Entity().OwnsMany(x => x.OwnedCollectionRoot).ToJson("json_collection_custom_naming"); + + modelBuilder.Entity().OwnsMany(x => x.OwnedCollection).ToJson(); + + modelBuilder.Entity( + b => + { + b.OwnsOne(x => x.ReferenceOnBase).ToJson(); + b.OwnsMany(x => x.CollectionOnBase).ToJson(); + }); + + modelBuilder.Entity( + b => + { + b.HasBaseType(); + b.OwnsOne(x => x.ReferenceOnDerived).ToJson(); + b.OwnsMany(x => x.CollectionOnDerived).ToJson(); + }); + + modelBuilder.Entity().OwnsOne(x => x.Reference).ToJson(); + modelBuilder.Entity().OwnsMany(x => x.Collection).ToJson(); + + modelBuilder.Entity().OwnsOne(x => x.Reference).ToJson(); + } +} diff --git a/test/EFCore.Relational.Specification.Tests/Query/JsonQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/JsonQueryRelationalTestBase.cs new file mode 100644 index 00000000000..852441f58ac --- /dev/null +++ b/test/EFCore.Relational.Specification.Tests/Query/JsonQueryRelationalTestBase.cs @@ -0,0 +1,605 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.EntityFrameworkCore.TestModels.JsonQuery; + +namespace Microsoft.EntityFrameworkCore.Query; +public abstract class JsonQueryRelationalTestBase : JsonQueryTestBase + where TFixture : JsonQueryRelationalFixture, new() +{ + protected JsonQueryRelationalTestBase(TFixture fixture) + : base(fixture) + { + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public override async Task Project_json_reference_in_tracking_query_fails(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Project_json_reference_in_tracking_query_fails(async))).Message; + + Assert.Equal( + RelationalStrings.JsonEntityOrCollectionProjectedAtRootLevelInTrackingQuery( + nameof(EntityFrameworkQueryableExtensions.AsNoTracking)), message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public override async Task Project_json_collection_in_tracking_query_fails(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Project_json_collection_in_tracking_query_fails(async))).Message; + + Assert.Equal( + RelationalStrings.JsonEntityOrCollectionProjectedAtRootLevelInTrackingQuery( + nameof(EntityFrameworkQueryableExtensions.AsNoTracking)), message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public override async Task Project_json_entity_in_tracking_query_fails_even_when_owner_is_present(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.Project_json_entity_in_tracking_query_fails_even_when_owner_is_present(async))).Message; + + Assert.Equal( + RelationalStrings.JsonEntityOrCollectionProjectedAtRootLevelInTrackingQuery( + nameof(EntityFrameworkQueryableExtensions.AsNoTracking)), message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FromSql_on_entity_with_json_basic(bool async) + => AssertQuery( + async, + ss => ((DbSet)ss.Set()).FromSqlRaw( + Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesBasic] AS j")), + ss => ss.Set()); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FromSql_on_entity_with_json_project_json_reference(bool async) + => AssertQuery( + async, + ss => ((DbSet)ss.Set()).FromSqlRaw( + Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesBasic] AS j")) + .AsNoTracking() + .Select(x => x.OwnedReferenceRoot.OwnedReferenceBranch), + ss => ss.Set().Select(x => x.OwnedReferenceRoot.OwnedReferenceBranch)); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FromSql_on_entity_with_json_project_json_collection(bool async) + => AssertQuery( + async, + ss => ((DbSet)ss.Set()).FromSqlRaw( + Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesBasic] AS j")) + .AsNoTracking() + .Select(x => x.OwnedReferenceRoot.OwnedCollectionBranch), + ss => ss.Set().Select(x => x.OwnedReferenceRoot.OwnedCollectionBranch), + elementAsserter: (e, a) => AssertCollection(e, a, elementSorter: ee => (ee.Date, ee.Enum, ee.Fraction))); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FromSql_on_entity_with_json_inheritance_on_base(bool async) + => AssertQuery( + async, + ss => ((DbSet)ss.Set()).FromSqlRaw( + Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesInheritance] AS j")), + ss => ss.Set()); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FromSql_on_entity_with_json_inheritance_on_derived(bool async) + => AssertQuery( + async, + ss => ((DbSet)ss.Set()).FromSqlRaw( + Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesInheritance] AS j")), + ss => ss.Set()); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FromSql_on_entity_with_json_inheritance_project_reference_on_base(bool async) + => AssertQuery( + async, + ss => ((DbSet)ss.Set()).FromSqlRaw( + Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesInheritance] AS j")) + .AsNoTracking() + .OrderBy(x => x.Id) + .Select(x => x.ReferenceOnBase), + ss => ss.Set().OrderBy(x => x.Id).Select(x => x.ReferenceOnBase), + assertOrder: true); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FromSql_on_entity_with_json_inheritance_project_reference_on_derived(bool async) + => AssertQuery( + async, + ss => ((DbSet)ss.Set()).FromSqlRaw( + Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesInheritance] AS j")) + .AsNoTracking() + .OrderBy(x => x.Id) + .Select(x => x.CollectionOnDerived), + ss => ss.Set().OrderBy(x => x.Id).Select(x => x.CollectionOnDerived), + elementAsserter: (e, a) => AssertCollection(e, a, elementSorter: ee => (ee.Date, ee.Enum, ee.Fraction)), + assertOrder: true); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_using_queryable_methods_on_top_of_JSON_collection_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Skip = x.OwnedCollectionRoot.Skip(1).ToList(), + Take = x.OwnedCollectionRoot.Take(2).ToList(), + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertCollection(e.Skip, a.Skip); + AssertCollection(e.Take, a.Take); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_nested_collection_anonymous_projection_in_projection_NoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set() + .OrderBy(x => x.Id) + .Select( + x => x.OwnedCollectionRoot + .Select( + xx => xx.OwnedCollectionBranch.Select( + xxx => new + { + xxx.Date, + xxx.Enum, + xxx.Enums, + xxx.Fraction, + xxx.OwnedReferenceLeaf, + xxx.OwnedCollectionLeaf + }).ToList())) + .AsNoTrackingWithIdentityResolution(), + assertOrder: true, + elementAsserter: (e, a) => AssertCollection( + e, a, ordered: true, elementAsserter: (ee, aa) => AssertCollection( + ee, aa, ordered: true, elementAsserter: (eee, aaa) => + { + AssertEqual(eee.Date, aaa.Date); + AssertEqual(eee.Enum, aaa.Enum); + AssertCollection(eee.Enums, aaa.Enums, ordered: true); + AssertEqual(eee.Fraction, aaa.Fraction); + AssertEqual(eee.OwnedReferenceLeaf, aaa.OwnedReferenceLeaf); + AssertCollection(eee.OwnedCollectionLeaf, aaa.OwnedCollectionLeaf, ordered: true); + }))))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_nested_collection_and_element_using_parameter_AsNoTrackingWithIdentityResolution(bool async) + { + var prm = 0; + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf, + Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf[1], + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Duplicate, a.Duplicate); + AssertCollection(e.Original, a.Original, ordered: true); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_nested_collection_and_element_using_parameter_AsNoTrackingWithIdentityResolution2(bool async) + { + var prm1 = 0; + var prm2 = 0; + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm1].OwnedCollectionLeaf[1], + Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm2].OwnedCollectionLeaf, + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Duplicate, a.Duplicate); + AssertCollection(e.Original, a.Original, ordered: true); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_second_element_through_collection_element_parameter_different_values_projected_before_owner_nested_AsNoTrackingWithIdentityResolution(bool async) + { + var prm1 = 0; + var prm2 = 1; + + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm1].OwnedCollectionLeaf[1], + Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm2].OwnedCollectionLeaf, + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertCollection(e.Original, a.Original, ordered: true); + AssertEqual(e.Duplicate, a.Duplicate); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_second_element_through_collection_element_parameter_projected_before_owner_nested_AsNoTrackingWithIdentityResolution(bool async) + { + var prm = 0; + + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf[1], + Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf, + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertCollection(e.Original, a.Original, ordered: true); + AssertEqual(e.Duplicate, a.Duplicate); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_second_element_through_collection_element_parameter_projected_before_owner_nested_AsNoTrackingWithIdentityResolution2(bool async) + { + var prm1 = 0; + var prm2 = 0; + + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm1].OwnedCollectionLeaf[1], + Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm2].OwnedCollectionLeaf, + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Original, a.Original); + AssertEqual(e.Duplicate, a.Duplicate); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_second_element_through_collection_element_parameter_projected_after_owner_nested_AsNoTrackingWithIdentityResolution(bool async) + { + var prm = 0; + + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf, + Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf[1], + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertCollection(e.Original, a.Original, ordered: true); + AssertEqual(e.Duplicate, a.Duplicate); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_second_element_through_collection_element_constant_projected_before_owner_nested_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[0].OwnedCollectionLeaf[1], + Original = x.OwnedReferenceRoot.OwnedCollectionBranch[0].OwnedCollectionLeaf, + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Original, a.Original); + AssertEqual(e.Duplicate, a.Duplicate); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_branch_collection_distinct_and_other_collection_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set() + .OrderBy(x => x.Id) + .Select( + x => new + { + First = x.EntityCollection.ToList(), + Second = x.OwnedReferenceRoot.OwnedCollectionBranch.Distinct().ToList() + }) + .AsNoTrackingWithIdentityResolution(), + assertOrder: true, + elementAsserter: (e, a) => + { + AssertCollection(e.First, a.First, ordered: true); + AssertCollection(e.Second, a.Second, elementSorter: ee => ee.Fraction); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_collection_SelectMany_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set() + .SelectMany(x => x.OwnedCollectionRoot) + .AsNoTrackingWithIdentityResolution(), + elementSorter: e => (e.Number, e.Name)))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_deduplication_with_collection_indexer_in_target_AsNoTrackingWithIdentityResolution(bool async) + { + var prm = 1; + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Duplicate1 = x.OwnedReferenceRoot.OwnedCollectionBranch[1], + Original = x.OwnedReferenceRoot, + Duplicate2 = x.OwnedReferenceRoot.OwnedReferenceBranch.OwnedCollectionLeaf[prm] + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Original, a.Original); + AssertEqual(e.Duplicate1, a.Duplicate1); + AssertEqual(e.Duplicate2, a.Duplicate2); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_nested_collection_and_element_wrong_order_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[0].OwnedCollectionLeaf[1], + Original = x.OwnedReferenceRoot.OwnedCollectionBranch[0].OwnedCollectionLeaf, + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Duplicate, a.Duplicate); + AssertCollection(e.Original, a.Original, ordered: true); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_second_element_projected_before_entire_collection_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[1], + Original = x.OwnedReferenceRoot.OwnedCollectionBranch, + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Original, a.Original); + AssertEqual(e.Duplicate, a.Duplicate); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_second_element_projected_before_owner_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[1], + Original = x.OwnedReferenceRoot, + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Original, a.Original); + AssertEqual(e.Duplicate, a.Duplicate); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Json_projection_second_element_projected_before_owner_nested_AsNoTrackingWithIdentityResolution(bool async) + { + var message = (await Assert.ThrowsAsync(() => + AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x.Id, + Duplicate = x.OwnedReferenceRoot.OwnedReferenceBranch.OwnedCollectionLeaf[1], + Original = x.OwnedReferenceRoot.OwnedReferenceBranch.OwnedCollectionLeaf, + Parent = x.OwnedReferenceRoot.OwnedReferenceBranch, + }).AsNoTrackingWithIdentityResolution(), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Original, a.Original); + AssertEqual(e.Duplicate, a.Duplicate); + }))).Message; + + Assert.Equal( + RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( + "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedReferenceBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", + nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), + message); + } +} diff --git a/test/EFCore.Relational.Specification.Tests/Query/JsonQueryFixtureBase.cs b/test/EFCore.Specification.Tests/Query/JsonQueryFixtureBase.cs similarity index 97% rename from test/EFCore.Relational.Specification.Tests/Query/JsonQueryFixtureBase.cs rename to test/EFCore.Specification.Tests/Query/JsonQueryFixtureBase.cs index 0b1f9f47519..db55c4a6700 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/JsonQueryFixtureBase.cs +++ b/test/EFCore.Specification.Tests/Query/JsonQueryFixtureBase.cs @@ -7,7 +7,7 @@ namespace Microsoft.EntityFrameworkCore.Query; #nullable disable -public abstract class JsonQueryFixtureBase : SharedStoreFixtureBase, IQueryFixtureBase, ITestSqlLoggerFactory +public abstract class JsonQueryFixtureBase : SharedStoreFixtureBase, IQueryFixtureBase { private JsonQueryData _expectedData; @@ -30,7 +30,7 @@ public virtual ISetSource GetExpectedData() { typeof(JsonEntityAllTypes), e => ((JsonEntityAllTypes)e)?.Id }, }.ToDictionary(e => e.Key, e => (object)e.Value); - public IReadOnlyDictionary EntityAsserters { get; } = new Dictionary> + public virtual IReadOnlyDictionary EntityAsserters { get; } = new Dictionary> { { typeof(EntityBasic), (e, a) => @@ -448,24 +448,6 @@ public static void AssertConverters(JsonOwnedConverters expected, JsonOwnedConve Assert.Equal(expected.StringYNConvertedToBool, actual.StringYNConvertedToBool); } - protected override string StoreName { get; } = "JsonQueryTest"; - - public new RelationalTestStore TestStore - => (RelationalTestStore)base.TestStore; - - public TestSqlLoggerFactory TestSqlLoggerFactory - => (TestSqlLoggerFactory)ListLoggerFactory; - - public override JsonQueryContext CreateContext() - { - var context = base.CreateContext(); - - return context; - } - - protected override async Task SeedAsync(JsonQueryContext context) - => await JsonQueryContext.SeedAsync(context); - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) { modelBuilder.Entity().Property(x => x.Id).ValueGeneratedNever(); @@ -481,7 +463,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity().OwnsOne( x => x.OwnedReferenceRoot, b => { - b.ToJson(); b.WithOwner(x => x.Owner); b.OwnsOne( @@ -522,7 +503,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con bb.OwnsOne(x => x.OwnedReferenceLeaf).WithOwner(x => x.Parent); bb.OwnsMany(x => x.OwnedCollectionLeaf); }); - b.ToJson(); }); modelBuilder.Entity().Property(x => x.Id).ValueGeneratedNever(); @@ -532,13 +512,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con b.Property(x => x.Enum).HasConversion(); b.OwnsOne(x => x.OwnedReferenceBranch); b.OwnsMany(x => x.OwnedCollectionBranch); - b.ToJson("json_reference_custom_naming"); }); modelBuilder.Entity().OwnsMany( x => x.OwnedCollectionRoot, b => { - b.ToJson("json_collection_custom_naming"); b.Property(x => x.Enum).HasConversion(); b.OwnsOne(x => x.OwnedReferenceBranch); b.OwnsMany(x => x.OwnedCollectionBranch); @@ -548,7 +526,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity().OwnsMany( x => x.OwnedCollection, b => { - b.ToJson(); b.Ignore(x => x.Parent); }); @@ -559,7 +536,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con b.OwnsOne( x => x.ReferenceOnBase, bb => { - bb.ToJson(); bb.OwnsOne(x => x.OwnedReferenceLeaf); bb.OwnsMany(x => x.OwnedCollectionLeaf); bb.Property(x => x.Fraction).HasPrecision(18, 2); @@ -568,7 +544,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con b.OwnsMany( x => x.CollectionOnBase, bb => { - bb.ToJson(); bb.OwnsOne(x => x.OwnedReferenceLeaf); bb.OwnsMany(x => x.OwnedCollectionLeaf); bb.Property(x => x.Fraction).HasPrecision(18, 2); @@ -582,7 +557,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con b.OwnsOne( x => x.ReferenceOnDerived, bb => { - bb.ToJson(); bb.OwnsOne(x => x.OwnedReferenceLeaf); bb.OwnsMany(x => x.OwnedCollectionLeaf); bb.Property(x => x.Fraction).HasPrecision(18, 2); @@ -591,7 +565,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con b.OwnsMany( x => x.CollectionOnDerived, bb => { - bb.ToJson(); bb.OwnsOne(x => x.OwnedReferenceLeaf); bb.OwnsMany(x => x.OwnedCollectionLeaf); bb.Property(x => x.Fraction).HasPrecision(18, 2); @@ -602,7 +575,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity().OwnsOne( x => x.Reference, b => { - b.ToJson(); b.Property(x => x.TestMaxLengthString).HasMaxLength(5); b.Property(x => x.TestDecimal).HasPrecision(18, 3); b.Property(x => x.TestEnumWithIntConverter).HasConversion(); @@ -630,7 +602,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity().OwnsMany( x => x.Collection, b => { - b.ToJson(); b.Property(x => x.TestMaxLengthString).HasMaxLength(5); b.Property(x => x.TestDecimal).HasPrecision(18, 3); b.Property(x => x.TestEnumWithIntConverter).HasConversion(); @@ -660,7 +631,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity().OwnsOne( x => x.Reference, b => { - b.ToJson(); b.Property(x => x.BoolConvertedToIntZeroOne).HasConversion>(); b.Property(x => x.BoolConvertedToStringTrueFalse).HasConversion(new BoolToStringConverter("False", "True")); b.Property(x => x.BoolConvertedToStringYN).HasConversion(new BoolToStringConverter("N", "Y")); @@ -680,4 +650,16 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con x => x == true ? "Y" : "N")); }); } + + protected override string StoreName { get; } = "JsonQueryTest"; + + public override JsonQueryContext CreateContext() + { + var context = base.CreateContext(); + + return context; + } + + protected override async Task SeedAsync(JsonQueryContext context) + => await JsonQueryContext.SeedAsync(context); } diff --git a/test/EFCore.Relational.Specification.Tests/Query/JsonQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/JsonQueryTestBase.cs similarity index 80% rename from test/EFCore.Relational.Specification.Tests/Query/JsonQueryTestBase.cs rename to test/EFCore.Specification.Tests/Query/JsonQueryTestBase.cs index bafca02ed0a..2a8c939eceb 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/JsonQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/JsonQueryTestBase.cs @@ -114,57 +114,6 @@ public virtual Task Basic_json_projection_owner_entity_twice_NoTrackingWithIdent AssertEqual(e.Second, a.Second); }); - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Project_json_reference_in_tracking_query_fails(bool async) - { - var message = (await Assert.ThrowsAsync( - () => - AssertQuery( - async, - ss => ss.Set().Select(x => x.OwnedReferenceRoot)))).Message; - - Assert.Equal( - RelationalStrings.JsonEntityOrCollectionProjectedAtRootLevelInTrackingQuery( - nameof(EntityFrameworkQueryableExtensions.AsNoTracking)), message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Project_json_collection_in_tracking_query_fails(bool async) - { - var message = (await Assert.ThrowsAsync( - () => - AssertQuery( - async, - ss => ss.Set().Select(x => x.OwnedCollectionRoot)))).Message; - - Assert.Equal( - RelationalStrings.JsonEntityOrCollectionProjectedAtRootLevelInTrackingQuery( - nameof(EntityFrameworkQueryableExtensions.AsNoTracking)), message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Project_json_entity_in_tracking_query_fails_even_when_owner_is_present(bool async) - { - var message = (await Assert.ThrowsAsync( - () => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x, - x.OwnedReferenceRoot, - x.OwnedCollectionRoot - })))).Message; - - Assert.Equal( - RelationalStrings.JsonEntityOrCollectionProjectedAtRootLevelInTrackingQuery( - nameof(EntityFrameworkQueryableExtensions.AsNoTracking)), message); - } - [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Basic_json_projection_owned_reference_root(bool async) @@ -358,7 +307,8 @@ public virtual Task Basic_json_projection_enum_inside_json_entity(bool async) ss => ss.Set().Select( x => new { - x.Id, x.OwnedReferenceRoot.OwnedReferenceBranch.Enum, + x.Id, + x.OwnedReferenceRoot.OwnedReferenceBranch.Enum, }), elementSorter: e => e.Id, elementAsserter: (e, a) => @@ -375,7 +325,8 @@ public virtual Task Json_projection_enum_with_custom_conversion(bool async) ss => ss.Set().Select( x => new { - x.Id, x.OwnedReferenceRoot.Enum, + x.Id, + x.OwnedReferenceRoot.Enum, }), elementSorter: e => e.Id, elementAsserter: (e, a) => @@ -1879,7 +1830,8 @@ public virtual Task Json_collection_index_in_projection_when_owner_is_present_mi ss => ss.Set().Select( x => new { - x, CollectionElement = x.OwnedCollectionRoot[1].OwnedCollectionBranch[prm], + x, + CollectionElement = x.OwnedCollectionRoot[1].OwnedCollectionBranch[prm], }).AsNoTracking(), elementSorter: e => e.x.Id, elementAsserter: (e, a) => @@ -1900,7 +1852,8 @@ public virtual Task Json_collection_index_in_projection_when_owner_is_not_presen ss => ss.Set().Select( x => new { - x.Id, CollectionElement = x.OwnedCollectionRoot[1].OwnedCollectionBranch[prm], + x.Id, + CollectionElement = x.OwnedCollectionRoot[1].OwnedCollectionBranch[prm], }).AsNoTracking(), elementSorter: e => e.Id, elementAsserter: (e, a) => @@ -2635,561 +2588,6 @@ public virtual Task Json_predicate_on_string_Y_N_converted_to_bool(bool async) async, ss => ss.Set().Where(x => x.Reference.StringYNConvertedToBool == "N")); - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual Task FromSql_on_entity_with_json_basic(bool async) - => AssertQuery( - async, - ss => ((DbSet)ss.Set()).FromSqlRaw( - Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesBasic] AS j")), - ss => ss.Set()); - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual Task FromSql_on_entity_with_json_project_json_reference(bool async) - => AssertQuery( - async, - ss => ((DbSet)ss.Set()).FromSqlRaw( - Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesBasic] AS j")) - .AsNoTracking() - .Select(x => x.OwnedReferenceRoot.OwnedReferenceBranch), - ss => ss.Set().Select(x => x.OwnedReferenceRoot.OwnedReferenceBranch)); - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual Task FromSql_on_entity_with_json_project_json_collection(bool async) - => AssertQuery( - async, - ss => ((DbSet)ss.Set()).FromSqlRaw( - Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesBasic] AS j")) - .AsNoTracking() - .Select(x => x.OwnedReferenceRoot.OwnedCollectionBranch), - ss => ss.Set().Select(x => x.OwnedReferenceRoot.OwnedCollectionBranch), - elementAsserter: (e, a) => AssertCollection(e, a, elementSorter: ee => (ee.Date, ee.Enum, ee.Fraction))); - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual Task FromSql_on_entity_with_json_inheritance_on_base(bool async) - => AssertQuery( - async, - ss => ((DbSet)ss.Set()).FromSqlRaw( - Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesInheritance] AS j")), - ss => ss.Set()); - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual Task FromSql_on_entity_with_json_inheritance_on_derived(bool async) - => AssertQuery( - async, - ss => ((DbSet)ss.Set()).FromSqlRaw( - Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesInheritance] AS j")), - ss => ss.Set()); - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual Task FromSql_on_entity_with_json_inheritance_project_reference_on_base(bool async) - => AssertQuery( - async, - ss => ((DbSet)ss.Set()).FromSqlRaw( - Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesInheritance] AS j")) - .AsNoTracking() - .OrderBy(x => x.Id) - .Select(x => x.ReferenceOnBase), - ss => ss.Set().OrderBy(x => x.Id).Select(x => x.ReferenceOnBase), - assertOrder: true); - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual Task FromSql_on_entity_with_json_inheritance_project_reference_on_derived(bool async) - => AssertQuery( - async, - ss => ((DbSet)ss.Set()).FromSqlRaw( - Fixture.TestStore.NormalizeDelimitersInRawString("SELECT * FROM [JsonEntitiesInheritance] AS j")) - .AsNoTracking() - .OrderBy(x => x.Id) - .Select(x => x.CollectionOnDerived), - ss => ss.Set().OrderBy(x => x.Id).Select(x => x.CollectionOnDerived), - elementAsserter: (e, a) => AssertCollection(e, a, elementSorter: ee => (ee.Date, ee.Enum, ee.Fraction)), - assertOrder: true); - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_using_queryable_methods_on_top_of_JSON_collection_AsNoTrackingWithIdentityResolution(bool async) - { - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Skip = x.OwnedCollectionRoot.Skip(1).ToList(), - Take = x.OwnedCollectionRoot.Take(2).ToList(), - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertCollection(e.Skip, a.Skip); - AssertCollection(e.Take, a.Take); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_nested_collection_anonymous_projection_in_projection_NoTrackingWithIdentityResolution(bool async) - { - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set() - .OrderBy(x => x.Id) - .Select( - x => x.OwnedCollectionRoot - .Select( - xx => xx.OwnedCollectionBranch.Select( - xxx => new - { - xxx.Date, - xxx.Enum, - xxx.Enums, - xxx.Fraction, - xxx.OwnedReferenceLeaf, - xxx.OwnedCollectionLeaf - }).ToList())) - .AsNoTrackingWithIdentityResolution(), - assertOrder: true, - elementAsserter: (e, a) => AssertCollection( - e, a, ordered: true, elementAsserter: (ee, aa) => AssertCollection( - ee, aa, ordered: true, elementAsserter: (eee, aaa) => - { - AssertEqual(eee.Date, aaa.Date); - AssertEqual(eee.Enum, aaa.Enum); - AssertCollection(eee.Enums, aaa.Enums, ordered: true); - AssertEqual(eee.Fraction, aaa.Fraction); - AssertEqual(eee.OwnedReferenceLeaf, aaa.OwnedReferenceLeaf); - AssertCollection(eee.OwnedCollectionLeaf, aaa.OwnedCollectionLeaf, ordered: true); - }))))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_nested_collection_and_element_using_parameter_AsNoTrackingWithIdentityResolution(bool async) - { - var prm = 0; - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf, - Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf[1], - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertEqual(e.Duplicate, a.Duplicate); - AssertCollection(e.Original, a.Original, ordered: true); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_nested_collection_and_element_using_parameter_AsNoTrackingWithIdentityResolution2(bool async) - { - var prm1 = 0; - var prm2 = 0; - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm1].OwnedCollectionLeaf[1], - Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm2].OwnedCollectionLeaf, - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertEqual(e.Duplicate, a.Duplicate); - AssertCollection(e.Original, a.Original, ordered: true); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_second_element_through_collection_element_parameter_different_values_projected_before_owner_nested_AsNoTrackingWithIdentityResolution(bool async) - { - var prm1 = 0; - var prm2 = 1; - - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm1].OwnedCollectionLeaf[1], - Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm2].OwnedCollectionLeaf, - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertCollection(e.Original, a.Original, ordered: true); - AssertEqual(e.Duplicate, a.Duplicate); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_second_element_through_collection_element_parameter_projected_before_owner_nested_AsNoTrackingWithIdentityResolution(bool async) - { - var prm = 0; - - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf[1], - Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf, - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertCollection(e.Original, a.Original, ordered: true); - AssertEqual(e.Duplicate, a.Duplicate); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_second_element_through_collection_element_parameter_projected_before_owner_nested_AsNoTrackingWithIdentityResolution2(bool async) - { - var prm1 = 0; - var prm2 = 0; - - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm1].OwnedCollectionLeaf[1], - Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm2].OwnedCollectionLeaf, - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertEqual(e.Original, a.Original); - AssertEqual(e.Duplicate, a.Duplicate); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_second_element_through_collection_element_parameter_projected_after_owner_nested_AsNoTrackingWithIdentityResolution(bool async) - { - var prm = 0; - - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Original = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf, - Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[prm].OwnedCollectionLeaf[1], - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertCollection(e.Original, a.Original, ordered: true); - AssertEqual(e.Duplicate, a.Duplicate); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingCollectionElementAccessedUsingParmeterNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_second_element_through_collection_element_constant_projected_before_owner_nested_AsNoTrackingWithIdentityResolution(bool async) - { - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[0].OwnedCollectionLeaf[1], - Original = x.OwnedReferenceRoot.OwnedCollectionBranch[0].OwnedCollectionLeaf, - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertEqual(e.Original, a.Original); - AssertEqual(e.Duplicate, a.Duplicate); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_branch_collection_distinct_and_other_collection_AsNoTrackingWithIdentityResolution(bool async) - { - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set() - .OrderBy(x => x.Id) - .Select( - x => new - { - First = x.EntityCollection.ToList(), - Second = x.OwnedReferenceRoot.OwnedCollectionBranch.Distinct().ToList() - }) - .AsNoTrackingWithIdentityResolution(), - assertOrder: true, - elementAsserter: (e, a) => - { - AssertCollection(e.First, a.First, ordered: true); - AssertCollection(e.Second, a.Second, elementSorter: ee => ee.Fraction); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_collection_SelectMany_AsNoTrackingWithIdentityResolution(bool async) - { - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set() - .SelectMany(x => x.OwnedCollectionRoot) - .AsNoTrackingWithIdentityResolution(), - elementSorter: e => (e.Number, e.Name)))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_deduplication_with_collection_indexer_in_target_AsNoTrackingWithIdentityResolution(bool async) - { - var prm = 1; - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Duplicate1 = x.OwnedReferenceRoot.OwnedCollectionBranch[1], - Original = x.OwnedReferenceRoot, - Duplicate2 = x.OwnedReferenceRoot.OwnedReferenceBranch.OwnedCollectionLeaf[prm] - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertEqual(e.Original, a.Original); - AssertEqual(e.Duplicate1, a.Duplicate1); - AssertEqual(e.Duplicate2, a.Duplicate2); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_nested_collection_and_element_wrong_order_AsNoTrackingWithIdentityResolution(bool async) - { - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[0].OwnedCollectionLeaf[1], - Original = x.OwnedReferenceRoot.OwnedCollectionBranch[0].OwnedCollectionLeaf, - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertEqual(e.Duplicate, a.Duplicate); - AssertCollection(e.Original, a.Original, ordered: true); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_second_element_projected_before_entire_collection_AsNoTrackingWithIdentityResolution(bool async) - { - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[1], - Original = x.OwnedReferenceRoot.OwnedCollectionBranch, - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertEqual(e.Original, a.Original); - AssertEqual(e.Duplicate, a.Duplicate); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_second_element_projected_before_owner_AsNoTrackingWithIdentityResolution(bool async) - { - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Duplicate = x.OwnedReferenceRoot.OwnedCollectionBranch[1], - Original = x.OwnedReferenceRoot, - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertEqual(e.Original, a.Original); - AssertEqual(e.Duplicate, a.Duplicate); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedCollectionBranch#JsonOwnedBranch", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual async Task Json_projection_second_element_projected_before_owner_nested_AsNoTrackingWithIdentityResolution(bool async) - { - var message = (await Assert.ThrowsAsync(() => - AssertQuery( - async, - ss => ss.Set().Select( - x => new - { - x.Id, - Duplicate = x.OwnedReferenceRoot.OwnedReferenceBranch.OwnedCollectionLeaf[1], - Original = x.OwnedReferenceRoot.OwnedReferenceBranch.OwnedCollectionLeaf, - Parent = x.OwnedReferenceRoot.OwnedReferenceBranch, - }).AsNoTrackingWithIdentityResolution(), - elementSorter: e => e.Id, - elementAsserter: (e, a) => - { - AssertEqual(e.Id, a.Id); - AssertEqual(e.Original, a.Original); - AssertEqual(e.Duplicate, a.Duplicate); - }))).Message; - - Assert.Equal( - RelationalStrings.JsonProjectingEntitiesIncorrectOrderNoTrackingWithIdentityResolution( - "JsonEntityBasic.OwnedReferenceRoot#JsonOwnedRoot.OwnedReferenceBranch#JsonOwnedBranch.OwnedCollectionLeaf#JsonOwnedLeaf", - nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)), - message); - } - [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Json_projection_collection_element_and_reference_AsNoTrackingWithIdentityResolution(bool async) @@ -3496,4 +2894,34 @@ public virtual Task Json_projection_second_element_projected_before_owner_nested AssertCollection(e.Original, a.Original, ordered: true); AssertEqual(e.Owner, a.Owner); }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_json_reference_in_tracking_query_fails(bool async) + // verify exception on the provider level, relational and core throw different exceptions + => AssertQuery( + async, + ss => ss.Set().Select(x => x.OwnedReferenceRoot)); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_json_collection_in_tracking_query_fails(bool async) + // verify exception on the provider level, relational and core throw different exceptions + => AssertQuery( + async, + ss => ss.Set().Select(x => x.OwnedCollectionRoot)); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_json_entity_in_tracking_query_fails_even_when_owner_is_present(bool async) + // verify exception on the provider level, relational and core throw different exceptions + => AssertQuery( + async, + ss => ss.Set().Select( + x => new + { + x, + x.OwnedReferenceRoot, + x.OwnedCollectionRoot + })); } diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/EntityBasic.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/EntityBasic.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/EntityBasic.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/EntityBasic.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityAllTypes.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityAllTypes.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityAllTypes.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityAllTypes.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityBasic.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityBasic.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityBasic.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityBasic.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityBasicForCollection.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityBasicForCollection.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityBasicForCollection.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityBasicForCollection.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityBasicForReference.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityBasicForReference.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityBasicForReference.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityBasicForReference.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityConverters.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityConverters.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityConverters.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityConverters.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityCustomNaming.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityCustomNaming.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityCustomNaming.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityCustomNaming.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityInheritanceBase.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityInheritanceBase.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityInheritanceBase.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityInheritanceBase.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityInheritanceDerived.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityInheritanceDerived.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntityInheritanceDerived.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntityInheritanceDerived.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntitySingleOwned.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntitySingleOwned.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEntitySingleOwned.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEntitySingleOwned.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEnum.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEnum.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonEnum.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonEnum.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedAllTypes.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedAllTypes.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedAllTypes.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedAllTypes.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedBranch.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedBranch.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedBranch.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedBranch.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedConverters.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedConverters.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedConverters.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedConverters.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedCustomNameBranch.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedCustomNameBranch.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedCustomNameBranch.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedCustomNameBranch.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedCustomNameRoot.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedCustomNameRoot.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedCustomNameRoot.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedCustomNameRoot.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedLeaf.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedLeaf.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedLeaf.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedLeaf.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedRoot.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedRoot.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonOwnedRoot.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonOwnedRoot.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonQueryContext.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonQueryContext.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonQueryContext.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonQueryContext.cs diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonQueryData.cs b/test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonQueryData.cs similarity index 100% rename from test/EFCore.Relational.Specification.Tests/TestModels/JsonQuery/JsonQueryData.cs rename to test/EFCore.Specification.Tests/TestModels/JsonQuery/JsonQueryData.cs diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/JsonQuerySqlServerFixture.cs b/test/EFCore.SqlServer.FunctionalTests/Query/JsonQuerySqlServerFixture.cs index 8a27e9a4204..21d51690775 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/JsonQuerySqlServerFixture.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/JsonQuerySqlServerFixture.cs @@ -7,7 +7,7 @@ namespace Microsoft.EntityFrameworkCore.Query; #nullable disable -public class JsonQuerySqlServerFixture : JsonQueryFixtureBase +public class JsonQuerySqlServerFixture : JsonQueryRelationalFixture { protected override ITestStoreFactory TestStoreFactory => SqlServerTestStoreFactory.Instance; diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/JsonQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/JsonQuerySqlServerTest.cs index 4708094c080..391940ef030 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/JsonQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/JsonQuerySqlServerTest.cs @@ -8,7 +8,7 @@ namespace Microsoft.EntityFrameworkCore.Query; #nullable disable -public class JsonQuerySqlServerTest : JsonQueryTestBase +public class JsonQuerySqlServerTest : JsonQueryRelationalTestBase { public JsonQuerySqlServerTest(JsonQuerySqlServerFixture fixture, ITestOutputHelper testOutputHelper) : base(fixture) diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/JsonQuerySqliteFixture.cs b/test/EFCore.Sqlite.FunctionalTests/Query/JsonQuerySqliteFixture.cs index 904e795ae09..691db31b098 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/JsonQuerySqliteFixture.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/JsonQuerySqliteFixture.cs @@ -7,7 +7,7 @@ namespace Microsoft.EntityFrameworkCore.Query; #nullable disable -public class JsonQuerySqliteFixture : JsonQueryFixtureBase +public class JsonQuerySqliteFixture : JsonQueryRelationalFixture { protected override ITestStoreFactory TestStoreFactory => SqliteTestStoreFactory.Instance; diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/JsonQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/JsonQuerySqliteTest.cs index 6ef5930c7d5..d4340526ff2 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/JsonQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/JsonQuerySqliteTest.cs @@ -10,7 +10,7 @@ namespace Microsoft.EntityFrameworkCore.Query; #nullable disable -public class JsonQuerySqliteTest : JsonQueryTestBase +public class JsonQuerySqliteTest : JsonQueryRelationalTestBase { public JsonQuerySqliteTest(JsonQuerySqliteFixture fixture, ITestOutputHelper testOutputHelper) : base(fixture)