Пример #1
0
        public FormattableString TryGetFriendlyMessage(FailedAssertion assertion)
        {
            var notContains = assertion.IsNegated;

            var callExpression = (MethodCallExpression)assertion.ExpressionWithoutNegation;

            var instance = callExpression.Object;

            var isExtensionMethod = callExpression.Method.IsDefined(typeof(ExtensionAttribute), false);

            if (isExtensionMethod)
            {
                instance = callExpression.Arguments.First();
            }

            var expectedContainedValueExpression = callExpression.Arguments.Skip(isExtensionMethod ? 1 : 0).First();

            FormattableString expectedValueString;

            if (ExpressionHelper.IsConstantExpression(expectedContainedValueExpression))
            {
                expectedValueString = $"{expectedContainedValueExpression}";
            }
            else
            {
                expectedValueString = $"{expectedContainedValueExpression} (value: {expectedContainedValueExpression.ToValue()})";
            }

            if (instance != null && instance.Type == typeof(string))
            {
                return($"Expected {instance} (value: {instance.ToValue()}) to{(notContains ? " not " : " ")}contain {expectedValueString}.");
            }

            return($"Expected {instance} to{(notContains ? " not " : " ")}contain {expectedValueString}.");
        }
Пример #2
0
        public HandledException?Handle(FailedAssertion assertion)
        {
            var nullVisitor = new NullReferenceVisitor();

            nullVisitor.Visit(assertion.Expression);

            if (nullVisitor.CauseOfNullReference != null)
            {
                var message = nullVisitor.CauseOfNullReference switch
                {
                    MemberExpression memberExpression => nullVisitor.ExceptionWasThrownInternally
            ? GetReasonMessageInternalException(memberExpression)
            : GetReasonMessage(memberExpression),
                    MethodCallExpression methodCallExpression => nullVisitor.ExceptionWasThrownInternally
            ? GetReasonMessageInternalException(methodCallExpression)
            : GetReasonMessage(methodCallExpression),
                    UnaryExpression unaryExpression when unaryExpression.NodeType == ExpressionType.ArrayLength =>
                    GetReasonMessage(unaryExpression),
                    BinaryExpression binaryExpression when binaryExpression.NodeType == ExpressionType.ArrayIndex =>
                    GetReasonMessage(binaryExpression),
                    _ => null
                };

                if (message != null)
                {
                    return(new HandledException(message, nullVisitor.CauseOfNullReference));
                }
            }

            return(null);
        }
Пример #3
0
 private static bool IsNullEqualityCheck(FailedAssertion failedAssertion)
 {
     return((failedAssertion.Expression.NodeType == ExpressionType.Equal || failedAssertion.Expression.NodeType == ExpressionType.NotEqual) &&
            failedAssertion.Expression is BinaryExpression b &&
            ((b.Right is ConstantExpression c &&
              c.Value == null) || (b.Right is DefaultExpression && b.Right.Type.IsClass)));
 }
Пример #4
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(failedAssertion.Expression is MethodCallExpression methodCallExpression &&
            methodCallExpression.Method.Name == nameof(Enumerable.SequenceEqual) &&
            methodCallExpression.Arguments.Count >= 2 &&
            ExpressionHelper.GetInstanceOfMethodCall(methodCallExpression).Type.IsType <IEnumerable>() &&
            methodCallExpression.Arguments[1].Type.IsType <IEnumerable>());
 }
Пример #5
0
        public bool IsMatch(FailedAssertion failedAssertion)
        {
            var expression = failedAssertion.Expression;

            return((EqualityPattern.IsEqualityComparison(expression) ||
                    LessThanOrGreaterThanPattern.IsNumericalComparison(expression)) &&
                   expression is BinaryExpression binaryExpression &&
                   IsLengthAccess(binaryExpression.Left));
        }
