using NUnit.Framework;
using Sasa.QualityTools.DrFx.Console;
using System;
using System.Collections.Generic;

namespace Sasa.QualityTools.DrFx.Console.Tests.Unit
{
    [TestFixture]
    public class WarningTest
    {
        /// <summary>
        /// 厳密に型指定された等値比較メソッドが期待通り動作することをテストします。
        /// </summary>
        /// <param name="warning1">FxCop 警告メッセージ。</param>
        /// <param name="warning2">FxCop 警告メッセージ。</param>
        /// <returns>比較結果。</returns>
        [TestCaseSource(typeof(EqualityWithEqualsTestCaseGenerator), "Generate")]
        public bool TestEqualityWithEquals(Warning warning1, Warning warning2)
        {
            return warning1.Equals(warning2);
        }

        /// <summary>
        /// 厳密に型指定されていない等値比較メソッドが期待通り動作することをテストします。
        /// </summary>
        /// <param name="warning">FxCop 警告メッセージ。</param>
        /// <param name="target">比較対象オブジェクト。</param>
        /// <returns></returns>
        [TestCaseSource(typeof(EqualityWithLooselyTypedEqualsTestCaseGenerator), "Generate")]
        public bool TestEqualityWithLooselyTypedEquals(Warning warning, object target)
        {
            return warning.Equals(target);
        }

        /// <summary>
        /// 等値演算子が期待通り動作することをテストします。
        /// </summary>
        /// <param name="warning1">FxCop 警告メッセージ。</param>
        /// <param name="warning2">FxCop 警告メッセージ。</param>
        /// <returns>比較結果。</returns>
        [TestCaseSource(typeof(EqualityWithOperatorEqTestCaseGenerator), "Generate")]
        public bool TestEqualityWithOperatorEq(Warning warning1, Warning warning2)
        {
            return warning1 == warning2;
        }

        /// <summary>
        /// 非等値演算子が期待通り動作することをテストします。
        /// </summary>
        /// <param name="warning1">FxCop 警告メッセージ。</param>
        /// <param name="warning2">FxCop 警告メッセージ。</param>
        /// <returns>比較結果。</returns>
        [TestCaseSource(typeof(EqualityWithOperatorNeTestCaseGenerator), "Generate")]
        public bool TestEqualityWithOperatorNe(Warning warning1, Warning warning2)
        {
            return warning1 != warning2;
        }

        /// <summary>
        /// 厳密に型指定された等値比較メソッドテスト用のテストケースデータ生成クラスです。
        /// </summary>
        private class EqualityWithEqualsTestCaseGenerator
        {
            /// <summary>
            /// テストケースデータのコレクションを生成します。
            /// </summary>
            /// <returns>生成したテストケースデータのコレクション。</returns>
            internal IEnumerable<TestCaseData> Generate()
            {
                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" })
                    .Returns(true)
                    .SetDescription("各プロパティが等しければ Eqauls が true となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "X", Level = "B", Category = "C", CheckId = "D", Issue = "E" })
                    .Returns(false)
                    .SetDescription("SourceContext プロパティが等しくなければ Eqauls が false となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "X", Category = "C", CheckId = "D", Issue = "E" })
                    .Returns(false)
                    .SetDescription("Type プロパティが等しくなければ Eqauls が false となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "X", CheckId = "D", Issue = "E" })
                    .Returns(false)
                    .SetDescription("Category プロパティが等しくなければ Eqauls が false となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "X", Issue = "E" })
                    .Returns(false)
                    .SetDescription("CheckId プロパティが等しくなければ Eqauls が false となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "X" })
                    .Returns(false)
                    .SetDescription("Issue プロパティが等しくなければ Eqauls が false となることをテストします。");

                yield return new TestCaseData(new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" }, null)
                    .Returns(false)
                    .SetDescription("比較対象が null ならば Eqauls が false となることをテストします。");
            }
        }

        /// <summary>
        /// 厳密に型指定されていない等値比較メソッドテスト用のテストケースデータ生成クラスです。
        /// </summary>
        private class EqualityWithLooselyTypedEqualsTestCaseGenerator
        {
            /// <summary>
            /// テストケースデータのコレクションを生成します。
            /// </summary>
            /// <returns>生成したテストケースデータのコレクション。</returns>
            internal IEnumerable<TestCaseData> Generate()
            {
                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" })
                    .Returns(true)
                    .SetDescription("比較対象が Warning クラスで、各プロパティが等しければ Eqauls が true となることをテストします。");

                yield return new TestCaseData(new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" }, "A,B,C,D,E")
                    .Returns(false)
                    .SetDescription("比較対象が Warning クラスでなければ Equals が false となることをテストします。");
            }
        }

        /// <summary>
        /// 等値演算子テスト用のテストケースデータ生成クラスです。
        /// </summary>
        private class EqualityWithOperatorEqTestCaseGenerator
        {
            /// <summary>
            /// テストケースデータのコレクションを生成します。
            /// </summary>
            /// <returns>生成したテストケースデータのコレクション。</returns>
            internal IEnumerable<TestCaseData> Generate()
            {
                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" })
                    .Returns(true)
                    .SetDescription("各プロパティが等しければ == が true となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "X", Level = "B", Category = "C", CheckId = "D", Issue = "E" })
                    .Returns(false)
                    .SetDescription("SourceContext プロパティが等しくなければ == が false となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "X", Category = "C", CheckId = "D", Issue = "E" })
                    .Returns(false)
                    .SetDescription("Type プロパティが等しくなければ == が false となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "X", CheckId = "D", Issue = "E" })
                    .Returns(false)
                    .SetDescription("Category プロパティが等しくなければ == が false となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "X", Issue = "E" })
                    .Returns(false)
                    .SetDescription("CheckId プロパティが等しくなければ == が false となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "X" })
                    .Returns(false)
                    .SetDescription("Issue プロパティが等しくなければ == が false となることをテストします。");

                yield return new TestCaseData(new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" }, null)
                    .Returns(false)
                    .SetDescription("比較対象が null ならば == が false となることをテストします。");
            }
        }

        /// <summary>
        /// 非等値演算子テスト用のテストケースデータ生成クラスです。
        /// </summary>
        private class EqualityWithOperatorNeTestCaseGenerator
        {
            /// <summary>
            /// テストケースデータのコレクションを生成します。
            /// </summary>
            /// <returns>生成したテストケースデータのコレクション。</returns>
            internal IEnumerable<TestCaseData> Generate()
            {
                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" })
                    .Returns(false)
                    .SetDescription("各プロパティが等しければ != が false となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "X", Level = "B", Category = "C", CheckId = "D", Issue = "E" })
                    .Returns(true)
                    .SetDescription("SourceContext プロパティが等しくなければ != が true となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "X", Category = "C", CheckId = "D", Issue = "E" })
                    .Returns(true)
                    .SetDescription("Type プロパティが等しくなければ != が true となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "X", CheckId = "D", Issue = "E" })
                    .Returns(true)
                    .SetDescription("Category プロパティが等しくなければ != が true となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "X", Issue = "E" })
                    .Returns(true)
                    .SetDescription("CheckId プロパティが等しくなければ != が true となることをテストします。");

                yield return new TestCaseData(
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" },
                    new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "X" })
                    .Returns(true)
                    .SetDescription("Issue プロパティが等しくなければ != が true となることをテストします。");

                yield return new TestCaseData(new Warning { SourceContext = "A", Level = "B", Category = "C", CheckId = "D", Issue = "E" }, null)
                    .Returns(true)
                    .SetDescription("比較対象が null ならば != が true となることをテストします。");
            }
        }
    }
}
