/// <summary> /// Returns all the values of the enumerable that don't belong to the expected ones. /// </summary> /// <param name="enumerable">The enumerable to inspect.</param> /// <param name="expectedValues">The allowed values to be part of the enumerable.</param> /// <returns> /// A list with all the values found in the enumerable that don't belong to the expected ones. /// </returns> private static IList <object> ExtractUnexpectedValues(IEnumerable enumerable, IEnumerable expectedValues) { var equalityComparer = new EqualityHelper.EqualityComparer <object>(); var values = (expectedValues ?? new List <object>()).Cast <object>().ToList(); return(enumerable.Cast <object>().Where(element => !values.Contains(element, equalityComparer)).ToList()); }
/// <summary> /// Returns all expected values that aren't present in the enumerable. /// </summary> /// <param name="enumerable">The enumerable to inspect.</param> /// <param name="expectedValues">The expected values to search within the enumerable.</param> /// <returns> /// A list containing all the expected values that aren't present in the enumerable. /// </returns> private static IList <object> ExtractNotFoundValues(IEnumerable enumerable, IEnumerable expectedValues) { if (expectedValues == null) { return(new List <object>()); } // Prepares the list to return var values = expectedValues as IList <object> ?? expectedValues.Cast <object>().ToList(); var notFoundValues = values.ToList(); var comparer = new EqualityHelper.EqualityComparer <object>(); foreach (var element in enumerable) { foreach (var expectedValue in values) { if (!comparer.Equals(element, expectedValue)) { continue; } notFoundValues.RemoveAll(one => comparer.Equals(one, expectedValue)); break; } } return(notFoundValues); }
/// <summary> /// Checks that the enumerable contains only the values of another enumerable and nothing else, in order. /// This check should only be used with IEnumerable that have a consistent iteration order /// (i.e. don't use it with Hashtable, prefer <see cref="IsOnlyMadeOf{T}" /> in that case). /// </summary> /// <param name="check">The fluent check to be extended.</param> /// <param name="otherEnumerable">The other enumerable containing the exact expected values to be found.</param> /// <returns> /// A check link. /// </returns> /// <exception cref="FluentCheckException"> /// The enumerable does not contains only the exact given values and nothing else, /// in order. /// </exception> public static ICheckLink <ICheck <TU> > ContainsExactly <TU>( this ICheck <TU> check, IEnumerable otherEnumerable) where TU : IEnumerable { var enumerable = otherEnumerable == null ? null : otherEnumerable as IList <object> ?? otherEnumerable.Cast <object>().ToList(); var test = ExtensibilityHelper.BeginCheck(check). DefineExpectedValues(enumerable, enumerable?.Count ?? 0). FailWhen(sut => sut == null && enumerable != null, "The {0} is null and thus does not contain exactly the {1}.", MessageOption.NoCheckedBlock). FailWhen(sut => sut != null && enumerable == null, "The {0} is not null whereas it should.", MessageOption.NoExpectedBlock). OnNegate("The {0} contains exactly the given values whereas it must not.", MessageOption.NoExpectedBlock); test.Analyze((sut, runner) => { if (sut == null || otherEnumerable == null) { return; } var index = 0; var first = sut.GetEnumerator(); var comparer = new EqualityHelper.EqualityComparer <object>(); var sutCount = sut.Count(); var expectedCount = enumerable.Count; var failed = false; using (var second = enumerable.GetEnumerator()) { while (first.MoveNext()) { if (!second.MoveNext() || !comparer.Equals(first.Current, second.Current)) { if (sutCount > expectedCount && index == expectedCount) { test.Fail($"The {{0}} does not contain exactly the expected value(s). There are extra elements starting at index #{index}."); } else { test.Fail($"The {{0}} does not contain exactly the expected value(s). First difference is at index #{index}."); } test.SetValuesIndex(index); failed = true; break; } index++; } if (second.MoveNext() && !failed) { test.Fail($"The {{0}} does not contain exactly the expected value(s). Elements are missing starting at index #{index}."); test.SetValuesIndex(index); } } }); test.EndCheck(); return(ExtensibilityHelper.BuildCheckLink(check)); }
/// <summary> /// Checks that the actual value is one of the legal values. /// </summary> /// <typeparam name="T">Type of the checked value.</typeparam> /// <param name="check">The fluent check context object.</param> /// <param name="values">List of possible values.</param> /// <returns>A check link</returns> public static ICheckLink <ICheck <T> > IsOneOf <T>(this ICheck <T> check, params T[] values) { var comparer = new EqualityHelper.EqualityComparer <T>(); ExtensibilityHelper.BeginCheck(check) .ExpectingValues(values, values.Length, "one of", "none of") .FailsIf(sut => !values.Any(value => comparer.Equals(sut, value)), "The {0} is not one of the {1}.") .Negates("The {0} should not be one of the {1}."). EndCheck(); return(ExtensibilityHelper.BuildCheckLink(check)); }
private static void ImplementContainsExactly <T, TU>(ICheckLogic <T> test, IEnumerable <TU> enumerable) where T : IEnumerable <TU> { var count = enumerable?.Count() ?? 0; test.DefineExpectedValues(enumerable, count). FailWhen(sut => sut == null && enumerable != null, "The {0} is null and thus does not contain exactly the {1}.", MessageOption.NoCheckedBlock). FailWhen(sut => sut != null && enumerable == null, "The {0} is not null whereas it should.", MessageOption.NoExpectedBlock). OnNegate("The {0} contains exactly the given values whereas it must not.", MessageOption.NoExpectedBlock); test.Analyze((sut, runner) => { if (sut == null) { return; } var index = 0; using (var first = sut.GetEnumerator()) { var comparer = new EqualityHelper.EqualityComparer <object>(); // ReSharper disable once PossibleNullReferenceException var expectedCount = count; var failed = false; using (var second = enumerable.GetEnumerator()) { while (first.MoveNext()) { if (!second.MoveNext() || !comparer.Equals(first.Current, second.Current)) { test.Fail( index == expectedCount ? $"The {{0}} does not contain exactly the expected value(s). There are extra elements starting at index #{index}." : $"The {{0}} does not contain exactly the expected value(s). First difference is at index #{index}."); test.SetValuesIndex(index); failed = true; break; } index++; } if (!second.MoveNext() || failed) { return; } test.Fail( $"The {{0}} does not contain exactly the expected value(s). Elements are missing starting at index #{index}."); test.SetValuesIndex(index); } } }); test.EndCheck(); }
/// <summary> /// Checks that the actual value is one of the legal values. /// </summary> /// <typeparam name="T">Type of the checked value.</typeparam> /// <param name="check">The fluent check context object.</param> /// <param name="values">List of possible values.</param> /// <returns>A check link</returns> public static ICheckLink <ICheck <T> > IsOneOf <T>(this ICheck <T> check, params T[] values) { var comparer = new EqualityHelper.EqualityComparer <T>(); ExtensibilityHelper.BeginCheck(check) .DefinePossibleValues(values, values.Length) .FailWhen(sut => !values.Any(value => comparer.Equals(sut, value)), "The {0} is not one of the {1}.") .OnNegate("The {0} should not be one of the {1}."). EndCheck(); return(ExtensibilityHelper.BuildCheckLink(check)); }