Esempio n. 1
0
        private void ChecksForMessage(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv,
                                      TestMessageResult testMessageResult, bool allowSubset)
        {
            var dataType = propertySchemaObject.GetDataType();

            if (dataType == DataType.Integer)
            {
                CheckIntegerType(propertySchemaObject, kv, testMessageResult);
            }

            if (dataType == DataType.Number)
            {
                CheckNumberType(propertySchemaObject, kv, testMessageResult);
            }

            if (dataType == DataType.Boolean)
            {
                CheckBooleanType(propertySchemaObject, kv, testMessageResult);
            }

            if (dataType == DataType.String)
            {
                CheckStringType(propertySchemaObject, kv, testMessageResult);
            }

            if (dataType == DataType.Array)
            {
                CheckArrayType(propertySchemaObject, kv, testMessageResult);
            }

            if (dataType == DataType.Object)
            {
                CheckObjectType(propertySchemaObject, kv, testMessageResult, allowSubset);
            }
        }
Esempio n. 2
0
        private static void CheckIntegerType(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv,
                                             TestMessageResult testMessageResult)
        {
            var isInt32 = int.TryParse(kv.Value.ToString(), out _);
            var isInt64 = long.TryParse(kv.Value.ToString(), out _);

            // Validate integer data type
            if (!isInt32 && !isInt64)
            {
                AddTypeError(testMessageResult, kv.Value.ToString(), kv.Key, propertySchemaObject.Type);
            }

            if (propertySchemaObject.Format != null)
            {
                // Validate specific integer formats
                if (propertySchemaObject.Format.EqualsCaseInsensitive("int32") && !isInt32)
                {
                    AddFormatError(testMessageResult, kv.Value.ToString(), kv.Key, Format.Int32);
                }
                else if (propertySchemaObject.Format.EqualsCaseInsensitive("int64") && !isInt64)
                {
                    AddFormatError(testMessageResult, kv.Value.ToString(), kv.Key, Format.Int64);
                }
            }
        }
Esempio n. 3
0
        private static void CheckStringType(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv,
                                            TestMessageResult testMessageResult)
        {
            if (kv.Value != null)
            {
                var notGuid     = (!Guid.TryParse(kv.Value.ToString(), out _));
                var notDateTime = (!DateTime.TryParse(kv.Value.ToString(), out _));

                if (propertySchemaObject.Format != null)
                {
                    var format = propertySchemaObject.GetFormat();
                    // Validate specific string formats
                    if (format == Format.DateTime && notDateTime)
                    {
                        AddFormatError(testMessageResult, kv.Value.ToString(), kv.Key, Format.DateTime);
                    }
                }
                if (notGuid && propertySchemaObject.Reference == "Guid")
                {
                    AddFormatError(testMessageResult, kv.Value.ToString(), kv.Key, Format.Guid);
                }
            }
            else if (kv.Value == null && propertySchemaObject.Reference == "Guid")
            {
                AddFormatError(testMessageResult, null, kv.Key, Format.Guid);
            }
        }
Esempio n. 4
0
        private static void CheckNumberType(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv,
                                            TestMessageResult testMessageResult)
        {
            var stringVal = kv.Value.ToString();
            var isDouble  = double.TryParse(stringVal, out var doubleVal) && double.IsFinite(doubleVal);
            var isFloat   = float.TryParse(stringVal, out var floatVal) && float.IsFinite(floatVal);

            // Validate number data type
            if (!isDouble && !isFloat)
            {
                AddTypeError(testMessageResult, stringVal, kv.Key, propertySchemaObject.Type);
            }

            if (propertySchemaObject.Format != null)
            {
                var format = propertySchemaObject.GetFormat();
                // Validate specific number formats
                if (format == Format.Float && !isFloat)
                {
                    AddFormatError(testMessageResult, stringVal, kv.Key, Format.Float);
                }
                else if (format == Format.Double && !isDouble)
                {
                    AddFormatError(testMessageResult, stringVal, kv.Key, Format.Double);
                }
            }
        }
