internal PayloadComplexProperty parseComplexObject(PayloadObject parent, JSField field) { PayloadComplexProperty payloadProperty = new PayloadComplexProperty(parent); payloadProperty.Name = field.Name; JSObject fieldValue = (JSObject)field.GetValue(field); FieldInfo[] fieldInfo = fieldValue.GetFields(BindingFlags.Default); for (int j = 0; j < fieldInfo.Length; j++) { JSField currentField = (JSField)fieldInfo[j]; if (currentField.GetValue(currentField) is JSObject) { PayloadComplexProperty payloadComplexProperty = this.parseComplexObject(parent, (JSField)fieldInfo[j]); payloadProperty.PayloadProperties.Add(payloadComplexProperty.Name, payloadComplexProperty); } else { PayloadProperty payloadSimpleProperty = this.parseSimpleObject(parent, (JSField)fieldInfo[j]); payloadProperty.PayloadProperties.Add(payloadSimpleProperty.Name, payloadSimpleProperty); } } return(payloadProperty); }
protected bool EquivalentValues(NodeType firstType, PayloadProperty first, NodeType secondType, PayloadProperty second) { PayloadSimpleProperty firstSimple = first as PayloadSimpleProperty; PayloadSimpleProperty secondSimple = second as PayloadSimpleProperty; if (firstSimple == null || secondSimple == null) { return(false); } if ((firstType == Clr.Types.Double || firstType == Clr.Types.Float)) { if (second.ParentObject.Format == SerializationFormatKind.JSON) { if (secondType == Clr.Types.Int16 || secondType == Clr.Types.Int32 || secondType == Clr.Types.Int64) { if (((long)double.Parse(firstSimple.Value)) == long.Parse(secondSimple.Value)) { return(true); } } } } return(false); }
protected void CompareDynamicPropertyValues(PayloadProperty inserted, PayloadProperty returned) { if (inserted.IsNull || returned.IsNull) { if (!inserted.IsNull) { AstoriaTestLog.FailAndThrow("Null inserted value was non-null in return payload"); } if (!returned.IsNull) { AstoriaTestLog.FailAndThrow("Non-null inserted value was null in return payload"); } } else { NodeType insertType = GetDynamicPropertyType(inserted); NodeType returnType = GetDynamicPropertyType(returned); if (inserted.MappedOutOfContent == returned.MappedOutOfContent) { bool equivalentTypes = false; if (EquivalentValues(insertType, inserted, returnType, returned)) { equivalentTypes = true; } if (EquivalentValues(returnType, returned, insertType, inserted)) { equivalentTypes = true; } if (!equivalentTypes) { AstoriaTestLog.AreEqual(insertType, returnType, "Type of inserted/updated dynamic property value does not match returned type for property", false); } } else if (inserted.MappedOutOfContent) { insertType = returnType; } ComparePropertyValues(insertType, inserted, returned, true); } }
private void VerifyProperties(ResourceType type, PayloadObject inserted, PayloadObject returned, bool missingInsertPropertiesOk, Func <ResourceProperty, bool> strictEquality) { List <string> propertyNames = inserted.PayloadProperties.Union(returned.PayloadProperties).Select(p => p.Name).ToList(); propertyNames.AddRange(inserted.CustomEpmMappedProperties.Keys); propertyNames.AddRange(returned.CustomEpmMappedProperties.Keys); foreach (string propertyName in propertyNames.Distinct()) { PayloadProperty insertedProperty; if (inserted.Format == SerializationFormatKind.JSON) //in JSON the first one wins { insertedProperty = inserted.PayloadProperties.FirstOrDefault(p => p.Name == propertyName); } else //in xml the last one wins { insertedProperty = inserted.PayloadProperties.LastOrDefault(p => p.Name == propertyName); } bool insertHadProperty = insertedProperty != null; PayloadProperty returnedProperty = returned.PayloadProperties.LastOrDefault(p => p.Name == propertyName);; bool returnedHadProperty = returnedProperty != null; ResourceProperty property = type.Properties.OfType <ResourceProperty>().SingleOrDefault(p => p.Name == propertyName); if (property == null || !property.Facets.IsDeclaredProperty) { if (!type.Facets.IsOpenType) { string error = "included dynamic property '" + propertyName + "' despite '" + type.Name + "' not being an open type"; if (insertHadProperty && returnedHadProperty) { AstoriaTestLog.FailAndThrow("Both the inserted and returned objects " + error); } else if (insertHadProperty) { AstoriaTestLog.FailAndThrow("The inserted object " + error); } else if (returnedHadProperty) { AstoriaTestLog.FailAndThrow("The returned object " + error); } } else { if (insertHadProperty && returnedHadProperty) { CompareDynamicPropertyValues(insertedProperty, returnedProperty); } else if (insertHadProperty) { // only acceptable if inserted value was null if (insertedProperty.IsNull) { AstoriaTestLog.FailAndThrow("Returned object missing non-null dynamic property '" + propertyName + "'"); } } } } else { if (property.IsNavigation) { // the insert payload may not specify this property //PayloadObject insertedObject = inserted.PayloadObjects.SingleOrDefault(o => o.Name == property.Name); PayloadObject returnedObject = returned.PayloadObjects.Single(o => o.Name == property.Name); // returned thing should be deferred whether its a reference or not AstoriaTestLog.AreEqual(true, returnedObject.Deferred, "!returnedObject.Deferred", false); // TODO: verify only expected links are present (based on uri and payload values as well) } else { if (insertHadProperty && returnedHadProperty) { try { ComparePropertyValues(property, insertedProperty, returnedProperty, strictEquality(property)); } catch (Exception e) { throw new TestFailedException("Value of property '" + property.Name + "' does not match inserted value", null, null, e); } } else if (insertHadProperty) { AstoriaTestLog.FailAndThrow("Returned object unexpectedly missing declared property '" + propertyName + "'"); } else if (returnedHadProperty) { if (missingInsertPropertiesOk) { AstoriaTestLog.WriteLineIgnore("Ignoring missing declared property '" + propertyName + "' in insert payload"); } else { AstoriaTestLog.FailAndThrow("Inserted object unexpectedly missing declared property '" + propertyName + "'"); } } } } } }
protected void ComparePropertyValues(NodeType type, PayloadProperty first, PayloadProperty second, bool checkValue) { if (type is ComplexType) { if (first.IsNull) { if (!second.IsNull) { AstoriaTestLog.FailAndThrow("Second property is unexpectedly non-null"); } return; } else if (second.IsNull) { AstoriaTestLog.FailAndThrow("Second property is unexpectedly null"); } PayloadComplexProperty firstComplex = first as PayloadComplexProperty; PayloadComplexProperty secondComplex = second as PayloadComplexProperty; if (firstComplex == null) { AstoriaTestLog.FailAndThrow("First property was not a complex property"); } if (secondComplex == null) { AstoriaTestLog.FailAndThrow("Second property was not a complex property"); } foreach (string propertyName in firstComplex.PayloadProperties.Keys.Union(secondComplex.PayloadProperties.Keys)) { // TODO: verify typing if (propertyName == "__metadata") { continue; } PayloadProperty firstProperty; bool firstHadProperty = firstComplex.PayloadProperties.TryGetValue(propertyName, out firstProperty); PayloadProperty secondProperty; bool secondHadProperty = secondComplex.PayloadProperties.TryGetValue(propertyName, out secondProperty); // so that we can ignore this case later on, check it now if (!firstHadProperty && !secondHadProperty) { AstoriaTestLog.FailAndThrow("Property list contained property '" + propertyName + "' despite neither complex property containing it"); } // since a complex type is never open, there shouldnt be any unexpected properties NodeProperty property = (type as ComplexType).Properties.SingleOrDefault(p => p.Name == propertyName); if (property == null) { if (firstHadProperty && secondHadProperty) { AstoriaTestLog.FailAndThrow("Both complex properties contained sub-property '" + propertyName + "' which is not defined on type '" + type.Name + "'"); } else if (firstHadProperty) { AstoriaTestLog.FailAndThrow("First complex property contained sub-property '" + propertyName + "' which is not defined on type '" + type.Name + "'"); } else if (secondHadProperty) { AstoriaTestLog.FailAndThrow("Second complex property contained sub-property '" + propertyName + "' which is not defined on type '" + type.Name + "'"); } } if (!firstHadProperty) { AstoriaTestLog.FailAndThrow("First complex property property missing sub-property '" + propertyName + "'"); } else if (!secondHadProperty) { AstoriaTestLog.FailAndThrow("Second complex property property missing sub-property '" + propertyName + "'"); } ComparePropertyValues(property, firstProperty, secondProperty, checkValue && !property.Facets.ServerGenerated); } } else { PayloadSimpleProperty firstSimple = first as PayloadSimpleProperty; PayloadSimpleProperty secondSimple = second as PayloadSimpleProperty; if (firstSimple == null) { AstoriaTestLog.FailAndThrow("First property was not a simple property"); } if (secondSimple == null) { AstoriaTestLog.FailAndThrow("Second property was not a simple property"); } object expectedObject = CommonPayload.DeserializeStringToObject(firstSimple.Value, type.ClrType, false, first.ParentObject.Format); if (checkValue) { CommonPayload.ComparePrimitiveValuesObjectAndString(expectedObject, type.ClrType, secondSimple.Value, false, second.ParentObject.Format, true); } else { CommonPayload.DeserializeStringToObject(secondSimple.Value, type.ClrType, false, second.ParentObject.Format); } } }
protected void ComparePropertyValues(NodeProperty property, PayloadProperty first, PayloadProperty second, bool checkValue) { // in case we need to do any facet-based logic ComparePropertyValues(property.Type, first, second, checkValue); }
protected NodeType GetDynamicPropertyType(PayloadProperty property) { string typeName = property.Type; if (typeName == null) { if (property.ParentObject.Format == SerializationFormatKind.JSON) { if (property is PayloadComplexProperty) { PayloadComplexProperty complexProperty = property as PayloadComplexProperty; PayloadProperty metadata; if (!complexProperty.PayloadProperties.TryGetValue("__metadata", out metadata) || !(metadata is PayloadComplexProperty)) { AstoriaTestLog.FailAndThrow("Complex type properties did not contain __metadata complex property"); } PayloadProperty metadataType; if (!(metadata as PayloadComplexProperty).PayloadProperties.TryGetValue("type", out metadataType) || !(metadataType is PayloadSimpleProperty)) { AstoriaTestLog.FailAndThrow("__metadata property did not contain complex type's name"); } typeName = (metadataType as PayloadSimpleProperty).Value; } if (typeName == null) { typeName = "String"; } } else { typeName = "String"; } } else if (typeName.StartsWith("Edm.")) { typeName = typeName.Replace("Edm.", null); } if (typeName == "Binary") { typeName = "Byte[]"; } // json datetime check if (typeName == "String" && property.ParentObject.Format == SerializationFormatKind.JSON && property is PayloadSimpleProperty) { PayloadSimpleProperty simpleProperty = property as PayloadSimpleProperty; if (Util.JsonPrimitiveTypesUtil.DateTimeRegex.IsMatch(simpleProperty.Value)) { typeName = "DateTime"; } } NodeType type = Clr.Types.SingleOrDefault(t => t.Name.Equals(typeName)); if (type == null) { type = Response.Workspace.ServiceContainer.ComplexTypes.SingleOrDefault(ct => typeName.Equals(ct.Namespace + "." + ct.Name)); } if (type == null) { AstoriaTestLog.FailAndThrow("Could not find type '" + typeName + "'"); } return(type); }
private PayloadObject parseJsonObject(JSObject jsObject) { PayloadObject payloadObject = new PayloadObject(this); FieldInfo[] fields = jsObject.GetFields(BindingFlags.Default); for (int i = 0; i < fields.Length; i++) { JSField field = (JSField)fields[i]; var value = field.GetValue(field); if (value is ArrayObject) { PayloadObject payloadNestedParentObject = new PayloadObject(this); payloadNestedParentObject.Name = field.Name; ArrayObject nestedPayloadObjects = (ArrayObject)field.GetValue(field); payloadNestedParentObject.PayloadObjects.AddRange(this.ParseJsonArray(nestedPayloadObjects)); foreach (PayloadObject po in payloadNestedParentObject.PayloadObjects) { po.Name = field.Name; } payloadObject.PayloadObjects.Add(payloadNestedParentObject); } else if (value is JSObject) { if (field.Name == "__metadata") { payloadObject.Uri = this.GetArrayString(field, "uri"); payloadObject.Type = this.GetArrayString(field, "type"); string etag = this.GetArrayString(field, "etag"); if (etag != null) { payloadObject.ETag = etag; } } else { JSField firstChild = this.GetArrayField(field, 0); if (firstChild != null && firstChild.Name == v2JsonResultsField) { PayloadObject payloadNestedParentObject = new PayloadObject(this); payloadNestedParentObject.Name = field.Name; ArrayObject nestedPayloadObjects = (ArrayObject)firstChild.GetValue(firstChild); payloadNestedParentObject.PayloadObjects.AddRange(this.ParseJsonArray(nestedPayloadObjects)); foreach (PayloadObject po in payloadNestedParentObject.PayloadObjects) { po.Name = field.Name; } payloadObject.PayloadObjects.Add(payloadNestedParentObject); } else if (firstChild != null && firstChild.Name == "__deferred") // Deferred reference/collection { PayloadObject deferredObject = new PayloadObject(this); deferredObject.Name = field.Name; deferredObject.Uri = this.GetArrayString(firstChild, "uri"); deferredObject.Deferred = true; payloadObject.PayloadObjects.Add(deferredObject); } else if (firstChild != null && firstChild.Name == "__mediaresource") { PayloadNamedStream stream = new PayloadNamedStream(); stream.Name = field.Name; stream.ContentType = this.GetArrayString(firstChild, "content-type"); stream.EditLink = this.GetArrayString(firstChild, "edit_media"); stream.SelfLink = this.GetArrayString(firstChild, "media_src"); stream.ETag = this.GetArrayString(firstChild, "etag"); payloadObject.NamedStreams.Add(stream); } else { JSObject objectValue = (JSObject)field.GetValue(field); var objectValueFields = objectValue.GetFields(BindingFlags.Default); if (objectValueFields.Any(f => f.Name == "__metadata" && GetArrayString((JSField)f, "uri") != null)) { PayloadObject referencePayloadObject = parseJsonObject(objectValue); referencePayloadObject.Name = field.Name; referencePayloadObject.Reference = true; payloadObject.PayloadObjects.Add(referencePayloadObject); } else { PayloadComplexProperty payloadProperty = this.parseComplexObject(payloadObject, field); // Complex object payloadObject.PayloadProperties.Add(payloadProperty); } } } } else { PayloadProperty payloadProperty = this.parseSimpleObject(payloadObject, field); payloadObject.PayloadProperties.Add(payloadProperty); } } return(payloadObject); }
protected void ComparePropertyValues(NodeProperty property, PayloadProperty first, PayloadProperty second, bool checkValue) { // in case we need to do any facet-based logic ComparePropertyValues(property.Type, first, second, checkValue); }
protected void ComparePropertyValues(NodeType type, PayloadProperty first, PayloadProperty second, bool checkValue) { if (type is ComplexType) { if(first.IsNull) { if (!second.IsNull) AstoriaTestLog.FailAndThrow("Second property is unexpectedly non-null"); return; } else if(second.IsNull) AstoriaTestLog.FailAndThrow("Second property is unexpectedly null"); PayloadComplexProperty firstComplex = first as PayloadComplexProperty; PayloadComplexProperty secondComplex = second as PayloadComplexProperty; if (firstComplex == null) AstoriaTestLog.FailAndThrow("First property was not a complex property"); if( secondComplex == null) AstoriaTestLog.FailAndThrow("Second property was not a complex property"); foreach (string propertyName in firstComplex.PayloadProperties.Keys.Union(secondComplex.PayloadProperties.Keys)) { // TODO: verify typing if (propertyName == "__metadata") continue; PayloadProperty firstProperty; bool firstHadProperty = firstComplex.PayloadProperties.TryGetValue(propertyName, out firstProperty); PayloadProperty secondProperty; bool secondHadProperty = secondComplex.PayloadProperties.TryGetValue(propertyName, out secondProperty); // so that we can ignore this case later on, check it now if (!firstHadProperty && !secondHadProperty) AstoriaTestLog.FailAndThrow("Property list contained property '" + propertyName + "' despite neither complex property containing it"); // since a complex type is never open, there shouldnt be any unexpected properties NodeProperty property = (type as ComplexType).Properties.SingleOrDefault(p => p.Name == propertyName); if (property == null) { if (firstHadProperty && secondHadProperty) AstoriaTestLog.FailAndThrow("Both complex properties contained sub-property '" + propertyName + "' which is not defined on type '" + type.Name + "'"); else if(firstHadProperty) AstoriaTestLog.FailAndThrow("First complex property contained sub-property '" + propertyName + "' which is not defined on type '" + type.Name + "'"); else if (secondHadProperty) AstoriaTestLog.FailAndThrow("Second complex property contained sub-property '" + propertyName + "' which is not defined on type '" + type.Name + "'"); } if (!firstHadProperty) AstoriaTestLog.FailAndThrow("First complex property property missing sub-property '" + propertyName + "'"); else if (!secondHadProperty) AstoriaTestLog.FailAndThrow("Second complex property property missing sub-property '" + propertyName + "'"); ComparePropertyValues(property, firstProperty, secondProperty, checkValue && !property.Facets.ServerGenerated); } } else { PayloadSimpleProperty firstSimple = first as PayloadSimpleProperty; PayloadSimpleProperty secondSimple = second as PayloadSimpleProperty; if (firstSimple == null) AstoriaTestLog.FailAndThrow("First property was not a simple property"); if (secondSimple == null) AstoriaTestLog.FailAndThrow("Second property was not a simple property"); object expectedObject = CommonPayload.DeserializeStringToObject(firstSimple.Value, type.ClrType, false, first.ParentObject.Format); if (checkValue) CommonPayload.ComparePrimitiveValuesObjectAndString(expectedObject, type.ClrType, secondSimple.Value, false, second.ParentObject.Format, true); else CommonPayload.DeserializeStringToObject(secondSimple.Value, type.ClrType, false, second.ParentObject.Format); } }
protected NodeType GetDynamicPropertyType(PayloadProperty property) { string typeName = property.Type; if(typeName == null) { if (property.ParentObject.Format == SerializationFormatKind.JSON) { if (property is PayloadComplexProperty) { PayloadComplexProperty complexProperty = property as PayloadComplexProperty; PayloadProperty metadata; if (!complexProperty.PayloadProperties.TryGetValue("__metadata", out metadata) || !(metadata is PayloadComplexProperty)) AstoriaTestLog.FailAndThrow("Complex type properties did not contain __metadata complex property"); PayloadProperty metadataType; if(!(metadata as PayloadComplexProperty).PayloadProperties.TryGetValue("type", out metadataType) || !(metadataType is PayloadSimpleProperty)) AstoriaTestLog.FailAndThrow("__metadata property did not contain complex type's name"); typeName = (metadataType as PayloadSimpleProperty).Value; } if(typeName == null) { typeName = "String"; } } else { typeName = "String"; } } else if (typeName.StartsWith("Edm.")) { typeName = typeName.Replace("Edm.", null); } if (typeName == "Binary") typeName = "Byte[]"; // json datetime check if (typeName == "String" && property.ParentObject.Format == SerializationFormatKind.JSON && property is PayloadSimpleProperty) { PayloadSimpleProperty simpleProperty = property as PayloadSimpleProperty; if (Util.JsonPrimitiveTypesUtil.DateTimeRegex.IsMatch(simpleProperty.Value)) typeName = "DateTime"; } NodeType type = Clr.Types.SingleOrDefault(t => t.Name.Equals(typeName)); if (type == null) type = Response.Workspace.ServiceContainer.ComplexTypes.SingleOrDefault(ct => typeName.Equals(ct.Namespace + "." + ct.Name)); if (type == null) AstoriaTestLog.FailAndThrow("Could not find type '" + typeName + "'"); return type; }
protected bool EquivalentValues(NodeType firstType, PayloadProperty first, NodeType secondType, PayloadProperty second) { PayloadSimpleProperty firstSimple = first as PayloadSimpleProperty; PayloadSimpleProperty secondSimple = second as PayloadSimpleProperty; if (firstSimple == null || secondSimple == null) return false; if ((firstType == Clr.Types.Double || firstType == Clr.Types.Float)) { if (second.ParentObject.Format == SerializationFormatKind.JSON) { if (secondType == Clr.Types.Int16 || secondType == Clr.Types.Int32 || secondType == Clr.Types.Int64) { if (((long)double.Parse(firstSimple.Value)) == long.Parse(secondSimple.Value)) return true; } } } return false; }
protected void CompareDynamicPropertyValues(PayloadProperty inserted, PayloadProperty returned) { if (inserted.IsNull || returned.IsNull) { if (!inserted.IsNull) AstoriaTestLog.FailAndThrow("Null inserted value was non-null in return payload"); if (!returned.IsNull) AstoriaTestLog.FailAndThrow("Non-null inserted value was null in return payload"); } else { NodeType insertType = GetDynamicPropertyType(inserted); NodeType returnType = GetDynamicPropertyType(returned); if (inserted.MappedOutOfContent == returned.MappedOutOfContent) { bool equivalentTypes = false; if (EquivalentValues(insertType, inserted, returnType, returned)) equivalentTypes = true; if (EquivalentValues(returnType, returned, insertType, inserted)) equivalentTypes = true; if (!equivalentTypes) AstoriaTestLog.AreEqual(insertType, returnType, "Type of inserted/updated dynamic property value does not match returned type for property", false); } else if(inserted.MappedOutOfContent) { insertType = returnType; } ComparePropertyValues(insertType, inserted, returned, true); } }
private void Verify(AstoriaRequest request) { RequestVerb verb = request.EffectiveVerb; bool merge = verb == RequestVerb.Patch; PayloadObject entityBefore; if (!TryGetSingleObjectFromPayload(request.BeforeUpdatePayload, out entityBefore)) { AstoriaTestLog.FailAndThrow("Pre-update payload did not contain a single entity"); } // determine the type based on what was there (doing .Single() doesn't work for MEST, because the type shows up twice) ResourceType type = request.Workspace.ServiceContainer.ResourceTypes.First(rt => entityBefore.Type.Equals(rt.Namespace + "." + rt.Name)); PayloadObject entityAfter; if (!TryGetSingleObjectFromPayload(request.AfterUpdatePayload, out entityAfter)) { AstoriaTestLog.FailAndThrow("Post-update payload did not contain a single entity"); } CommonPayload updatePayload = request.CommonPayload; PayloadObject entityUpdate = null; if (request.URI.EndsWith("$value")) { Match match = Regex.Match(request.URI, @".*/(.+)/\$value"); if (!match.Success) { AstoriaTestLog.FailAndThrow("Could not determine property name for $value request"); } string propertyValue = null; if (request.ContentType.Equals(SerializationFormatKinds.MimeApplicationOctetStream, StringComparison.InvariantCultureIgnoreCase)) { object value = (request.UpdateTree as ResourceInstanceSimpleProperty).PropertyValue; if (updatePayload.Format == SerializationFormatKind.JSON) { propertyValue = JSONPayload.ConvertJsonValue(value); } else { AstoriaTestLog.FailAndThrow("Unsure how to fake property value"); } } else { propertyValue = request.Payload; } entityUpdate = new PayloadObject(updatePayload); PayloadSimpleProperty propertyUpdate = new PayloadSimpleProperty(entityUpdate); propertyUpdate.Name = match.Groups[1].Value; propertyUpdate.Value = propertyValue; entityUpdate.PayloadProperties.Add(propertyUpdate); merge = true; //PUT to a single property doesn't reset the resource } else if (!TryGetSingleObjectFromPayload(updatePayload, out entityUpdate)) { // must be a single property update PayloadProperty propertyUpdate = updatePayload.Resources as PayloadProperty; if (propertyUpdate == null) { AstoriaTestLog.FailAndThrow("Expected either a property or an entity in the update payload"); } entityUpdate = new PayloadObject(updatePayload); entityUpdate.PayloadProperties.Add(propertyUpdate); propertyUpdate.ParentObject = entityUpdate; merge = true; //PUT to a single property doesn't reset the resource } List <string> allPropertyNames = entityBefore.PayloadProperties .Union(entityAfter.PayloadProperties) .Union(entityUpdate.PayloadProperties) .Select(p => p.Name) .ToList(); allPropertyNames.AddRange(entityBefore.CustomEpmMappedProperties.Keys); allPropertyNames.AddRange(entityUpdate.CustomEpmMappedProperties.Keys); allPropertyNames.AddRange(entityAfter.CustomEpmMappedProperties.Keys); foreach (string propertyName in allPropertyNames.Distinct()) { PayloadProperty original = null; bool originalHadProperty = entityBefore.PayloadProperties.Any(p => (original = p).Name == propertyName); PayloadProperty update = null; bool updateHadProperty = entityUpdate.PayloadProperties.Any(p => (update = p).Name == propertyName); PayloadProperty final = null; bool finalHadProperty = entityAfter.PayloadProperties.Any(p => (final = p).Name == propertyName); if (type.Properties.Any(p => p.Name == propertyName && p.Facets.IsDeclaredProperty)) { // declared property if (!finalHadProperty) { AstoriaTestLog.FailAndThrow("Final version of entity is missing declared property '" + propertyName + "'"); } ResourceProperty property = type.Properties[propertyName] as ResourceProperty; if (property.IsNavigation) { continue; } if (!originalHadProperty) { AstoriaTestLog.FailAndThrow("Original version of entity is missing declared property '" + propertyName + "'"); } bool checkValue = property.PrimaryKey == null && !property.Facets.ServerGenerated; // if we changed it, we don't care what it was if (updateHadProperty) { ComparePropertyValues(property, update, final, checkValue); } else if (merge) { ComparePropertyValues(property, original, final, checkValue); } else if (checkValue) { CompareResetProperty(property, final); } } else { // dynamic property if (updateHadProperty) { if (!finalHadProperty) { AstoriaTestLog.FailAndThrow("Final version of entity is missing dynamic property '" + propertyName + "'"); } CompareDynamicPropertyValues(update, final); } else if (merge) { if (!finalHadProperty) { AstoriaTestLog.FailAndThrow("Final version of entity is missing dynamic property '" + propertyName + "'"); } CompareDynamicPropertyValues(original, final); } else if (finalHadProperty) { AstoriaTestLog.FailAndThrow("Dynamic property '" + propertyName + "' was not cleared after reset"); } } } }
private void CompareResetProperty(NodeProperty property, PayloadProperty value) { bool complexType = property.Type is ComplexType; Workspace w = value.ParentObject.Payload.Workspace; bool expectNull = false; if (w.DataLayerProviderKind == DataLayerProviderKind.NonClr && (!property.Facets.IsClrProperty || complexType)) { expectNull = true; } if (w.DataLayerProviderKind == DataLayerProviderKind.InMemoryLinq && complexType) { expectNull = true; } if (!property.Facets.IsDeclaredProperty) { expectNull = true; } if (property.Facets.Nullable) { expectNull = true; } if (property.Type is ComplexType) { if (value.IsNull) { if (!expectNull) { AstoriaTestLog.FailAndThrow("Complex property '" + property.Name + " is unexpectedly null after reset"); } } else { if (!(value is PayloadComplexProperty)) { AstoriaTestLog.FailAndThrow("Property '" + property.Name + "' is complex, but a simple property was found instead"); } ComplexType ct = property.Type as ComplexType; PayloadComplexProperty complexProperty = value as PayloadComplexProperty; foreach (NodeProperty subProperty in ct.Properties) { PayloadProperty subValue; if (!complexProperty.PayloadProperties.TryGetValue(subProperty.Name, out subValue)) { AstoriaTestLog.FailAndThrow("Property of complex type '" + ct.Name + "' missing sub-property '" + subProperty.Name + "'"); } CompareResetProperty(subProperty, subValue); } } } else { PayloadSimpleProperty simpleProperty = value as PayloadSimpleProperty; if (simpleProperty == null) { AstoriaTestLog.FailAndThrow("Property was unexpectedly not a simple property"); } Type propertyType = property.Type.ClrType; object expected = null; if (!expectNull) { expected = DefaultValue(propertyType); } CommonPayload.ComparePrimitiveValuesObjectAndString(expected, propertyType, simpleProperty.Value, false, value.ParentObject.Format, true); } }