Beispiel #1
0
        public virtual bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
        {
            var subject     = context.Subject as IDictionary;
            var expectation = context.Expectation as IDictionary;

            if (PreconditionsAreMet(expectation, subject))
            {
                if (expectation != null)
                {
                    foreach (object key in expectation.Keys)
                    {
                        if (config.IsRecursive)
                        {
                            context.TraceSingle(path => $"Recursing into dictionary item {key} at {path}");
                            parent.AssertEqualityUsing(context.CreateForDictionaryItem(key, subject[key], expectation[key]));
                        }
                        else
                        {
                            context.TraceSingle(path => $"Comparing dictionary item {key} at {path} between subject and expectation");
                            subject[key].Should().Be(expectation[key], context.Because, context.BecauseArgs);
                        }
                    }
                }
            }

            return(true);
        }
        private void LooselyMatchAgainst <T>(IList <object> subjects, T expectation, int expectationIndex)
        {
            var results = new AssertionResultSet();

            foreach (int index in Enumerable.Range(0, subjects.Count))
            {
                if (!matchedSubjectIndexes.Contains(index))
                {
                    object subject = subjects[index];

                    using (context.TraceBlock(path => $"Comparing subject at {path}[{index}] with the expectation at {path}[{expectationIndex}]"))
                    {
                        string[] failures = TryToMatch(subject, expectation, expectationIndex);

                        results.AddSet(index, failures);
                        if (results.ContainsSuccessfulSet())
                        {
                            context.TraceSingle(_ => $"It's a match");
                            matchedSubjectIndexes.Add(index);
                            break;
                        }
                        else
                        {
                            context.TraceSingle(_ => $"Contained {failures.Length} failures");
                        }
                    }
                }
            }

            foreach (string failure in results.SelectClosestMatchFor(expectationIndex))
            {
                AssertionScope.Current.AddPreFormattedFailure(failure);
            }
        }
Beispiel #3
0
        private void AssertElementGraphEquivalencyWithStrictOrdering <T>(object[] subjects, T[] expectations)
        {
            int failedCount = 0;

            foreach (int index in Enumerable.Range(0, expectations.Length))
            {
                T expectation = expectations[index];

                using (context.TraceBlock(path =>
                                          $"Strictly comparing expectation {expectation} at {path} to item with index {index} in {subjects}"))
                {
                    bool succeeded = StrictlyMatchAgainst(subjects, expectation, index);
                    if (!succeeded)
                    {
                        failedCount++;
                        if (failedCount >= FailedItemsFastFailThreshold)
                        {
                            context.TraceSingle(path =>
                                                $"Aborting strict order comparison of collections after {FailedItemsFastFailThreshold} items failed at {path}");
                            break;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
        {
            if ((context.Expectation is null) || (context.Subject is null))
            {
                return(false);
            }

            Type subjectType     = context.Subject.GetType();
            Type expectationType = context.Expectation.GetType();

            if (subjectType.IsSameOrInherits(expectationType))
            {
                return(false);
            }

            if (TryChangeType(context.Subject, expectationType, out object convertedSubject))
            {
                context.TraceSingle(path => $"Converted subject {context.Subject} at {path} to {expectationType}");

                context.Subject = convertedSubject;
            }
            else
            {
                context.TraceSingle(path => $"Subject {context.Subject} at {path} could not be converted to {expectationType}");
            }

            return(false);
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator structuralEqualityValidator,
                           IEquivalencyAssertionOptions config)
        {
            if ((context.Expectation is null) || (context.Subject is null))
            {
                return(false);
            }

            Type subjectType     = context.Subject.GetType();
            Type expectationType = context.Expectation.GetType();

            if (subjectType.IsSameOrInherits(expectationType))
            {
                return(false);
            }

            if (TryChangeType(context.Subject, expectationType, out object convertedSubject))
            {
                context.TraceSingle(path => $"Converted subject {context.Subject} at {path} to {expectationType}");

                var newContext = context.CreateWithDifferentSubject(convertedSubject, expectationType);

                structuralEqualityValidator.AssertEqualityUsing(newContext);
                return(true);
            }

            context.TraceSingle(path => $"Subject {context.Subject} at {path} could not be converted to {expectationType}");

            return(false);
        }
        private void LooselyMatchAgainst <T>(IList <object> subjects, T expectation, int expectationIndex)
        {
            var             results          = new AssertionResultSet();
            int             index            = 0;
            GetTraceMessage getMessage       = path => $"Comparing subject at {path}[{index}] with the expectation at {path}[{expectationIndex}]";
            int             count            = subjects.Count;
            int             indexToBeRemoved = -1;

            for (var metaIndex = 0; metaIndex < unmatchedSubjectIndexes.Count; metaIndex++)
            {
                index = unmatchedSubjectIndexes[metaIndex];
                object subject = subjects[index];

                using (context.TraceBlock(getMessage))
                {
                    string[] failures = TryToMatch(subject, expectation, expectationIndex);

                    results.AddSet(index, failures);
                    if (results.ContainsSuccessfulSet())
                    {
                        context.TraceSingle(_ => "It's a match");
                        indexToBeRemoved = metaIndex;
                        break;
                    }
                    else
                    {
                        context.TraceSingle(_ => $"Contained {failures.Length} failures");
                    }
                }
            }

            if (indexToBeRemoved != -1)
            {
                unmatchedSubjectIndexes.RemoveAt(indexToBeRemoved);
            }

            foreach (string failure in results.SelectClosestMatchFor(expectationIndex))
            {
                AssertionScope.Current.AddPreFormattedFailure(failure);
            }
        }
        /// <summary>
        /// Gets a value indicating whether this step can handle the current subject and/or expectation.
        /// </summary>
        public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
        {
            Type type = config.GetSubjectType(context);

            bool canHandle =
                (type != null) &&
                (type != typeof(object)) &&
                config.IsValueType(type) &&
                !type.IsArray;

            if (canHandle)
            {
                context.TraceSingle(path => $"Treating {path} as a value type");
            }

            return(canHandle);
        }
        /// <summary>
        /// Gets a value indicating whether this step can handle the current subject and/or expectation.
        /// </summary>
        public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
        {
            Type             type     = config.GetExpectationType(context);
            EqualityStrategy strategy = config.GetEqualityStrategy(type);

            bool canHandle = (strategy == EqualityStrategy.Equals) || (strategy == EqualityStrategy.ForceEquals);

            if (canHandle)
            {
                context.TraceSingle(path =>
                {
                    string strategyName = (strategy == EqualityStrategy.Equals)
                        ? "Equals must be used" : "object overrides Equals";

                    return($"Treating {path} as a value type because {strategyName}.");
                });
            }

            return(canHandle);
        }