// <著作権>
// Copyright (c) 2008, NTT DATA Corporation.

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Text;
using System.Collections.Generic;
using TERASOLUNA.Fw.Common.Validation;
using System.Configuration;
using System.Xml.Schema;
using TERASOLUNA.Fw.Common;
using TERASOLUNA.Fw.Utlib.Logging;
using TERASOLUNA.Fw.Common.Logging;
namespace TERASOLUNA.Fw.CommonUT.Validation
{
    /// <summary>
    /// ValidatorFactoryのテストクラスです。
    /// </summary>
    [TestClass()]
    public class ValidatorFactoryTest
    {
        private TestContext testContextInstance;

        /// <summary>
        /// 現在のテストの実行についての情報および機能を
        /// 提供するテスト コンテキストを取得または設定します。
        /// </summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }
        #region 追加のテスト属性
        // 
        //テストを作成するときに、次の追加属性を使用することができます:
        //
        //クラスの最初のテストを実行する前にコードを実行するには、ClassInitialize を使用
        //
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //クラスのすべてのテストを実行した後にコードを実行するには、ClassCleanup を使用
        //
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //各テストを実行する前にコードを実行するには、TestInitialize を使用
        //
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //各テストを実行した後にコードを実行するには、TestCleanup を使用
        //
        [TestCleanup()]
        public void MyTestCleanup()
        {
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory = null;
            
            String typeName = "ValidatorTypeName";
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_TYPENAME = typeName;
            ConfigurationManager.AppSettings[typeName] = null;

            String factoryTypeName = "ValidatorFactoryTypeName";
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_FACTORY_TYPENAME = factoryTypeName;
            ConfigurationManager.AppSettings[typeName] = null;
        }
        //
        #endregion


        /// <summary>
        /// CreateValidator() のテスト
        /// </summary>
        /// <remarks>
        /// _factory が null, _validatorType が null, 
        /// 構成ファイルに設定する ValidatorFactoryTypeName と ValidatorTypeName の記述がない場合、
        /// IValidator を実装した既定の VabValidator が返却されることを確認するテスト。
        /// </remarks>
        [TestMethod()]
        public void CreateValidatorTest01()
        {
            //準備
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory = null;
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_FACTORY_TYPENAME = "DummyValidatorFactoryTypeName";
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_TYPENAME = "DummyValidatorTypeName";
            
            //実行
            IValidator target = ValidatorFactory.CreateValidator();
            
            //検証
            Assert.IsInstanceOfType(target, typeof(VabValidator));
            Assert.IsInstanceOfType(TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory,
                typeof(ValidatorFactory));

            ValidatorFactory factory = TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory;
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor accessor =
                new TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor(factory);
            Assert.AreEqual(typeof(VabValidator), accessor._validatorType);

            // ログの確認
            Assert.AreEqual(0, LogUTUtil.CountLogs(typeof(ValidatorFactory), LogLevel.INFO));
        }

        /// <summary>
        /// CreateValidator() のテスト
        /// </summary>
        /// <remarks>
        /// _factory が not null, _validatorType が null, 
        /// 構成ファイルに設定する ValidatorFactoryTypeName と ValidatorTypeName の記述がない場合、
        /// IValidator を実装した既定の VabValidator が返却されることを確認するテスト。
        /// </remarks>
        [TestMethod()]
        public void CreateValidatorTest02()
        {
            //準備
            ValidatorFactory factory = new ValidatorFactory();
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory = factory;
            
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_FACTORY_TYPENAME = "DummyValidatorFactoryTypeName";
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_TYPENAME = "DummyValidatorTypeName";

            //実行
            IValidator target = ValidatorFactory.CreateValidator();

            //検証
            Assert.IsInstanceOfType(target, typeof(VabValidator));
            Assert.AreSame(factory, TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory);

            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor accessor =
                new TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor(factory);
            Assert.AreEqual(typeof(VabValidator), accessor._validatorType);

            // ログの確認
            Assert.AreEqual(0, LogUTUtil.CountLogs(typeof(ValidatorFactory), LogLevel.INFO));
        }

