public virtual void TryCompare_SupportsDifferentValidTypes() { foreach (Type type in _validTypes) { object one = null, two = null; try { one = Tools.Randomizer.Create(type); two = Tools.Mutator.Variant(one.GetType(), one); (bool, IEnumerable <Difference>)result = TestInstance.TryCompare(one, two, CreateChainer()); Tools.Asserter.Is(true, result.Item1, $"Hint '{typeof(T).Name}' failed to support '{type.Name}'."); Tools.Asserter.IsNotEmpty(result.Item2.ToArray(), $"Hint '{typeof(T).Name}' didn't find differences with two random '{type.Name}'."); } catch (Exception e) { ExpandReflectionException(e); throw; } finally { Disposer.Cleanup(one, two); } } }
public void TryCopy_SupportsValidTypes() { foreach (Type type in _validTypes) { object data = null; (bool, object)result = (false, null); try { data = Tools.Randomizer.Create(type); result = TestInstance.TryCopy(data, CreateChainer()); Tools.Asserter.Is((true, data), result, "Hint '" + typeof(T).Name + "' failed to clone type '" + type.Name + "'."); if (_copiesByRef || data is string) { Tools.Asserter.ReferenceEqual(data, result.Item2, "Hint '" + typeof(T).Name + "' expected to copy value types by ref of type '" + type.Name + "'."); } else { Tools.Asserter.ReferenceNotEqual(data, result.Item2, "Hint '" + typeof(T).Name + "' copied by ref instead of a deep clone of type '" + type.Name + "'."); } } finally { Disposer.Cleanup(data, result.Item2); } } }
public void TryGetHashCode_SupportsDifferentValidTypes() { foreach (Type type in _validTypes) { object data = null, dataDiffer = null; try { data = Tools.Randomizer.Create(type); dataDiffer = Tools.Mutator.Variant(data); (bool, int)dataHash = TestInstance.TryGetHashCode(data, CreateChainer()); Tools.Asserter.Is(true, dataHash.Item1, $"Hint '{typeof(T).Name}' failed to support '{type.Name}'."); Tools.Asserter.IsNot(dataHash, TestInstance.TryGetHashCode(dataDiffer, CreateChainer()), $"Hint '{typeof(T).Name}' generated same hash for different '{type.Name}'."); } catch (Exception e) { ExpandReflectionException(e); throw; } finally { Disposer.Cleanup(data, dataDiffer); } } }
public void TryCompare_SupportsSameValidTypes() { foreach (Type type in _validTypes) { object data = null; try { data = Tools.Randomizer.Create(type); (bool, IEnumerable <Difference>)result = TestInstance.TryCompare(data, data, CreateChainer()); Tools.Asserter.Is(true, result.Item1, $"Hint '{typeof(T).Name}' failed to support '{type.Name}'."); Tools.Asserter.IsEmpty(result.Item2, $"Hint '{typeof(T).Name}' found differences with same '{type.Name}' of '{data.GetType()}'."); } catch (Exception e) { ExpandReflectionException(e); throw; } finally { Disposer.Cleanup(data); } } }
public void TryCompare_InvalidTypesFail() { foreach (Type type in _invalidTypes) { object one = null, two = null; try { one = Tools.Randomizer.Create(type); two = Tools.Randomizer.Create(one.GetType()); Tools.Asserter.Is((false, (IEnumerable <Difference>)null), TestInstance.TryCompare(one, two, CreateChainer()), $"Hint '{typeof(T).Name}' should not support type '{type.Name}'."); } catch (Exception e) { ExpandReflectionException(e); throw; } finally { Disposer.Cleanup(one, two); } } }
/// <summary>Checks data for disposables and disposes them.</summary> /// <param name="injectedValues">Injected values to ignore.</param> /// <param name="data">Data to check and dispose.</param> protected void DisposeAllButInjected(object[] injectedValues, params object[] data) { foreach (object item in data ?? Array.Empty <object>()) { if (item is object[] nested) { DisposeAllButInjected(injectedValues, nested); } else if (!(injectedValues?.Any(v => ReferenceEquals(item, v)) ?? false)) { Disposer.Cleanup(item); } } }
public void TryCopy_InvalidTypesFail() { foreach (Type type in _invalidTypes) { object data = Tools.Randomizer.Create(type); try { Tools.Asserter.Is((false, (object)null), TestInstance.TryCopy(data, CreateChainer()), "Hint '" + typeof(T).Name + "' should not support type '" + type.Name + "'."); } finally { Disposer.Cleanup(data); } } }
/// <summary>Verifies the type works with the tools.</summary> /// <param name="type">Type to test.</param> private static void TestTrip(Type type) { string failMessage = "Behavior did not work for type '" + type.FullName + "'."; object original = null, variant = null, dupe = null; try { original = Tools.Randomizer.Create(type); dupe = Tools.Duplicator.Copy(original); Tools.Asserter.ValuesEqual(original, dupe, failMessage); Tools.Asserter.ValuesEqual( Tools.Valuer.GetHashCode(original), Tools.Valuer.GetHashCode(dupe), $"Hashcode {failMessage}"); if (type.GetProperties(_Mutable).Any() || type.GetFields(_Mutable).Any()) { variant = Tools.Mutator.Variant(type, original); Tools.Asserter.ValuesNotEqual(original, variant, failMessage); Tools.Asserter.ValuesNotEqual( Tools.Valuer.GetHashCode(original), Tools.Valuer.GetHashCode(variant), failMessage); if (Tools.Mutator.Modify(original)) { Tools.Asserter.ValuesNotEqual(dupe, original); } } if (Tools.Faker.Supports(type) && !type.Inherits <IDisposable>()) { Tools.Faker.Mock(type); } } finally { Disposer.Cleanup(original, variant, dupe); } }
/// <summary>Verifies the given behavior throws an exception.</summary> /// <typeparam name="TException">Exception type expected.</typeparam> /// <param name="details">Optional failure details.</param> /// <exception cref="AssertException">If the expected behavior doesn't happen.</exception> public virtual TException Throws <TException>(string details = null) where TException : Exception { string errorMessage = $"Expected exception of type '{typeof(TException).FullName}'."; try { if (Behavior is Action action) { action.Invoke(); } else { Disposer.Cleanup(((dynamic)Behavior)?.Invoke()); } } catch (TException e) { return(e); } catch (AggregateException e) { if (e.InnerExceptions.Count == 1 && e.InnerExceptions[0] is TException actual) { return(actual); } else { throw new AssertException(errorMessage, details, Gen.InitialSeed, e); } } catch (Exception e) { throw new AssertException(errorMessage, details, Gen.InitialSeed, e); } throw new AssertException(errorMessage, details, Gen.InitialSeed); }
/// <summary>Calls all methods to test parameter being set to null.</summary> /// <param name="testOrigin">Method under test.</param> /// <param name="testParam">Parameter being set to null.</param> /// <param name="instance">Instance whose methods to test.</param> /// <param name="injectionValues">Values to inject into the method.</param> protected void CallAllMethods(MethodBase testOrigin, ParameterInfo testParam, object instance, object[] injectionValues) { if (instance == null) { throw new ArgumentNullException(nameof(instance)); } foreach (MethodInfo method in FindAllMethods(instance.GetType(), BindingFlags.Instance) .Where(m => m.Name is not "Finalize" and not "Dispose") .Where(m => !m.IsFamily) .Select(m => Fixer.FixMethod(m))) { object[] data = Randomizer.CreateFor(method, injectionValues).Args.ToArray(); try { Disposer.Cleanup(RunCheck(testOrigin ?? method, testParam, () => method.Invoke(instance, data))); } finally { DisposeAllButInjected(injectionValues, data); } } }
public void TryGetHashCode_InvalidTypesFail() { foreach (Type type in _invalidTypes) { object data = null; try { data = Tools.Randomizer.Create(type); Tools.Asserter.Is((false, default(int)), TestInstance.TryGetHashCode(data, CreateChainer()), $"Hint '{typeof(T).Name}' should not support type '{type.Name}'."); } catch (Exception e) { ExpandReflectionException(e); throw; } finally { Disposer.Cleanup(data); } } }
public void TryCreate_SupportsValidTypes() { foreach (Type type in _validTypes) { (bool, object)result = TestInstance.TryCreate(type, CreateChainer()); try { Tools.Asserter.Is(true, result.Item1, "Hint '" + typeof(T).Name + "' did not support type '" + type.Name + "'."); Tools.Asserter.IsNot(null, result.Item2, "Hint '" + typeof(T).Name + "' did not create valid '" + type.Name + "'."); if (result.Item2 is IEnumerable collection) { Tools.Asserter.Is(true, collection.GetEnumerator().MoveNext(), "Hint '" + typeof(T).Name + "' failed to create populated '" + type + "'."); } } finally { Disposer.Cleanup(result.Item2); } } }