Пример #6
0
        public FormattableString TryGetFriendlyMessage(FailedAssertion assertion)
        {
            var methodCallExpression = (MethodCallExpression)((UnaryExpression)assertion.Expression).Operand;

            var collectionExpression = ExpressionHelper.GetInstanceOfMethodCall(methodCallExpression);

            var filter = (LambdaExpression)methodCallExpression.Arguments[1];

            return($"Did not expect all items of {collectionExpression} to match the filter {filter.Body}.");
        }
Пример #7
0
        public FormattableString?TryGetFriendlyMessage(FailedAssertion assertion)
        {
            var methodCall = (MethodCallExpression)assertion.ExpressionWithoutNegation;

            var arg1 = methodCall.Arguments[0];
            var arg2 = methodCall.Arguments[1];

            var result = assertion.IsNegated ? (FormattableString)$"Expected {arg1} and {arg2} to be a different instances." : $"Expected {arg1} and {arg2} to be the same instance.";

            return(result);
        }
Пример #8
0
        public FormattableString TryGetFriendlyMessage(FailedAssertion assertion)
        {
            var memberExpression = (MemberExpression)assertion.ExpressionWithoutNegation;

            if (assertion.IsNegated)
            {
                return
                    ($"Expected {memberExpression.Expression} to not have a value but its value was {memberExpression.Expression.ToValue()}.");
            }

            return($"Expected {memberExpression.Expression} to have a value.");
        }
Пример #9
0
        public FormattableString TryGetFriendlyMessage(FailedAssertion assertion)
        {
            var notAny = assertion.IsNegated;

            MethodCallExpression methodCallExpression;

            if (notAny)
            {
                methodCallExpression = (MethodCallExpression)((UnaryExpression)assertion.Expression).Operand;
            }
            else
            {
                methodCallExpression = (MethodCallExpression)assertion.Expression;
            }

            var collection = ExpressionHelper.GetInstanceOfMethodCall(methodCallExpression);

            FormattableString filterString;

            if (methodCallExpression.Arguments.Count == 2 && methodCallExpression.Arguments[1] is LambdaExpression lambdaExpression)
            {
                filterString = $" that match the filter {lambdaExpression.Body}";
            }
            else
            {
                filterString = $"";
            }

            string actualCountString = "";

            if (notAny)
            {
                var actualCount = ExpressionHelper.GetCollectionItemCount(collection, methodCallExpression);
                actualCountString = $" but it actually contained {actualCount} {(actualCount == 1 ? "item" : "items")}";
            }


            FormattableString result = $"Expected {collection} to {(notAny ? "not " : "")}contain {(notAny ? "any " : "")}items{filterString}{actualCountString}.";

            if (notAny)
            {
                result = $@"{result}

Value of {collection}:
";
            }

            return(result);
        }
Пример #10
0
        public HandledException?Handle(FailedAssertion assertion)
        {
            var nullVisitor = new ArgumentNullVisitor();

            nullVisitor.Visit(assertion.Expression);

            if (nullVisitor.CauseOfArgumentNull != null)
            {
                var message = GetReasonMessage(nullVisitor.CauseOfArgumentNull);

                return(new HandledException(message, nullVisitor.CauseOfArgumentNull));
            }

            return(null);
        }
Пример #11
0
        public FormattableString?TryGetFriendlyMessage(FailedAssertion assertion)
        {
            var typeAssertion = ((TypeBinaryExpression)assertion.ExpressionWithoutNegation);

            var result = ExpressionHelper.EvaluateExpression(typeAssertion.Expression);

            var expectedType = TypeHelper.TypeNameToString(typeAssertion.TypeOperand);

            if (result == null)
            {
                return($"Expected {typeAssertion.Expression} to be of type {expectedType} but it was null.");
            }

            return(!assertion.IsNegated ?
                   $"Expected {typeAssertion.Expression} to be of type {expectedType} but its actual type was {TypeHelper.TypeNameToString(result.GetType())}."
        : (FormattableString)$"Expected {typeAssertion.Expression} to not be of type {expectedType}.");
        }