        /// <summary>
        /// CreateValidator() のテスト
        /// </summary>
        /// <remarks>
        /// _factory が not null, _validatorType が not null, 
        /// 構成ファイルに設定する ValidatorFactoryTypeName と ValidatorTypeName の記述がないの場合、
        /// IValidator を実装した既定の VabValidator が返却されることを確認するテスト。
        /// </remarks>
        [TestMethod()]
        public void CreateValidatorTest03()
        {
            //準備
            ValidatorFactory factory = new ValidatorFactory();
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory = factory;

            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor factoryAccessor =
                new TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor(factory);
            Type expectedType = typeof(VabValidator);
            factoryAccessor._validatorType = expectedType;

            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_FACTORY_TYPENAME = "DummyValidatorFactoryTypeName";
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_TYPENAME = "DummyValidatorTypeName";

            //実行
            IValidator target = ValidatorFactory.CreateValidator();

            //検証
            Assert.IsInstanceOfType(target, typeof(VabValidator));
            Assert.AreSame(factory, TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory);

            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor accessor =
                new TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor(factory);             
            Assert.AreSame(expectedType, accessor._validatorType);

            // ログの確認
            Assert.AreEqual(0, LogUTUtil.CountLogs(typeof(ValidatorFactory), LogLevel.INFO));
        }

        /// <summary>
        /// CreateValidator() のテスト
        /// </summary>
        /// <remarks>
        /// 構成ファイルに設定する ValidatorFactoryTypeName の記述があるが、
        /// ValidatorFactory 派生クラスのインスタンスを生成できない場合、
        /// TerasolunaException がスローされることを確認するテスト。
        /// </remarks>
        [TestMethod()]
        public void CreateValidatorTest04()
        {
            //準備
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory = null;

            String factoryTypeName = TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_FACTORY_TYPENAME;
            ConfigurationManager.AppSettings[factoryTypeName] = typeof(ValidatorFactory_Stub01).AssemblyQualifiedName;

            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_TYPENAME = "DummyValidatorTypeName";

            try
            {
                //実行
                IValidator target = ValidatorFactory.CreateValidator();
                Assert.Fail("到達してはいけないコードです。");
            }
            catch (TerasolunaException e)
            {
                // 成功
                string exceptionMessage = MessageManager.GetMessage("E_MEMBER_ACCESS_EXCEPTION",
                    typeof(ValidatorFactory_Stub01).AssemblyQualifiedName);
                Assert.AreEqual(exceptionMessage, e.Message);
            }
            catch (Exception e)
            {
                Assert.Fail("到達してはいけないコードです。" + e.ToString());
            }

            // ログの確認
            Assert.AreEqual(0, LogUTUtil.CountLogs(typeof(ValidatorFactory), LogLevel.INFO));
        }

        /// <summary>
        /// CreateValidator() のテスト
        /// </summary>
        /// <remarks>
        /// 構成ファイルに設定する ValidatorFactoryTypeName と ValidatorTypeName の記述があり、
        /// それぞれのクラスのインスタンスを生成できる場合、
        /// IValidator 実装クラスのインスタンスが返却されることを確認するテスト。
        /// </remarks>
        [TestMethod()]
        public void CreateValidatorTest05()
        {
            //準備
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory = null;

            String factoryTypeName = TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_FACTORY_TYPENAME;
            ConfigurationManager.AppSettings[factoryTypeName] = typeof(ValidatorFactory_Stub02).AssemblyQualifiedName;

            //実行
            IValidator target = ValidatorFactory.CreateValidator();

            //検証
            ValidatorFactory factory = TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory;
            Assert.IsInstanceOfType(target, typeof(ValidatorFactory_IValidatorImpl01));
            Assert.IsInstanceOfType(factory, typeof(ValidatorFactory_Stub02));

            Assert.AreEqual(typeof(ValidatorFactory_IValidatorImpl01), ((ValidatorFactory_Stub02)factory)._validatorType);

            // ログの確認
            Assert.AreEqual(0, LogUTUtil.CountLogs(typeof(ValidatorFactory), LogLevel.INFO));
        }

