context: // ---------------------------------------------------------------------------------
  //  Copyright (C) 2007-2010 Chillisoft Solutions
  //  
  //  This file is part of the Habanero framework.
  //  
  //      Habanero is a free framework: you can redistribute it and/or modify
  //      it under the terms of the GNU Lesser General Public License as published by
  //      the Free Software Foundation, either version 3 of the License, or
  //      (at your option) any later version.
  //  
  //      The Habanero framework is distributed in the hope that it will be useful,
  //      but WITHOUT ANY WARRANTY; without even the implied warranty of
  //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  //      GNU Lesser General Public License for more details.
  //  
  //      You should have received a copy of the GNU Lesser General Public License
  //      along with the Habanero framework.  If not, see <http://www.gnu.org/licenses/>.
  // ---------------------------------------------------------------------------------
  using System;
  using System.Linq;
  using System.Reflection;
  using Habanero.Smooth.Test.ExtensionMethods;
  using Habanero.Base;
  using Habanero.Base.Exceptions;
  using Habanero.BO.ClassDefinition;
  using Habanero.Smooth.ReflectionWrappers;
  using NUnit.Framework;
  using Rhino.Mocks;
  
  namespace Habanero.Smooth.Test
  {
      [TestFixture]
      public class TestAutoMapperExtensions
      {
          [SetUp]
          public void Setup()
          {
              AllClassesAutoMapper.PropNamingConvention = new DefaultPropNamingConventions();
          }
  
  #region OneToOneReverseRelationship
  
  
          [Test]
          public void Test_HasSingleReverseRelationship_WhenRevHasM_1Attr_ShouldBeFalse()
          {
              //FakeBOWithSingleAttributeDeclaredRevRel has a relationship 'MySingleRelationship'
              // that is mapped via an AutoMapOneToMany Attribute to 'FakeBOWithUndefinableSingleRel'
              // AttributeRevRelName relationship. Because it is a single Relationship
              // and is mapped via AutoMap Attribute as a ManyToOne this will always return
              // that there are no single reverse relationships event though 'SingleRel' would 
              // be found if it were not for the autoMapping Prop.
              //---------------Set up test pack-------------------
              const string expectedPropName = "MySingleRelationship";
              var type = typeof(FakeBOWithSingleAttributeDeclaredRevRel).ToTypeWrapper();
              //---------------Assert Precondition----------------
              PropertyWrapper propertyInfo = type.GetProperty(expectedPropName);
              Assert.IsTrue(propertyInfo.IsSingleRelationship);
              //---------------Execute Test ----------------------
              var hasSingleReverseRelationship = propertyInfo.HasSingleReverseRelationship;
              //---------------Test Result -----------------------
              Assert.IsFalse(hasSingleReverseRelationship);
          }
  
          [Test]
          public void Test_HasSingleReverseRelationship_WhenHasAndOwnerSingle_ShouldBeTrue()
          {
              //---------------Set up test pack-------------------
              var classType = typeof(FakeBOWithReverseSingleRel).ToTypeWrapper();
              const string expectedPropName = "MySingleRelationship";
              var propertyInfo = classType.GetProperty(expectedPropName);
              var reverseClassType = propertyInfo.RelatedClassType;
              //---------------Assert Precondition----------------
              classType.AssertPropertyExists(expectedPropName);
              propertyInfo.AssertIsOfType<FakeBOWithTwoSingleRel>();
              var reversePropInfo = reverseClassType.GetProperty("MyReverseSingleRel");
              Assert.IsNotNull(reversePropInfo);
              reversePropInfo.AssertIsOfType<FakeBOWithReverseSingleRel>();
              //---------------Execute Test ----------------------
              var hasSingleReverseRelationship = propertyInfo.HasSingleReverseRelationship;
              //---------------Test Result -----------------------
              Assert.IsTrue(hasSingleReverseRelationship);
          }
  
          [Test]
          public void Test_HasSingleReverseRelationship_WhenHasAndOwnerMultiple_ShouldBeTrue()
          {
              //'FakeBoWithMultipleRel' has relationship 'MyMultipleWithTwoSingleReverse'
              // that is related to 'FakeWithTwoSingleReverseRel' which has two 
              // single relationships that could be mapped back.
              var classType = typeof(FakeBoWithMultipleRel).ToTypeWrapper();
              const string expectedPropName = "MyMultipleWithTwoSingleReverse";
              var propertyInfo = classType.GetProperty(expectedPropName);
              var reverseClassType = propertyInfo.RelatedClassType;
              //---------------Assert Precondition----------------
              classType.AssertPropertyExists(expectedPropName);
              propertyInfo.AssertIsMultipleRelationship();
              AssertRelationshipIsForOwnerClass(classType, reverseClassType, "MySingleRelationship1");
              AssertRelationshipIsForOwnerClass(classType, reverseClassType, "MySingleRelationship2");
              //---------------Execute Test ----------------------
              var hasSingleReverseRelationship = propertyInfo.HasSingleReverseRelationship;
              //---------------Test Result -----------------------
              Assert.IsTrue(hasSingleReverseRelationship);
          }
  
          //The GetOneToOneReverseRelationshipInfos for a SingleRelationship should return all Props for SingleRelationships 
          //      that that are for the ownerClass 
          //   ----Unless----
          //1- This Relationship is mapped as a ManyToOneAttribute Or ReverseRelationship MappedVia M:1
          //2 - ReverseRel directly mapped via a OneToOne attribute to this relationship.
          //Or 3 - This Relationship is mapped by a OnetoOne Attribute on reverse relationship.
          //Or 4 - This Relationship has an Ignore Attribute.
          //or 5 - The Reverse Relationship has an Ignore Attribute
          [Test]
          public void Test_Get1_1RevRels_WhenNotHas_ShouldNotHaveItems()
          {
              //You have a single Relationship that is referencing a class
              // that does not have any reverse single relationships back to
              // 'FakeBOWithSingleAttributeDeclaredRevRel'
              //---------------Set up test pack-------------------
              const string expectedPropName = "MySingleRelationship";
              var type = typeof(FakeBoWithNoSingleReverse).ToTypeWrapper();
              //---------------Assert Precondition----------------
              var propertyInfo = type.GetProperty(expectedPropName);
              propertyInfo.AssertIsSingleRelationship();
              //---------------Execute Test ----------------------
              var singleRevRels = propertyInfo.GetOneToOneReverseRelationshipInfos();
              //---------------Test Result -----------------------
              Assert.AreEqual(0, singleRevRels.Count);
          }
          [Test]
          public void Test_Get1_1RevRels_WhenRelHasManyToOneAttribute_ShouldNotHaveItems()
          {
              //You have a single Relationship that has a ManyToOne Attribute
              // Its reverse relationship can never be single.
              //---------------Set up test pack-------------------
              const string expectedPropName = "MySingleRelationshipRev";
              var type = typeof(FakeBOWithM1Attribute).ToTypeWrapper();
              //---------------Assert Precondition----------------
              var propertyInfo = type.GetProperty(expectedPropName);
              propertyInfo.AssertIsSingleRelationship();
              propertyInfo.HasAttribute<AutoMapManyToOneAttribute>();
              //---------------Execute Test ----------------------
              var singleRevRels = propertyInfo.GetOneToOneReverseRelationshipInfos();
              //---------------Test Result -----------------------
              Assert.AreEqual(0, singleRevRels.Count);
          }
  
          [Test]
          public void Test_Get1_1RevRels_WhenReverseRelHasManyToOne_ShouldNotHaveItems()
          {
              //You have a single Relationship that has a ManyToOne Attribute
              // Its reverse relationship can never be single.
              //---------------Set up test pack-------------------
              const string expectedPropName = "MySingleRelationship";
              var ownerClassType = typeof(FakeBOWithReverseSingle).ToTypeWrapper();
              var propertyInfo = ownerClassType.GetProperty(expectedPropName);
              var reverseClassType = propertyInfo.RelatedClassType;
              //---------------Assert Precondition----------------
              propertyInfo.AssertIsSingleRelationship();
              const string reveresRelationshipName = "MySingleRelationshipRev";
              AssertRelationshipIsForOwnerClass(ownerClassType, reverseClassType, reveresRelationshipName);
              var reversePropInfo = reverseClassType.GetProperty(reveresRelationshipName);
              reversePropInfo.HasAttribute<AutoMapManyToOneAttribute>();
              //---------------Execute Test ----------------------
              var singleRevRels = propertyInfo.GetOneToOneReverseRelationshipInfos();
              //---------------Test Result -----------------------
              Assert.AreEqual(0, singleRevRels.Count);
          }
  
          [Test]
          public void Test_Get1_1RevRels_WhenHasOneSingleRev_ShouldReturnOneItem()
          {
              //'FakeBOWithReverseSingleRel' has a Relationship 'MySingleRelationship'
              // to 'FakeBOWithTwoSingleRelNoRevs' that has two single relationships.
              // but only 'MyReverseSingleRel' returns the owner Class.
              //---------------Set up test pack-------------------
              var classType = typeof(FakeBOWithReverseSingleRel).ToTypeWrapper();
              const string expectedPropName = "MySingleRelationship";
              var propertyInfo = classType.GetProperty(expectedPropName);
              var reverseClassType = propertyInfo.RelatedClassType;
  
              //---------------Assert Precondition----------------
              classType.AssertPropertyExists(expectedPropName);
              propertyInfo.AssertIsOfType<FakeBOWithTwoSingleRel>();
              propertyInfo.AssertIsSingleRelationship();
              AssertRelationshipIsForOwnerClass(classType, reverseClassType, "MyReverseSingleRel");
              AssertReverseRelationshipNotForOwnerClass(classType, reverseClassType, "MySingleRelationship");
              //---------------Execute Test ----------------------
              var singleRevRels = propertyInfo.GetOneToOneReverseRelationshipInfos();
              //---------------Test Result -----------------------
              Assert.AreEqual(1, singleRevRels.Count);
              Assert.AreEqual("MyReverseSingleRel", singleRevRels[0].Name);
          }
  
          [Test]
          public void Test_Get1_1RevRels_WhenAutoMapOneToOne_ShouldReturnOneItem()
          {
              //---------------Set up test pack-------------------
              var classType = typeof(FakeBOWithReverseSingle).ToTypeWrapper();
              const string expectedPropName = "MySingleRelationship2";
              var propertyInfo = classType.GetProperty(expectedPropName);
              var reverseClassType = propertyInfo.RelatedClassType;
  
              //---------------Assert Precondition----------------
              classType.AssertPropertyExists(expectedPropName);
              propertyInfo.AssertIsOfType<FakeBOWith11Attribute>();
              propertyInfo.AssertIsSingleRelationship();
              propertyInfo.AssertHasAttribute<AutoMapOneToOneAttribute>();
  
              const string expectedRevRelName = "MySingleRevRelationship";
              AssertRelationshipIsForOwnerClass(classType, reverseClassType, expectedRevRelName);
              AssertRelationshipIsForOwnerClass(classType, reverseClassType, "MySingleRelationship2");
              AssertHasOneToOneWithReverseRelationship(propertyInfo, expectedRevRelName);
              //---------------Execute Test ----------------------
              var singleRevRels = propertyInfo.GetOneToOneReverseRelationshipInfos();
              //---------------Test Result -----------------------
              Assert.AreEqual(1, singleRevRels.Count);
              Assert.AreEqual(expectedRevRelName, singleRevRels[0].Name);
          }
  
          [Test]
          public void Test_Get1_1RevRels_WhenReverseAutoMapOneToOne_ShouldReturnOneItem()
          {
              //'FakeBOWith11Attribute' has a Relationship 'MySingleRevRelationship'
              // to 'FakeBOWithReverseSingle' that has two single relationships back.
              // but 'MySingleRelationship2' has a OneToOneAttribute back to 'MySingleRevRelationship'
              //---------------Set up test pack-------------------
              var classType = typeof(FakeBOWith11Attribute).ToTypeWrapper();
              const string expectedPropName = "MySingleRevRelationship";
              var propertyInfo = classType.GetProperty(expectedPropName);
              var reverseClassType = propertyInfo.RelatedClassType;
              //---------------Assert Precondition----------------
              classType.AssertPropertyExists(expectedPropName);
              propertyInfo.AssertIsOfType<FakeBOWithReverseSingle>();
              propertyInfo.AssertIsSingleRelationship();
              
              const string expectedRevRelName = "MySingleRelationship2";
              AssertRelationshipIsForOwnerClass(classType, reverseClassType, expectedRevRelName);
              AssertRelationshipIsForOwnerClass(classType, reverseClassType, "MySingleRelationship2");
              var reversePropertyInfo = reverseClassType.GetProperty(expectedRevRelName);
              AssertHasOneToOneWithReverseRelationship(reversePropertyInfo, expectedPropName);
              //---------------Execute Test ----------------------
              var singleRevRels = propertyInfo.GetOneToOneReverseRelationshipInfos();
              //---------------Test Result -----------------------
              Assert.AreEqual(1, singleRevRels.Count);
              Assert.AreEqual(expectedRevRelName, singleRevRels[0].Name);
          }
  
          [Test]
          public void Test_Get1_1RevRels_WhenHasIgnore_ShouldReturnNoItems()
          {
              //---------------Set up test pack-------------------
              var classType = typeof(FakeBOWithReverseSingle).ToTypeWrapper();
              const string expectedPropName = "MySingleIgnorRelationship";
              var propertyInfo = classType.GetProperty(expectedPropName);
              var reverseClassType = propertyInfo.RelatedClassType;
              //---------------Assert Precondition----------------
              classType.AssertPropertyExists(expectedPropName);
              propertyInfo.AssertIsOfType<FakeBOWith11Attribute>();
              propertyInfo.AssertIsSingleRelationship();
              propertyInfo.AssertHasIgnoreAttribute();
  
              AssertRelationshipIsForOwnerClass(classType, reverseClassType, "MySingleRevRelationship");
              AssertRelationshipIsForOwnerClass(classType, reverseClassType, "MySingleRelationship2");
  
              //---------------Execute Test ----------------------
              var singleRevRels = propertyInfo.GetOneToOneReverseRelationshipInfos();
              //---------------Test Result -----------------------
              Assert.AreEqual(0, singleRevRels.Count);
          }
          [Test]
          public void Test_Get1_1RevRels_WhenReverseHasIgnore_ShouldReturnNoItems()
          {
              //---------------Set up test pack-------------------
              var classType = typeof(FakeBOWithReverseSingle).ToTypeWrapper();
              const string expectedPropName = "MySingleWithReverseIgnore";
              var propertyInfo = classType.GetProperty(expectedPropName);
              var reverseClassType = propertyInfo.RelatedClassType;
              //---------------Assert Precondition----------------
              classType.AssertPropertyExists(expectedPropName);
              propertyInfo.AssertIsOfType<FakeBOWithIgnoreAttribute>();
              propertyInfo.AssertIsSingleRelationship();
  
              AssertRelationshipIsForOwnerClass(classType, reverseClassType, "MySingleRelationship1");
              AssertReverseRelationshipHasIgnoreAttribute(reverseClassType, "MySingleRelationship1");
              //---------------Execute Test ----------------------
              var singleRevRels = propertyInfo.GetOneToOneReverseRelationshipInfos();
              //---------------Test Result -----------------------
              Assert.AreEqual(0, singleRevRels.Count);
          }
          [Test]
          public void Test_Get1_1RevRels_WhenHasMultipleReverse_NoAttributes_ShouldReturnBothPotentialReverseRels()
          {
              //---------------Set up test pack-------------------
              var classType = typeof(FakeBOWithReverseSingle).ToTypeWrapper();
              const string expectedPropName = "MySingleRelationship3";
  
gt:             var propertyInfo = classType.GetProperty(expectedPropName);