



#if NUnit
using TestFixtureAttribute = NUnit.Framework.TestFixtureAttribute;
using TestAttribute = NUnit.Framework.TestAttribute;
#elif MsTest
using TestFixtureAttribute = Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute;
using TestAttribute = Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute;
#elif Xunit
using TestAttribute = Xunit.FactAttribute;
#endif
using System;
using System.Collections.Generic;
using System.Collections.Generic.Prig;
using Test.program1.TestUtilities;
using Urasandesu.Prig.Framework;

namespace Test.program1.System.Collections.Generic.Prig
{
    [TestFixture]
    public class PListTest
    {
        [Test]
        public void Add_should_be_callable_indirectly()
        {
            using (new IndirectionsContext())
            {
                // Arrange
                var actual = default(int);
                PList<int>.AddT().Body = (@this, item) => actual = item;

                // Act
                var list = new List<int>();
                list.Add(42);

                // Assert
                Assert.AreEqual(0, list.Count);
                Assert.AreEqual(42, actual);
            }
        }

        [Test]
        public void Add_should_be_callable_indirectly_against_only_specified_instance()
        {
            using (new IndirectionsContext())
            {
                // Arrange
                var actual = default(int);
                var listProxy = new PProxyList<int>();
                listProxy.AddT().Body = (@this, item) => actual = item;
                var list_sut = (List<int>)listProxy;

                var list = new List<int>();

                // Act
                list_sut.Add(42);
                list.Add(10);

                // Assert
                Assert.AreEqual(42, actual);
            }
        }



        [Test]
        public void Add_should_throw_NotImplementedException_if_the_instance_behavior_is_set_that()
        {
            using (new IndirectionsContext())
            {
                // Arrange
                var listProxy = new PProxyList<int>();
                listProxy.
                    ExcludeGeneric().
                    IncludeAddT().
                    DefaultBehavior = IndirectionBehaviors.NotImplemented;
                var list_sut = (List<int>)listProxy;

                var list = new List<int>();

                // Act, Assert
                ExceptionAssert.Throws<NotImplementedException>(() => list_sut.Add(42));
                ExceptionAssert.DoesNotThrow(() => list.Add(10));
            }
        }

        [Test]
        public void Add_should_do_nothing_if_the_instance_behavior_is_set_that()
        {
            using (new IndirectionsContext())
            {
                // Arrange
                var listProxy = new PProxyList<int>();
                listProxy.
                    ExcludeGeneric().
                    IncludeAddT().
                    DefaultBehavior = IndirectionBehaviors.DefaultValue;
                var list_sut = (List<int>)listProxy;

                var list = new List<int>();

                // Act
                list_sut.Add(42);
                list.Add(10);

                // Assert
                CollectionAssert.IsEmpty(list_sut);
                CollectionAssert.AreEqual(new[] { 10 }, list);
            }
        }

        [Test]
        public void Add_should_behave_as_same_as_original_if_the_instance_behavior_is_set_that()
        {
            using (new IndirectionsContext())
            {
                // Arrange
                var listProxy = new PProxyList<int>();
                listProxy.
                    ExcludeGeneric().
                    IncludeAddT().
                    DefaultBehavior = IndirectionBehaviors.Fallthrough;
                var list_sut = (List<int>)listProxy;
                // You have to call the constructor of the type that is original for a proxy.
                // This isn't easy usage, but I believe that proxy is usually set indirection settings explicitly.
                typeof(List<int>).GetConstructor(Type.EmptyTypes).Invoke(list_sut, new object[0]);

                var list = new List<int>();

                // Act
                list_sut.Add(42);
                list.Add(10);

                // Assert
                CollectionAssert.AreEqual(new[] { 42 }, list_sut);
                CollectionAssert.AreEqual(new[] { 10 }, list);
            }
        }
    }
}