Esempio n. 5
0
        private void CheckObjectType(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv,
                                     TestMessageResult testMessageResult, bool allowSubset)
        {
            CaseInsensitiveDictionary <object> innerObject = null;

            try
            {
                var json = JsonConvert.SerializeObject(kv.Value);
                innerObject = JsonConvert.DeserializeObject <CaseInsensitiveDictionary <object> >(json);
            }
            catch (Exception)
            {
                AddTypeError(testMessageResult, kv.Value.ToString(), kv.Key, "Object");
            }
            if (propertySchemaObject.Properties != null)
            {
                foreach (var innerProperty in propertySchemaObject.Properties)
                {
                    if (innerObject != null && innerObject.ContainsKey(innerProperty.Key))
                    {
                        ChecksForMessage(innerProperty.Value,
                                         new KeyValuePair <string, object>($"{kv.Key}{ParentOfSymbol}{innerProperty.Key}",
                                                                           innerObject[innerProperty.Key]), testMessageResult, allowSubset);
                    }
                    else
                    {
                        if (!allowSubset)
                        {
                            AddNotFoundError(testMessageResult, $"{kv.Key}{ParentOfSymbol}{innerProperty.Key}");
                        }
                    }
                }
            }
        }
Esempio n. 6
0
        private static void AddItemTypeError(TestMessageResult result, string key, DataType dataType, Format format = null)
        {
            var modifier = format?.Value ?? dataType.Value;

            result.IsMessageValid = false;
            result.MessageErrors.Add(
                $"An item in the Items array for {key} does not match the required data type ({modifier}).");
        }
Esempio n. 7
0
        private static void CheckBooleanType(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv,
                                             TestMessageResult testMessageResult)
        {
            var isBool = bool.TryParse(kv.Value.ToString(), out _);

            // Validate number data type
            if (!isBool)
            {
                AddTypeError(testMessageResult, kv.Value.ToString(), kv.Key, propertySchemaObject.Type);
            }
        }
Esempio n. 8
0
        private void CheckArrayType(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv,
                                    TestMessageResult testMessageResult)
        {
            if (propertySchemaObject.Items == null)
            {
                AddRequiredError(testMessageResult, kv.Key, "Array", "Items");
            }
            else
            {
                var     itemSchema = propertySchemaObject.Items;
                dynamic itemArray  = JsonConvert.DeserializeObject(kv.Value.ToString());
                var     dataType   = itemSchema.GetDataType();

                if (itemArray is IEnumerable array)
                {
                    var count = array.Cast <object>().Count();
                    if (propertySchemaObject.MinItems != 0 && count < propertySchemaObject.MinItems)
                    {
                        AddArrayMinLengthError(testMessageResult, kv.Key, propertySchemaObject.MinItems);
                    }

                    if (propertySchemaObject.MaxItems != 0 && count > propertySchemaObject.MaxItems)
                    {
                        AddArrayMaxLengthError(testMessageResult, kv.Key, propertySchemaObject.MaxItems);
                    }

                    if (dataType == DataType.String)
                    {
                        TryParseStringArray(propertySchemaObject, kv, itemArray, testMessageResult, itemSchema.Reference == "Guid");
                    }

                    if (dataType == DataType.Integer)
                    {
                        TryParseIntegerArray(propertySchemaObject, kv, itemArray, testMessageResult);
                    }

                    if (dataType == DataType.Number)
                    {
                        TryParseNumberArray(propertySchemaObject, kv, itemArray, testMessageResult);
                    }
                }
                else
                {
                    AddTypeError(testMessageResult, kv.Value.ToString(), kv.Key, DataType.Array.Value);
                }

                if (dataType == DataType.Boolean)
                {
                    TryParseBooleanArray(propertySchemaObject, kv, itemArray, testMessageResult);
                }
            }
        }
Esempio n. 9
0
        public TestMessageResult AreAllElementsInMessageContainedInContract(CaseInsensitiveDictionary <object> messageKeyDictionary, CaseInsensitiveDictionary <SchemaObject> contractDictionary)
        {
            var result = new TestMessageResult();

            foreach (var kv in messageKeyDictionary)
            {
                if (contractDictionary.Keys.Contains(kv.Key, StringComparer.InvariantCultureIgnoreCase))
                {
                    continue;
                }

                result.IsMessageValid = true;
                result.Warnings.Add($"Message property \"{kv.Key}\" is not part of the contract.");
            }

            return(result);
        }
