<commit_before>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Xunit;
using Xunit.Extensions;
using Xunit.Sdk;

namespace Jwc.Experiment
{
    /// <summary>
    /// 이 attribute는 method위에 선언되어 해당 method가 test case라는 것을
    /// 지칭하게 되며, non-parameterized test 뿐 아니라 parameterized test에도
    /// 사용될 수 있다.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "Parameterized test에 auto data를 제공하기 위해, Subclass에서 ITestFixture factory를 제공할 수 있음.")]
    [AttributeUsage(AttributeTargets.Method)]
    public class NaiveTheoremAttribute : FactAttribute
    {
        private readonly Func<MethodInfo, ITestFixture> _fixtureFactory;

        /// <summary>
        /// Initializes a new instance of the <see cref="NaiveTheoremAttribute"/> class.
        /// </summary>
        public NaiveTheoremAttribute()
        {
            _fixtureFactory = mi => new NotSupportedFixture();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NaiveTheoremAttribute"/> class.
        /// </summary>
        /// <param name="fixtureType">Type of the fixture.</param>
        /// <exception cref="System.ArgumentNullException">fixtureType</exception>
        public NaiveTheoremAttribute(Type fixtureType)
        {
            if (fixtureType == null)
            {
                throw new ArgumentNullException("fixtureType");
            }

            _fixtureFactory = mi => (ITestFixture)Activator.CreateInstance(fixtureType);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NaiveTheoremAttribute"/> class.
        /// </summary>
        /// <param name="fixtureFactory">The fixture factory.</param>
        /// <exception cref="System.ArgumentNullException">fixtureFactory</exception>
        protected NaiveTheoremAttribute(Func<ITestFixture> fixtureFactory)
        {
            if (fixtureFactory == null)
            {
                throw new ArgumentNullException("fixtureFactory");
            }

            _fixtureFactory = mi => fixtureFactory();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NaiveTheoremAttribute"/> class.
        /// </summary>
        /// <param name="fixtureFactory">The fixture factory.</param>
        protected NaiveTheoremAttribute(Func<MethodInfo, ITestFixture> fixtureFactory)
        {
            if (fixtureFactory == null)
            {
                throw new ArgumentNullException("fixtureFactory");
            }

            _fixtureFactory = fixtureFactory;
        }

        /// <summary>
        /// Gets a value indicating the fixture type passed from a constructor.
        /// </summary>
        public object FixtureType
        {
            get
            {
                var dummyMethodInfo = typeof(object).GetMethod("ToString");
                return FixtureFactory.Invoke(dummyMethodInfo).GetType();
            }
        }

        /// <summary>
        /// Gets a value indicating the fixture factory passed from a constructor.
        /// </summary>
        public Func<MethodInfo, ITestFixture> FixtureFactory
        {
            get
            {
                return _fixtureFactory;
            }
        }

        /// <summary>
        /// Enumerates the test commands represented by this test method.
        /// Derived classes should override this method to return instances of
        /// <see cref="ITestCommand" />, one per execution of a test method.
        /// </summary>
        /// <param name="method">The test method</param>
        /// <returns>
        /// The test commands which will execute the test runs for the given method
        /// </returns>
        protected override IEnumerable<ITestCommand> EnumerateTestCommands(IMethodInfo method)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

            var dataAttributes = ((IEnumerable<DataAttribute>)method
                .MethodInfo
                .GetCustomAttributes(typeof(DataAttribute), false)).ToArray();
            var testData = new TestData(method.MethodInfo, dataAttributes);

            if (!testData.Any())
            {
                yield return CreateSingleTestCommand(method);
                yield break;
            }

            foreach (var testCommand in testData.Select(tcd => CreateEachTestCommand(method, tcd)))
            {
                yield return testCommand;
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification="auto data를 만들 때 발생되는 unhandled exception을 처리하기 위해서 이 경고 무시함.")]
        private ITestCommand CreateSingleTestCommand(IMethodInfo method)
        {
            var autoArguments = new AutoArgumentCollection(
                FixtureFactory, method.MethodInfo, method.MethodInfo.GetParameters());

            if (!autoArguments.HasAutoParemeters)
            {
                return base.EnumerateTestCommands(method).Single();
            }
           
            try
            {
                return new TheoryCommand(method, autoArguments.ToArray());
            }
            catch (Exception exception)
            {
                return new ExceptionCommand(method, exception);
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "auto data를 만들 때 발생되는 unhandled exception을 처리하기 위해서 이 경고 무시함.")]
        private ITestCommand CreateEachTestCommand(IMethodInfo method, object[] testCaseData)
        {
            var autoArguments = new AutoArgumentCollection(
                FixtureFactory,
                method.MethodInfo,
                method.MethodInfo.GetParameters(),
                testCaseData.Length);
            var argument = testCaseData.Concat(autoArguments);

            try
            {
                return new TheoryCommand(method, argument.ToArray());
            }
            catch (Exception exception)
            {
                return new ExceptionCommand(method, exception);
            }
        }

        private class TestData : IEnumerable<object[]>
        {
            private readonly MethodInfo _method;
            private readonly DataAttribute[] _dataAttributes;

            public TestData(MethodInfo method, DataAttribute[] dataAttributes)
            {
                _method = method;
                _dataAttributes = dataAttributes;
            }

            public IEnumerator<object[]> GetEnumerator()
            {
                var parameterTypes = _method.GetParameters().Select(pi => pi.ParameterType).ToArray();
                return _dataAttributes.SelectMany(da => da.GetData(_method, parameterTypes)).GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }

        private class AutoArgumentCollection : IEnumerable<object>
        {
            private readonly Func<MethodInfo, ITestFixture> _fixtureFactory;
            private readonly MethodInfo _methodInfo;
            private readonly ParameterInfo[] _parameters;
            private readonly int _skipCount;

            public AutoArgumentCollection(
                Func<MethodInfo, ITestFixture> fixtureFactory,
                MethodInfo methodInfo,
                ParameterInfo[] parameters,
                int skipCount = 0)
            {
                _fixtureFactory = fixtureFactory;
                _methodInfo = methodInfo;
                _parameters = parameters;
                _skipCount = skipCount;
            }

            public bool HasAutoParemeters
            {
                get
                {
                    return _parameters.Length != 0;
                }
            }

            public IEnumerator<object> GetEnumerator()
            {
                var testFixture = _fixtureFactory.Invoke(_methodInfo);
                return _parameters
                    .Skip(_skipCount)
                    .Select(pi => testFixture.Create(pi.ParameterType))
                    .GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }
    }
}<commit_msg>refactor: rename TestData class to TestDataCollection.<commit_after>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Xunit;
using Xunit.Extensions;
using Xunit.Sdk;

namespace Jwc.Experiment
{
    /// <summary>
    /// 이 attribute는 method위에 선언되어 해당 method가 test case라는 것을
    /// 지칭하게 되며, non-parameterized test 뿐 아니라 parameterized test에도
    /// 사용될 수 있다.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "Parameterized test에 auto data를 제공하기 위해, Subclass에서 ITestFixture factory를 제공할 수 있음.")]
    [AttributeUsage(AttributeTargets.Method)]
    public class NaiveTheoremAttribute : FactAttribute
    {
        private readonly Func<MethodInfo, ITestFixture> _fixtureFactory;

        /// <summary>
        /// Initializes a new instance of the <see cref="NaiveTheoremAttribute"/> class.
        /// </summary>
        public NaiveTheoremAttribute()
        {
            _fixtureFactory = mi => new NotSupportedFixture();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NaiveTheoremAttribute"/> class.
        /// </summary>
        /// <param name="fixtureType">Type of the fixture.</param>
        /// <exception cref="System.ArgumentNullException">fixtureType</exception>
        public NaiveTheoremAttribute(Type fixtureType)
        {
            if (fixtureType == null)
            {
                throw new ArgumentNullException("fixtureType");
            }

            _fixtureFactory = mi => (ITestFixture)Activator.CreateInstance(fixtureType);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NaiveTheoremAttribute"/> class.
        /// </summary>
        /// <param name="fixtureFactory">The fixture factory.</param>
        /// <exception cref="System.ArgumentNullException">fixtureFactory</exception>
        protected NaiveTheoremAttribute(Func<ITestFixture> fixtureFactory)
        {
            if (fixtureFactory == null)
            {
                throw new ArgumentNullException("fixtureFactory");
            }

            _fixtureFactory = mi => fixtureFactory();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NaiveTheoremAttribute"/> class.
        /// </summary>
        /// <param name="fixtureFactory">The fixture factory.</param>
        protected NaiveTheoremAttribute(Func<MethodInfo, ITestFixture> fixtureFactory)
        {
            if (fixtureFactory == null)
            {
                throw new ArgumentNullException("fixtureFactory");
            }

            _fixtureFactory = fixtureFactory;
        }

        /// <summary>
        /// Gets a value indicating the fixture type passed from a constructor.
        /// </summary>
        public object FixtureType
        {
            get
            {
                var dummyMethodInfo = typeof(object).GetMethod("ToString");
                return FixtureFactory.Invoke(dummyMethodInfo).GetType();
            }
        }

        /// <summary>
        /// Gets a value indicating the fixture factory passed from a constructor.
        /// </summary>
        public Func<MethodInfo, ITestFixture> FixtureFactory
        {
            get
            {
                return _fixtureFactory;
            }
        }

        /// <summary>
        /// Enumerates the test commands represented by this test method.
        /// Derived classes should override this method to return instances of
        /// <see cref="ITestCommand" />, one per execution of a test method.
        /// </summary>
        /// <param name="method">The test method</param>
        /// <returns>
        /// The test commands which will execute the test runs for the given method
        /// </returns>
        protected override IEnumerable<ITestCommand> EnumerateTestCommands(IMethodInfo method)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

            var dataAttributes = ((IEnumerable<DataAttribute>)method
                .MethodInfo
                .GetCustomAttributes(typeof(DataAttribute), false)).ToArray();
            var testData = new TestDataCollection(method.MethodInfo, dataAttributes);

            if (!testData.Any())
            {
                yield return CreateSingleTestCommand(method);
                yield break;
            }

            foreach (var testCommand in testData.Select(tcd => CreateEachTestCommand(method, tcd)))
            {
                yield return testCommand;
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification="auto data를 만들 때 발생되는 unhandled exception을 처리하기 위해서 이 경고 무시함.")]
        private ITestCommand CreateSingleTestCommand(IMethodInfo method)
        {
            var autoArguments = new AutoArgumentCollection(
                FixtureFactory, method.MethodInfo, method.MethodInfo.GetParameters());

            if (!autoArguments.HasAutoParemeters)
            {
                return base.EnumerateTestCommands(method).Single();
            }
           
            try
            {
                return new TheoryCommand(method, autoArguments.ToArray());
            }
            catch (Exception exception)
            {
                return new ExceptionCommand(method, exception);
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "auto data를 만들 때 발생되는 unhandled exception을 처리하기 위해서 이 경고 무시함.")]
        private ITestCommand CreateEachTestCommand(IMethodInfo method, object[] testCaseData)
        {
            var autoArguments = new AutoArgumentCollection(
                FixtureFactory,
                method.MethodInfo,
                method.MethodInfo.GetParameters(),
                testCaseData.Length);
            var argument = testCaseData.Concat(autoArguments);

            try
            {
                return new TheoryCommand(method, argument.ToArray());
            }
            catch (Exception exception)
            {
                return new ExceptionCommand(method, exception);
            }
        }

        private class TestDataCollection : IEnumerable<object[]>
        {
            private readonly MethodInfo _method;
            private readonly DataAttribute[] _dataAttributes;

            public TestDataCollection(MethodInfo method, DataAttribute[] dataAttributes)
            {
                _method = method;
                _dataAttributes = dataAttributes;
            }

            public IEnumerator<object[]> GetEnumerator()
            {
                var parameterTypes = _method.GetParameters().Select(pi => pi.ParameterType).ToArray();
                return _dataAttributes.SelectMany(da => da.GetData(_method, parameterTypes)).GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }

        private class AutoArgumentCollection : IEnumerable<object>
        {
            private readonly Func<MethodInfo, ITestFixture> _fixtureFactory;
            private readonly MethodInfo _methodInfo;
            private readonly ParameterInfo[] _parameters;
            private readonly int _skipCount;

            public AutoArgumentCollection(
                Func<MethodInfo, ITestFixture> fixtureFactory,
                MethodInfo methodInfo,
                ParameterInfo[] parameters,
                int skipCount = 0)
            {
                _fixtureFactory = fixtureFactory;
                _methodInfo = methodInfo;
                _parameters = parameters;
                _skipCount = skipCount;
            }

            public bool HasAutoParemeters
            {
                get
                {
                    return _parameters.Length != 0;
                }
            }

            public IEnumerator<object> GetEnumerator()
            {
                var testFixture = _fixtureFactory.Invoke(_methodInfo);
                return _parameters
                    .Skip(_skipCount)
                    .Select(pi => testFixture.Create(pi.ParameterType))
                    .GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }
    }
}
{'fraction_non_alphanumeric': 0.08693622731781317, 'fraction_numerical': 0.0016337009160394423, 'mean_word_length': 1.7685349701179132, 'pattern_counts': {'":': 0, '<': 97, '<?xml version=': 0, '>': 111, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1200023', 'n_tokens_mistral': 4241, 'n_tokens_neox': 4176, 'n_words': 971}