Пример #1
0
        private static bool ExecuteTest(TestDetails testItemDetails, bool showDetailedInformation, HTMLElement appendSuccessesTo, HTMLElement appendFailuresTo)
        {
            try
            {
                var testItem = TestItemInstanceCreator.GetInstance(testItemDetails.FullName);
                var decoder  = GetTypedMessagePackSerializerDeserializeCall(testItem.DeserialiseAs, testItem.DecodeOptions);
                if (testItemDetails.ExpectedError is null)
                {
                    var clone          = decoder(testItemDetails.Serialised);
                    var expectedResult = (testItemDetails.AlternateResultJson is null) ? testItem.Value : DeserialiseAlternateResultJson(testItemDetails.AlternateResultJson);
                    if (ObjectComparer.AreEqual(expectedResult, clone, out var messageIfNotEqual))
                    {
                        RenderSuccess($"Expected and received: {JsonSerialiserForComparison.ToJson(expectedResult)}");
                        return(true);
                    }
                    RenderFailure(messageIfNotEqual);
                    return(false);
                }
                else
                {
                    try
                    {
                        decoder(testItemDetails.Serialised);
                        RenderFailure("No exception was thrown but expected: " + testItemDetails.ExpectedError.ExceptionType.FullName);
                        return(false);
                    }
                    catch (Exception deserialisationException)
                    {
                        if (deserialisationException.GetType() != testItemDetails.ExpectedError.ExceptionType)
                        {
                            var additionalInfo = $"Expected exception {testItemDetails.ExpectedError.ExceptionType.FullName} but {deserialisationException.GetType().FullName} was thrown";
                            if (showDetailedInformation)
                            {
                                additionalInfo += "\n\n" + deserialisationException.ToString();
                            }
                            RenderFailure(additionalInfo);
                            return(false);
                        }
                        if (deserialisationException.Message != testItemDetails.ExpectedError.Message)
                        {
                            var additionalInfo = $"Expected exception message \"{testItemDetails.ExpectedError.Message}\" but received \"{deserialisationException.Message}\"";
                            if (showDetailedInformation)
                            {
                                additionalInfo += "\n\n" + deserialisationException.ToString();
                            }
                            RenderFailure(additionalInfo);
                            return(false);
                        }
                        RenderSuccess($"Expected and received error: {deserialisationException.Message}");
                        return(true);
                    }
                }
            }
            catch (Exception e)
            {
                RenderFailure(e.Message, e.ToString());
            }
            return(false);

            void RenderSuccess(string extendedAdditionalInfo)
            {
                appendSuccessesTo.appendChild(
                    GetMessage(testItemDetails.DisplayName, hrefIfTextShouldLink: GetHrefForFilteringToTest(testItemDetails.DisplayName), isSuccess: true, additionalInfo: showDetailedInformation ? extendedAdditionalInfo : null)
                    );
            }

            void RenderFailure(string summary, string extendedAdditionalInfo = null)
            {
                appendFailuresTo.appendChild(
                    GetMessage(testItemDetails.DisplayName, hrefIfTextShouldLink: GetHrefForFilteringToTest(testItemDetails.DisplayName), isSuccess: false, additionalInfo: showDetailedInformation ? (extendedAdditionalInfo ?? summary) : summary)
                    );
            }
        }