Esempio n. 10
0
        public TestMessageResult AreAllElementsInContractContainedInMessage(CaseInsensitiveDictionary <object> messageKeyDictionary, CaseInsensitiveDictionary <SchemaObject> contractDictionary)
        {
            var result = new TestMessageResult();

            foreach (var kv in contractDictionary)
            {
                if (messageKeyDictionary.Keys.Contains(kv.Key, StringComparer.InvariantCultureIgnoreCase))
                {
                    continue;
                }

                result.IsMessageValid = false;
                result.MessageErrors.Add($"Message is missing expected property \"{kv.Key}\".");
            }

            return(result);
        }
Esempio n. 11
0
        public TestMessageResult DoAllMessageValuesMatchDataTypes(CaseInsensitiveDictionary <object> messageKeyDictionary,
                                                                  CaseInsensitiveDictionary <SchemaObject> contractDictionary, bool allowSubset = false)
        {
            var testMessageResult = new TestMessageResult();

            // loop through each property in the message Dictionary - trying to parse the values into the data type in the contract
            foreach (KeyValuePair <string, object> kv in messageKeyDictionary)
            {
                // if the contract doesn't supply the datatype for the parameter -> then the message doesn't match the contract.
                contractDictionary.TryGetValue(kv.Key, out var propertySchemaObject);

                if (propertySchemaObject != null)
                {
                    ChecksForMessage(propertySchemaObject, kv, testMessageResult, allowSubset);
                }
            }

            return(testMessageResult);
        }
Esempio n. 12
0
        private static void TryParseIntegerArray(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv, dynamic itemArray, TestMessageResult testMessageResult)
        {
            var itemFormat = propertySchemaObject.Items.GetFormat();

            foreach (var item in itemArray)
            {
                var isInt32 = int.TryParse(item.ToString(), out int _);
                var isInt64 = long.TryParse(item.ToString(), out long _);

                // Validate integer data type, which is int32.
                if (itemFormat == null && !isInt32)
                {
                    AddItemTypeError(testMessageResult, kv.Key, DataType.Integer);
                    break;
                }

                if (itemFormat != null)
                {
                    // Validate specific integer formats
                    if (itemFormat == Format.Int32 && !isInt32)
                    {
                        AddItemTypeError(testMessageResult, kv.Key, DataType.Integer, Format.Int32);
                        break;
                    }

                    if (itemFormat == Format.Int64 && !isInt64)
                    {
                        AddItemTypeError(testMessageResult, kv.Key, DataType.Integer, Format.Int64);
                        break;
                    }
                }
            }
        }
Esempio n. 13
0
        private static void TryParseStringArray(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv, dynamic itemArray, TestMessageResult testMessageResult, bool itemIsGuid)
        {
            var itemFormat = propertySchemaObject.Items.GetFormat();

            if (itemFormat == Format.DateTime)
            {
                foreach (var item in itemArray)
                {
                    if (!DateTime.TryParse(item.ToString(), out DateTime _))
                    {
                        AddItemTypeError(testMessageResult, kv.Key, DataType.String, Format.DateTime);
                        break;
                    }
                }
            }
            else if (itemIsGuid)
            {
                foreach (var item in itemArray)
                {
                    if (!Guid.TryParse(item.ToString(), out Guid _))
                    {
                        AddItemTypeError(testMessageResult, kv.Key, DataType.String, Format.Guid);
                        break;
                    }
                }
            }
        }
Esempio n. 14
0
 private static void AddArrayMaxLengthError(TestMessageResult result, string key, int max)
 {
     result.IsMessageValid = false;
     result.MessageErrors.Add(
         $"The Items array for {key} has greater than the maximum number ({max}) of items allowed.");
 }
Esempio n. 15
0
 private static void AddArrayMinLengthError(TestMessageResult result, string key, int min)
 {
     result.IsMessageValid = false;
     result.MessageErrors.Add(
         $"The Items array for {key} does not have the minimum number ({min}) of items required.");
 }
Esempio n. 16
0
 private static void AddRequiredError(TestMessageResult result, string key, string type, string requiredProperty)
 {
     result.IsMessageValid = false;
     result.MessageErrors.Add(
         $"\"{key}\" does not have the required property({requiredProperty}) for type({type}).");
 }
Esempio n. 17
0
 private static void AddNotFoundError(TestMessageResult result, string property)
 {
     result.IsMessageValid = false;
     result.MessageErrors.Add(
         $"The value for field \"{property}\" was not found.");
 }
Esempio n. 18
0
 private static void AddFormatError(TestMessageResult result, string value, string key, Format format)
 {
     result.IsMessageValid = false;
     result.MessageErrors.Add(
         $"\"{value}\" does not match the required format for {key} ({format.DisplayName}).");
 }