Пример #12
0
        public FormattableString TryGetFriendlyMessage(FailedAssertion assertion)
        {
            var left = EqualityPattern.GetLeftSide(assertion.Expression);

            var right = EqualityPattern.GetRightSide(assertion.Expression, left);

            if (right.NodeType == ExpressionType.Convert && right.Type == typeof(object))
            {
                right = ((UnaryExpression)right).Operand;
            }

            if (IsConstantExpression(right))
            {
                return($"Expected {left} to equal {right} but {left} was {left.ToValue()}.");
            }

            return($"Expected {left} to equal {right} but {left} was {left.ToValue()} while {right} was {right.ToValue()}.");
        }
Пример #13
0
        public FormattableString?TryGetFriendlyMessage(FailedAssertion assertion)
        {
            bool       expectedNull = false;
            Expression?expression   = null;

            if (assertion.Expression is BinaryExpression b)
            {
                if (b.NodeType == ExpressionType.Equal)
                {
                    expectedNull = true;
                }

                expression = b.Left;
            }
            else if (assertion.ExpressionWithoutNegation is TypeBinaryExpression typeIsExpression)
            {
                if (assertion.IsNegated)
                {
                    expectedNull = true;
                }

                expression = typeIsExpression.Expression;
            }

            if (expression != null)
            {
                if (expectedNull)
                {
                    return($"Expected {expression} to be null but it was {expression.ToValue()} instead.");
                }
                else
                {
                    return($"Expected {expression} to not be null.");
                }
            }

            return(default);
Пример #14
0
        public HandledException?Handle(FailedAssertion assertion)
        {
            var visitor = new IndexOutOfRangeExceptionVisitor();

            visitor.Visit(assertion.Expression);

            var causeOfException = visitor.CauseOfIndexOutOfRangeException;

            if (causeOfException == null)
            {
                return(null);
            }

            Expression indexExpression;
            Expression operand;
            int?       actualLength;
            string     lengthString;

            if (causeOfException.NodeType == ExpressionType.ArrayIndex && assertion.Exception is IndexOutOfRangeException)
            {
                var b = (BinaryExpression)causeOfException;

                indexExpression = b.Right;
                operand         = b.Left;
                actualLength    = (int?)ExpressionHelper.EvaluateExpression(Expression.ArrayLength(operand));
                lengthString    = "length";
            }
            else if (assertion.Exception is ArgumentOutOfRangeException &&
                     causeOfException is MethodCallExpression methodCallExpression &&
                     methodCallExpression.Method.Name == "get_Item" &&
                     methodCallExpression.Arguments.Count == 1)
            {
                indexExpression = methodCallExpression.Arguments[0];
                operand         = methodCallExpression.Object;
                actualLength    = ExpressionHelper.GetCollectionItemCount(operand);
                lengthString    = "count";
            }
Пример #15
0
        public FormattableString TryGetFriendlyMessage(FailedAssertion assertion)
        {
            var startsWith = IsStartsOrEndsWithCall(assertion.Expression);

            var methodCallExpression = (MethodCallExpression)assertion.ExpressionWithoutNegation;

            var method = methodCallExpression.Method.Name == nameof(string.StartsWith)
        ? "start with" : "end with";

            var arg = methodCallExpression.Arguments[0];

            var instance = GetInstanceOfMethodCall(methodCallExpression);

            if (IsConstantExpression(arg))
            {
                return($@"Expected {instance} to{(startsWith ? " " : " not ")}{method} {arg}.

Value of {instance}: {instance.ToValue()}");
            }

            return($@"Expected {instance} to{(startsWith ? " " : " not ")}{method} {arg} (value: {arg.ToValue()}).

Value of {instance}: {instance.ToValue()}");
        }
Пример #16
0
        public HandledException?Handle(FailedAssertion assertion)
        {
            var linqVisitor = new LinqElementCountVisitor();

            linqVisitor.Visit(assertion.Expression);

            if (linqVisitor.CauseOfLinqException != null)
            {
                var filtered = linqVisitor.CauseOfLinqException.Arguments.Count == 2 &&
                               linqVisitor.CauseOfLinqException.Arguments[1] is LambdaExpression;

                var instanceOfMethodCallExpression = ExpressionHelper.GetInstanceOfMethodCall(linqVisitor.CauseOfLinqException);

                var message = GetReasonMessage(linqVisitor.CauseOfLinqException, linqVisitor.Error, linqVisitor.ActualCount,
                                               filtered, instanceOfMethodCallExpression);

                if ((linqVisitor.Error == LinqElementCountErrorTypes.TooFew && filtered) ||
                    linqVisitor.Error == LinqElementCountErrorTypes.TooMany)
                {
                    var filter = filtered && linqVisitor.Error == LinqElementCountErrorTypes.TooMany ? (LambdaExpression)linqVisitor.CauseOfLinqException.Arguments[1] : null;

                    var items = GetItems(filter, linqVisitor.CauseOfLinqException, instanceOfMethodCallExpression);

                    if (items != null)
                    {
                        message = $@"{message}

Value of {(filter != null ? linqVisitor.CauseOfLinqException : instanceOfMethodCallExpression)}: {Serializer.Serialize(items)}";
                    }
                }

                return(new HandledException(message, linqVisitor.CauseOfLinqException));
            }

            return(null);
        }
Пример #17
0
 public FormattableString?TryGetFriendlyMessage(FailedAssertion assertion)
 {
     return(null);
 }
Пример #18
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(IsAllMethodCall(failedAssertion.Expression));
 }
Пример #19
0
        public FormattableString TryGetFriendlyMessage(FailedAssertion assertion)
        {
            var methodCallExpression = (MethodCallExpression)assertion.Expression;

            var collectionExpression = ExpressionHelper.GetInstanceOfMethodCall(methodCallExpression);

            var filter = (LambdaExpression)methodCallExpression.Arguments[1];

            var collection = ((IEnumerable)ExpressionHelper.EvaluateExpression(collectionExpression) !).Cast <object>();

            var compiledFilter = filter.Compile(true);

            var invalidMatches = new List <object>();

            var moreItems    = false;
            var invalidCount = 0;

            var subMessages = new List <FormattableString>();

            var index = 0;

            foreach (var obj in collection)
            {
                var isMatch = (bool)compiledFilter.DynamicInvoke(obj);

                if (!isMatch)
                {
                    invalidCount++;

                    if (invalidMatches.Count == 10)
                    {
                        moreItems = true;
                    }
                    else
                    {
                        invalidMatches.Add(obj);

                        var namedConstant = new NamedConstantExpression("item", obj);

                        var newExpression =
                            Expression.Lambda <Func <bool> >(
                                ExpressionHelper.ReplaceParameter(filter.Body, filter.Parameters[0], namedConstant));

                        var analyzer = new AssertionFailureAnalyzer(new AssertionFailureContext(new Assertion(newExpression, null, null), null));

                        var failures = analyzer.AnalyzeAssertionFailures();

                        foreach (var failure in failures)
                        {
                            if (failure.Message != null)
                            {
                                subMessages.Add(collectionExpression is MethodCallExpression
                  ? $"[{index}] - {failure.Message}"
                  : (FormattableString)$"{collectionExpression}[{index}] - {failure.Message}");
                            }
                        }
                    }
                }

                index++;
            }

            FormattableString MessagesPerItem()
            {
                return(subMessages.Count switch
                {
                    0 => $"",
                    1 when invalidCount == 1 => $@"

{subMessages[0]}",
                    _ => $@"

Messages per item:

{subMessages}"
                });
            }
Пример #20
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(IsEqualityComparison(failedAssertion.Expression));
 }
Пример #21
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(failedAssertion.Expression.NodeType == ExpressionType.Equal ||
            EqualityPattern.EqualsMethodShouldBeTrue(failedAssertion.Expression));
 }
Пример #22
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(IsNullEqualityCheck(failedAssertion) ||
            IsObjectCheck(failedAssertion));
 }
Пример #23
0
 private static bool IsObjectCheck(FailedAssertion failedAssertion)
 {
     return(failedAssertion.ExpressionWithoutNegation is TypeBinaryExpression t &&
            t.NodeType == ExpressionType.TypeIs &&
            t.TypeOperand == typeof(object));
 }
Пример #24
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(IsStartsOrEndsWithCall(failedAssertion.ExpressionWithoutNegation));
 }
