Esempio n. 1
0
        private static IEnumerable <SpecificationException> ShouldBeLikeInternal(object obj, object expected, string nodeName, HashSet <ReferentialEqualityTuple> visited)
        {
            // Stop at already checked <actual,expected>-pairs to prevent infinite loops (cycles in object graphs). Additionally
            // this also avoids re-equality-evaluation for already compared pairs.
            var objExpectedTuple = new ReferentialEqualityTuple(obj, expected);

            if (visited.Contains(objExpectedTuple))
            {
                return(Enumerable.Empty <SpecificationException>());
            }

            visited.Add(objExpectedTuple);

            ObjectGraphHelper.INode expectedNode = null;

            var nodeType = typeof(ObjectGraphHelper.LiteralNode);

            if (obj != null && expected != null)
            {
                expectedNode = ObjectGraphHelper.GetGraph(expected);
                nodeType     = expectedNode.GetType();
            }

            if (nodeType == typeof(ObjectGraphHelper.LiteralNode))
            {
                try
                {
                    obj.ShouldEqual(expected);
                }
                catch (SpecificationException ex)
                {
                    return(new[] { NewException($"{{0}}:{Environment.NewLine}{ex.Message}", nodeName) });
                }

                return(Enumerable.Empty <SpecificationException>());
            }

            if (nodeType == typeof(ObjectGraphHelper.SequenceNode))
            {
                if (obj == null)
                {
                    var errorMessage = PrettyPrintingExtensions.FormatErrorMessage(null, expected);

                    return(new[] { NewException($"{{0}}:{Environment.NewLine}{errorMessage}", nodeName) });
                }

                var actualNode = ObjectGraphHelper.GetGraph(obj);

                if (actualNode.GetType() != typeof(ObjectGraphHelper.SequenceNode))
                {
                    var errorMessage = $"  Expected: Array or Sequence{Environment.NewLine}  But was:  {obj.GetType()}";

                    return(new[] { NewException($"{{0}}:{Environment.NewLine}{errorMessage}", nodeName) });
                }

                var expectedValues = ((ObjectGraphHelper.SequenceNode)expectedNode)?.ValueGetters.ToArray();
                var actualValues   = ((ObjectGraphHelper.SequenceNode)actualNode).ValueGetters.ToArray();

                var expectedCount = expectedValues?.Length ?? 0;
                var actualCount   = actualValues.Length;

                if (expectedCount != actualCount)
                {
                    var errorMessage = string.Format("  Expected: Sequence length of {1}{0}  But was:  {2}", Environment.NewLine, expectedCount, actualCount);

                    return(new[] { NewException($"{{0}}:{Environment.NewLine}{errorMessage}", nodeName) });
                }

                return(Enumerable.Range(0, expectedCount)
                       .SelectMany(i => ShouldBeLikeInternal(actualValues.ElementAt(i)(), expectedValues?.ElementAt(i)(), $"{nodeName}[{i}]", visited)));
            }

            if (nodeType == typeof(ObjectGraphHelper.KeyValueNode))
            {
                var actualNode = ObjectGraphHelper.GetGraph(obj);

                if (actualNode.GetType() != typeof(ObjectGraphHelper.KeyValueNode))
                {
                    var errorMessage = $"  Expected: Class{Environment.NewLine}  But was:  {obj?.GetType()}";

                    return(new[] { NewException($"{{0}}:{Environment.NewLine}{errorMessage}", nodeName) });
                }

                var expectedKeyValues = ((ObjectGraphHelper.KeyValueNode)expectedNode)?.KeyValues;
                var actualKeyValues   = ((ObjectGraphHelper.KeyValueNode)actualNode).KeyValues;

                return(expectedKeyValues?.SelectMany(kv =>
                {
                    var fullNodeName = string.IsNullOrEmpty(nodeName)
                        ? kv.Name
                        : $"{nodeName}.{kv.Name}";
                    var actualKeyValue = actualKeyValues.SingleOrDefault(k => k.Name == kv.Name);

                    if (actualKeyValue == null)
                    {
                        var errorMessage = string.Format("  Expected: {1}{0}  But was:  Not Defined",
                                                         Environment.NewLine, kv.ValueGetter().ToUsefulString());

                        return new[] { NewException($"{{0}}:{Environment.NewLine}{errorMessage}", fullNodeName) };
                    }

                    return ShouldBeLikeInternal(actualKeyValue.ValueGetter(), kv.ValueGetter(), fullNodeName, visited);
                }));
            }

            throw new InvalidOperationException("Unknown node type");
        }