        /// <summary>
        /// CreateValidator() のテスト
        /// </summary>
        /// <remarks>
        /// 構成ファイルに設定する ValidatorFactoryTypeName の記述なし、
        /// ValidatorTypeName の記述があるが IValidator 実装クラスのインスタンスを生成できない場合、
        /// TerasolunaException がスローされることを確認するテスト。
        /// </remarks>
        [TestMethod()]
        public void CreateValidatorTest06()
        {
            //準備
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory = null;

            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_FACTORY_TYPENAME = "DummyValidatorFactoryTypeName";
            
            String typeName = TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_TYPENAME;
            ConfigurationManager.AppSettings[typeName] = typeof(ValidatorFactory_IValidatorImpl02).AssemblyQualifiedName; ;

            try
            {
                //実行
                IValidator target = ValidatorFactory.CreateValidator();
                Assert.Fail("到達してはいけないコードです。");
            }
            catch (TerasolunaException e)
            {
                // 成功
                string exceptionMessage = MessageManager.GetMessage("E_MEMBER_ACCESS_EXCEPTION",
                    typeof(ValidatorFactory_IValidatorImpl02).AssemblyQualifiedName);
                Assert.AreEqual(exceptionMessage, e.Message);
            }
            catch (Exception e)
            {
                Assert.Fail("到達してはいけないコードです。" + e.ToString());
            }

            // ログの確認
            Assert.AreEqual(0, LogUTUtil.CountLogs(typeof(ValidatorFactory), LogLevel.INFO));
        }

        /// <summary>
        /// CreateValidator() のテスト
        /// </summary>
        /// <remarks>
        /// 構成ファイルに設定する ValidatorFactoryTypeName の記述なし、
        /// ValidatorTypeName の記述があり IValidator 実装クラスのインスタンスを生成できる場合、
        /// IValidator 実装クラスのインスタンスが返却されることを確認するテスト。
        /// </remarks>
        [TestMethod()]
        public void CreateValidatorTest07()
        {
            //準備
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory = null;

            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_FACTORY_TYPENAME = "DummyValidatorFactoryTypeName";

            String typeName = TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor.VALIDATOR_TYPENAME;
            ConfigurationManager.AppSettings[typeName] = typeof(ValidatorFactory_IValidatorImpl01).AssemblyQualifiedName;

            //実行
            IValidator target = ValidatorFactory.CreateValidator();

            //検証
            Assert.IsInstanceOfType(target, typeof(ValidatorFactory_IValidatorImpl01));
            Assert.IsInstanceOfType(TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory,
                typeof(ValidatorFactory));

            ValidatorFactory factory = TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor._factory;
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor accessor =
                new TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor(factory);
            Assert.AreEqual(typeof(ValidatorFactory_IValidatorImpl01), accessor._validatorType);

            // ログの確認
            Assert.AreEqual(0, LogUTUtil.CountLogs(typeof(ValidatorFactory), LogLevel.INFO));
        }

        /// <summary>
        /// ValidatorType プロパティのテスト
        /// </summary>
        [TestMethod()]
        public void ValidatorTypeTest01()
        {
            // 準備
            ValidatorFactory factory = new ValidatorFactory();
            TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor accessor =
                new TERASOLUNA_Fw_Common_Validation_ValidatorFactoryAccessor(factory);
            Type expected = typeof(Object);

            // 実施
            accessor.ValidatorType = expected;
            Type actual = accessor.ValidatorType;

            // 確認
            Assert.AreEqual(expected, actual);
        }
    }
}
