From 506f61be8d766554a7ca88c925eb275a729d7934 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Wed, 13 Mar 2019 06:45:02 +0200 Subject: [PATCH 1/4] Tests for proxy interface handling --- .../InterfaceHandling/Fixture.cs | 169 +++++++++++++++++ .../InterfaceHandling/BaseInterfaces.cs | 16 ++ .../InterfaceHandling/Entities.cs | 71 ++++++++ .../InterfaceHandling/Fixture.cs | 171 ++++++++++++++++++ .../InterfaceHandling/SubclassEntities.cs | 31 ++++ 5 files changed, 458 insertions(+) create mode 100644 src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs create mode 100644 src/NHibernate.Test/StaticProxyTest/InterfaceHandling/BaseInterfaces.cs create mode 100644 src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs create mode 100644 src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs create mode 100644 src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs diff --git a/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs b/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs new file mode 100644 index 00000000000..75dffc4101d --- /dev/null +++ b/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs @@ -0,0 +1,169 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by AsyncGenerator. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +using System; +using NHibernate.Cfg; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.StaticProxyTest.InterfaceHandling +{ + using System.Threading.Tasks; + [TestFixture] + public class FixtureAsync : TestCaseMappingByCode + { + private Guid _id = Guid.NewGuid(); + + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + + #region Subclass hierarchy + + mapper.Class( + rc => + { + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + mapper.UnionSubclass( + rc => + { + rc.Proxy(typeof(ISubEntityProxy)); + + rc.Property(x => x.AnotherName); + }); + + mapper.UnionSubclass( + rc => + { + rc.Proxy(typeof(IAnotherSubEntityProxy)); + + rc.Property(x => x.AnotherName); + }); + + mapper.Class( + rc => + { + rc.Id(x => x.Id); + rc.Property(x => x.Name); + rc.ManyToOne(x => x.EntityLookup, x => x.Class(typeof(EntityClassProxy))); + }); + + #endregion Subclass hierarchy + + mapper.Class( + rc => + { + + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + mapper.Class( + rc => + { + + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + mapper.Class( + rc => + { + + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + mapper.Class( + rc => + { + + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + return mapper.CompileMappingForAllExplicitlyAddedEntities(); + } + + [Test] + public async Task ProxyForBaseSubclassCanBeCreatedAsync() + { + using (var session = OpenSession()) + { + var entity = await (session.LoadAsync(_id)); + } + } + + [Test] + public async Task ProxyForBaseSubclassByInterfaceAsync() + { + using (var session = OpenSession()) + { + var entity = (IEntity) await (session.LoadAsync(typeof(EntityClassProxy), _id)); + ThrowOnIdAccess(entity); + } + } + + [Test] + public async Task ProxyForEntityImplicitInterfaceAsync() + { + using (var session = OpenSession()) + { + var entity = (IEntity) await (session.LoadAsync(_id)); + ThrowOnIdAccess(entity); + ThrowOnNameAccess(entity); + + var multiInterface = await (session.LoadAsync(_id)); + ThrowOnIdAccess(multiInterface); + ThrowOnIdAccessSecond(multiInterface); + } + } + + [Test] + public async Task ProxyForEntityInitializeOnExplicitInterfaceAsync() + { + using (var session = OpenSession()) + { + var entity = await (session.LoadAsync(_id)); + ThrowOnIdAccess(entity); + } + } + + [Test] + public async Task ProxyForEntityWithMixedImplicitExplicitInterfacesAreHandledCorrectlyAsync() + { + using (var session = OpenSession()) + { + var entity = await (session.LoadAsync(_id)); + ThrowOnIdAccessSecond(entity); + ThrowOnIdAccess(entity); + } + } + + private void ThrowOnNameAccess(IEntity entity) + { + Assert.That(() => entity.Name, Throws.TypeOf(), "Non Id interface access should lead to proxy initialization"); + } + + private void ThrowOnIdAccess(IEntity entity) + { + Assert.That(() => entity.Id, Throws.TypeOf(), "IEntity.Id access should lead to proxy initialization"); + } + + private void ThrowOnIdAccessSecond(IEntityId entity) + { + Assert.That(() => entity.Id, Throws.TypeOf(), "IEntityId.Id access should lead to proxy initialization"); + } + } +} diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/BaseInterfaces.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/BaseInterfaces.cs new file mode 100644 index 00000000000..51821ec4517 --- /dev/null +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/BaseInterfaces.cs @@ -0,0 +1,16 @@ +using System; + +namespace NHibernate.Test.StaticProxyTest.InterfaceHandling +{ + public interface IEntity + { + Guid Id { get; set; } + + string Name { get; set; } + } + + public interface IEntityId + { + Guid Id { get; set; } + } +} diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs new file mode 100644 index 00000000000..663b9950ff1 --- /dev/null +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs @@ -0,0 +1,71 @@ +using System; + +namespace NHibernate.Test.StaticProxyTest.InterfaceHandling +{ + public class EntitySimple : IEntity + { + public virtual Guid Id { get; set; } + + public virtual string Name { get; set; } + } + + public class EntityMultiInterfaces : IEntity, IEntityId + { + public virtual Guid Id { get; set; } + + public virtual string Name { get; set; } + } + + public class EntityExplicitInterface : IEntity + { + private Guid id; + private string name; + + public virtual Guid Id { get; set; } + + public virtual string Name { get; set; } + + Guid IEntity.Id + { + get => id; + set => id = value; + } + + string IEntity.Name + { + get => name; + set => name = value; + } + } + + public class EntityMixExplicitImplicitInterface : IEntity, IEntityId + { + private Guid id; + private string name; + + public virtual Guid Id { get; set; } + + public virtual string Name { get; set; } + + Guid IEntity.Id + { + get => id; + set => id = value; + } + + string IEntity.Name + { + get => name; + set => name = value; + } + } + + public class EntityWithSuperClassInterfaceLookup + { + public virtual Guid Id { get; set; } + + public virtual string Name { get; set; } + + public virtual IEntity EntityLookup { get; set; } + } +} diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs new file mode 100644 index 00000000000..e1985e59c2a --- /dev/null +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs @@ -0,0 +1,171 @@ +using System; +using NHibernate.Cfg; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.StaticProxyTest.InterfaceHandling +{ + [TestFixture] + public class Fixture : TestCaseMappingByCode + { + private Guid _id = Guid.NewGuid(); + + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + + #region Subclass hierarchy + + mapper.Class( + rc => + { + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + mapper.UnionSubclass( + rc => + { + rc.Proxy(typeof(ISubEntityProxy)); + + rc.Property(x => x.AnotherName); + }); + + mapper.UnionSubclass( + rc => + { + rc.Proxy(typeof(IAnotherSubEntityProxy)); + + rc.Property(x => x.AnotherName); + }); + + mapper.Class( + rc => + { + rc.Id(x => x.Id); + rc.Property(x => x.Name); + rc.ManyToOne(x => x.EntityLookup, x => x.Class(typeof(EntityClassProxy))); + }); + + #endregion Subclass hierarchy + + mapper.Class( + rc => + { + + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + mapper.Class( + rc => + { + + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + mapper.Class( + rc => + { + + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + mapper.Class( + rc => + { + + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + return mapper.CompileMappingForAllExplicitlyAddedEntities(); + } + + [Test] + public void ProxyForBaseSubclassCanBeCreated() + { + using (var session = OpenSession()) + { + var entity = session.Load(_id); + } + } + + //This test is passed because of wrong proxy generation (generated proxy is not based on EntityClassProxy) + [Test] + public void ProxyForBaseSubclassByInterface() + { + using (var session = OpenSession()) + { + var entity = (IEntity) session.Load(typeof(EntityClassProxy), _id); + ThrowOnIdAccess(entity); + } + } + + [Test] + public void ProxyForEntityImplicitInterface() + { + using (var session = OpenSession()) + { + var entity = (IEntity) session.Load(_id); + ThrowOnIdAccess(entity); + ThrowOnNameAccess(entity); + + var multiInterface = session.Load(_id); + ThrowOnIdAccess(multiInterface); + ThrowOnIdAccessSecond(multiInterface); + } + } + + [Test] + public void ProxyForEntityInitializeOnExplicitInterface() + { + using (var session = OpenSession()) + { + var entity = session.Load(_id); + ThrowOnIdAccess(entity); + } + } + + [Test] + public void ProxyForEntityWithMixedImplicitExplicitInterfacesAreHandledCorrectly() + { + using (var session = OpenSession()) + { + var entity = session.Load(_id); + ThrowOnIdAccessSecond(entity); + ThrowOnIdAccess(entity); + } + } + + private void ThrowOnNameAccess(IEntity entity) + { + Assert.That(() => entity.Name, Throws.TypeOf(), "Non Id interface access should lead to proxy initialization"); + } + + private void ThrowOnIdAccess(IEntity entity) + { + Assert.That(() => entity.Id, Throws.TypeOf(), "IEntity.Id access should lead to proxy initialization"); + } + + private void ThrowOnIdAccessSecond(IEntityId entity) + { + Assert.That(() => entity.Id, Throws.TypeOf(), "IEntityId.Id access should lead to proxy initialization"); + } + + private void CanAccessId(IEntity entity) + { + Assert.That(() => entity.Id, Throws.Nothing, "Failed to access proxy IEntity.Id interface"); + Assert.That(entity.Id, Is.EqualTo(_id)); + } + + private void CanAccessSecond(IEntityId entity) + { + Assert.That(() => entity.Id, Throws.Nothing, "Failed to access proxy IEntityId.Id interface"); + Assert.That(entity.Id, Is.EqualTo(_id)); + } + } +} diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs new file mode 100644 index 00000000000..a804f9bd0bd --- /dev/null +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs @@ -0,0 +1,31 @@ +using System; + +namespace NHibernate.Test.StaticProxyTest.InterfaceHandling +{ + public interface ISubEntityProxy : IEntity + { + string AnotherName { get; set; } + } + + public class EntityClassProxy : IEntity + { + public virtual Guid Id { get; set; } + + public virtual string Name { get; set; } + } + + class SubEntityInterfaceProxy : EntityClassProxy, ISubEntityProxy + { + public virtual string AnotherName { get; set; } + } + + public interface IAnotherSubEntityProxy : IEntity + { + string AnotherName { get; set; } + } + + class AnotherSubEntityInterfaceProxy : EntityClassProxy, IAnotherSubEntityProxy + { + public virtual string AnotherName { get; set; } + } +} From 2c29dc5e960ae9c7dbe2757e6384574904a1e3c7 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Tue, 12 Nov 2019 12:24:18 +0200 Subject: [PATCH 2/4] Adjust tests --- .../InterfaceHandling/Fixture.cs | 77 ++++++++++++------ .../InterfaceHandling/BaseInterfaces.cs | 4 +- .../InterfaceHandling/Entities.cs | 4 +- .../InterfaceHandling/Fixture.cs | 81 +++++++++++-------- .../InterfaceHandling/SubclassEntities.cs | 4 +- 5 files changed, 106 insertions(+), 64 deletions(-) diff --git a/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs b/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs index 75dffc4101d..9e2d3df3d75 100644 --- a/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs +++ b/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs @@ -9,7 +9,6 @@ using System; -using NHibernate.Cfg; using NHibernate.Cfg.MappingSchema; using NHibernate.Mapping.ByCode; using NUnit.Framework; @@ -20,7 +19,7 @@ namespace NHibernate.Test.StaticProxyTest.InterfaceHandling [TestFixture] public class FixtureAsync : TestCaseMappingByCode { - private Guid _id = Guid.NewGuid(); + private readonly Guid _id = Guid.NewGuid(); protected override HbmMapping GetMappings() { @@ -46,7 +45,7 @@ protected override HbmMapping GetMappings() mapper.UnionSubclass( rc => { - rc.Proxy(typeof(IAnotherSubEntityProxy)); + rc.Proxy(typeof(IAmbigiousSubEntityProxy)); rc.Property(x => x.AnotherName); }); @@ -105,65 +104,93 @@ public async Task ProxyForBaseSubclassCanBeCreatedAsync() } } + //Id access via implicit interface should not lead to proxy initialization [Test] - public async Task ProxyForBaseSubclassByInterfaceAsync() + public async Task ProxyClassIdAccessByImplicitInterfaceAsync() { using (var session = OpenSession()) { - var entity = (IEntity) await (session.LoadAsync(typeof(EntityClassProxy), _id)); - ThrowOnIdAccess(entity); + var entity = (IEntity) await (session.LoadAsync(_id)); + CanAccessIEntityId(entity); + ThrowOnIEntityNameAccess(entity); + Assert.That(entity.Id, Is.EqualTo(_id)); + + var multiInterface = await (session.LoadAsync(_id)); + CanAccessIEntityId(multiInterface); + CanAccessIEntity2Id(multiInterface); + Assert.That(multiInterface.Id, Is.EqualTo(_id)); } } [Test] - public async Task ProxyForEntityImplicitInterfaceAsync() + public async Task ProxyClassIdAccessExplicitInterfaceAsync() { using (var session = OpenSession()) { - var entity = (IEntity) await (session.LoadAsync(_id)); - ThrowOnIdAccess(entity); - ThrowOnNameAccess(entity); + var entity = await (session.LoadAsync(_id)); - var multiInterface = await (session.LoadAsync(_id)); - ThrowOnIdAccess(multiInterface); - ThrowOnIdAccessSecond(multiInterface); + ThrowOnIEntityIdAccess(entity); + Assert.That(entity.Id, Is.EqualTo(_id)); } } [Test] - public async Task ProxyForEntityInitializeOnExplicitInterfaceAsync() + public async Task ProxyClassIdAccessBothImplicitExplicitInterfacesAsync() { using (var session = OpenSession()) { - var entity = await (session.LoadAsync(_id)); - ThrowOnIdAccess(entity); + var entity = await (session.LoadAsync(_id)); + + //IEntity2 is implicit and should be accessible without proxy initialization + CanAccessIEntity2Id(entity); + ThrowOnIEntityIdAccess(entity); } } [Test] - public async Task ProxyForEntityWithMixedImplicitExplicitInterfacesAreHandledCorrectlyAsync() + public async Task ProxyInterfaceAsync() { using (var session = OpenSession()) { - var entity = await (session.LoadAsync(_id)); - ThrowOnIdAccessSecond(entity); - ThrowOnIdAccess(entity); + var entity = await (session.LoadAsync(_id)); + + CanAccessIEntityId(entity); } } - private void ThrowOnNameAccess(IEntity entity) + [KnownBug("GH-2271")] + [Test] + public async Task ProxyInterfaceCanAccessIdFromDifferentInterfacesAsync() { - Assert.That(() => entity.Name, Throws.TypeOf(), "Non Id interface access should lead to proxy initialization"); + using (var session = OpenSession()) + { + var entity = await (session.LoadAsync(_id)); + + CanAccessIEntityId(entity); + CanAccessIEntity2Id(entity); + } } - private void ThrowOnIdAccess(IEntity entity) + private void ThrowOnIEntityNameAccess(IEntity entity) + { + Assert.That(() => entity.Name, Throws.TypeOf(), "IEntity.Name access should lead to proxy initialization"); + } + + private void ThrowOnIEntityIdAccess(IEntity entity) { Assert.That(() => entity.Id, Throws.TypeOf(), "IEntity.Id access should lead to proxy initialization"); } - private void ThrowOnIdAccessSecond(IEntityId entity) + private void CanAccessIEntityId(IEntity entity) + { + Assert.That(() => entity.Id, Throws.Nothing, "Failed to access proxy IEntity.Id interface"); + Assert.That(entity.Id, Is.EqualTo(_id)); + } + + private void CanAccessIEntity2Id(IEntity2 entity) { - Assert.That(() => entity.Id, Throws.TypeOf(), "IEntityId.Id access should lead to proxy initialization"); + Assert.That(() => entity.Id, Throws.Nothing, "Failed to access proxy IEntity2.Id interface"); + Assert.That(entity.Id, Is.EqualTo(_id)); } } } diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/BaseInterfaces.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/BaseInterfaces.cs index 51821ec4517..7beade98061 100644 --- a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/BaseInterfaces.cs +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/BaseInterfaces.cs @@ -8,8 +8,8 @@ public interface IEntity string Name { get; set; } } - - public interface IEntityId + + public interface IEntity2 { Guid Id { get; set; } } diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs index 663b9950ff1..8c393267d3c 100644 --- a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs @@ -9,7 +9,7 @@ public class EntitySimple : IEntity public virtual string Name { get; set; } } - public class EntityMultiInterfaces : IEntity, IEntityId + public class EntityMultiInterfaces : IEntity, IEntity2 { public virtual Guid Id { get; set; } @@ -38,7 +38,7 @@ string IEntity.Name } } - public class EntityMixExplicitImplicitInterface : IEntity, IEntityId + public class EntityMixExplicitImplicitInterface : IEntity, IEntity2 { private Guid id; private string name; diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs index e1985e59c2a..f0d44539ac6 100644 --- a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs @@ -1,5 +1,4 @@ using System; -using NHibernate.Cfg; using NHibernate.Cfg.MappingSchema; using NHibernate.Mapping.ByCode; using NUnit.Framework; @@ -9,7 +8,7 @@ namespace NHibernate.Test.StaticProxyTest.InterfaceHandling [TestFixture] public class Fixture : TestCaseMappingByCode { - private Guid _id = Guid.NewGuid(); + private readonly Guid _id = Guid.NewGuid(); protected override HbmMapping GetMappings() { @@ -35,7 +34,7 @@ protected override HbmMapping GetMappings() mapper.UnionSubclass( rc => { - rc.Proxy(typeof(IAnotherSubEntityProxy)); + rc.Proxy(typeof(IAmbigiousSubEntityProxy)); rc.Property(x => x.AnotherName); }); @@ -53,7 +52,6 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { - rc.Id(x => x.Id); rc.Property(x => x.Name); }); @@ -61,7 +59,6 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { - rc.Id(x => x.Id); rc.Property(x => x.Name); }); @@ -69,7 +66,6 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { - rc.Id(x => x.Id); rc.Property(x => x.Name); }); @@ -77,7 +73,6 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { - rc.Id(x => x.Id); rc.Property(x => x.Name); }); @@ -93,78 +88,98 @@ public void ProxyForBaseSubclassCanBeCreated() var entity = session.Load(_id); } } - - //This test is passed because of wrong proxy generation (generated proxy is not based on EntityClassProxy) + + //Id access via implicit interface should not lead to proxy initialization [Test] - public void ProxyForBaseSubclassByInterface() + public void ProxyClassIdAccessByImplicitInterface() { using (var session = OpenSession()) { - var entity = (IEntity) session.Load(typeof(EntityClassProxy), _id); - ThrowOnIdAccess(entity); + var entity = (IEntity) session.Load(_id); + CanAccessIEntityId(entity); + ThrowOnIEntityNameAccess(entity); + Assert.That(entity.Id, Is.EqualTo(_id)); + + var multiInterface = session.Load(_id); + CanAccessIEntityId(multiInterface); + CanAccessIEntity2Id(multiInterface); + Assert.That(multiInterface.Id, Is.EqualTo(_id)); } } [Test] - public void ProxyForEntityImplicitInterface() + public void ProxyClassIdAccessExplicitInterface() { using (var session = OpenSession()) { - var entity = (IEntity) session.Load(_id); - ThrowOnIdAccess(entity); - ThrowOnNameAccess(entity); + var entity = session.Load(_id); - var multiInterface = session.Load(_id); - ThrowOnIdAccess(multiInterface); - ThrowOnIdAccessSecond(multiInterface); + ThrowOnIEntityIdAccess(entity); + Assert.That(entity.Id, Is.EqualTo(_id)); } } [Test] - public void ProxyForEntityInitializeOnExplicitInterface() + public void ProxyClassIdAccessBothImplicitExplicitInterfaces() { using (var session = OpenSession()) { - var entity = session.Load(_id); - ThrowOnIdAccess(entity); + var entity = session.Load(_id); + + //IEntity2 is implicit and should be accessible without proxy initialization + CanAccessIEntity2Id(entity); + ThrowOnIEntityIdAccess(entity); } } [Test] - public void ProxyForEntityWithMixedImplicitExplicitInterfacesAreHandledCorrectly() + public void ProxyInterface() { using (var session = OpenSession()) { - var entity = session.Load(_id); - ThrowOnIdAccessSecond(entity); - ThrowOnIdAccess(entity); + var entity = session.Load(_id); + + CanAccessIEntityId(entity); + } + } + + [KnownBug("GH-2271")] + [Test] + public void ProxyInterfaceCanAccessIdFromDifferentInterfaces() + { + using (var session = OpenSession()) + { + var entity = session.Load(_id); + + CanAccessIEntityId(entity); + CanAccessIEntity2Id(entity); } } - private void ThrowOnNameAccess(IEntity entity) + private void ThrowOnIEntityNameAccess(IEntity entity) { - Assert.That(() => entity.Name, Throws.TypeOf(), "Non Id interface access should lead to proxy initialization"); + Assert.That(() => entity.Name, Throws.TypeOf(), "IEntity.Name access should lead to proxy initialization"); } - private void ThrowOnIdAccess(IEntity entity) + private void ThrowOnIEntityIdAccess(IEntity entity) { Assert.That(() => entity.Id, Throws.TypeOf(), "IEntity.Id access should lead to proxy initialization"); } - private void ThrowOnIdAccessSecond(IEntityId entity) + private void ThrowOnIEntity2IdAccess(IEntity2 entity) { Assert.That(() => entity.Id, Throws.TypeOf(), "IEntityId.Id access should lead to proxy initialization"); } - private void CanAccessId(IEntity entity) + private void CanAccessIEntityId(IEntity entity) { Assert.That(() => entity.Id, Throws.Nothing, "Failed to access proxy IEntity.Id interface"); Assert.That(entity.Id, Is.EqualTo(_id)); } - private void CanAccessSecond(IEntityId entity) + private void CanAccessIEntity2Id(IEntity2 entity) { - Assert.That(() => entity.Id, Throws.Nothing, "Failed to access proxy IEntityId.Id interface"); + Assert.That(() => entity.Id, Throws.Nothing, "Failed to access proxy IEntity2.Id interface"); Assert.That(entity.Id, Is.EqualTo(_id)); } } diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs index a804f9bd0bd..491d0df87be 100644 --- a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs @@ -19,12 +19,12 @@ class SubEntityInterfaceProxy : EntityClassProxy, ISubEntityProxy public virtual string AnotherName { get; set; } } - public interface IAnotherSubEntityProxy : IEntity + public interface IAmbigiousSubEntityProxy : IEntity, IEntity2 { string AnotherName { get; set; } } - class AnotherSubEntityInterfaceProxy : EntityClassProxy, IAnotherSubEntityProxy + class AnotherSubEntityInterfaceProxy : EntityClassProxy, IAmbigiousSubEntityProxy { public virtual string AnotherName { get; set; } } From 666494cba45ff5a2b3e1643d0a6921f23d930869 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Tue, 12 Nov 2019 16:51:16 +0200 Subject: [PATCH 3/4] User shorter names --- .../Async/StaticProxyTest/InterfaceHandling/Fixture.cs | 5 +---- .../StaticProxyTest/InterfaceHandling/Fixture.cs | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs b/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs index 9e2d3df3d75..97db33c16e3 100644 --- a/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs +++ b/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs @@ -53,6 +53,7 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { + rc.Table("ClassWithInterfaceLookup"); rc.Id(x => x.Id); rc.Property(x => x.Name); rc.ManyToOne(x => x.EntityLookup, x => x.Class(typeof(EntityClassProxy))); @@ -63,7 +64,6 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { - rc.Id(x => x.Id); rc.Property(x => x.Name); }); @@ -71,7 +71,6 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { - rc.Id(x => x.Id); rc.Property(x => x.Name); }); @@ -79,7 +78,6 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { - rc.Id(x => x.Id); rc.Property(x => x.Name); }); @@ -87,7 +85,6 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { - rc.Id(x => x.Id); rc.Property(x => x.Name); }); diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs index f0d44539ac6..2028ad4026f 100644 --- a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs @@ -42,6 +42,7 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { + rc.Table("ClassWithInterfaceLookup"); rc.Id(x => x.Id); rc.Property(x => x.Name); rc.ManyToOne(x => x.EntityLookup, x => x.Class(typeof(EntityClassProxy))); From fadf5b682a4b029f5767a110064437f07c52ae73 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Wed, 13 Nov 2019 10:45:02 +0200 Subject: [PATCH 4/4] Use simpler mapping for interface proxy test --- .../InterfaceHandling/Fixture.cs | 17 +++++++++++++---- .../InterfaceHandling/Entities.cs | 11 +++++++++++ .../InterfaceHandling/Fixture.cs | 17 +++++++++++++---- .../InterfaceHandling/SubclassEntities.cs | 4 ++-- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs b/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs index 97db33c16e3..80cb249dce3 100644 --- a/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs +++ b/src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs @@ -45,7 +45,7 @@ protected override HbmMapping GetMappings() mapper.UnionSubclass( rc => { - rc.Proxy(typeof(IAmbigiousSubEntityProxy)); + rc.Proxy(typeof(IAnotherEntityProxy)); rc.Property(x => x.AnotherName); }); @@ -85,6 +85,15 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { + rc.Table("multiInterface"); + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + mapper.Class( + rc => + { + rc.Proxy(typeof(IMultiIdProxy)); rc.Id(x => x.Id); rc.Property(x => x.Name); }); @@ -145,7 +154,7 @@ public async Task ProxyClassIdAccessBothImplicitExplicitInterfacesAsync() } [Test] - public async Task ProxyInterfaceAsync() + public async Task ProxyInterfaceIdAccessAsync() { using (var session = OpenSession()) { @@ -157,11 +166,11 @@ public async Task ProxyInterfaceAsync() [KnownBug("GH-2271")] [Test] - public async Task ProxyInterfaceCanAccessIdFromDifferentInterfacesAsync() + public async Task ProxyInterfaceIdAccessFromDifferentInterfacesAsync() { using (var session = OpenSession()) { - var entity = await (session.LoadAsync(_id)); + var entity = await (session.LoadAsync(_id)); CanAccessIEntityId(entity); CanAccessIEntity2Id(entity); diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs index 8c393267d3c..37976a51382 100644 --- a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Entities.cs @@ -38,6 +38,17 @@ string IEntity.Name } } + //Proxy contains IEntity.Id and IEntity2.Id + public interface IMultiIdProxy : IEntity, IEntity2 + { + } + + public class EntityMultiIdProxy : IMultiIdProxy + { + public virtual Guid Id { get; set; } + public virtual string Name { get; set; } + } + public class EntityMixExplicitImplicitInterface : IEntity, IEntity2 { private Guid id; diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs index 2028ad4026f..b2e9e36becb 100644 --- a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/Fixture.cs @@ -34,7 +34,7 @@ protected override HbmMapping GetMappings() mapper.UnionSubclass( rc => { - rc.Proxy(typeof(IAmbigiousSubEntityProxy)); + rc.Proxy(typeof(IAnotherEntityProxy)); rc.Property(x => x.AnotherName); }); @@ -74,6 +74,15 @@ protected override HbmMapping GetMappings() mapper.Class( rc => { + rc.Table("multiInterface"); + rc.Id(x => x.Id); + rc.Property(x => x.Name); + }); + + mapper.Class( + rc => + { + rc.Proxy(typeof(IMultiIdProxy)); rc.Id(x => x.Id); rc.Property(x => x.Name); }); @@ -134,7 +143,7 @@ public void ProxyClassIdAccessBothImplicitExplicitInterfaces() } [Test] - public void ProxyInterface() + public void ProxyInterfaceIdAccess() { using (var session = OpenSession()) { @@ -146,11 +155,11 @@ public void ProxyInterface() [KnownBug("GH-2271")] [Test] - public void ProxyInterfaceCanAccessIdFromDifferentInterfaces() + public void ProxyInterfaceIdAccessFromDifferentInterfaces() { using (var session = OpenSession()) { - var entity = session.Load(_id); + var entity = session.Load(_id); CanAccessIEntityId(entity); CanAccessIEntity2Id(entity); diff --git a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs index 491d0df87be..5a5c54b9015 100644 --- a/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs +++ b/src/NHibernate.Test/StaticProxyTest/InterfaceHandling/SubclassEntities.cs @@ -19,12 +19,12 @@ class SubEntityInterfaceProxy : EntityClassProxy, ISubEntityProxy public virtual string AnotherName { get; set; } } - public interface IAmbigiousSubEntityProxy : IEntity, IEntity2 + public interface IAnotherEntityProxy : IEntity { string AnotherName { get; set; } } - class AnotherSubEntityInterfaceProxy : EntityClassProxy, IAmbigiousSubEntityProxy + class AnotherSubEntityInterfaceProxy : EntityClassProxy, IAnotherEntityProxy { public virtual string AnotherName { get; set; } }