示例#1
0
        public AstoriaResponse SendRequest(AstoriaRequest request)
        {
            AstoriaResponse response;

            SendRequest(request, out response);
            return(response);
        }
示例#2
0
        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;
            }
        }
示例#3
0
        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();
            }
        }
示例#4
0
        /// <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);
            }
        }
示例#5
0
        public static void GetAndVerifyStatusCode(Workspace w, QueryNode query)
        {
            AstoriaRequest  request  = w.CreateRequest(query);
            AstoriaResponse response = request.GetResponse();

            ResponseVerification.VerifyStatusCode(response);
        }
示例#6
0
        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());
            }
        }
示例#7
0
        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);
            }
        }
示例#8
0
        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);
            }
        }
示例#9
0
        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);
                }
            }
        }
示例#10
0
        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);
        }
示例#11
0
        public AstoriaRequest EntitySetServiceOp(string serviceOpName)
        {
            AstoriaRequest request = _workspace.CreateRequest();

            request.URI += serviceOpName;

            return(request);
        }
示例#12
0
        public AstoriaRequest MakeMergeRequest(AstoriaRequest request, KeyedResourceInstance resourceInstance)
        {
            request.Verb        = RequestVerb.Patch;
            request.ContentType = "application/atom+xml";
            request.UpdateTree  = resourceInstance;

            return(request);
        }
示例#13
0
        // ServiceRoot
        public AstoriaRequest ServiceRoot()
        {
            AstoriaRequest request = _workspace.CreateRequest();

            request.Accept = "*/*";

            return(request);
        }
示例#14
0
 public void Add(AstoriaRequest request, string contentID, bool includeIfNull)
 {
     if (includeIfNull || contentID != null)
     {
         request.Headers["Content-ID"] = contentID;
     }
     request.Batched = true;
     _requests.Add(request);
 }
示例#15
0
        // Metadata
        public AstoriaRequest Metadata()
        {
            AstoriaRequest request = _workspace.CreateRequest();

            request.URI   += "/$metadata";
            request.Accept = "*/*";

            return(request);
        }
示例#16
0
        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);
        }
示例#17
0
        public AstoriaRequest EntitySetServiceOp(out ResourceContainer container)
        {
            container = _workspace.ServiceContainer.ResourceContainers.Choose();

            AstoriaRequest request = _workspace.CreateRequest();

            request.URI += "Get" + container.Name;

            return(request);
        }
示例#18
0
        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);
        }
示例#19
0
        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;
        }
示例#20
0
        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));
        }
示例#21
0
 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;
 }
示例#22
0
        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);
        }
示例#23
0
        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");
            }
        }
示例#24
0
        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);
        }
示例#25
0
        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);
        }
示例#26
0
        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);
            }
        }
示例#27
0
        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();
        }
示例#28
0
        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");
                }
            }
        }
示例#29
0
        /// <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);
            }
        }
示例#30
0
        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);
            }
        }
示例#31
0
        public AstoriaRequest MakeMergeRequest(AstoriaRequest request, KeyedResourceInstance resourceInstance)
        {
            request.Verb = RequestVerb.Patch;
            request.ContentType = "application/atom+xml";
            request.UpdateTree = resourceInstance;

            return request;
        }
示例#32
0
 internal AstoriaResponse(AstoriaRequest originalRequest)
     : base(originalRequest.Workspace)
 {
     Request = originalRequest;
 }
示例#33
0
 public AstoriaRequest MakeDeleteRequest(AstoriaRequest request)
 {
     request.Verb = RequestVerb.Delete;
     return(request);
 }
示例#34
0
        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);
        }
示例#35
0
        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;
        }
示例#36
0
 public override void PrepareRequest(AstoriaRequest request)
 {
     request.ExtraVerification += ResponseVerification.DefaultVerify;
 }
示例#37
0
        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);
        }
示例#38
0
        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;
        }
示例#39
0
        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);
        }
示例#40
0
 public override void PrepareRequest(AstoriaRequest request)
 {
     // do nothing, test cases will handle verification
 }
示例#41
0
 public virtual void PrepareRequest(AstoriaRequest request)
 {
     // do nothing (to be overridden in derived workspace classes)
 }
示例#42
0
 public AstoriaResponse SendRequest(AstoriaRequest request)
 {
     AstoriaResponse response;
     SendRequest(request, out response);
     return response;
 }
示例#43
0
        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;
        }
示例#44
0
        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;
            }
        }
示例#45
0
 public AstoriaRequest MakeDeleteRequest(AstoriaRequest request)
 {
     request.Verb = RequestVerb.Delete;
     return request;
 }
示例#46
0
 protected abstract bool SendRequest_Internal(AstoriaRequest request, out AstoriaResponse response);
示例#47
0
        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;
            }
        }
示例#48
0
        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;
        }
示例#49
0
        public override void PrepareRequest(AstoriaRequest request)
        {
            request.ExtraVerification += this.NonClrDefaultVerify;

            request.OnReceiveEvent += HandleResponseEvent;
        }
示例#50
0
 public RequestEventArgs(AstoriaRequest request)
 {
     Request = request;
 }