/// <summary>
 /// <paramref name="value"/> is used to connect the caller with the underlying
 /// <see cref="Keyed.Flags.Enumeration{T}"/> type only. Additionally, we are making
 /// the assumption that <see cref="Enumeration.GetValues{T}"/> are unique not only
 /// in <see cref="Enumeration.Name"/>, but also in
 /// <see cref="Keyed.Enumeration{TKey}.Key"/> value. In truth, this could go either
 /// way, but for now I will expect that there must be uniqueness throughout.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="value"></param>
 /// <param name="reporter"></param>
 /// <param name="outputHelper"></param>
 /// <see cref="!:http://en.wikipedia.org/wiki/Enumeration"/>
 public static void KeysShallBeUniquelyAssigned <T>(this T value
                                                    , IEnumerationCoverageReporter <T> reporter = null
                                                    , ITestOutputHelper outputHelper            = null)
     where T : Keyed.Flags.Enumeration <T>
 => value.KeysShallBeUniquelyAssigned <ImmutableBitArray, uint, T>(
     x => x.ToInts().Single(), reporter, outputHelper
     );
        /// <summary>
        /// Connect the verification with the <see cref="Enumeration"/> <paramref name="_"/> only.
        /// We do not require the connection with the test class itself. In fact, we want it to be
        /// separate, so we can do some independent verification of different good, bad, or ugly
        /// use cases. We expect there to be no <see cref="Public"/>, <see cref="Instance"/>
        /// Constructors.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_">An anchor value rooting the Type <typeparamref name="T"/> only.</param>
        /// <param name="reporter">Disables the Reported following this invocation.</param>
        /// <see cref="Public"/>
        /// <see cref="Instance"/>
        /// <see cref="Type.GetConstructors(BindingFlags)"/>
        internal static void ShallNotHaveAnyPublicCtors <T>(this T _, IEnumerationCoverageReporter <T> reporter = null)
            where T : Enumeration
        {
            if (reporter != null)
            {
                reporter.Enabled = false;
            }

            // We do not care about the Value apart from identifying the underlying Enumeration Type.
            typeof(T).GetConstructors(Public | Instance).AssertEmpty();
        }
        /// <summary>
        /// Connect the verification with the <see cref="Keyed.Flags.Enumeration{T}"/>
        /// <paramref name="_"/> only. We do not require the connection with the test class
        /// itself. In fact, we want that to be separate and distinct in order so that we may
        /// do some independent verification of good, bad, or ugly test cases. Returns whether
        /// the Type <typeparamref name="T"/> Has the Expected Flags Constructors. That is,
        /// whether there is One <see cref="NonPublic"/>, <see cref="Instance"/> Constructor
        /// accepting a single <see cref="byte"/> Array. The Constructor must also be
        /// <see cref="MethodBase.IsPrivate"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_">Given a root value in order to inform the <typeparamref name="T"/> Type.</param>
        /// <param name="reporter"></param>
        /// <see cref="ConstructorInfo"/>
        /// <see cref="MethodBase.IsPrivate"/>
        /// <see cref="NonPublic"/>
        /// <see cref="Instance"/>
        /// <see cref="T:byte[]"/>
        internal static void HasExpectedFlagsCtors <T>(this T _, IEnumerationCoverageReporter <T> reporter = null)
            where T : Keyed.Flags.Enumeration <T>
        {
            if (reporter != null)
            {
                reporter.Enabled = false;
            }

            const BindingFlags nonPublicInstance = NonPublic | Instance;
            var types = new[] { typeof(byte[]) };
            var ctor  = typeof(T).GetConstructor(nonPublicInstance, DefaultBinder, types, null);

            ctor.AssertNotNull().AssertTrue(x => x.IsPrivate);
        }
        /// <summary>
        /// Verifies that the type <typeparamref name="T"/> Shall Have At Least One Value. We do
        /// not care about the <paramref name="_"/> itself apart from its connection with the
        /// generic type <typeparamref name="T"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_">Given a pass through anchor value rooting the Type <typeparamref name="T"/>.</param>
        /// <param name="reporter">Reporter is disabled following this invocation.</param>
        /// <returns>The pass through <paramref name="_"/> value.</returns>
        /// <see cref="Enumeration.GetValues{T}"/>
        internal static T ShallHaveAtLeastOneValue <T>(this T _, IEnumerationCoverageReporter <T> reporter = null)
            where T : Enumeration
        {
            if (reporter != null)
            {
                reporter.Enabled = false;
            }

            /* Do not Report any Names at this level; this is intentional. Rather, do leave that
             * level of reporting for the actual unit test coverage. This ensures that we enforce
             * appropriate Enumeration Test Coverage at appropriate levels. */
            Enumeration.GetValues <T>().AssertNotNull().AssertNotEmpty();

            return(_);
        }
        /// <summary>
        /// <typeparamref name="T"/> <see cref="Keyed.Flags.Enumeration{T}"/> values Shall All
        /// have Consistent <see cref="Keyed.Enumeration{TKey}.Key"/> lengths. Rules out false
        /// positives in the form of empty <see cref="Enumeration.GetValues{T}"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="ignoreNulls"></param>
        /// <param name="reporter"></param>
        internal static void ShallAllHaveConsistentBitLengths <T>(this T value, bool ignoreNulls = true
                                                                  , IEnumerationCoverageReporter <T> reporter = null)
            where T : Keyed.Flags.Enumeration <T>
        {
            var values = Enumeration.GetValues <T>(ignoreNulls).AssertNotNull().AssertNotEmpty();

            // ReSharper disable once UnusedVariable
            var distinct = values.Select(x =>
            {
                Assert.NotNull(x);

                /* There must be some Bits for this to work...
                 * Yes, while we could Assert NotEmpty here, I am trying to keep the thrown
                 * Exceptions as distinct as possible, not least of which for unit test purposes. */

                var length = x.Key.AssertNotNull().AssertNotEmpty().Length;
                reporter?.Report(x.Name);
                return(length);
            }).Distinct().AssertEqual(1, x => x.Count());
        }