Esempio n. 2
0
        static IEnumerable <SpecificationException> ShouldBeLikeInternal(object obj, object expected, string nodeName, List <object> visited)
        {
            if (IsReferenceTypeNotNullOrString(obj) && IsReferenceTypeNotNullOrString(expected))
            {
                if (visited.Any(o => ReferenceEquals(o, expected)))
                {
                    return(Enumerable.Empty <SpecificationException>());
                }

                visited.Add(expected);
            }

            ObjectGraphHelper.INode expectedNode = null;
            var nodeType = typeof(ObjectGraphHelper.LiteralNode);

            if (obj != null && expected != null)
            {
                expectedNode = ObjectGraphHelper.GetGraph(expected);
                nodeType     = expectedNode.GetType();
            }

            if (nodeType == typeof(ObjectGraphHelper.LiteralNode))
            {
                try
                {
                    obj.ShouldEqual(expected);
                }
                catch (SpecificationException ex)
                {
                    return(new[] { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, ex.Message), nodeName) });
                }

                return(Enumerable.Empty <SpecificationException>());
            }
            else if (nodeType == typeof(ObjectGraphHelper.SequenceNode))
            {
                if (obj == null)
                {
                    var errorMessage = PrettyPrintingExtensions.FormatErrorMessage(null, expected);
                    return(new[] { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), nodeName) });
                }
                var actualNode = ObjectGraphHelper.GetGraph(obj);
                if (actualNode.GetType() != typeof(ObjectGraphHelper.SequenceNode))
                {
                    var errorMessage = string.Format("  Expected: Array or Sequence{0}  But was:  {1}", Environment.NewLine, obj.GetType());
                    return(new[] { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), nodeName) });
                }

                var expectedValues = ((ObjectGraphHelper.SequenceNode)expectedNode).ValueGetters;
                var actualValues   = ((ObjectGraphHelper.SequenceNode)actualNode).ValueGetters;

                var expectedCount = Enumerable.Count <Func <object> >(expectedValues);
                var actualCount   = Enumerable.Count <Func <object> >(actualValues);
                if (expectedCount != actualCount)
                {
                    var errorMessage = string.Format("  Expected: Sequence length of {1}{0}  But was:  {2}", Environment.NewLine, expectedCount, actualCount);
                    return(new[] { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), nodeName) });
                }

                return(Enumerable.Range(0, expectedCount)
                       .SelectMany(i => ShouldBeLikeInternal(Enumerable.ElementAt <Func <object> >(actualValues, i)(),
                                                             Enumerable.ElementAt <Func <object> >(expectedValues, i)(),
                                                             string.Format("{0}[{1}]", nodeName, i), visited)));
            }
            else if (nodeType == typeof(ObjectGraphHelper.KeyValueNode))
            {
                var actualNode = ObjectGraphHelper.GetGraph(obj);
                if (actualNode.GetType() != typeof(ObjectGraphHelper.KeyValueNode))
                {
                    var errorMessage = string.Format("  Expected: Class{0}  But was:  {1}", Environment.NewLine, obj.GetType());
                    return(new[] { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), nodeName) });
                }

                var expectedKeyValues = ((ObjectGraphHelper.KeyValueNode)expectedNode).KeyValues;
                var actualKeyValues   = ((ObjectGraphHelper.KeyValueNode)actualNode).KeyValues;

                return(expectedKeyValues
                       .SelectMany(kv =>
                {
                    var fullNodeName = string.IsNullOrEmpty(nodeName) ? kv.Name : string.Format("{0}.{1}", nodeName, kv.Name);
                    var actualKeyValue = actualKeyValues.SingleOrDefault(k => k.Name == kv.Name);
                    if (actualKeyValue == null)
                    {
                        var errorMessage = string.Format("  Expected: {1}{0}  But was:  Not Defined", Environment.NewLine, kv.ValueGetter().ToUsefulString());
                        return new[] { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), fullNodeName) };
                    }

                    return ShouldBeLikeInternal(actualKeyValue.ValueGetter(), kv.ValueGetter(), fullNodeName, visited);
                }));
            }
            else
            {
                throw new InvalidOperationException("Unknown node type");
            }
        }
        static IEnumerable <SpecificationException> ShouldBeLikeObjectGraphInternal(
            object obj, object expected, string nodeName, double tolerance)
        {
            ObjectGraphHelper.INode expectedNode = null;
            var nodeType = typeof(ObjectGraphHelper.LiteralNode);

            if (expected != null)
            {
                expectedNode = ObjectGraphHelper.GetGraph(expected);
                nodeType     = expectedNode.GetType();
            }

            if (nodeType == typeof(ObjectGraphHelper.LiteralNode))
            {
                try
                {
                    if (obj is double)
                    {
                        ((double)obj).ShouldBeCloseTo((double)expected, tolerance);
                    }
                    else if (obj is float)
                    {
                        ((float)obj).ShouldBeCloseTo((float)expected, (float)tolerance);
                    }
                    else
                    {
                        obj.ShouldEqual(expected);
                    }
                }
                catch (SpecificationException ex)
                {
                    return(new[]
                           { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, ex.Message), nodeName) });
                }

                return(Enumerable.Empty <SpecificationException>());
            }
            if (nodeType == typeof(ObjectGraphHelper.SequenceNode))
            {
                if (obj == null)
                {
                    var errorMessage = PrettyPrintingExtensions.FormatErrorMessage(null, expected);
                    return(new[]
                           { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), nodeName) });
                }
                var actualNode = ObjectGraphHelper.GetGraph(obj);
                if (actualNode.GetType() != typeof(ObjectGraphHelper.SequenceNode))
                {
                    var errorMessage = string.Format(
                        "  Expected: Array or Sequence{0}  But was:  {1}", Environment.NewLine, obj.GetType());
                    return(new[]
                           { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), nodeName) });
                }

                var expectedValues = ((ObjectGraphHelper.SequenceNode)expectedNode).ValueGetters;
                var actualValues   = ((ObjectGraphHelper.SequenceNode)actualNode).ValueGetters;

                var expectedCount = expectedValues.Count();
                var actualCount   = actualValues.Count();
                if (expectedCount != actualCount)
                {
                    var errorMessage = string.Format(
                        "  Expected: Sequence length of {1}{0}  But was:  {2}", Environment.NewLine, expectedCount,
                        actualCount);
                    return(new[]
                           { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), nodeName) });
                }

                return
                    (Enumerable.Range(0, expectedCount)
                     .SelectMany(
                         i =>
                         ShouldBeLikeObjectGraphInternal(
                             actualValues.ElementAt(i)(), expectedValues.ElementAt(i)(),
                             string.Format("{0}[{1}]", nodeName, i), tolerance)));
            }
            if (nodeType == typeof(ObjectGraphHelper.KeyValueNode))
            {
                var actualNode = ObjectGraphHelper.GetGraph(obj);
                if (actualNode.GetType() != typeof(ObjectGraphHelper.KeyValueNode))
                {
                    var errorMessage = string.Format(
                        "  Expected: Class{0}  But was:  {1}", Environment.NewLine, obj.GetType());
                    return(new[]
                           { NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), nodeName) });
                }

                var expectedKeyValues = ((ObjectGraphHelper.KeyValueNode)expectedNode).KeyValues;
                var actualKeyValues   = ((ObjectGraphHelper.KeyValueNode)actualNode).KeyValues;

                return(expectedKeyValues.SelectMany(
                           kv =>
                {
                    var fullNodeName = string.IsNullOrEmpty(nodeName)
                            ? kv.Name
                            : string.Format("{0}.{1}", nodeName, kv.Name);
                    var actualKeyValue = actualKeyValues.SingleOrDefault(k => k.Name == kv.Name);
                    if (actualKeyValue == null)
                    {
                        var errorMessage = string.Format(
                            "  Expected: {1}{0}  But was:  Not Defined", Environment.NewLine,
                            ToUsefulString(kv.ValueGetter()));
                        return new[]
                        {
                            NewException(
                                string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), fullNodeName)
                        };
                    }

                    return ShouldBeLikeObjectGraphInternal(
                        actualKeyValue.ValueGetter(), kv.ValueGetter(), fullNodeName, tolerance);
                }));
            }
            throw new InvalidOperationException("Unknown node type");
        }