/*
 * DrFx - FxCop Report Translator and Visualizer.
 * Copyright (C) 2010 Sasa Yuan
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */



using NUnit.Framework;
using Sasa.QualityTools.DrFx.Explorer;
using Sasa.QualityTools.DrFx.Explorer.Report;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Sasa.QualityTools.DrFx.Explorer.Tests.Unit
{
    /// <summary>
    /// <see cref="Sasa.QualityTools.DrFx.Explorer.FxCopReportWindow"/> クラスのテストクラスです。
    /// </summary>
    [TestFixture]
    public class FxCopReportWindowTest
    {
        /// <summary>
        /// 違反リレーションシップリスト作成メソッドに、空のメンバー警告情報を渡した場合に、空のリストが作成されることをテストします。
        /// </summary>
        [Test]
        [Description("違反リレーションシップリスト作成メソッドに、空のメンバー警告情報を渡した場合に、空のリストが作成されることをテストします。")]
        public void TestCreateRelationshipsWithEmptyMember()
        {
            MemberWarning member = new MemberWarning();
            List<FxCopIssueRelationship> actual = new List<FxCopIssueRelationship>(FxCopReportWindow.CreateRelationships(member));

            Assert.AreEqual(0, actual.Count);
        }

        /// <summary>
        /// 違反リレーションシップリスト作成メソッドに、メンバー警告情報を渡した場合に、メンバー警告情報を反映したリストが作成されることをテストします。
        /// </summary>
        [Test]
        [Description("違反リレーションシップリスト作成メソッドに、メンバー警告情報を渡した場合に、メンバー警告情報を反映したリストが作成されることをテストします。")]
        public void TestCreateRelationshipsWithMember()
        {
            MemberWarning member = new MemberWarning();
            member.Issues.Add(new FxCopIssue());

            var expected = new List<FxCopIssueRelationship>
            {
                new FxCopIssueRelationship { Member = member, Issue = member.Issues[0], Target= WarningTarget.Member }
            };

            var actual = FxCopReportWindow.CreateRelationships(member);

            AssertRelationships(expected, actual);
        }

        /// <summary>
        /// 違反リレーションシップリスト作成メソッドに、空の型警告情報を渡した場合に、空のリストが作成されることをテストします。
        /// </summary>
        [Test]
        [Description("違反リレーションシップリスト作成メソッドに、空の型警告情報を渡した場合に、空のリストが作成されることをテストします。")]
        public void TestCreateRelationshipsWithEmptyType()
        {
            TypeWarning type = new TypeWarning();
            List<FxCopIssueRelationship> actual = new List<FxCopIssueRelationship>(FxCopReportWindow.CreateRelationships(type));

            Assert.AreEqual(0, actual.Count);
        }

        /// <summary>
        /// 違反リレーションシップリスト作成メソッドに、型警告情報を渡した場合に、型警告情報を反映したリストが作成されることをテストします。
        /// </summary>
        [Test]
        [Description("違反リレーションシップリスト作成メソッドに、型警告情報を渡した場合に、型警告情報を反映したリストが作成されることをテストします。")]
        public void TestCreateRelationshipsWithType()
        {
            MemberWarning member = new MemberWarning();
            member.Issues.Add(new FxCopIssue());
            TypeWarning type = new TypeWarning();
            type.Issues.Add(new FxCopIssue());
            type.Members.Add(member);

            var expected = new List<FxCopIssueRelationship>
            {
                new FxCopIssueRelationship { Type = type, Issue = type.Issues[0], Target= WarningTarget.Type },
                new FxCopIssueRelationship { Type = type, Member = member, Issue = member.Issues[0], Target= WarningTarget.Member }
            };

            var actual = FxCopReportWindow.CreateRelationships(type);

            AssertRelationships(expected, actual);
        }

        /// <summary>
        /// 違反リレーションシップリスト作成メソッドに、空の名前空間警告情報を渡した場合に、空のリストが作成されることをテストします。
        /// </summary>
        [Test]
        [Description("違反リレーションシップリスト作成メソッドに、空の名前空間警告情報を渡した場合に、空のリストが作成されることをテストします。")]
        public void TestCreateRelationshipsWithEmptyNamespace()
        {
            NamespaceWarning nameSpace = new NamespaceWarning();
            List<FxCopIssueRelationship> actual = new List<FxCopIssueRelationship>(FxCopReportWindow.CreateRelationships(nameSpace));

            Assert.AreEqual(0, actual.Count);
        }

        /// <summary>
        /// 違反リレーションシップリスト作成メソッドに、名前空間警告情報を渡した場合に、名前空間警告情報を反映したリストが作成されることをテストします。
        /// </summary>
        [Test]
        [Description("違反リレーションシップリスト作成メソッドに、名前空間警告情報を渡した場合に、名前空間警告情報を反映したリストが作成されることをテストします。")]
        public void TestCreateRelationshipsWithNamespace()
        {
            MemberWarning member = new MemberWarning();
            member.Issues.Add(new FxCopIssue());
            TypeWarning type = new TypeWarning();
            type.Issues.Add(new FxCopIssue());
            type.Members.Add(member);
            NamespaceWarning nameSpace = new NamespaceWarning();
            nameSpace.Issues.Add(new FxCopIssue());
            nameSpace.Types.Add(type);

            var expected = new List<FxCopIssueRelationship>
            {
                new FxCopIssueRelationship { Namespace = nameSpace, Issue = nameSpace.Issues[0], Target= WarningTarget.Namespace },
                new FxCopIssueRelationship { Namespace = nameSpace, Type = type, Issue = type.Issues[0], Target= WarningTarget.Type },
                new FxCopIssueRelationship { Namespace = nameSpace, Type = type, Member = member, Issue = member.Issues[0], Target= WarningTarget.Member }
            };

            var actual = FxCopReportWindow.CreateRelationships(nameSpace);

            AssertRelationships(expected, actual);
        }

        /// <summary>
        /// 違反リレーションシップリスト作成メソッドに、空のアセンブリ警告情報を渡した場合に、空のリストが作成されることをテストします。
        /// </summary>
        [Test]
        [Description("違反リレーションシップリスト作成メソッドに、空のアセンブリ警告情報を渡した場合に、空のリストが作成されることをテストします。")]
        public void TestCreateRelationshipsWithEmptyAssembly()
        {
            AssemblyWarning assembly = new AssemblyWarning();
            List<FxCopIssueRelationship> actual = new List<FxCopIssueRelationship>(FxCopReportWindow.CreateRelationships(assembly));

            Assert.AreEqual(0, actual.Count);
        }

        /// <summary>
        /// 違反リレーションシップリスト作成メソッドに、アセンブリ警告情報を渡した場合に、アセンブリ警告情報を反映したリストが作成されることをテストします。
        /// </summary>
        [Test]
        [Description("違反リレーションシップリスト作成メソッドに、アセンブリ警告情報を渡した場合に、アセンブリ警告情報を反映したリストが作成されることをテストします。")]
        public void TestCreateRelationshipsWithAssembly()
        {
            MemberWarning member = new MemberWarning();
            member.Issues.Add(new FxCopIssue());
            TypeWarning type = new TypeWarning();
            type.Issues.Add(new FxCopIssue());
            type.Members.Add(member);
            NamespaceWarning nameSpace = new NamespaceWarning();
            nameSpace.Issues.Add(new FxCopIssue());
            nameSpace.Types.Add(type);
            AssemblyWarning assembly = new AssemblyWarning();
            assembly.Issues.Add(new FxCopIssue());
            assembly.Namespaces.Add(nameSpace);

            var expected = new List<FxCopIssueRelationship>
            {
                new FxCopIssueRelationship { Assembly = assembly, Issue = assembly.Issues[0], Target= WarningTarget.Assembly },
                new FxCopIssueRelationship { Assembly = assembly, Namespace = nameSpace, Issue = nameSpace.Issues[0], Target= WarningTarget.Namespace },
                new FxCopIssueRelationship { Assembly = assembly, Namespace = nameSpace, Type = type, Issue = type.Issues[0], Target= WarningTarget.Type },
                new FxCopIssueRelationship { Assembly = assembly, Namespace = nameSpace, Type = type, Member = member, Issue = member.Issues[0], Target= WarningTarget.Member }
            };

            var actual = FxCopReportWindow.CreateRelationships(assembly);

            AssertRelationships(expected, actual);
        }

        /// <summary>
        /// ２つの違反リレーションシップを比較します。
        /// </summary>
        /// <param name="expected">期待値。</param>
        /// <param name="actual">実際の値。</param>
        private void AssertRelationships(IEnumerable<FxCopIssueRelationship> expected, IEnumerable<FxCopIssueRelationship> actual)
        {
            Assert.AreEqual(expected.Count(), actual.Count());
            for (int i = 0; i < expected.Count(); i++)
            {
                Assert.AreSame(expected.ElementAt(i).Assembly, actual.ElementAt(i).Assembly);
                Assert.AreSame(expected.ElementAt(i).Namespace, actual.ElementAt(i).Namespace);
                Assert.AreSame(expected.ElementAt(i).Type, actual.ElementAt(i).Type);
                Assert.AreSame(expected.ElementAt(i).Member, actual.ElementAt(i).Member);
                Assert.AreSame(expected.ElementAt(i).Issue, actual.ElementAt(i).Issue);
                Assert.AreSame(expected.ElementAt(i).Rule, actual.ElementAt(i).Rule);
                Assert.AreEqual(expected.ElementAt(i).Target, actual.ElementAt(i).Target);
            }
        }
    }
}
