/// <summary> /// Implements IDataInserter.AddEntity by creating a POST-based insert request and adding it to the batch queue /// </summary> /// <param name="key">Key expression for new entity</param> /// <param name="entity">Update tree for new entity</param> public void AddEntity(KeyExpression key, KeyedResourceInstance entity) { // build the request // ExpNode containerQuery = ContainmentUtil.BuildCanonicalQuery(key, true); AstoriaRequest request = workspace.CreateRequest(containerQuery, entity, RequestVerb.Post); // set ETagHeaderExpected appropriately if (key.ResourceType.Properties.Any(p => p.Facets.ConcurrencyModeFixed)) { request.ETagHeaderExpected = true; } // add it to the queue // queue.Add(request); // store the content-id // contentIDMap[entity] = request.Headers["Content-ID"]; // fire the event // if (this.OnAddingEntity != null) { OnAddingEntity(key, entity); } }
//--------------------------------------------------------------------- // Constructs AstoriaRequest and sets. //--------------------------------------------------------------------- private BlobsRequest(Workspace w, SerializationFormatKind format, RequestVerb verb, string uri, HttpStatusCode expectedStatusCode) : base(w) { // Common settings for MLEs and MRs. base.IsBlobRequest = true; base.Verb = verb; base.ExpectedStatusCode = expectedStatusCode; // Construct request URI. if (uri.Contains("(*)")) { // Replace (*) with random key. string relativeURI = uri.Remove(0, w.ServiceUri.Length + 1); ResourceContainer container = w.ServiceContainer.ResourceContainers[relativeURI.Substring(0, relativeURI.IndexOf("(*)"))]; KeyExpression key = null; try { key = w.GetRandomExistingKey(container, container.BaseType); } catch (Exception e) { AstoriaTestLog.Skip("Unable to get random key"); } base.Query = ContainmentUtil.BuildCanonicalQuery(key); base.URI += relativeURI.Substring(relativeURI.IndexOf("(*)") + 3); } else { // Deterministic URI. base.URI = uri; } LastURI = base.URI; }
public static AstoriaRequest BuildGet(Workspace workspace, KeyExpression key, HttpStatusCode expectedStatusCode, SerializationFormatKind format) { QueryNode query = ContainmentUtil.BuildCanonicalQuery(key); string keyString = UriQueryBuilder.CreateKeyString(key, false); if ((expectedStatusCode == System.Net.HttpStatusCode.OK) && (keyString.Contains("/") || keyString.Contains(Uri.EscapeDataString("/")))) { expectedStatusCode = System.Net.HttpStatusCode.BadRequest; } return(BuildGet(workspace, query, expectedStatusCode, format)); }
public static AstoriaRequest BuildInsert(Workspace workspace, ResourceContainer container, ResourceType type, HttpStatusCode expectedStatusCode, SerializationFormatKind format, out KeyExpression createdKey) { KeyedResourceInstance newResource = type.CreateRandomResource(container); if (newResource == null) { newResource = ResourceInstanceUtil.CreateKeyedResourceInstanceByClone(container, type); if (newResource == null) { createdKey = null; return(null); } } QueryNode query; if (!type.Key.Properties.Any(p => p.Facets.ServerGenerated) && newResource.ResourceInstanceKey != null) { createdKey = newResource.ResourceInstanceKey.CreateKeyExpression(container, type); query = ContainmentUtil.BuildCanonicalQuery(createdKey, true); } else { createdKey = null; // the key is unknown, must be server generated // in this case, lets hope that containment is a non-issue query = Query.From(Exp.Variable(container)) .Select(); if (!container.Facets.TopLevelAccess && expectedStatusCode == HttpStatusCode.Created) { expectedStatusCode = HttpStatusCode.BadRequest; } } AstoriaRequest request = workspace.CreateRequest(); request.Verb = RequestVerb.Post; request.Query = query; request.UpdateTree = newResource; request.ExpectedStatusCode = expectedStatusCode; request.Format = format; return(request); }
public static AstoriaRequest BuildDelete(Workspace workspace, KeyExpression toDelete, HttpStatusCode expectedStatusCode, SerializationFormatKind format) { QueryNode query = ContainmentUtil.BuildCanonicalQuery(toDelete); AstoriaRequest request = workspace.CreateRequest(); request.Verb = RequestVerb.Delete; request.Query = query; request.Format = format; request.ExpectedStatusCode = expectedStatusCode; if (toDelete.ResourceType.Properties.Any(p => p.Facets.ConcurrencyModeFixed)) { request.Headers[ConcurrencyUtil.IfMatchHeader] = toDelete.ETag; } return(request); }
protected string CreateCanonicalUri(ResourceInstanceKey key) { UriQueryBuilder builder = new UriQueryBuilder(Workspace, Workspace.ServiceUri); builder.UseBinaryFormatForDates = false; builder.CleanUpSpecialCharacters = false; KeyExpression keyExpression = ResourceInstanceUtil.ConvertToKeyExpression(key, Workspace); if (keyExpression != null) { QueryNode query = ContainmentUtil.BuildCanonicalQuery(keyExpression); return(builder.Build(query)); } IEnumerable <ResourceInstanceSimpleProperty> properties = key.KeyProperties.OfType <ResourceInstanceSimpleProperty>(); string keyString = builder.CreateKeyString(properties.Select(p => p.Name).ToArray(), properties.Select(p => p.PropertyValue).ToArray()); string uri = Workspace.ServiceUri + "/" + key.ResourceSetName + "(" + keyString + ")"; return(uri); }
public static AstoriaRequest BuildUpdate(Workspace workspace, KeyExpression modifiedKey, bool replace, HttpStatusCode expectedStatusCode, SerializationFormatKind format) { if (modifiedKey == null) { return(null); } ResourceContainer container = modifiedKey.ResourceContainer; ResourceType resourceType = modifiedKey.ResourceType; if (replace && resourceType.Properties.Any(p => p.Facets.IsIdentity)) { return(null); } string keyString = UriQueryBuilder.CreateKeyString(modifiedKey, false); if (expectedStatusCode == HttpStatusCode.NoContent && (keyString.Contains("/") || keyString.Contains(Uri.EscapeDataString("/")))) { expectedStatusCode = HttpStatusCode.BadRequest; } QueryNode query = ContainmentUtil.BuildCanonicalQuery(modifiedKey); List <ResourceInstanceProperty> properties = new List <ResourceInstanceProperty>(); string[] propertiesToSkip; //Skip because setting the birthdate to a random Datetime won't work due to contraints //if (resourceType.Name == "Employees") // propertiesToSkip = new string[] { "BirthDate" }; ////Skipping because it has some weird constraint on it //else if (resourceType.Name == "Order_Details") // propertiesToSkip = new string[] { "Discount" }; //else // propertiesToSkip = new string[] { }; foreach (ResourceProperty resourceProperty in resourceType.Properties.OfType <ResourceProperty>() .Where(p => !p.IsNavigation && p.PrimaryKey == null && !p.Facets.IsIdentity)) //&& !p.IsComplexType //&& !propertiesToSkip.Contains(p.Name))) { properties.Add(resourceProperty.CreateRandomResourceInstanceProperty()); } if (!properties.Any()) { return(null); } KeyedResourceInstance resourceInstance = new KeyedResourceInstance( ResourceInstanceKey.ConstructResourceInstanceKey(modifiedKey), properties.ToArray()); AstoriaRequest request = workspace.CreateRequest(); request.Verb = replace ? RequestVerb.Put : RequestVerb.Patch; request.Query = query; request.UpdateTree = resourceInstance; request.ExpectedStatusCode = expectedStatusCode; request.Format = format; if (modifiedKey.ResourceType.Properties.Any(p => p.Facets.ConcurrencyModeFixed)) { request.Headers[ConcurrencyUtil.IfMatchHeader] = modifiedKey.ETag; request.ETagHeaderExpected = true; } return(request); }
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); }
private static bool compareKeyURI(string uriFound, KeyExpression keyExpected) { UriQueryBuilder builder = new UriQueryBuilder(keyExpected.ResourceContainer.Workspace, keyExpected.ResourceContainer.Workspace.ServiceUri); builder.EscapeUriValues = true; builder.CleanUpSpecialCharacters = false; builder.UseBinaryFormatForDates = false; switch (keyExpected.IncludeInUri.Count(i => i)) { case 0: AstoriaTestLog.FailAndThrow("Cannot compare KeyExpression to URI, key has no included values"); return(false); case 1: // TODO: stop ignoring case QueryNode query = ContainmentUtil.BuildCanonicalQuery(keyExpected); string expected = builder.Build(query); expected = expected.Replace(".0f", "f"); //this is kinda a hack, but TypeData.FormatForKey is going to add the .0, so we need to remove it expected = expected.Replace(".0D", "D"); //this is kinda a hack, but TypeData.FormatForKey is going to add the .0, so we need to remove it bool match = uriFound.Equals(expected, StringComparison.InvariantCultureIgnoreCase); if (!match) { AstoriaTestLog.WriteLineIgnore("Link did not match key, expected '" + expected + "'"); } return(match); default: QueryNode setQuery = ContainmentUtil.BuildCanonicalQuery(keyExpected, true); Workspace w = keyExpected.ResourceContainer.Workspace; string setUri = builder.Build(setQuery); string keySegment = uriFound.Substring(setUri.Length); string expectedKeySegment = "(" + UriQueryBuilder.CreateKeyString(keyExpected, false) + ")"; if (keySegment.Equals(expectedKeySegment, StringComparison.InvariantCultureIgnoreCase)) { return(true); } // if not explicitely equal, need to make sure its not due to a re-ordering of the properties // List <KeyValuePair <string, int> > predicateLocations = new List <KeyValuePair <string, int> >(); for (int i = 0; i < keyExpected.Values.Length; i++) { string predicate = builder.CreateKeyStringPair(keyExpected.Properties[i].Name, keyExpected.Values[i].ClrValue); int offset = keySegment.IndexOf(predicate); if (offset < 0) { return(false); } predicateLocations.Add(new KeyValuePair <string, int>(predicate, offset)); } predicateLocations.Sort(delegate(KeyValuePair <string, int> pair1, KeyValuePair <string, int> pair2) { return(pair1.Value.CompareTo(pair2.Value)); }); expectedKeySegment = "(" + String.Join(",", predicateLocations.Select(pair => pair.Key).ToArray()) + ")"; return(keySegment.Equals(expectedKeySegment, StringComparison.InvariantCultureIgnoreCase)); } }