private static void VerifyLinksPayload(Workspace w, CommonPayload payload, LinqQueryBuilder linqBuilder) { ArrayList expectedEntities = CommonPayload.CreateList(linqBuilder.QueryResult); if (payload == null) { AstoriaTestLog.AreEqual(expectedEntities.Count, 0, "Unexpected null $ref payload"); } else { KeyExpressions expectedKeys = new KeyExpressions(); foreach (object o in expectedEntities) { KeyExpression keyExp = w.CreateKeyExpressionFromProviderObject(o); expectedKeys.Add(keyExp); } List <string> linksFound = new List <string>(); if (payload.Resources == null) { linksFound.Add(payload.Value); } else { foreach (PayloadObject o in (payload.Resources as List <PayloadObject>)) { if (o.PayloadProperties.Any(p => p.Name == "uri")) { linksFound.Add((o["uri"] as PayloadSimpleProperty).Value); } } } AstoriaTestLog.AreEqual(expectedKeys.Count, linksFound.Count, "Number of expected entities does not match number of links found"); foreach (string link in linksFound) { KeyExpression match = null; foreach (KeyExpression expectedKey in expectedKeys) { if (compareKeyURI(link, expectedKey)) { match = expectedKey; break; } } if (match != null) { expectedKeys.Remove(match); } else { AstoriaTestLog.WriteLineIgnore("Unexpected URI: '" + link + "'"); AstoriaTestLog.FailAndThrow("Unexpected URI found in $ref payload"); } } } }
private static ResourceInstanceComplexProperty ConvertComplexPayloadObjectToComplexProperty(ResourceProperty rp, PayloadComplexProperty payloadComplexProperty) { List <ResourceInstanceProperty> properties = new List <ResourceInstanceProperty>(); foreach (ResourceProperty childProperty in (rp.Type as ComplexType).Properties.OfType <ResourceProperty>()) { if (childProperty.IsComplexType) { PayloadComplexProperty fromPayload = payloadComplexProperty.PayloadProperties[childProperty.Name] as PayloadComplexProperty; properties.Add(ConvertComplexPayloadObjectToComplexProperty(childProperty, fromPayload)); } else { PayloadSimpleProperty fromPayload = payloadComplexProperty.PayloadProperties[childProperty.Name] as PayloadSimpleProperty; if (fromPayload != null) { ResourceInstanceProperty newProperty = null; object val = CommonPayload.DeserializeStringToObject(fromPayload.Value, childProperty.Type.ClrType, false, fromPayload.ParentObject.Format); newProperty = new ResourceInstanceSimpleProperty(childProperty.Name, new NodeValue(val, childProperty.Type)); properties.Add(newProperty); } } } ComplexResourceInstance complexResourceInstance = new ComplexResourceInstance(rp.Type.Name, properties.ToArray()); return(new ResourceInstanceComplexProperty(rp.Type.Name, rp.Name, complexResourceInstance)); }
public PayloadObject(CommonPayload parent) { Payload = parent; PayloadObjects = new List <PayloadObject>(); PayloadProperties = new List <PayloadProperty>(); NamedStreams = new List <PayloadNamedStream>(); CustomEpmMappedProperties = new Dictionary <string, string>(); }
protected static bool TryGetSingleObjectFromPayload(CommonPayload payload, out PayloadObject payloadObject) { List <PayloadObject> list = payload.Resources as List <PayloadObject>; if (list == null || list.Count != 1) { payloadObject = null; return(false); } payloadObject = list[0]; return(true); }
internal static KeyedResourceInstance CreateKeyedResourceInstanceFromPayloadObject(ResourceContainer container, ResourceType resourceType, PayloadObject payloadObject) { List <ResourceInstanceProperty> properties = new List <ResourceInstanceProperty>(); List <ResourceInstanceProperty> keyProperties = new List <ResourceInstanceProperty>(); foreach (ResourceProperty property in resourceType.Properties.OfType <ResourceProperty>()) { if (property.IsNavigation) { continue; } if (property.IsComplexType) { PayloadComplexProperty fromPayload = payloadObject[property.Name] as PayloadComplexProperty; properties.Add(ConvertComplexPayloadObjectToComplexProperty(property, fromPayload)); } else { string stringValue; if (payloadObject.PayloadProperties.Any(p => p.Name == property.Name)) { PayloadSimpleProperty fromPayload = payloadObject[property.Name] as PayloadSimpleProperty; stringValue = fromPayload.Value; } else { if (!payloadObject.CustomEpmMappedProperties.TryGetValue(property.Name, out stringValue)) { stringValue = null; } } ResourceInstanceProperty newProperty = null; object val = CommonPayload.DeserializeStringToObject(stringValue, property.Type.ClrType, false, payloadObject.Format); newProperty = new ResourceInstanceSimpleProperty(property.Name, new NodeValue(val, property.Type)); if (property.PrimaryKey != null) { keyProperties.Add(newProperty); } else { properties.Add(newProperty); } } } ResourceInstanceKey key = new ResourceInstanceKey(container, resourceType, keyProperties.ToArray()); return(new KeyedResourceInstance(key, properties.ToArray())); }
public static KeyExpression ConstructKey(ResourceContainer container, PayloadObject entity) { Dictionary <string, object> properties = new Dictionary <string, object>(); ResourceType type = container.BaseType; if (entity.Type != type.Namespace + "." + type.Name) { type = container.ResourceTypes.SingleOrDefault(rt => rt.Namespace + "." + rt.Name == entity.Type); if (type == null) { AstoriaTestLog.FailAndThrow("Could not find resource type for payload type value: " + entity.Type); } } foreach (ResourceProperty property in type.Properties.OfType <ResourceProperty>()) { if (property.IsNavigation || property.IsComplexType) { continue; } string propertyName = property.Name; string valueString; if (entity.PayloadProperties.Any(p => p.Name == propertyName)) { PayloadSimpleProperty simpleProperty = entity[propertyName] as PayloadSimpleProperty; if (simpleProperty == null) { continue; } valueString = simpleProperty.Value; } else { continue; } object value = CommonPayload.DeserializeStringToObject(valueString, property.Type.ClrType, false, entity.Format); if (value is DateTime && entity.Format == SerializationFormatKind.JSON) { // TODO: this is because the server will make any JSON datetime into UTC, and currently we always send 'unspecified' values value = new DateTime(((DateTime)value).Ticks, DateTimeKind.Unspecified); } properties[propertyName] = value; } return(new KeyExpression(container, type, properties)); }
public static void VerifyLinq(Workspace workspace, ExpNode q, IQueryable results) { //verify if the results are ok before building the URI System.Collections.ArrayList list = new System.Collections.ArrayList(); foreach (object element in results) { list.Add(element); } //UriQueryBuilder ub = new UriQueryBuilder(workspace, ""); // string ruri = ub.Build(q); //System.Uri uri = new Uri(workspace.ServiceUri); // string uriRel = ruri.Substring(ruri.IndexOf("/") + 1); // AstoriaTestLog.WriteLineIgnore(uri.ToString() + uriRel); AstoriaRequest request = workspace.CreateRequest(q); request.Format = SerializationFormatKind.Atom; try { AstoriaResponse response = request.GetResponse(); //response.VerifyHttpStatusCodeOk(response.StatusCode); CommonPayload payload = response.CommonPayload; if (payload.Value != null) { payload.CompareValue(results, false, false); } else { payload.Compare(results); } //AstoriaTestLog.AreEqual(response.ContentType, SerializationFormatKinds.ContentTypeFromKind(response.OriginalRequest.SerializationKind), //"Content-Type does not match Accept header request"); } catch (Exception e) { AstoriaTestLog.FailAndContinue(e); } }
public virtual void Compare(IQueryable baseline) { System.Collections.ArrayList baseLineEntities = CommonPayload.CreateList(baseline); if (this.Resources is PayloadComplexProperty) { PayloadComplexProperty complexProperty = (PayloadComplexProperty)this.Resources; this.CompareComplexType(complexProperty, baseLineEntities[0], false); } else if (this.Resources is PayloadSimpleProperty) { PayloadSimpleProperty simpleProperty = (PayloadSimpleProperty)this.Resources; this.CompareSimpleType(simpleProperty, baseLineEntities[0], false); } else if (this.Resources is List <PayloadObject> ) { List <PayloadObject> payloadObjects = (List <PayloadObject>) this.Resources; Compare(baseLineEntities.OfType <object>().ToList(), payloadObjects, false); } }
public static void GetAndVerifyStatusCode(Workspace w, string uri, HttpStatusCode expectedStatusCode, out CommonPayload responsePayload) { AstoriaResponse response; GetAndVerifyStatusCode(w, uri, expectedStatusCode, out response); responsePayload = response.CommonPayload; }
public static void Verify(Workspace w, ExpNode q, IEnumerable results, ResourceType resType, ComplexType cType, bool bCount) { long count = 0; if (bCount) { object[] args = new object[] { results }; Type qorType = typeof(QueryOperationResponseWrapper <>).MakeGenericType(resType.ClientClrType); object qor = Activator.CreateInstance(qorType, args); PropertyInfo pi = qor.GetType().GetProperty("GetTotalCount"); object i = pi.GetValue(qor, new object[] { }); count = (long)i; LinqQueryBuilder lb = new LinqQueryBuilder(w); lb.CountingMode = true; lb.Build(q); object baselineElementsCount = CommonPayload.CreateList(lb.QueryResult).Count; AstoriaTestLog.IsTrue(count == Convert.ToInt64(baselineElementsCount), "Count is different.Count is " + count.ToString() + ". Baseline count is " + baselineElementsCount.ToString()); } LinqQueryBuilder linqBuilder = new LinqQueryBuilder(w); linqBuilder.Build(q); IQueryable baselines = linqBuilder.QueryResult; IEnumerator b = null; IEnumerator r = null; try { b = TrustedMethods.IQueryableGetEnumerator(baselines); r = results.GetEnumerator(); } catch (InvalidOperationException invalidOperation) { if (!AstoriaTestProperties.IsRemoteClient) { throw invalidOperation; } } PropertyInfo propertyInfo = null; Object expectedResult1 = null; Object expectedResult2 = null; try { while (b.MoveNext() && r.MoveNext()) { if (b.Current == null) { return; } if (r.Current == null) { throw new TestFailedException("Less results than expected"); } //skip verification for Binary data type for Linq to Sql if (AstoriaTestProperties.DataLayerProviderKinds[0] == DataLayerProviderKind.LinqToSql && b.Current is System.Byte[]) { return; } if (b.Current is System.Byte[]) { byte[] newBase = (byte[])b.Current; byte[] newAct = (byte[])r.Current; if (newBase.Length != newAct.Length) { throw new TestFailedException("Failed to compare the results!"); } } #if !ClientSKUFramework else if (b.Current is System.Data.Linq.Binary) { System.Data.Linq.Binary newBase = (System.Data.Linq.Binary)b.Current; System.Data.Linq.Binary newAct = new System.Data.Linq.Binary((byte[])r.Current); if (newBase.Length != newAct.Length) { throw new TestFailedException("Failed to compare the results!"); } } #endif else if (b.Current is System.Xml.Linq.XElement) { if (b.Current.ToString() != r.Current.ToString()) { throw new TestFailedException("Failed to compare the results!"); } } else { if (!b.Current.Equals(r.Current)) { if (cType != null) { foreach (ResourceProperty property in cType.Properties) { if (!property.IsNavigation && !property.IsComplexType && !(property.Type is CollectionType)) { propertyInfo = b.Current.GetType().GetProperty(property.Name); expectedResult1 = propertyInfo.GetValue(b.Current, null); PropertyInfo propertyInfo2 = r.Current.GetType().GetProperty(property.Name); expectedResult2 = propertyInfo2.GetValue(r.Current, null); if (expectedResult1 != expectedResult2) { if (expectedResult1 is System.Xml.Linq.XElement) { expectedResult1 = ((System.Xml.Linq.XElement)expectedResult1).ToString(System.Xml.Linq.SaveOptions.None); } if (expectedResult2 is System.Xml.Linq.XElement) { expectedResult2 = ((System.Xml.Linq.XElement)expectedResult2).ToString(System.Xml.Linq.SaveOptions.None); } #if !ClientSKUFramework if (expectedResult1 is byte[]) { expectedResult1 = new System.Data.Linq.Binary((byte[])expectedResult1); } if (expectedResult2 is byte[]) { expectedResult2 = new System.Data.Linq.Binary((byte[])expectedResult2); } #endif AstoriaTestLog.AreEqual(expectedResult1, expectedResult2, String.Format("Resource value for {0} does not match", property.Name), false); } } } } else { foreach (ResourceProperty property in resType.Properties) { if (!property.IsNavigation && !property.IsComplexType && !(property.Type is CollectionType)) { //skip verification for Binary data type for Linq to Sql if (AstoriaTestProperties.DataLayerProviderKinds[0] == DataLayerProviderKind.LinqToSql && property.Type.Name == "LinqToSqlBinary") { return; } propertyInfo = b.Current.GetType().GetProperty(property.Name); expectedResult1 = propertyInfo.GetValue(b.Current, null); PropertyInfo propertyinfo2 = r.Current.GetType().GetProperty(property.Name); expectedResult2 = propertyinfo2.GetValue(r.Current, null); if (expectedResult1 != expectedResult2) { if (expectedResult1 is System.Xml.Linq.XElement) { expectedResult1 = ((System.Xml.Linq.XElement)expectedResult1).ToString(System.Xml.Linq.SaveOptions.None); } if (expectedResult2 is System.Xml.Linq.XElement) { expectedResult2 = ((System.Xml.Linq.XElement)expectedResult2).ToString(System.Xml.Linq.SaveOptions.None); } #if !ClientSKUFramework if (expectedResult1 is byte[]) { expectedResult1 = new System.Data.Linq.Binary((byte[])expectedResult1); } if (expectedResult2 is byte[]) { expectedResult2 = new System.Data.Linq.Binary((byte[])expectedResult2); } #endif AstoriaTestLog.AreEqual(expectedResult1, expectedResult2, String.Format("Resource value for {0} does not match", property.Name), false); } } } } } } } } catch (Exception e) { AstoriaTestLog.WriteLine(e.ToString()); throw; } }
protected override void Verify() { if (!Applies(Response)) { return; } // build a common payload for the insert // CommonPayload insertPayload = Response.Request.CommonPayload; // get the entity that was inserted PayloadObject inserted; if (!TryGetSingleObjectFromPayload(insertPayload, out inserted)) { ResponseVerification.LogFailure(Response, new Exception("Insert request payload did not contain a single entity")); } // determine the type based on what was inserted ResourceType type = Response.Workspace.ServiceContainer.ResourceTypes.Single(rt => inserted.Type.Equals(rt.Namespace + "." + rt.Name)); // get the entity that was returned PayloadObject returned; if (!TryGetSingleObjectFromPayload(Response.CommonPayload, out returned)) { if (Versioning.Server.SupportsLiveFeatures) { string preferHeader; if (Response.Request.Headers.TryGetValue("prefer", out preferHeader) && preferHeader == "return=minimal") { return; } } ResponseVerification.LogFailure(Response, new Exception("Insert response payload did not contain a single entity")); } // verify that the inserted and returned entities are equivalent VerifyInsertResponse(type, inserted, returned); // re-query the entity Workspace workspace = Response.Workspace; AstoriaRequest queryRequest = workspace.CreateRequest(); if (type.Properties.Any(p => p.Facets.ConcurrencyModeFixed)) { queryRequest.ETagHeaderExpected = true; } if (type.Key.Properties.Any(p => p.Type == Clr.Types.DateTime)) { // this will blow up for MEST, but we don't currently have any datetime key + MEST types ResourceContainer container = Response.Workspace.ServiceContainer.ResourceContainers.Single(rc => !(rc is ServiceOperation) && rc.ResourceTypes.Contains(type)); queryRequest.Query = ContainmentUtil.BuildCanonicalQuery(ConcurrencyUtil.ConstructKey(container, returned)); } else { queryRequest.URI = Uri.UnescapeDataString(returned.AbsoluteUri); if (queryRequest.URI.Contains("E+")) { queryRequest.URI = queryRequest.URI.Replace("E+", "E"); } if (queryRequest.URI.Contains("e+")) { queryRequest.URI = queryRequest.URI.Replace("e+", "e"); } } AstoriaResponse queryResponse = queryRequest.GetResponse(); if (queryResponse.ActualStatusCode == HttpStatusCode.BadRequest) { // try it as a filter instead (possibly caused by the URI being too long) // this will blow up for MEST ResourceContainer container = Response.Workspace.ServiceContainer.ResourceContainers .Single(rc => !(rc is ServiceOperation) && rc.ResourceTypes.Contains(type)); KeyExpression key = ConcurrencyUtil.ConstructKey(container, returned); queryRequest = workspace.CreateRequest(Query.From(Exp.Variable(container)).Where(key.Predicate)); queryResponse = queryRequest.GetResponse(); } queryResponse.Verify(); // get the entity from the query PayloadObject queried; if (!TryGetSingleObjectFromPayload(queryResponse.CommonPayload, out queried)) { ResponseVerification.LogFailure(queryResponse, new Exception("Query response payload did not contain a single entity")); } // ensure that the entity did not change between the insert and the re-query VerifyQueryResponse(type, returned, queried); }
public static void ValidateCountException(AstoriaResponse response, AstoriaRequest request, TestFailedException tfe) { // Errors are expected for older versions. if (!Versioning.Server.SupportsV2Features) { if (request.URI.Contains("$inlinecount=allpages")) { // Query parameter not recognized. if (response.ActualStatusCode == System.Net.HttpStatusCode.BadRequest) { return; } } //anything other than http 404 or 400 is an invalid status code for a count query else if ( response.ActualStatusCode != System.Net.HttpStatusCode.BadRequest || response.ActualStatusCode != System.Net.HttpStatusCode.NotFound) { throw tfe; } else { // Resource segment $count not found. if (response.ActualStatusCode == System.Net.HttpStatusCode.NotFound || response.ActualStatusCode == System.Net.HttpStatusCode.BadRequest) { return; } } } LinqQueryBuilder linqBuilder = new LinqQueryBuilder(request.Workspace); linqBuilder.CountingMode = request.URI.Contains("$inlinecount=allpages"); try { linqBuilder.Build(request.Query); } catch (KeyNotFoundException kfe) { if (!AstoriaTestProperties.DataLayerProviderKinds.Contains(DataLayerProviderKind.NonClr)) { throw kfe; } } bool isInvalidError = true; if (response.ActualStatusCode == System.Net.HttpStatusCode.NotFound) { if (request.Query.Input is CountExpression) { ExpNode internalQuery = ((CountExpression)request.Query.Input).ScanNode; if (internalQuery is KeyExpression || internalQuery is PredicateExpression) { isInvalidError = false; } } if (isInvalidError) { if (CommonPayload.CreateList(linqBuilder.QueryResult).Count == 0) { isInvalidError = false; } } } if (response.ActualStatusCode == System.Net.HttpStatusCode.BadRequest) { if (request.Query.Input is CountExpression) { ExpNode internalQuery = ((CountExpression)request.Query.Input).ScanNode; if (internalQuery is KeyExpression || internalQuery is PredicateExpression) { isInvalidError = false; } } else if (request.Query.Input is KeyExpression) { isInvalidError = false; } } if (isInvalidError) { throw tfe; } }
public static void VerifyGet(AstoriaResponse response) { AstoriaRequest request = response.Request; if (request.Query != null) { LinqQueryBuilder linqBuilder = new LinqQueryBuilder(request.Workspace); linqBuilder.Build(request.Query); if (request.URI.Contains("$value")) { CommonPayload payload; // $value queries will sometimes return unexpected 404s due to null values // if we get a 404 unexpectedly, the underlying result must be null if (response.ActualStatusCode == System.Net.HttpStatusCode.NotFound) { payload = request.CommonPayload; } IEnumerable enumerable = linqBuilder.QueryResult; object expectedResult = CommonPayload.GetSingleValueFromIQueryable(linqBuilder.QueryResult, false); ResourceProperty rp = request.GetPropertyFromQuery(); CommonPayload.ComparePrimitiveValuesObjectAndString(expectedResult, rp.Type.ClrType, response.Payload, true, request.Format, false); } else if (request.URI.Contains("$count") || request.URI.Contains("$inlinecount")) { if (request.URI.Contains("$count")) { // Versioning: make sure the server always returns 2.0. VerifySpecificResponseVersion(response, 2, 0); // PlainText payload. try { VerifyStatusCode(response); if (response.Request.ExpectedStatusCode == System.Net.HttpStatusCode.OK) { int countPayload = Int32.Parse(response.Payload); int countBaseline = CommonPayload.CreateList(linqBuilder.QueryResult).Count; AstoriaTestLog.AreEqual(countPayload, countBaseline, "Counts in payload (" + countPayload + ") and baseline (" + countBaseline + ") differ."); } } catch (TestFailedException tfe) { //When the underlying resource has zero elements, the server now throws a 404 error , causing false negatives ValidateCountException(response, request, tfe); } } else { VerifySpecificResponseVersion(response, 2, 0); try { // JSON, Atom or PlainXml ($ref) payload. VerifyStatusCode(response); if (response.Request.ExpectedStatusCode == System.Net.HttpStatusCode.OK) { CommonPayload payload = response.CommonPayload; LinqQueryBuilder baselineLinqBuilder = new LinqQueryBuilder(request.Workspace); baselineLinqBuilder.CountingMode = true; baselineLinqBuilder.Build(request.Query); object baselineElementsCount = CommonPayload.CreateList(baselineLinqBuilder.QueryResult).Count; payload.CompareCountInline(linqBuilder.QueryResult, baselineElementsCount); AstoriaTestLog.WriteLine(linqBuilder.QueryExpression); if (request.URI.Contains("$ref")) { VerifyLinksPayload(request.Workspace, payload, linqBuilder); } } } catch (TestFailedException tfe) { //When the underlying resource has zero elements, the server now throws a 404 error , causing false negatives ValidateCountException(response, request, tfe); } } } else { if (response.ActualStatusCode == System.Net.HttpStatusCode.NoContent && response.Payload == "") { response.Payload = null; // allow result from Linq query and payload to be compared (NoContent is a get to a null Nav prop) } if (response.ActualStatusCode == System.Net.HttpStatusCode.NotFound) { return; } CommonPayload payload = response.CommonPayload; if (request.URI.Contains("$ref")) { VerifyLinksPayload(request.Workspace, payload, linqBuilder); } else if (payload.Resources == null) { if (request.Format == SerializationFormatKind.JSON) { payload.CompareValue(linqBuilder.QueryResult, true, false); } else { payload.CompareValue(linqBuilder.QueryResult, false, false); } } else { payload.Compare(linqBuilder.QueryResult); } } } }
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); } } }
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); } }