public AstoriaResponse SendRequest(AstoriaRequest request) { AstoriaResponse response; SendRequest(request, out response); return(response); }
public static void DefaultVerify(AstoriaResponse response) { // special case for ETags if (response.ActualStatusCode == System.Net.HttpStatusCode.NotModified) { return; } AstoriaRequest request = response.Request; RequestVerb verb = request.EffectiveVerb; switch (verb) { case RequestVerb.Get: VerifyGet(response); break; case RequestVerb.Post: case RequestVerb.Patch: case RequestVerb.Put: case RequestVerb.Delete: // other verbs now handled by default elsewhere break; default: VerifyUnknownVerb(response); break; } }
public void Add(AstoriaRequest request) { if (currentBatch == null) { currentBatch = new BatchRequest(request.Workspace); } if (request.Verb == RequestVerb.Get) { currentBatch.Add(request); } else { if (currentChangeset == null) { currentChangeset = currentBatch.GetChangeset(); } currentChangeset.Add(request); } if (currentBatch.TotalRequests >= Size && AutoSubmit) { Finish(); } }
/// <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); } }
public static void GetAndVerifyStatusCode(Workspace w, QueryNode query) { AstoriaRequest request = w.CreateRequest(query); AstoriaResponse response = request.GetResponse(); ResponseVerification.VerifyStatusCode(response); }
public void VerifyServer(ExpNode q) { AstoriaTestLog.WriteLineIgnore("Verify server query"); try { UriQueryBuilder ub = new UriQueryBuilder(_workspace, ""); string ruri = ub.Build(q); AstoriaTestLog.WriteLineIgnore(ruri); AstoriaRequest request = _workspace.CreateRequest(q); request.Format = _kind; if (request.URI.Length > 260) { return; } AstoriaResponse response = request.GetResponse(); response.Verify(); } catch (Exception e) { AstoriaTestLog.WriteLineIgnore(e.ToString()); } }
protected override void Verify() { if (!Applies(Response)) { return; } AstoriaRequest request = Response.Request; if (!request.SnapshotForUpdate) { return; } try { Verify(request); } catch (Exception e) { AstoriaTestLog.WriteLineIgnore("Pre-update snapshot:"); AstoriaTestLog.WriteLineIgnore(request.BeforeUpdatePayload.RawPayload); AstoriaTestLog.WriteLineIgnore("--------------------"); AstoriaTestLog.WriteLineIgnore("Post-update snapshot:"); AstoriaTestLog.WriteLineIgnore(request.AfterUpdatePayload.RawPayload); throw new TestFailedException("Update verification failed", null, null, e); } }
public static void GetAndVerifyStatusCode(Workspace w, string uri, HttpStatusCode expectedStatusCode, out AstoriaResponse response, WebHeaderCollection requestHeaders) { AstoriaRequest request = w.CreateRequest(); request.URI = uri; request.ExpectedStatusCode = expectedStatusCode; request.Accept = "*/*"; if (requestHeaders != null) { foreach (string header in requestHeaders.AllKeys) { request.Headers[header] = requestHeaders[header]; } } response = request.GetResponse(); try { ResponseVerification.VerifyStatusCode(response); } catch (Exception e) { ResponseVerification.LogFailure(response, e); } }
protected override void Verify() { if (!Applies(Response)) { return; } AstoriaRequest request = Response.Request; ResourceProperty property = request.GetPropertyFromQuery(); if (property == null) { RequestUtil.GetAndVerifyStatusCode(Response.Workspace, request.URI, System.Net.HttpStatusCode.NotFound); } else { if (property.IsNavigation && property.OtherAssociationEnd.Multiplicity != Multiplicity.One) { RequestUtil.GetAndVerifyStatusCode(Response.Workspace, request.URI, System.Net.HttpStatusCode.NoContent); } else { // TODO: is this always right if its not a nav prop? RequestUtil.GetAndVerifyStatusCode(Response.Workspace, request.URI, System.Net.HttpStatusCode.NotFound); } } }
public static void WriteBatchRequestFragment(AstoriaRequest request, StringWriter writer) { // assume boundary has been written //Content-Type: application/http //Content-Transfer-Encoding:binary writer.WriteLine("Content-Type: " + RequestUtil.RandomizeContentTypeCapitalization("application/http")); writer.WriteLine("Content-Transfer-Encoding:binary"); writer.WriteLine(); //GET {uri} HTTP/1.1 //Content-Type: application/atom+xml;type=entry //Content-Length: ### string uri; if(request.UseRelativeUri) uri = request.RelativeUri; else uri = request.URI; writer.WriteLine("{0} {1} HTTP/1.1", request.Verb.ToString().ToUpper(), Uri.EscapeUriString(uri)); foreach (KeyValuePair<string, string> header in request.Headers) writer.WriteLine("{0}: {1}", header.Key, header.Value); writer.WriteLine(); if(request.Payload != null) writer.WriteLine(request.Payload); }
public AstoriaRequest EntitySetServiceOp(string serviceOpName) { AstoriaRequest request = _workspace.CreateRequest(); request.URI += serviceOpName; return(request); }
public AstoriaRequest MakeMergeRequest(AstoriaRequest request, KeyedResourceInstance resourceInstance) { request.Verb = RequestVerb.Patch; request.ContentType = "application/atom+xml"; request.UpdateTree = resourceInstance; return(request); }
// ServiceRoot public AstoriaRequest ServiceRoot() { AstoriaRequest request = _workspace.CreateRequest(); request.Accept = "*/*"; return(request); }
public void Add(AstoriaRequest request, string contentID, bool includeIfNull) { if (includeIfNull || contentID != null) { request.Headers["Content-ID"] = contentID; } request.Batched = true; _requests.Add(request); }
// Metadata public AstoriaRequest Metadata() { AstoriaRequest request = _workspace.CreateRequest(); request.URI += "/$metadata"; request.Accept = "*/*"; return(request); }
public static BatchResponse ParseBatchResponse(BatchRequest batchRequest, StringReader reader, string boundary) { // even if content-id is specified, we may not get it back in error cases. This doesn't feel entirely correct, it seems like there should // always be a 1-1 mapping that explicitly honors content-id's // TODO: responses / requests without content IDs should be matched up in order within changeset only // changesets should have the right number of responses too BatchResponse response = null;// new BatchResponse(batchRequest); List <ResponseFragment> unmatchedFragments = new List <ResponseFragment>(); List <AstoriaRequest> unmatchedRequests = batchRequest.Requests .Union(batchRequest.Changesets.SelectMany(changeset => changeset.AsEnumerable())) .ToList(); foreach (ResponseFragment fragment in ParseBatchResponse(reader, boundary)) { AstoriaRequest request = null; if (fragment.ContentID != null) { request = unmatchedRequests .FirstOrDefault(r => r.Headers.ContainsKey("Content-ID") && r.Headers["Content-ID"].Equals(fragment.ContentID)); } if (request == null) { unmatchedFragments.Add(fragment); } else { unmatchedRequests.Remove(request); response.Responses.Add(FragmentToResponse(request, fragment)); } } if (unmatchedFragments.Any()) { if (unmatchedFragments.Count < unmatchedRequests.Count) { AstoriaTestLog.WriteLine("Warning: recieved fewer batch response fragments than expected"); } else if (unmatchedFragments.Count > unmatchedRequests.Count) { AstoriaTestLog.FailAndThrow("Recieved more batch fragments than expected"); } for (int i = 0; i < unmatchedFragments.Count; i++) { response.Responses.Add(FragmentToResponse(unmatchedRequests[i], unmatchedFragments[i])); } } return(response); }
public AstoriaRequest EntitySetServiceOp(out ResourceContainer container) { container = _workspace.ServiceContainer.ResourceContainers.Choose(); AstoriaRequest request = _workspace.CreateRequest(); request.URI += "Get" + container.Name; return(request); }
public static AstoriaRequest BuildGet(Workspace workspace, QueryNode query, HttpStatusCode expectedStatusCode, SerializationFormatKind format) { AstoriaRequest request = workspace.CreateRequest(); request.Verb = RequestVerb.Get; request.Query = query; request.ExpectedStatusCode = expectedStatusCode; request.Format = format; return(request); }
public static void SetDefaultHost(AstoriaRequest request) { Uri rootUri = request.Workspace.ServiceRoot; string host = rootUri.Scheme + "://" + rootUri.Host; if (!rootUri.IsDefaultPort) { host += ":" + rootUri.Port; } request.Host = host; }
public static CommonPayload CreateCommonPayload(AstoriaRequest request, string responsePayload) { if (request == null) { throw new ArgumentNullException("request"); } AstoriaResponse response = new AstoriaResponse(request); response.Payload = responsePayload; return(CreateCommonPayload(response)); }
private static AstoriaResponse FragmentToResponse(AstoriaRequest request, ResponseFragment fragment) { AstoriaResponse response = new AstoriaResponse(request); response.Payload = fragment.Payload; response.ContentType = fragment.ContentType; response.ActualStatusCode = fragment.StatusCode; response.ETagHeaderFound = false; foreach (var header in fragment.Headers) { if (header.Key == "ETag") response.ETagHeaderFound = true; response.Headers[header.Key] = header.Value; } return response; }
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 void SendRequest(AstoriaRequest request, out AstoriaResponse response) { // doing it this way so the compiler knows that response got initialized if (!SendRequest_Internal(request, out response)) { bool valid = false; for (int retry = 0; retry < 4; retry++) { valid = SendRequest_Internal(request, out response); if (valid) break; } if (!valid) throw new Microsoft.Test.ModuleCore.TestFailedException("Could not get a valid response despite retrying"); } }
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); }
private static AstoriaResponse FragmentToResponse(AstoriaRequest request, ResponseFragment fragment) { AstoriaResponse response = new AstoriaResponse(request); response.Payload = fragment.Payload; response.ContentType = fragment.ContentType; response.ActualStatusCode = fragment.StatusCode; response.ETagHeaderFound = false; foreach (var header in fragment.Headers) { if (header.Key == "ETag") { response.ETagHeaderFound = true; } response.Headers[header.Key] = header.Value; } return(response); }
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 void Add(AstoriaRequest request) { if (currentBatch == null) currentBatch = new BatchRequest(request.Workspace); if (request.Verb == RequestVerb.Get) { currentBatch.Add(request); } else { if (currentChangeset == null) currentChangeset = currentBatch.GetChangeset(); currentChangeset.Add(request); } if (currentBatch.TotalRequests >= Size && AutoSubmit) Finish(); }
public void SendRequest(AstoriaRequest request, out AstoriaResponse response) { // doing it this way so the compiler knows that response got initialized if (!SendRequest_Internal(request, out response)) { bool valid = false; for (int retry = 0; retry < 4; retry++) { valid = SendRequest_Internal(request, out response); if (valid) { break; } } if (!valid) { throw new Microsoft.Test.ModuleCore.TestFailedException("Could not get a valid response despite retrying"); } } }
/// <summary> /// Implements IDataInserter.AddAssociation by creating a PUT/POST $ref request using cross-referencing, and adds it to the batch /// </summary> /// <param name="parent">Update tree of parent, must have already been added using AddEntity</param> /// <param name="property">Navigation property for the association</param> /// <param name="child">Update tree of child, must have already been added using AddEntity</param> public void AddAssociation(KeyedResourceInstance parent, ResourceProperty property, KeyedResourceInstance child) { // determine which verb to use // RequestVerb verb; if (property.OtherAssociationEnd.Multiplicity == Multiplicity.Many) { verb = RequestVerb.Post; } else { verb = RequestVerb.Put; } // create the request // AstoriaRequest request = workspace.CreateRequest(); request.Verb = verb; // use content-id cross referencing to link them // string parentContentId = contentIDMap[parent]; string childContentId = contentIDMap[child]; request.URI = "$" + parentContentId + "/" + property.Name + "/$ref"; request.Payload = "<adsm:uri xmlns:adsm=\"http://docs.oasis-open.org/odata/ns/metadata\">$" + childContentId + "</adsm:uri>"; // add it to the queue // queue.Add(request); // fire the event // if (this.OnAddingAssociation != null) { OnAddingAssociation(parent, property, child); } }
public static void WriteBatchRequestFragment(AstoriaRequest request, StringWriter writer) { // assume boundary has been written //Content-Type: application/http //Content-Transfer-Encoding:binary writer.WriteLine("Content-Type: " + RequestUtil.RandomizeContentTypeCapitalization("application/http")); writer.WriteLine("Content-Transfer-Encoding:binary"); writer.WriteLine(); //GET {uri} HTTP/1.1 //Content-Type: application/atom+xml;type=entry //Content-Length: ### string uri; if (request.UseRelativeUri) { uri = request.RelativeUri; } else { uri = request.URI; } writer.WriteLine("{0} {1} HTTP/1.1", request.Verb.ToString().ToUpper(), Uri.EscapeUriString(uri)); foreach (KeyValuePair <string, string> header in request.Headers) { writer.WriteLine("{0}: {1}", header.Key, header.Value); } writer.WriteLine(); if (request.Payload != null) { writer.WriteLine(request.Payload); } }
public AstoriaRequest MakeMergeRequest(AstoriaRequest request, KeyedResourceInstance resourceInstance) { request.Verb = RequestVerb.Patch; request.ContentType = "application/atom+xml"; request.UpdateTree = resourceInstance; return request; }
internal AstoriaResponse(AstoriaRequest originalRequest) : base(originalRequest.Workspace) { Request = originalRequest; }
public AstoriaRequest MakeDeleteRequest(AstoriaRequest request) { request.Verb = RequestVerb.Delete; return(request); }
public static AstoriaRequest BuildRandomRequest(Workspace workspace, RequestVerb verb, SerializationFormatKind format) { IEnumerable <ResourceContainer> safeContainers = workspace.ServiceContainer.ResourceContainers .Where(c => IsSafeOperation(verb, c)); if (verb != RequestVerb.Get) { safeContainers = safeContainers.Where(c => c.ResourceTypes.Any(t => IsSafeOperation(verb, c, t))); } fxList <ResourceContainer> containers = new fxList <ResourceContainer>(safeContainers); if (!containers.Any()) { return(null); } AstoriaRequest request = null; while (request == null && containers.Any()) { ResourceContainer container = null; ResourceType type = null; KeyExpression key = null; while (container == null && containers.Any()) { container = containers.Choose(); if (verb == RequestVerb.Get) { key = workspace.GetRandomExistingKey(container); if (key == null) { containers.Remove(container); container = null; } } else { fxList <ResourceType> types = new fxList <ResourceType>(container.ResourceTypes.Where(t => IsSafeOperation(verb, container, t))); if (!types.Any()) { containers.Remove(container); container = null; } if (verb != RequestVerb.Delete) { type = types.Choose(); } else { while (key == null && types.Any()) { type = types.Choose(); key = workspace.GetRandomExistingKey(container, type); if (key == null) { types.Remove(type); } } if (key == null) { containers.Remove(container); container = null; } } } } // if we ran out of containers before finding one that would work // if (container == null) { return(null); } // if the Build___ method returns null, we'll come back around with a different container/key // switch (verb) { case RequestVerb.Get: request = BuildGet(workspace, key, HttpStatusCode.OK, format); break; case RequestVerb.Post: request = BuildInsert(workspace, container, type, HttpStatusCode.Created, format); break; case RequestVerb.Put: case RequestVerb.Patch: request = BuildUpdate(workspace, container, type, (verb == RequestVerb.Put), HttpStatusCode.NoContent, format); break; case RequestVerb.Delete: request = BuildDelete(workspace, key, HttpStatusCode.NoContent, format); break; default: throw new ArgumentException("Unsupported verb: " + verb.ToString()); } } // might be null, but we did our best // return(request); }
public static void SetDefaultHost(AstoriaRequest request) { Uri rootUri = request.Workspace.ServiceRoot; string host = rootUri.Scheme + "://" + rootUri.Host; if (!rootUri.IsDefaultPort) host += ":" + rootUri.Port; request.Host = host; }
public override void PrepareRequest(AstoriaRequest request) { request.ExtraVerification += ResponseVerification.DefaultVerify; }
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 AstoriaRequest CreateRequest(ExpNode query, ResourceBodyTree updateTree, RequestVerb operation) { AstoriaRequest request = new AstoriaRequest(this); request.Verb = operation; request.Query = query as QueryNode; request.UpdateTree = updateTree; PrepareRequest(request); return request; }
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); }
public override void PrepareRequest(AstoriaRequest request) { // do nothing, test cases will handle verification }
public virtual void PrepareRequest(AstoriaRequest request) { // do nothing (to be overridden in derived workspace classes) }
public AstoriaResponse SendRequest(AstoriaRequest request) { AstoriaResponse response; SendRequest(request, out response); return response; }
protected override sealed bool SendRequest_Internal(AstoriaRequest request, out AstoriaResponse response) { HttpWebRequest underlyingRequest = (HttpWebRequest)HttpWebRequest.Create(request.URI); WebResponse underlyingResponse; #region set up request // workaround: Protocol Violation in HttpWebRequest when receiving an immediate error response from server before sending request body // ideally, we would only flip this to false if we knew the request would have an error, // but we can't reliably tell at this point if (AstoriaTestProperties.Host == Host.IDSH || AstoriaTestProperties.Host == Host.IDSH2) { if (Environment.OSVersion.Version.Major < 6 || Environment.OSVersion.Version.Minor < 1) underlyingRequest.ServicePoint.Expect100Continue = false; } underlyingRequest.UseDefaultCredentials = AstoriaTestProperties.HostAuthenicationMethod.Equals("Windows", StringComparison.InvariantCultureIgnoreCase); underlyingRequest.Method = request.Verb.ToHttpMethod(); underlyingRequest.Accept = request.Accept; underlyingRequest.ContentType = request.ContentType; foreach (KeyValuePair<string, string> header in request.Headers) { switch (header.Key) { case "Accept": case "Content-Type": break; default: underlyingRequest.Headers.Add(header.Key, header.Value); break; } } underlyingRequest.ContentLength = 0; byte[] bytes = request.PayloadBytes; if (bytes != null) { underlyingRequest.ContentLength = bytes.Length; try { using (Stream os = underlyingRequest.GetRequestStream()) { os.Write(bytes, 0, bytes.Length); } } catch (WebException ex) { HandleWebException(ex, out underlyingResponse); response = null; return false; } } else if (request.HttpStreamWriter != null) { // Call external stream writer. try { // Set ContentLength header. underlyingRequest.ContentLength = request.HttpStreamWriter(null); // Stream payload. using (Stream requestStream = underlyingRequest.GetRequestStream()) { request.HttpStreamWriter(requestStream); } } catch (WebException ex) { HandleWebException(ex, out underlyingResponse); response = null; return false; } } #endregion try { underlyingResponse = underlyingRequest.GetResponse(); } catch (WebException webException) { if (HandleWebException(webException, out underlyingResponse)) { if (underlyingResponse == null) { response = null; return false; } } else throw webException; } // This should not be possible if (underlyingResponse == null) AstoriaTestLog.FailAndThrow("Somehow got a null underlying response"); HttpWebResponse httpResponse = underlyingResponse as HttpWebResponse; response = new AstoriaResponse(request); #region populate response response.ContentType = underlyingResponse.ContentType; // hook everything up if (httpResponse != null) response.ActualStatusCode = httpResponse.StatusCode; else response.ActualStatusCode = HttpStatusCode.Ambiguous; // have to be careful and only mark ETag as found if it was actually sent // regardless of whether the value was null response.ETagHeaderFound = false; foreach (string header in underlyingResponse.Headers.AllKeys) { if (header == "ETag") response.ETagHeaderFound = true; if (underlyingResponse is HttpWebResponse) response.Headers[header] = (underlyingResponse as HttpWebResponse).GetResponseHeader(header); else response.Headers[header] = string.Join(", ", underlyingResponse.Headers.GetValues(header)); } // For Streamed/StreamedResponse, Transfer-Encoding is chunked and ContentLength could be -1 if ((underlyingResponse.Headers[HttpResponseHeader.TransferEncoding] == "chunked" || underlyingResponse.ContentLength > 0)) { Encoding encoding = Encoding.UTF8; using (Stream responseStream = underlyingResponse.GetResponseStream()) { if (request.HttpStreamReader != null) { // Call external stream reader. response.Payload = request.HttpStreamReader(responseStream); } else { if (underlyingResponse.ContentLength > 0 && response.ContentType == SerializationFormatKinds.MimeApplicationOctetStream) { using (System.IO.BinaryReader reader = new System.IO.BinaryReader(responseStream)) response.Bytes = reader.ReadBytes((int)underlyingResponse.ContentLength); } else { using (System.IO.TextReader reader = new System.IO.StreamReader(responseStream, encoding)) response.Payload = reader.ReadToEnd(); } } } } else { // only make an assignment to response.Payload if we're sure there was no content // if we set this prematurely, it can mess up the internal state of the response response.Payload = string.Empty; } #endregion return true; }
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 AstoriaRequest MakeDeleteRequest(AstoriaRequest request) { request.Verb = RequestVerb.Delete; return request; }
protected abstract bool SendRequest_Internal(AstoriaRequest request, out AstoriaResponse response);
protected override bool SendRequest_Internal(AstoriaRequest request, out AstoriaResponse response) { string uri = request.URI; // workaround bug that same url is always cached. if (request.Verb == RequestVerb.Get) { if (uri.Contains('?')) { uri = String.Format("{0}&bug={1}", uri, DateTime.Now.Ticks.ToString()); } else { uri = String.Format("{0}?bug={1}", uri, DateTime.Now.Ticks.ToString()); } } Exception exc = null; int statusCode = -1; XmlHttpClassComWrapper nativeWebRequest; try { nativeWebRequest = XmlHttpClassComWrapper.CreateXmlHttpClassWrapper(); } catch { AstoriaTestLog.WriteLineIgnore("Could not create a new XmlHttp com wrapper"); AstoriaTestLog.WriteLineIgnore("Time before sleep: " + DateTime.Now); Threading.Thread.Sleep(new TimeSpan(0, 0, 30)); AstoriaTestLog.WriteLineIgnore("Time after sleep: " + DateTime.Now); response = null; return false; } using (nativeWebRequest) { string userName = null; string password = null; if (AstoriaTestProperties.HostAuthenicationMethod.ToLower().Equals("windows")) { userName = "******"; password = "******"; } nativeWebRequest.open(request.Verb.ToHttpMethod(), uri, false, userName, password); // this does Accept and Content-Type for us foreach (KeyValuePair<string, string> header in request.Headers) nativeWebRequest.setRequestHeader(header.Key, header.Value); byte[] toSend = request.PayloadBytes; try { nativeWebRequest.send(toSend); statusCode = nativeWebRequest.status; } catch (System.Reflection.TargetInvocationException targetInvokationException) { exc = targetInvokationException; if (targetInvokationException.InnerException != null && targetInvokationException.InnerException is System.Runtime.InteropServices.COMException) { //HACK DUE TO XmlHttpIssue // info at http://www.enhanceie.com/ie/bugs.asp if (nativeWebRequest.status == 1223) { statusCode = (int)HttpStatusCode.NoContent; } else { throw targetInvokationException; } } } response = new AstoriaResponse(request); // Assign status code. if (Enum.IsDefined(typeof(HttpStatusCode), statusCode)) response.ActualStatusCode = (HttpStatusCode)statusCode; else response.ActualStatusCode = HttpStatusCode.Ambiguous; // Assign Content-Type and other headers. string headers = nativeWebRequest.AllResponseHeaders; response.ContentType = null; if (headers != null) { // Parse headers. foreach (string headerLine in headers.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)) { int valueIndex = headerLine.IndexOf(':'); if (valueIndex > 0 && valueIndex < headerLine.Length - 1) response.Headers[headerLine.Substring(0, valueIndex)] = headerLine.Substring(valueIndex + 2); } } else { // No headers. if (statusCode == (int)HttpStatusCode.NoContent) AstoriaTestLog.WriteLine("Warning: XmlHttp does not return headers when status code is No Content"); else AstoriaTestLog.FailAndThrow("Failed to read headers from XmlHttp response"); } response.ETagHeaderFound = response.Headers.ContainsKey("ETag"); // Assign payload. if (response.ContentType == SerializationFormatKinds.MimeApplicationOctetStream) response.Bytes = nativeWebRequest.responseBody; else response.Payload = nativeWebRequest.responseText; GC.Collect(); return true; } }
private static CommonPayload SnapshotEntityState(AstoriaRequest request) { if (!request.SnapshotForUpdate) return null; request.SnapshotForUpdate = true; // try to figure out entity-level request Workspace workspace = request.Workspace; List<string> neededSegments = new List<string>() { workspace.ServiceUri }; string[] segments = request.URI.Replace(workspace.ServiceUri, null).Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); string firstSegment = segments[0]; neededSegments.Add(firstSegment); if (firstSegment.Contains('(')) firstSegment = firstSegment.Substring(0, firstSegment.IndexOf('(')); ResourceContainer container = workspace.ServiceContainer.ResourceContainers[firstSegment]; if (container == null) return null; ResourceType baseType = container.BaseType; bool etagExpected = baseType.Properties.Any(p => p.Facets.ConcurrencyModeFixed); for (int i = 1; i < segments.Length; i++) { string propertyName = segments[i]; if (propertyName.Contains('(')) propertyName = propertyName.Substring(0, propertyName.IndexOf('(')); ResourceProperty property = baseType.Properties[propertyName] as ResourceProperty; if (property == null || !property.IsNavigation) break; etagExpected = property.OtherAssociationEnd.ResourceType.Properties.Any(p => p.Facets.ConcurrencyModeFixed); neededSegments.Add(segments[i]); } AstoriaRequest get = workspace.CreateRequest(); get.Format = request.Format; get.ETagHeaderExpected = etagExpected; get.URI = string.Join("/", neededSegments.ToArray()); AstoriaResponse getResponse = get.GetResponse(); getResponse.Verify(); return getResponse.CommonPayload; }
public override void PrepareRequest(AstoriaRequest request) { request.ExtraVerification += this.NonClrDefaultVerify; request.OnReceiveEvent += HandleResponseEvent; }
public RequestEventArgs(AstoriaRequest request) { Request = request; }