/*
 * 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;

namespace Sasa.QualityTools.DrFx.Explorer.Tests.Integration
{
    /// <summary>
    /// <see cref="Sasa.QualityTools.DrFx.Explorer.FxCopReportWindow"/> クラスのテストクラスです。
    /// </summary>
    [TestFixture]
    public class FxCopIssueDetailWidgetTest
    {
        /// <summary>
        /// ソースコード行読み取りメソッドに、パスとして null を渡した場合に、空のリストが返されることをテストします。
        /// </summary>
        [Test]
        [Description("ソースコード行読み取りメソッドに、パスとして null を渡した場合に、空のリストが返されることをテストします。")]
        public void TestGetViolationCodeLinesWithNull()
        {
            var actual = FxCopIssueDetailWidget.GetViolationCodeLines(null, 1);
            Assert.AreEqual(0, actual.Count);
        }

        /// <summary>
        /// ソースコード行読み取りメソッドに、パスとして空文字列を渡した場合に、空のリストが返されることをテストします。
        /// </summary>
        [Test]
        [Description("ソースコード行読み取りメソッドに、パスとして空文字列を渡した場合に、空のリストが返されることをテストします。")]
        public void TestGetViolationCodeLinesWithEmpty()
        {
            var actual = FxCopIssueDetailWidget.GetViolationCodeLines(String.Empty, 1);
            Assert.AreEqual(0, actual.Count);
        }

        /// <summary>
        /// ソースコード行読み取りメソッドに、ファイルシステム上に存在しないパスを渡した場合に、空のリストが返されることをテストします。
        /// </summary>
        [Test]
        [Description("ソースコード行読み取りメソッドに、ファイルシステム上に存在しないパスを渡した場合に、空のリストが返されることをテストします。")]
        public void TestGetViolationCodeLinesWithNotExistFile()
        {
            var actual = FxCopIssueDetailWidget.GetViolationCodeLines(@"TestData\FxCopIssueDetailWidgetTest\notexist.txt", 1);
            Assert.AreEqual(0, actual.Count);
        }

        /// <summary>
        /// ソースコード行読み取りメソッドに、行数が少ない (10 行以下) ファイルを渡した場合に、全コード行のリストが返されることをテストします。
        /// </summary>
        [Test]
        [Description("ソースコード行読み取りメソッドに、行数が少ない (10 行以下) ファイルを渡した場合に、全コード行のリストが返されることをテストします。")]
        public void TestGetViolationCodeLinesWithFewFile()
        {
            var expected = new List<SourceCodeLine> {
               new SourceCodeLine { LineNumber = 1, Text = "a" },
               new SourceCodeLine { LineNumber = 2, Text = "b", IsViolationLine = true },
               new SourceCodeLine { LineNumber = 3, Text = "c" },
           };
            var actual = FxCopIssueDetailWidget.GetViolationCodeLines(@"TestData\FxCopIssueDetailWidgetTest\fewlines.txt", 2);
            AssertAreEqual(expected, actual);
        }

        /// <summary>
        /// ソースコード行読み取りメソッドに、違反した行番号として負の値を指定した場合に、空のリストが返されることをテストします。
        /// </summary>
        [Test]
        [Description("ソースコード行読み取りメソッドに、違反した行番号として負の値を指定した場合に、空のリストが返されることをテストします。")]
        public void TestGetViolationCodeLinesWithNegativeLineNumber()
        {
            var expected = new List<SourceCodeLine> {
               new SourceCodeLine { LineNumber = 1, Text = "a" },
               new SourceCodeLine { LineNumber = 2, Text = "b", IsViolationLine = true },
               new SourceCodeLine { LineNumber = 3, Text = "c" },
           };
            var actual = FxCopIssueDetailWidget.GetViolationCodeLines(@"TestData\FxCopIssueDetailWidgetTest\fewlines.txt", -1);
            Assert.AreEqual(0, actual.Count);
        }

        /// <summary>
        /// ソースコード行読み取りメソッドに、違反した行番号として 5 未満の行番号を渡した場合に、違反行以前のソースコード行は 1 行目から読み取られる (5 行分読み取られない) ことをテストします。
        /// </summary>
        [Test]
        [Description("ソースコード行読み取りメソッドに、違反した行番号として 5 未満の行番号を渡した場合に、違反行以前のソースコード行は 1 行目から読み取られる (5 行分読み取られない) ことをテストします。")]
        public void TestGetViolationCodeLinesWithLowLineNumber()
        {
            var expected = new List<SourceCodeLine> {
               new SourceCodeLine { LineNumber = 1, Text = "a" },
               new SourceCodeLine { LineNumber = 2, Text = "b" },
               new SourceCodeLine { LineNumber = 3, Text = "c", IsViolationLine = true },
               new SourceCodeLine { LineNumber = 4, Text = "d" },
               new SourceCodeLine { LineNumber = 5, Text = "e" },
               new SourceCodeLine { LineNumber = 6, Text = "f" },
               new SourceCodeLine { LineNumber = 7, Text = "g" },
               new SourceCodeLine { LineNumber = 8, Text = "h" },
           };
            var actual = FxCopIssueDetailWidget.GetViolationCodeLines(@"TestData\FxCopIssueDetailWidgetTest\manylines.txt", 3);
            AssertAreEqual(expected, actual);
        }

        /// <summary>
        /// ソースコード行読み取りメソッドに、違反した行番号としファイルの中央付近の行番号を渡した場合に、違反行の前後 5 行分が読み取られることをテストします。
        /// </summary>
        [Test]
        [Description("ソースコード行読み取りメソッドに、違反した行番号としファイルの中央付近の行番号を渡した場合に、違反行の前後 5 行分が読み取られることをテストします。")]
        public void TestGetViolationCodeLinesWithMiddleLineNumber()
        {
            var expected = new List<SourceCodeLine> {
               new SourceCodeLine { LineNumber = 9, Text = "i" },
               new SourceCodeLine { LineNumber = 10, Text = "j" },
               new SourceCodeLine { LineNumber = 11, Text = "k" },
               new SourceCodeLine { LineNumber = 12, Text = "l" },
               new SourceCodeLine { LineNumber = 13, Text = "m" },
               new SourceCodeLine { LineNumber = 14, Text = "n", IsViolationLine = true },
               new SourceCodeLine { LineNumber = 15, Text = "o" },
               new SourceCodeLine { LineNumber = 16, Text = "p" },
               new SourceCodeLine { LineNumber = 17, Text = "q" },
               new SourceCodeLine { LineNumber = 18, Text = "r" },
               new SourceCodeLine { LineNumber = 19, Text = "s" },
           };
            var actual = FxCopIssueDetailWidget.GetViolationCodeLines(@"TestData\FxCopIssueDetailWidgetTest\manylines.txt", 14);
            AssertAreEqual(expected, actual);
        }

        /// <summary>
        /// ソースコード行読み取りメソッドに、違反した行番号として最終行付近の行番号を渡した場合に、違反行以後のソースコード行は最終行まで読み取られる (5 行分読み取られない) ことをテストします。
        /// </summary>
        [Test]
        [Description("ソースコード行読み取りメソッドに、違反した行番号として最終行付近の行番号を渡した場合に、違反行以後のソースコード行は最終行まで読み取られる (5 行分読み取られない) ことをテストします。")]
        public void TestGetViolationCodeLinesWithLargeLineNumber()
        {
            var expected = new List<SourceCodeLine> {
               new SourceCodeLine { LineNumber = 18, Text = "r" },
               new SourceCodeLine { LineNumber = 19, Text = "s" },
               new SourceCodeLine { LineNumber = 20, Text = "t" },
               new SourceCodeLine { LineNumber = 21, Text = "u" },
               new SourceCodeLine { LineNumber = 22, Text = "v" },
               new SourceCodeLine { LineNumber = 23, Text = "w", IsViolationLine = true },
               new SourceCodeLine { LineNumber = 24, Text = "x" },
               new SourceCodeLine { LineNumber = 25, Text = "y" },
               new SourceCodeLine { LineNumber = 26, Text = "z" },
           };
            var actual = FxCopIssueDetailWidget.GetViolationCodeLines(@"TestData\FxCopIssueDetailWidgetTest\manylines.txt", 23);
            AssertAreEqual(expected, actual);
        }

        /// <summary>
        /// ソースコード行読み取りメソッドに、違反した行番号として大きすぎる (ファイル行数を超える) 行番号を指定した場合に、空のリストが返されることをテストします。
        /// </summary>
        [Test]
        [Description("ソースコード行読み取りメソッドに、違反した行番号として大きすぎる (ファイル行数を超える) 行番号を指定した場合に、空のリストが返されることをテストします。")]
        public void TestGetViolationCodeLinesWithOverlargeLineNumber()
        {
            var actual = FxCopIssueDetailWidget.GetViolationCodeLines(@"TestData\FxCopIssueDetailWidgetTest\manylines.txt", 1024);
            Assert.AreEqual(0, actual.Count);
        }

        /// <summary>
        /// ２つのソースコード行リストを比較します。
        /// </summary>
        /// <param name="expected">期待値。</param>
        /// <param name="actual">実際の値。</param>
        private void AssertAreEqual(List<SourceCodeLine> expected, List<SourceCodeLine> actual)
        {
            Assert.AreEqual(expected.Count, actual.Count);
            for (int i = 0; i < expected.Count; i++)
            {
                Assert.AreEqual(expected[i].LineNumber, actual[i].LineNumber);
                Assert.AreEqual(expected[i].Text, actual[i].Text);
                Assert.AreEqual(expected[i].IsViolationLine, actual[i].IsViolationLine);
            }
        }
    }
}