Пример #25
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(failedAssertion.ExpressionWithoutNegation is TypeBinaryExpression t &&
            t.NodeType == ExpressionType.TypeIs &&
            t.TypeOperand != typeof(object));
 }
Пример #26
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(failedAssertion.ExpressionWithoutNegation is MemberExpression);
 }
Пример #27
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(true);
 }
Пример #28
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(IsAnyMethodCall(failedAssertion.ExpressionWithoutNegation));
 }
Пример #29
0
 public bool IsMatch(FailedAssertion failedAssertion)
 {
     return(IsHasValueAccess(failedAssertion.ExpressionWithoutNegation));
 }
Пример #30
0
        public FormattableString?TryGetFriendlyMessage(FailedAssertion assertion)
        {
            var methodCallExpression  = (MethodCallExpression)assertion.Expression;
            var collection1Expression = ExpressionHelper.GetInstanceOfMethodCall(methodCallExpression);
            var collection2Expression = methodCallExpression.Arguments[1];

            var collection1 = ((IEnumerable)ExpressionHelper.EvaluateExpression(collection1Expression) !).Cast <object>();
            var collection2 = ((IEnumerable)ExpressionHelper.EvaluateExpression(collection2Expression) !).Cast <object>();

            var differences = new List <Difference>();

            var enumerableType = TypeHelper.GetTypeInsideEnumerable(collection1Expression.Type);

            if (enumerableType == null)
            {
                return(null);
            }

            var equals = GetComparerFunc(methodCallExpression, enumerableType);

            FormattableString result;

            if (equals != null)
            {
                var index = 0;

                var hasMoreDifferences = false;

                var differenceCount = 0;

                IEnumerator <object>?enumerator1 = null;
                IEnumerator <object>?enumerator2 = null;

                try
                {
                    enumerator1 = collection1.GetEnumerator();
                    enumerator2 = collection2.GetEnumerator();

                    while (true)
                    {
                        var moveNext1 = enumerator1.MoveNext();
                        var moveNext2 = enumerator2.MoveNext();

                        if (!moveNext1 && !moveNext2)
                        {
                            break;
                        }

                        var current1 = moveNext1 ? enumerator1.Current : null;
                        var current2 = moveNext2 ? enumerator2.Current : null;

                        if (!equals(current1, current2))
                        {
                            differenceCount++;

                            if (differences.Count == 10)
                            {
                                hasMoreDifferences = true;
                            }
                            else
                            {
                                differences.Add(new Difference()
                                {
                                    Index             = index,
                                    ValueSequence1    = current1,
                                    HasValueSequence1 = moveNext1,
                                    ValueSequence2    = current2,
                                    HasValueSequence2 = moveNext2
                                });
                            }
                        }

                        index++;
                    }
                }
                finally
                {
                    enumerator1?.Dispose();
                    enumerator2?.Dispose();
                }

                var differencesString = differences.Select(d =>
                                                           $"[{d.Index}]: {(d.HasValueSequence1 ? Serializer.Serialize(d.ValueSequence1) ?? "null" : "(no value)")} <> {(d.HasValueSequence2 ? Serializer.Serialize(d.ValueSequence2) ?? "null" : "(no value)")}")
                                        .ToList();

                result =
                    $@"Expected {collection1Expression} to be equal to {collection2Expression}, but there {(differenceCount > 1 ? $"were {differenceCount} differences" : "was 1 difference")}{(hasMoreDifferences ? " (first 10)" : "")}:

{string.Join("," + Environment.NewLine, differencesString)}";
            }
            else
            {
                result = $@"Expected {collection1Expression} to be equal to {collection2Expression} but they were not.";
            }

            return($@"{result}

Value of {collection1Expression}: {collection1}
Value of {collection2Expression}: {collection2}");
        }