Esempio n. 19
0
 private static void AddTypeError(TestMessageResult result, string value, string key, string type)
 {
     result.IsMessageValid = false;
     result.MessageErrors.Add(
         $"\"{value}\" does not match the required data type for {key} ({type}).");
 }
Esempio n. 20
0
        private static void TryParseNumberArray(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv, dynamic itemArray, TestMessageResult testMessageResult)
        {
            var itemFormat = propertySchemaObject.Items.GetFormat();

            foreach (var item in itemArray)
            {
                var isFloat  = float.TryParse(item.ToString(), out float _);
                var isDouble = double.TryParse(item.ToString(), out double _);

                // Validate integer data type, which is int32.
                if (itemFormat == null && !isFloat)
                {
                    AddItemTypeError(testMessageResult, kv.Key, DataType.Number);
                    break;
                }

                if (itemFormat != null)
                {
                    // Validate specific integer formats
                    if (itemFormat == Format.Float && !isFloat)
                    {
                        AddItemTypeError(testMessageResult, kv.Key, DataType.Number, Format.Float);
                        break;
                    }

                    if (itemFormat == Format.Double && !isDouble)
                    {
                        AddItemTypeError(testMessageResult, kv.Key, DataType.Number, Format.Double);
                        break;
                    }
                }
            }
        }
Esempio n. 21
0
        public TestMessageResult Execute(string contract, string message, bool allowSubset = false)
        {
            var schemaDictionary = SchemaObject.BuildSchemaDictionary(contract, HandleReferenceError, HandleFailure);

            if (!_isContractValid)
            {
                var contractInvalidMessage = new TestMessageResult
                {
                    IsMessageValid = false,
                    MessageErrors  = new List <string>()
                    {
                        _contractErrorMessage
                    }
                };
                _isContractValid      = true;
                _contractErrorMessage = "";
                return(contractInvalidMessage);
            }

            if (!TryParseJSON(message, out var messageJson))
            {
                return(new TestMessageResult
                {
                    IsMessageValid = false,
                    MessageErrors = new List <string> {
                        "Message contains invalid JSON."
                    }
                });
            }

            var messageDictionary = JsonConvert.DeserializeObject <CaseInsensitiveDictionary <object> >(messageJson.ToString());

            if (messageDictionary.Count <= 0)
            {
                return new TestMessageResult
                       {
                           IsMessageValid = false,
                           MessageErrors  = new List <string> {
                               "Message contains empty JSON."
                           }
                       }
            }
            ;

            var contractDictionary = schemaDictionary.TryGetValue("Contract", out _)
                ? schemaDictionary["Contract"].Properties
                : null;

            if (contractDictionary != null && _isContractValid)
            {
                TestCases.Clear();

                TestCases.Add(AreAllElementsInMessageContainedInContract(messageDictionary, contractDictionary));
                if (!allowSubset)
                {
                    TestCases.Add(AreAllElementsInContractContainedInMessage(messageDictionary, contractDictionary));
                }
                TestCases.Add(DoAllMessageValuesMatchDataTypes(messageDictionary, contractDictionary, allowSubset));
            }

            return(new TestMessageResult
            {
                IsMessageValid = TestCases.All(x => x.IsMessageValid),
                Warnings = TestCases.SelectMany(x => x.Warnings).ToList(),
                MessageErrors = TestCases.SelectMany(x => x.MessageErrors).ToList()
            });
        }
Esempio n. 22
0
        private void TryParseBooleanArray(SchemaObject propertySchemaObject, KeyValuePair <string, object> kv, dynamic itemArray, TestMessageResult testMessageResult)
        {
            var itemFormat = propertySchemaObject.Items.GetFormat();

            foreach (var item in itemArray)
            {
                var isBool = bool.TryParse(item.ToString(), out bool _);

                // Validate boolean data type
                if (itemFormat == null && !isBool)
                {
                    AddItemTypeError(testMessageResult, kv.Key, DataType.Boolean);
                    break;
                }
            }
        }
Esempio n. 23
0
 private static void AddSchemaNotFoundError(TestMessageResult result, string property)
 {
     result.IsMessageValid = false;
     result.MessageErrors.Add(
         $"The schema for \"{property}\" was not found in the contract definition.");
 }