Пример #2
0
        private static void Main(string[] args)
        {
            var projectFolderName = args?.FirstOrDefault();

            if (string.IsNullOrWhiteSpace(projectFolderName))
            {
                projectFolderName = Directory.GetCurrentDirectory();
                Console.WriteLine("Expected command line argument to specify project folder location to write Test Data file to - default to build folder " + projectFolderName);
            }
            var projectFolder = new DirectoryInfo(projectFolderName);

            if (!projectFolder.Exists)
            {
                throw new Exception("The specified project folder must already exist but it does not: " + projectFolderName);
            }

            var allTestItemTypes = AppDomain.CurrentDomain.GetAssemblies()
                                   .SelectMany(a => a.GetTypes())
                                   .Where(t => !t.IsAbstract && typeof(ITestItem).IsAssignableFrom(t))
                                   .OrderBy(t => t.FullName);
            var testItemEntries = new List <(string testItemTypeNameLiteral, string byteArrayRepresentation, string alternateResultJson, string errorRepresentation)>();

            foreach (var testItemType in allTestItemTypes)
            {
                var    testItem = TestItemInstanceCreator.GetInstance(testItemType.FullName);
                var    serialised = MessagePackSerializer.Serialize(type: testItem.SerialiseAs, obj: testItem.Value);
                string alternateResultJson, errorRepresentation;
                try
                {
                    var deserialised = MessagePackSerializer.Deserialize(type: testItem.DeserialiseAs, bytes: serialised);
                    if (!ObjectComparer.AreEqual(deserialised, testItem.Value, out _))
                    {
                        // h5's JsonConvert has a bug where JsonConvert.DeserializeObject<object>("12") will be deserialised into a string instead of an Int64 and this would cause a problem if we were, for example, serialising a byte and then wanting to deserialise
                        // it into an int because the ObjectComparer will be able to tell that they are not precisely the same value and so an alternateResultJson value would be written but this would cause a problem because the h5 Unit Tests code would see that
                        // alternateResultJson and think that the result should be a string (due to that bug). So, to avoid that confusion, if the JSON of the original value matches the JSON of the different value - because that indicates a case that we don't
                        // care about (which should only be primitives).
                        if (JsonSerialiserForComparison.ToJson(deserialised) == JsonSerialiserForComparison.ToJson(testItem.Value))
                        {
                            alternateResultJson = null;
                        }
                        else
                        {
                            alternateResultJson = ToLiteral(JsonSerialiserForComparison.ToJson(deserialised));
                        }
                    }
                    else
                    {
                        alternateResultJson = "null";
                    }
                    errorRepresentation = "null";
                }
                catch (Exception e)
                {
                    // 2020-07-25 DWR: By only checking the top level exception type and its messages, it means that the inner exception content may not be precisely the same but I'm happy with that (eg. when trying to deserialise to a type that has multiple
                    // properties with the same Key then the .NET library will throw a MessagePackSerializationException that has an InnerException that references the FormatterCache`1 and that will have an InnerException that describes the repeated key issue
                    // whereas this library will throw a MessagePackSerializationException with the same message as the C# version but wrap a RepeatedKeyValueException instance - that's close enough to like-for-like behaviour for me)
                    errorRepresentation = $"new ExceptionSummary(TypeRetriever.Get(\"{e.GetType().FullName}\"), {ToLiteral(e.Message)})";
                    alternateResultJson = null;
                }
                testItemEntries.Add((
                                        "\"" + testItem.GetType().FullName + "\"",
                                        "new byte[] { " + string.Join(", ", serialised) + " }",
                                        alternateResultJson,
                                        errorRepresentation
                                        ));
            }

            var content = new StringBuilder();

            content.AppendLine("using System.Collections.Generic;");
            content.AppendLine();
            content.AppendLine("namespace " + _testDataNamespace);
            content.AppendLine("{");
            content.AppendLine("    // This file is generated by the UnitTestDataGenerator project - run that to ensure that this is current (includes all of the tests in the SharedTestItems project) and then run the Unit Tests project");
            content.AppendLine("    internal static class TestData");
            content.AppendLine("    {");
            content.AppendLine("        public static IEnumerable<(string TestItemName, byte[] Serialised, string AlternateResultJson, ExceptionSummary ExpectedError)> GetItems()");
            content.AppendLine("        {");
            foreach (var(testItemTypeNameLiteral, byteArrayRepresentation, alternateResultJson, errorRepresentation) in testItemEntries)
            {
                content.AppendLine($"            yield return ({testItemTypeNameLiteral}, {byteArrayRepresentation}, {alternateResultJson ?? "null"}, {errorRepresentation});");
            }
            content.AppendLine("        }");
            content.AppendLine("    }");
            content.AppendLine("}");

            File.WriteAllText(
                Path.Combine(projectFolder.FullName, _testDataFilename),
                content.ToString()
                );
        }