예제 #1
0
        private static void CheckType(Type specType, string expectedType, JsonSchema schema, JsonSchema property,
                                      ImplementationProperty implementationProperty,
                                      TypeValidationResult result,
                                      Func <Type, bool> typeCheck
                                      )
        {
            var propertyType = implementationProperty.PropertyType;
            var nullable     = !propertyType.IsValueType;

            if (IsNullableType(propertyType))
            {
                nullable     = true;
                propertyType = Nullable.GetUnderlyingType(implementationProperty.PropertyType);
            }

            if (!typeCheck(propertyType))
            {
                result.AddError(TypeValidationError.ExpectedType(specType, propertyType, expectedType, schema.GetNameOrSpecificationId(),
                                                                 property.GetNameOrSpecificationId()));
            }

            if (result.Validation == Validation.SpecToType && property.Type.HasFlag(JsonObjectType.Null) && !nullable)
            {
                result.AddError(new TypeValidationError(specType, schema.GetNameOrSpecificationId(), property.GetNameOrSpecificationId(),
                                                        "expected type to be nullable"));
            }
        }
예제 #2
0
        private static void ValidateEnum(Type specType, JsonSchema schema,
                                         JsonSchema schemaProperty, ImplementationProperty specTypeProperty, TypeValidationResult result
                                         )
        {
            var enumValues = GetEnumValues(specTypeProperty.PropertyType);

            foreach (var enumValue in enumValues)
            {
                if (!schemaProperty.Enumeration.Cast <string>().Contains(enumValue))
                {
                    result.AddError(new TypeValidationError(specType, schema.GetNameOrSpecificationId(),
                                                            schemaProperty.GetNameOrSpecificationId(), $"enum did not contain value {enumValue}"));
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Get the properties for the given specification type, using the APM agent's serialization components.
        /// </summary>
        /// <remarks>
        /// Encapsulates the APM agent implementation for how specification constraints are enforced. This currently
        /// uses Json.NET for serialized property names and constraining max length.
        /// </remarks>
        /// <param name="specType">the specification type</param>
        /// <returns></returns>
        private static ImplementationProperty[] GetProperties(Type specType)
        {
            var resolver = new ElasticApmContractResolver();
            JsonObjectContract contract;

            try
            {
                // the json schema may indicate a type is an "object", but the agent may model it in some other way
                // e.g. samples on metricset is modelled as a collection. In these scenarios, we won't be dealing with
                // an object contract and won't be able to statically determine validity of the type to the schema through reflection.
                // The only way to validate these against the schema is to serialize the types.
                contract = (JsonObjectContract)resolver.ResolveContract(specType);
            }
            catch (InvalidCastException e)
            {
                throw new ContractResolveException(e.Message);
            }

            var specProperties = new List <ImplementationProperty>(contract.Properties.Count);

            foreach (var jsonProperty in contract.Properties)
            {
                if (jsonProperty.Ignored)
                {
                    continue;
                }

                var implementationProperty = new ImplementationProperty(jsonProperty.PropertyName, jsonProperty.PropertyType, specType);
                var maxLength = (MaxLengthAttribute)(jsonProperty.AttributeProvider.GetAttributes(typeof(MaxLengthAttribute), true).FirstOrDefault());

                if (maxLength != null)
                {
                    implementationProperty.MaxLength = maxLength.Length;
                }

                specProperties.Add(implementationProperty);
            }

            return(specProperties.ToArray());
        }
예제 #4
0
 private static void CheckMaxLength(Type specType, JsonSchema schema, JsonSchema schemaProperty, ImplementationProperty implementationProperty,
                                    TypeValidationResult result
                                    )
 {
     if (schemaProperty.MaxLength.HasValue)
     {
         var maxLength = schemaProperty.MaxLength.Value;
         if (!implementationProperty.MaxLength.HasValue)
         {
             result.AddError(new TypeValidationError(specType, schema.GetNameOrSpecificationId(), implementationProperty.Name,
                                                     $"expected property to enforce maxLength of {maxLength} but does not"));
         }
         else if (implementationProperty.MaxLength != maxLength)
         {
             result.AddError(new TypeValidationError(specType, schema.GetNameOrSpecificationId(), implementationProperty.Name,
                                                     $"property max length {implementationProperty.MaxLength} not equal to spec maxLength {maxLength}"));
         }
     }
 }
예제 #5
0
 private static void ValidateNumber(Type specType, JsonSchema schema, JsonSchema property, ImplementationProperty specTypeProperty,
                                    TypeValidationResult result
                                    ) =>
 CheckType(specType, "number", schema, property, specTypeProperty, result, t => NumericTypeNames.Contains(t.FullName));
예제 #6
0
 private static void ValidateInteger(Type specType, JsonSchema schema, JsonSchema property, ImplementationProperty specTypeProperty,
                                     TypeValidationResult result
                                     ) =>
 CheckType(specType, "integer", schema, property, specTypeProperty, result, t => t == typeof(int) || t == typeof(long));
예제 #7
0
 private static void ValidateBoolean(Type specType, JsonSchema schema, JsonSchema property, ImplementationProperty specTypeProperty,
                                     TypeValidationResult result
                                     ) =>
 CheckType(specType, "boolean", schema, property, specTypeProperty, result, t => t == typeof(bool));
예제 #8
0
 private static void ValidateString(Type specType, JsonSchema schema, JsonSchema property, ImplementationProperty specTypeProperty,
                                    TypeValidationResult result
                                    )
 {
     CheckType(specType, "string", schema, property, specTypeProperty, result, t => t == typeof(string));
     CheckMaxLength(specType, schema, property, specTypeProperty, result);
 }