Example #6
0
 /// <summary>
 /// Protected Constructor.
 /// </summary>
 /// <param name="outputHelper"></param>
 /// <param name="reporter"></param>
 /// <inheritdoc />
 protected EnumerationTestFixtureBase(ITestOutputHelper outputHelper, IEnumerationCoverageReporter <T> reporter)
     : base(outputHelper)
 {
     Reporter = reporter;
 }
 /// <summary>
 /// <paramref name="value"/> is used to connect the caller with the underlying
 /// <see cref="Keyed.Enumeration{TKey,T}"/> type only. Additionally, we are making
 /// the assumption that <see cref="Enumeration.GetValues{T}"/> are unique not only
 /// in <see cref="Enumeration.Name"/>, but also in
 /// <see cref="Keyed.Enumeration{TKey}.Key"/> value. In truth, this could go either
 /// way, but for now I will expect that there must be uniqueness throughout.
 /// </summary>
 /// <typeparam name="TKey"></typeparam>
 /// <typeparam name="T"></typeparam>
 /// <param name="value"></param>
 /// <param name="reporter"></param>
 /// <param name="outputHelper"></param>
 /// <see cref="!:http://en.wikipedia.org/wiki/Enumeration"/>
 public static void KeysShallBeUniquelyAssigned <TKey, T>(this T value
                                                          , IEnumerationCoverageReporter <T> reporter = null
                                                          , ITestOutputHelper outputHelper            = null)
     where T : Keyed.Enumeration <TKey, T>
     where TKey : IComparable <TKey>, IEquatable <TKey>
 => value.KeysShallBeUniquelyAssigned <TKey, TKey, T>(x => x, reporter, outputHelper);
        /// <summary>
        /// <paramref name="value"/> is used to connect the caller with the underlying
        /// <see cref="Keyed.Enumeration{TKey,T}"/> type only. Additionally, we are making
        /// the assumption that <see cref="Enumeration.GetValues{T}"/> are unique not only
        /// in <see cref="Enumeration.Name"/>, but also in
        /// <see cref="Keyed.Enumeration{TKey}.Key"/> value. In truth, this could go either
        /// way, but for now I will expect that there must be uniqueness throughout.
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TGroupByKey"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="groupByKey"></param>
        /// <param name="reporter"></param>
        /// <param name="outputHelper"></param>
        /// <see cref="!:http://en.wikipedia.org/wiki/Enumeration"/>
        public static void KeysShallBeUniquelyAssigned <TKey, TGroupByKey, T>(this T value
                                                                              , Func <TKey, TGroupByKey> groupByKey, IEnumerationCoverageReporter <T> reporter = null
                                                                              , ITestOutputHelper outputHelper = null)
            where T : Keyed.Enumeration <TKey, T>
            where TKey : IComparable <TKey>, IEquatable <TKey>
        {
            var values = Enumeration.GetValues <T>().Select(x =>
            {
                var result = x;
                reporter?.Report(x.Name);
                return(result);
            }).ToList();

            // This step is key, must all be Uniquely Assigned, that is, in Groups of One.
            //var grouped = values.GroupBy(x => x.Key).ToArray();
            var grouped = values.GroupBy(x => groupByKey.Invoke(x.Key)).ToArray();

            try
            {
                values.AssertEqual(grouped.Length, x => x.Count);
            }
            catch (EqualException)
            {
                string ListDupes() => Join(", ", grouped.Where(g => g.Count() > 1).Select(g => $"`{g.Key}ยด"));

                outputHelper?.WriteLine($"Some Enumerated values have Duplicate Bits: {ListDupes()}");
                throw;
            }
        }
Example #9
0
 /// <summary>
 /// Protected Constructor.
 /// </summary>
 /// <param name="outputHelper"></param>
 /// <param name="reporter"></param>
 /// <inheritdoc />
 protected OrdinalEnumerationTestFixtureBase(ITestOutputHelper outputHelper, IEnumerationCoverageReporter <T> reporter)
     : base(outputHelper, reporter)
 {
 }