Exemple #1
0
            public void QueryFailureUsingExecuteBatch()
            {
                DataServiceRequest <northwindClient.Customers> request  = new DataServiceRequest <northwindClient.Customers>(new Uri(ctx.BaseUri.OriginalString + "/Customers('QUICK')"));
                DataServiceRequest <northwindClient.Customers> request1 = new DataServiceRequest <northwindClient.Customers>(new Uri(ctx.BaseUri.OriginalString + "/Customers('NONEXIST')"));
                DataServiceResponse response = ctx.ExecuteBatch(request, request1);

                Utils.IsBatchResponse(response);

                List <QueryOperationResponse> responses = new List <QueryOperationResponse>();

                foreach (QueryOperationResponse queryResponse in response)
                {
                    responses.Add(queryResponse);
                }

                Assert.IsTrue(responses.Count == 2, "expecting 2 responses in batch query");

                // first one to succeed
                Utils.IsSuccessResponse(responses[0], HttpStatusCode.OK);
                Assert.IsTrue(responses[0].Query == request, "expecting the same request object");

                // expecting the second one to fail
                Utils.IsErrorResponse(responses[1], HttpStatusCode.NotFound, true);
                Assert.IsTrue(responses[1].Query == request1, "expecting the same request object1");
            }
        bool GenerateSecurityToken()
        {
            if (securityToken != string.Empty)
            {
                return(true);
            }

            securityToken = string.Empty;
            Uri uri = new Uri("GenerateSecurityToken", UriKind.Relative);

            DataServiceRequest <string> loginRequest = new DataServiceRequest <string>(uri);
            var loginResponse = sldDataServiceContext.ExecuteBatch(loginRequest);
            QueryOperationResponse <string> queryOperationResponse = loginResponse.FirstOrDefault() as QueryOperationResponse <string>;

            if (queryOperationResponse == null)
            {
                return(false);
            }

            string token = queryOperationResponse.FirstOrDefault();

            if (token == null)
            {
                return(false);
            }

            securityToken = token;

            return(true);
        }
Exemple #3
0
        public IEnumerable <T> ExecuteBatch <T>(DataServiceRequest request)
        {
#if NETFRAMEWORK
            return(_context.ExecuteBatch(request)
                   .Cast <QueryOperationResponse>()
                   .SelectMany(o => o.Cast <T>()));
#else
            throw new Exception("not ported");
#endif
        }
        private bool LoginIntoSLD(string URL, string SLDUsername, string SLDPassword)
        {
            lock (this)
            {
                try
                {
                    cookies = new CookieContainer();
                    sldDataServiceContext = new DataServiceContext(new Uri(URL));

                    sldDataServiceContext.SendingRequest         += new EventHandler <SendingRequestEventArgs>(sldDataServiceContext_SendingRequest);
                    sldDataServiceContext.IgnoreMissingProperties = true;

                    string strLogonCmd = string.Empty;

                    string tempUser     = System.Web.HttpUtility.UrlEncode(SLDUsername, System.Text.Encoding.UTF8);
                    string tempPassword = System.Web.HttpUtility.UrlEncode(SLDPassword, System.Text.Encoding.UTF8);
                    strLogonCmd = string.Format("LogonByNamedUser?Account='{0}'&Password='******'", tempUser, tempPassword);
                    Uri uri = new Uri(strLogonCmd, UriKind.Relative);

                    DataServiceRequest <bool> loginRequest = new DataServiceRequest <bool>(uri);
                    var loginResponse = sldDataServiceContext.ExecuteBatch(loginRequest);

                    foreach (var response in loginResponse)
                    {
                        var queryOperationResponse = response as QueryOperationResponse <bool>;
                        if (queryOperationResponse == null || !queryOperationResponse.FirstOrDefault())
                        {
                            return(false);
                        }
                    }
                }
                catch
                {
                    throw;
                }

                try
                {
                    if (!GenerateSecurityToken())
                    {
                        return(false);
                    }
                }
                catch
                {
                    throw;
                }

                return(true);
            }
        }
        public static IEnumerable ExecuteQuery(DataServiceContext context, DataServiceRequest query, QueryMode queryMode)
        {
            bool isQuery = (null != (query as DataServiceQuery));

            object result = null;

            switch (queryMode)
            {
            case QueryMode.GetEnumerator:     // IEnumerable.GetEnumerator
            {
                if (isQuery)
                {
                    result = query;
                }
                else
                {
                    goto case QueryMode.ExecuteMethod;
                }
                break;
            }

            case QueryMode.ExecuteMethod:     // DataServiceQuery<T>.Execute
            {
                if (isQuery)
                {
                    result = UnitTestCodeGen.InvokeMethod(query.GetType(), "Execute", null, null, query, null);
                }
                else
                {
                    result = UnitTestCodeGen.InvokeMethod(typeof(DataServiceContext), "Execute", TypesUri, new Type[] { query.ElementType }, context, query.RequestUri);
                }

                break;
            }

            case QueryMode.AsyncExecute:     // DataServiceQuery<T>.BeginExecute and wait
            {
                if (isQuery)
                {
                    IAsyncResult async = (IAsyncResult)UnitTestCodeGen.InvokeMethod(query.GetType(), "BeginExecute", TypesAsyncCallbackObject, null, query, new object[] { null, null });
                    if (!async.CompletedSynchronously)
                    {
                        Assert.IsTrue(async.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "BeginExecute timeout");
                    }

                    result = UnitTestCodeGen.InvokeMethod(query.GetType(), "EndExecute", TypesIAsyncResult, null, query, new object[] { async });
                }
                else
                {
                    IAsyncResult async = UnitTestCodeGen.InvokeMethod <DataServiceContext, IAsyncResult>("BeginExecute", TypesUriAsyncCallbackObject, new Type[] { query.ElementType }, context, query.RequestUri, null, null);
                    if (!async.CompletedSynchronously)
                    {
                        Assert.IsTrue(async.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "BeginExecute timeout");
                    }

                    result = UnitTestCodeGen.InvokeMethod(typeof(DataServiceContext), "EndExecute", TypesIAsyncResult, new Type[] { query.ElementType }, context, async);
                }

                break;
            }

            case QueryMode.AsyncExecuteWithCallback:     // DataServiceQuery<T>.BeginExecute with callback
            {
                ExecuteCallback callback = new ExecuteCallback();
                IAsyncResult    async;
                if (isQuery)
                {
                    async = (IAsyncResult)UnitTestCodeGen.InvokeMethod(query.GetType(), "BeginExecute", TypesAsyncCallbackObject, null, query, new object[] { (AsyncCallback)callback.CallbackMethod, new object[] { query, context } });
                }
                else
                {
                    async = UnitTestCodeGen.InvokeMethod <DataServiceContext, IAsyncResult>("BeginExecute", TypesUriAsyncCallbackObject, new Type[] { query.ElementType }, context, new object[] { query.RequestUri, (AsyncCallback)callback.CallbackMethod, new object[] { query, context } });
                }

                Assert.IsTrue(callback.Finished.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "Asyncallback timeout");
                Assert.IsTrue(async.IsCompleted);

                if (null != callback.CallbackFailure)
                {
                    Assert.IsNull(callback.CallbackResult, callback.CallbackFailure.ToString());
                    throw new Exception("failure in callback", callback.CallbackFailure);
                }

                result = callback.CallbackResult;
                Assert.IsNotNull(result);
                break;
            }

            case QueryMode.BatchExecute:     // DataServiceContext.ExecuteBatch
            {
                LastUriRequest = query.RequestUri;
                int countBefore = context.Entities.Count + context.Links.Count;
                DataServiceResponse response = context.ExecuteBatch(query);
                int countAfter = context.Entities.Count + context.Links.Count;
                Assert.AreEqual(countBefore, countAfter, "should not materialize during ExecuteBatch");
                result = HandleQueryResponse(response, query, context);
            }
            break;

            case QueryMode.BatchAsyncExecute:     // DataServiceContext.BeginExecuteBatch and wait
            {
                int count = context.Entities.Count + context.Links.Count;
                LastUriRequest = query.RequestUri;
                IAsyncResult async = context.BeginExecuteBatch(null, null, query);
                if (!async.CompletedSynchronously)
                {
                    Assert.IsTrue(async.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "BeginExecuteBatch timeout");
                }

                Assert.AreEqual(count, context.Entities.Count + context.Links.Count, "should not materialize until EndExecuteBatch");
                DataServiceResponse response = context.EndExecuteBatch(async);
                result = HandleQueryResponse(response, query, context);
                break;
            }

            case QueryMode.BatchAsyncExecuteWithCallback:     // DataServiceContext.BeginExecuteBatch with callback
            {
                ExecuteBatchCallback callback = new ExecuteBatchCallback();
                LastUriRequest = query.RequestUri;
                IAsyncResult async = context.BeginExecuteBatch(callback.CallbackMethod, new object[] { query, context }, query);

                Assert.IsTrue(callback.Finished.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "Asyncallback timeout {0}", LastUriRequest);
                Assert.IsTrue(async.IsCompleted);

                if (null != callback.CallbackFailure)
                {
                    Assert.IsNull(callback.CallbackResult, callback.CallbackFailure.ToString());
                    throw new Exception("failure in callback", callback.CallbackFailure);
                }

                result = callback.CallbackResult;
                Assert.IsNotNull(result);
                break;
            }

            default:
                Assert.Fail("shouldn't be here");
                break;
            }

            return((IEnumerable)result);
        }
 /// <summary>
 /// Extension method to perform sync/async version of DataServiceContext.ExecuteBatch dynamically
 /// </summary>
 /// <param name="context">The context to call execute batch on</param>
 /// <param name="continuation">The asynchronous continuation</param>
 /// <param name="async">A value indicating whether or not to use async API</param>
 /// <param name="queries">The queries to execute</param>
 /// <param name="onCompletion">A callback for when the call completes</param>
 public static void ExecuteBatch(this DataServiceContext context, IAsyncContinuation continuation, bool async, IEnumerable <DataServiceRequest> queries, Action <DataServiceResponse> onCompletion)
 {
     ExceptionUtilities.CheckArgumentNotNull(context, "context");
     AsyncHelpers.InvokeSyncOrAsyncMethodCall <DataServiceResponse>(continuation, async, () => context.ExecuteBatch(queries.ToArray()), c => context.BeginExecuteBatch(c, null, queries.ToArray()), r => context.EndExecuteBatch(r), onCompletion);
 }
Exemple #7
0
 public IEnumerable <T> ExecuteBatch <T>(DataServiceRequest request)
 {
     return(_context.ExecuteBatch(request)
            .Cast <QueryOperationResponse>()
            .SelectMany(o => o.Cast <T>()));
 }
Exemple #8
0
            [Ignore] // Remove Atom
            // [TestCategory("Partition2"), TestMethod, Variation]
            public void BatchContentTypeTest()
            {
                var testCases = new BatchContentTypeTestCase[]
                {
                    // Completely wrong content type
                    new BatchContentTypeTestCase
                    {
                        ContentType                = "text/plain",
                        ExpectedErrorStatusCode    = 400,
                        ExpectedClientErrorMessage = DataServicesClientResourceUtil.GetString("Batch_ExpectedContentType", "text/plain")
                    },
                    // Just type is correct, subtype is wrong
                    new BatchContentTypeTestCase
                    {
                        ContentType                = "multipart/text",
                        ExpectedErrorStatusCode    = 400,
                        ExpectedClientErrorMessage = DataServicesClientResourceUtil.GetString("Batch_ExpectedContentType", "multipart/text")
                    },
                    // No boundary - still wrong
                    new BatchContentTypeTestCase
                    {
                        ContentType                = "multipart/mixed",
                        ExpectedErrorStatusCode    = 400,
                        ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed", "boundary")
                    },
                    // Some other parameter but no boundary
                    new BatchContentTypeTestCase
                    {
                        ContentType                = "multipart/mixed;param=value",
                        ExpectedErrorStatusCode    = 400,
                        ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed;param=value", "boundary")
                    },
                    // Empty boundary - fails
                    new BatchContentTypeTestCase
                    {
                        ContentType                = "multipart/mixed;boundary=",
                        ExpectedErrorStatusCode    = 400,
                        ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_InvalidBatchBoundaryDelimiterLength", string.Empty, "70")
                    },
                    new BatchContentTypeTestCase
                    {
                        ContentType                = "multipart/mixed;boundary=;param=value",
                        ExpectedErrorStatusCode    = 400,
                        ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_InvalidBatchBoundaryDelimiterLength", string.Empty, "70")
                    },
                    // Two boundary parameters - wrong
                    new BatchContentTypeTestCase
                    {
                        ContentType                = "multipart/mixed;boundary=one;boundary=two",
                        ExpectedErrorStatusCode    = 400,
                        ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed;boundary=one;boundary=two", "boundary")
                    },
                    // Valid simple boundary
                    new BatchContentTypeTestCase
                    {
                        ContentType          = "multipart/mixed;boundary=batchboundary",
                        PayloadBatchBoundary = "batchboundary"
                    },
                    // Valid simple boundary - mimetype using different casing
                    new BatchContentTypeTestCase
                    {
                        ContentType          = "MultiPart/mIxed;boundary=batchboundary",
                        PayloadBatchBoundary = "batchboundary"
                    },
                    // Valid simple boundary - boundary parameter name different casing
                    new BatchContentTypeTestCase
                    {
                        ContentType          = "multipart/mixed;BounDary=batchboundary",
                        PayloadBatchBoundary = "batchboundary"
                    },
                };

                OpenWebDataServiceDefinition serverService = new OpenWebDataServiceDefinition()
                {
                    DataServiceType = typeof(CustomDataContext)
                };

                PlaybackServiceDefinition clientService = new PlaybackServiceDefinition();

                TestUtil.RunCombinations(
                    testCases,
                    (testCase) =>
                {
                    using (TestWebRequest request = serverService.CreateForInProcess())
                    {
                        request.RequestContentType = testCase.ContentType;
                        request.SetRequestStreamAsText(string.Format(
                                                           "--{0}\r\n" +
                                                           "Content-Type: multipart/mixed; boundary=changesetresponse_00000001-0000-0000-0000-000000000000\r\n\r\n" +
                                                           "--changesetresponse_00000001-0000-0000-0000-000000000000\r\n" +
                                                           "--changesetresponse_00000001-0000-0000-0000-000000000000--\r\n" +
                                                           "--{0}--\r\n", testCase.PayloadBatchBoundary));
                        request.RequestUriString = "/$batch";
                        request.HttpMethod       = "POST";

                        Exception exception = TestUtil.RunCatching(request.SendRequest);

                        int actualStatusCode = 0;
                        if (exception != null)
                        {
                            actualStatusCode = request.ResponseStatusCode;
                        }
                        else
                        {
                            Assert.AreEqual(202, request.ResponseStatusCode, "Wrong response code for no-exception request.");
                            BatchWebRequest batchResponse = BatchWebRequest.FromResponse(InMemoryWebRequest.FromResponse(request));
                            if (batchResponse.Parts.Count > 0)
                            {
                                actualStatusCode = batchResponse.Parts[0].ResponseStatusCode;
                                if (actualStatusCode == 200)
                                {
                                    actualStatusCode = 0;
                                }
                            }
                        }

                        Assert.AreEqual(testCase.ExpectedErrorStatusCode, actualStatusCode, "Wrong status code.");
                    }

                    using (TestWebRequest request = clientService.CreateForInProcessWcf())
                    {
                        request.StartService();

                        clientService.ProcessRequestOverride = clientRequest =>
                        {
                            var clientResponse = new InMemoryWebRequest();
                            clientResponse.SetResponseStatusCode(202);
                            clientResponse.ResponseHeaders["Content-Type"] = testCase.ContentType;
                            clientResponse.SetResponseStreamAsText(string.Format(
                                                                       "--{0}\r\n" +
                                                                       "Content-Type: application/http\r\n" +
                                                                       "Content-Transfer-Encoding: binary\r\n" +
                                                                       "\r\n" +
                                                                       "200 OK\r\n" +
                                                                       "<feed xmlns='http://www.w3.org/2005/Atom'/>\r\n" +
                                                                       "--{0}--\r\n",
                                                                       testCase.PayloadBatchBoundary));
                            return(clientResponse);
                        };

                        DataServiceContext ctx = new DataServiceContext(request.ServiceRoot);
                        Exception exception    = TestUtil.RunCatching(() => ctx.ExecuteBatch(ctx.CreateQuery <Customer>("/Customers")));

                        if (exception != null)
                        {
                            exception = ((DataServiceRequestException)exception).InnerException;
                            Assert.AreEqual(testCase.ExpectedClientErrorMessage, exception.Message, "Unexpected error message.");
                        }
                        else
                        {
                            Assert.IsNull(testCase.ExpectedClientErrorMessage, "Expected exception, but none was thrown.");
                        }
                    }
                });
            }
        public void NamedStreams_Projections_MergeInfoOptions()
        {
            // Make sure that based on the MergeOption, the value of the DataServiceStreamLink is updated
            TestUtil.RunCombinations(
                    new EntityStates[] { EntityStates.Added, EntityStates.Deleted, EntityStates.Modified, EntityStates.Unchanged },
                    new MergeOption[] { MergeOption.AppendOnly, MergeOption.OverwriteChanges, MergeOption.PreserveChanges },
                    new int[] { -1, 0, 1 }, // -1 indicates less links, 0 means exact same number of links, 1 means some extra links
                    UnitTestsUtil.BooleanValues,
                    (entityState, mergeOption, extraLinks, useBatchMode) =>
                    {
                        using (PlaybackService.OverridingPlayback.Restore())
                        {
                            DataServiceContext context = new DataServiceContext(request.ServiceRoot, ODataProtocolVersion.V4);
                            context.EnableAtom = true;
                            context.Format.UseAtom();
                            context.MergeOption = mergeOption;

                            // Populate the context with a single customer instance with 2 named streams
                            string originalServiceRoot = "http://randomservice/Foo.svc";
                            string newServiceRoot = "http://randomservice1/Foo1.svc";

                            string payload = AtomParserTests.AnyEntry(
                                id: NamedStreamTests.Id,
                                editLink: request.ServiceRoot.AbsoluteUri + "/editLink/Customers(1)",
                                properties: NamedStreamTests.Properties,
                                links: NamedStreamTests.GetNamedStreamEditLink(originalServiceRoot + "/Customers(1)/EditLink/Thumbnail"));

                            PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToPlaybackServicePayload(null, payload);
                            DataServiceQuery<StreamType2> query = (DataServiceQuery<StreamType2>)context.CreateQuery<StreamType2>("Customers");

                            StreamType2 c = DataServiceContextTestUtil.CreateEntity<StreamType2>(context, "Customers", entityState, query);
                            PlaybackService.OverridingPlayback.Value = null;

                            string linksPayload = null;

                            if (extraLinks == -1)
                            {
                                // send no links
                            }
                            else if (extraLinks == 0)
                            {
                                linksPayload = NamedStreamTests.GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Thumbnail");
                            }
                            else
                            {
                                linksPayload = NamedStreamTests.GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Thumbnail") +
                                               NamedStreamTests.GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Photo", name: "Photo");
                            }

                            payload = AtomParserTests.AnyEntry(
                                id: NamedStreamTests.Id,
                                editLink: request.ServiceRoot.AbsoluteUri + "/editLink/Customers(1)",
                                properties: NamedStreamTests.Properties,
                                links: linksPayload);

                            PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToPlaybackServicePayload(null, payload);

                            if (useBatchMode)
                            {
                                PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToBatchQueryResponsePayload(PlaybackService.OverridingPlayback.Value);
                                QueryOperationResponse<StreamType2> resp = (QueryOperationResponse<StreamType2>)context.ExecuteBatch((DataServiceRequest)query).Single();
                                c = resp.First();
                            }
                            else
                            {
                                switch (extraLinks)
                                {
                                    case -1:
                                        c = query.Select(s => new StreamType2()
                                        {
                                            ID = s.ID,
                                            Name = s.Name
                                        }).Single();
                                        break;
                                    case 0:
                                        c = query.Select(s => new StreamType2()
                                        {
                                            ID = s.ID,
                                            Name = s.Name,
                                            Thumbnail = s.Thumbnail
                                        }).Single();
                                        break;
                                    default:
                                        c = query.Select(s => new StreamType2()
                                        {
                                            ID = s.ID,
                                            Name = s.Name,
                                            Thumbnail = s.Thumbnail,
                                            Photo = s.Photo
                                        }).Single();
                                        break;
                                }
                            }

                            EntityDescriptor entityDescriptor = context.Entities.Where(ed => Object.ReferenceEquals(c, ed.Entity)).Single();
                            StreamDescriptor thumbnail = entityDescriptor.StreamDescriptors.Where(ns => ns.StreamLink.Name == "Thumbnail").SingleOrDefault();
                            //Assert.IsTrue(thumbnail == null || object.ReferenceEquals(thumbnail.EntityDescriptor, entityDescriptor), "StreamDescriptor.EntityDescriptor should point to the same instance of entity descriptor");
                            StreamDescriptor photo = entityDescriptor.StreamDescriptors.Where(ns => ns.StreamLink.Name == "Photo").SingleOrDefault();
                            //Assert.IsTrue(photo == null || object.ReferenceEquals(photo.EntityDescriptor, entityDescriptor), "StreamDescriptor.EntityDescriptor should point to the same instance of entity descriptor for photo");

                            string newEditLink = newServiceRoot + "/Customers(1)/EditLink/{0}";
                            string existingEditLink = originalServiceRoot + "/Customers(1)/EditLink/{0}";

                            if (entityState == EntityStates.Added)
                            {
                                Assert.AreEqual(2, context.Entities.Count, "since its in added state, we will get a new entity descriptor");
                                Assert.AreEqual(1 + extraLinks, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected");

                                if (extraLinks == -1)
                                {
                                    Assert.AreEqual(thumbnail, null, "photo must be null when extra links = -1 and state = added");
                                }
                                else if (extraLinks == 0)
                                {
                                    NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, newEditLink, null, null);
                                }
                                else if (extraLinks == 1)
                                {
                                    NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, newEditLink, null, null);
                                    NamedStreamTests.VerifyNamedStreamInfo(photo, null, newEditLink, null, null);
                                }
                            }
                            else if (mergeOption == MergeOption.OverwriteChanges ||
                                     (mergeOption == MergeOption.PreserveChanges && (entityState == EntityStates.Deleted || entityState == EntityStates.Unchanged)))
                            {
                                Assert.AreEqual(1, context.Entities.Count, "since its not in added state, we will only have one entity descriptor");
                                int numOfNamedStreams = 1;
                                if (extraLinks == 1)
                                {
                                    numOfNamedStreams = 2;
                                }
                                Assert.AreEqual(numOfNamedStreams, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected");

                                if (extraLinks == -1)
                                {
                                    NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, existingEditLink, null, null);
                                    Assert.AreEqual(photo, null, "photo must be null when extra links = -1");
                                }
                                else if (extraLinks == 0)
                                {
                                    NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, newEditLink, null, null);
                                    Assert.AreEqual(photo, null, "photo must be null when extra links = 0");
                                }
                                else if (extraLinks == 1)
                                {
                                    NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, newEditLink, null, null);
                                    NamedStreamTests.VerifyNamedStreamInfo(photo, null, newEditLink, null, null);
                                }
                            }
                            else
                            {
                                // no change should be made
                                Assert.AreEqual(1, context.Entities.Count, "since its not in added state, we will only have one entity descriptor");
                                Assert.AreEqual(1, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected");
                                NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, existingEditLink, null, null);
                                Assert.AreEqual(photo, null, "photo must be null when extra links = 0");
                            }
                        }
                    });
        }
        public void VerifyEntityDescriptorMergeFunctionality()
        {
            // Make sure that based on the MergeOption, the right links are exposed in the entity descriptor
            TestUtil.RunCombinations(
                    new EntityStates[] { EntityStates.Added, EntityStates.Deleted, EntityStates.Modified, EntityStates.Unchanged },
                    new MergeOption[] { MergeOption.AppendOnly, MergeOption.OverwriteChanges, MergeOption.PreserveChanges },
                    new int[] { -1, 0, 1 }, // -1 indicates less links, 0 means exact same number of links, 1 means some extra links
                    UnitTestsUtil.BooleanValues,
                    UnitTestsUtil.BooleanValues,
                    (entityState, mergeOption, extraLinks, useBatchMode, returnETag) =>
                    {
                        using (PlaybackService.OverridingPlayback.Restore())
                        {
                            DataServiceContext context = new DataServiceContext(request.ServiceRoot, ODataProtocolVersion.V4);
                            context.EnableAtom = true;
                            context.MergeOption = mergeOption;

                            // Populate the context with a single customer instance with 2 named streams
                            string originalServiceRoot = "http://randomservice/Foo.svc";
                            string newServiceRoot = "http://randomservice1/Foo1.svc";

                            string payload = AtomParserTests.AnyEntry(
                                id: Id,
                                editLink: request.ServiceRoot.AbsoluteUri + "/editLink/Customers(1)",
                                properties: Properties,
                                links: GetNamedStreamSelfLink(originalServiceRoot + "/Customers(1)/SelfLink/Thumbnail", contentType: MediaContentType) +
                                       GetNamedStreamEditLink(originalServiceRoot + "/Customers(1)/EditLink/Thumbnail", contentType: MediaContentType, etag: MediaETag) +
                                       GetNamedStreamSelfLink(originalServiceRoot + "/Customers(1)/SelfLink/Photo", contentType: MediaContentType, name: "Photo") +
                                       GetNamedStreamEditLink(originalServiceRoot + "/Customers(1)/EditLink/Photo", contentType: MediaContentType, name: "Photo"));

                            PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToPlaybackServicePayload(null, payload);
                            Customer c = DataServiceContextTestUtil.CreateEntity<Customer>(context, "Customers", entityState);
                            PlaybackService.OverridingPlayback.Value = null;

                            string linksPayload = null;
                            string newETag = returnETag ? MediaETag + 1 : null;

                            if (extraLinks == -1)
                            {
                                linksPayload = GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/Thumbnail", contentType: MediaContentType) +
                                               GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Thumbnail", contentType: MediaContentType, etag: newETag);
                            }
                            else if (extraLinks == 0)
                            {
                                linksPayload = GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/Thumbnail", contentType: MediaContentType) +
                                               GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Thumbnail", contentType: MediaContentType, etag: newETag) +
                                               GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/Photo", contentType: MediaContentType, name: "Photo") +
                                               GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Photo", contentType: MediaContentType, name: "Photo", etag: newETag);
                            }
                            else
                            {
                                linksPayload = GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/Thumbnail", contentType: MediaContentType) +
                                               GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Thumbnail", contentType: MediaContentType, etag: newETag) +
                                               GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/Photo", contentType: MediaContentType, name: "Photo") +
                                               GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Photo", contentType: MediaContentType, etag: newETag, name: "Photo") +
                                               GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/HighResolutionPhoto", contentType: MediaContentType, name: "HighResolutionPhoto") +
                                               GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/HighResolutionPhoto", contentType: MediaContentType, name: "HighResolutionPhoto", etag: newETag);
                            }

                            payload = AtomParserTests.AnyEntry(
                                id: Id,
                                editLink: request.ServiceRoot.AbsoluteUri + "/editLink/Customers(1)",
                                properties: Properties,
                                links: linksPayload);

                            PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToPlaybackServicePayload(null, payload);

                            if (useBatchMode)
                            {
                                PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToBatchQueryResponsePayload(PlaybackService.OverridingPlayback.Value);
                                QueryOperationResponse<Customer> resp = (QueryOperationResponse<Customer>)context.ExecuteBatch(context.CreateQuery<Customer>("/Customers(123)")).Single();
                                c = resp.First();
                            }
                            else
                            {
                                c = context.CreateQuery<Customer>("/Customers(123)").Execute().First();
                            }

                            EntityDescriptor entityDescriptor = context.Entities.Where(ed => Object.ReferenceEquals(c, ed.Entity)).Single();
                            StreamDescriptor thumbnail = entityDescriptor.StreamDescriptors.Where(ns => ns.StreamLink.Name == "Thumbnail").SingleOrDefault();
                            StreamDescriptor photo = entityDescriptor.StreamDescriptors.Where(ns => ns.StreamLink.Name == "Photo").SingleOrDefault();
                            StreamDescriptor highResPhoto = entityDescriptor.StreamDescriptors.Where(ns => ns.StreamLink.Name == "HighResolutionPhoto").SingleOrDefault();

                            string newSelfLink = newServiceRoot + "/Customers(1)/SelfLink/{0}";
                            string newEditLink = newServiceRoot + "/Customers(1)/EditLink/{0}";
                            string existingSelfLink = originalServiceRoot + "/Customers(1)/SelfLink/{0}";
                            string existingEditLink = originalServiceRoot + "/Customers(1)/EditLink/{0}";

                            if (entityState == EntityStates.Added)
                            {
                                Assert.AreEqual(2, context.Entities.Count, "since its in added state, we will get a new entity descriptor");
                                Assert.AreEqual(2 + extraLinks, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected");

                                VerifyNamedStreamInfo(thumbnail, newSelfLink, newEditLink, newETag, contentType: MediaContentType);
                                if (extraLinks == -1)
                                {
                                    Assert.AreEqual(photo, null, "photo must be null when extra links = -1 and state = added");
                                    Assert.AreEqual(highResPhoto, null, "highResPhoto must be null when extra links = -1 and state = added");
                                }
                                else if (extraLinks == 0)
                                {
                                    VerifyNamedStreamInfo(photo, newSelfLink, newEditLink, newETag, contentType: MediaContentType);
                                    Assert.AreEqual(highResPhoto, null, "highResPhoto must be null when extra links = 0 and state = added");
                                }
                                else if (extraLinks == 1)
                                {
                                    VerifyNamedStreamInfo(photo, newSelfLink, newEditLink, newETag, contentType: MediaContentType);
                                    VerifyNamedStreamInfo(highResPhoto, newSelfLink, newEditLink, newETag, contentType: MediaContentType);
                                }
                            }
                            else if (mergeOption == MergeOption.OverwriteChanges ||
                                     (mergeOption == MergeOption.PreserveChanges && (entityState == EntityStates.Deleted || entityState == EntityStates.Unchanged)))
                            {
                                Assert.AreEqual(1, context.Entities.Count, "since its not in added state, we will only have one entity descriptor");
                                int numOfNamedStreams = 2;
                                if (extraLinks == 1)
                                {
                                    numOfNamedStreams = 3;
                                }
                                Assert.AreEqual(numOfNamedStreams, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected");

                                VerifyNamedStreamInfo(thumbnail, newSelfLink, newEditLink, newETag ?? MediaETag, MediaContentType);
                                if (extraLinks == -1)
                                {
                                    VerifyNamedStreamInfo(photo, existingSelfLink, existingEditLink, null, MediaContentType);
                                    Assert.AreEqual(highResPhoto, null, "highResPhoto must be null when extra links = -1 and state = added");
                                }
                                else if (extraLinks == 0)
                                {
                                    VerifyNamedStreamInfo(photo, newSelfLink, newEditLink, newETag, MediaContentType);
                                    Assert.AreEqual(highResPhoto, null, "highResPhoto must be null when extra links = 0 and state = added");
                                }
                                else if (extraLinks == 1)
                                {
                                    VerifyNamedStreamInfo(photo, newSelfLink, newEditLink, newETag, MediaContentType);
                                    VerifyNamedStreamInfo(highResPhoto, newSelfLink, newEditLink, newETag, MediaContentType);
                                }
                            }
                            else
                            {
                                // no change should be made
                                Assert.AreEqual(1, context.Entities.Count, "since its not in added state, we will only have one entity descriptor");
                                Assert.AreEqual(2, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected");
                                VerifyNamedStreamInfo(thumbnail, existingSelfLink, existingEditLink, MediaETag, MediaContentType);
                                VerifyNamedStreamInfo(photo, existingSelfLink, existingEditLink, null, MediaContentType);
                                Assert.AreEqual(highResPhoto, null, "highResPhoto must be null in AppendOnly");
                            }
                        }
                    });
        }
        public void NamedStreams_PropertyOnClientNotDataServiceStreamLink()
        {
            // [Client-ODataLib-Integration] Astoria client does not fail if the client and server stream property does not match
            TestUtil.RunCombinations(
                    new MergeOption[] { MergeOption.AppendOnly, MergeOption.OverwriteChanges, MergeOption.PreserveChanges },
                    UnitTestsUtil.BooleanValues,
                    (mergeOption, useBatchMode) =>
                    {
                        using (PlaybackService.OverridingPlayback.Restore())
                        {
                            DataServiceContext context = new DataServiceContext(request.ServiceRoot, ODataProtocolVersion.V4);
                            context.EnableAtom = true;
                            context.MergeOption = mergeOption;

                            // Populate the context with a single customer instance with 2 named streams
                            string originalServiceRoot = "http://randomservice/Foo.svc";

                            string payload = AtomParserTests.AnyEntry(
                                id: NamedStreamTests.Id,
                                editLink: request.ServiceRoot.AbsoluteUri + "/editLink/Customers(1)",
                                properties: NamedStreamTests.Properties,
                                links: NamedStreamTests.GetNamedStreamEditLink(originalServiceRoot + "/Customers(1)/EditLink/Thumbnail"));

                            PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToPlaybackServicePayload(null, payload);
                            DataServiceQuery<StreamTypeWithMismatchedStreamProperty> query = (DataServiceQuery<StreamTypeWithMismatchedStreamProperty>)context.CreateQuery<StreamTypeWithMismatchedStreamProperty>("Customers");

                            Exception exception = null;
                            if (useBatchMode)
                            {
                                PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToBatchQueryResponsePayload(PlaybackService.OverridingPlayback.Value);
                                var batchResponse = context.ExecuteBatch(query);
                                foreach (var queryResponse in batchResponse.OfType<QueryOperationResponse<StreamTypeWithMismatchedStreamProperty>>())
                                {
                                    exception = TestUtil.RunCatching<InvalidOperationException>(() =>
                                    {
                                        foreach (var entity in queryResponse)
                                        {
                                            Assert.Fail("Should not reach here");
                                        }
                                    });
                                }
                            }
                            else
                            {
                                exception = TestUtil.RunCatching<InvalidOperationException>(() => query.ToList());
                            }

                            Assert.IsNotNull(exception, "Expected error on mismatched client named stream link property type");
                            Assert.IsInstanceOfType(exception, typeof(InvalidOperationException), "Expected InvalidOperationException on mismatched client named stream link property type");
                            string expectedErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_MismatchPropertyKindForStreamProperty", "Thumbnail");
                            Assert.AreEqual(expectedErrorMessage, exception.Message);
                        }
                    });
        }
Exemple #12
0
            public void BatchContentTypeTest()
            {
                var testCases = new BatchContentTypeTestCase[]
                {
                    // Completely wrong content type
                    new BatchContentTypeTestCase
                    {
                        ContentType = "text/plain",
                        ExpectedErrorStatusCode = 400,
                        ExpectedClientErrorMessage = DataServicesClientResourceUtil.GetString("Batch_ExpectedContentType", "text/plain")
                    },
                    // Just type is correct, subtype is wrong
                    new BatchContentTypeTestCase
                    {
                        ContentType = "multipart/text",
                        ExpectedErrorStatusCode = 400,
                        ExpectedClientErrorMessage = DataServicesClientResourceUtil.GetString("Batch_ExpectedContentType", "multipart/text")
                    },
                    // No boundary - still wrong
                    new BatchContentTypeTestCase
                    {
                        ContentType = "multipart/mixed",
                        ExpectedErrorStatusCode = 400,
                        ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed", "boundary")
                    },
                    // Some other parameter but no boundary
                    new BatchContentTypeTestCase
                    {
                        ContentType = "multipart/mixed;param=value",
                        ExpectedErrorStatusCode = 400,
                        ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed;param=value", "boundary")
                    },
                    // Empty boundary - fails
                    new BatchContentTypeTestCase
                    {
                        ContentType = "multipart/mixed;boundary=",
                        ExpectedErrorStatusCode = 400,
                        ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_InvalidBatchBoundaryDelimiterLength", string.Empty, "70")
                    },
                    new BatchContentTypeTestCase
                    {
                        ContentType = "multipart/mixed;boundary=;param=value",
                        ExpectedErrorStatusCode = 400,
                        ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_InvalidBatchBoundaryDelimiterLength", string.Empty, "70")
                    },
                    // Two boundary parameters - wrong
                    new BatchContentTypeTestCase
                    {
                        ContentType = "multipart/mixed;boundary=one;boundary=two",
                        ExpectedErrorStatusCode = 400,
                        ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed;boundary=one;boundary=two", "boundary")
                    },
                    // Valid simple boundary
                    new BatchContentTypeTestCase
                    {
                        ContentType = "multipart/mixed;boundary=batchboundary",
                        PayloadBatchBoundary = "batchboundary"
                    },
                    // Valid simple boundary - mimetype using different casing
                    new BatchContentTypeTestCase
                    {
                        ContentType = "MultiPart/mIxed;boundary=batchboundary",
                        PayloadBatchBoundary = "batchboundary"
                    },
                    // Valid simple boundary - boundary parameter name different casing
                    new BatchContentTypeTestCase
                    {
                        ContentType = "multipart/mixed;BounDary=batchboundary",
                        PayloadBatchBoundary = "batchboundary"
                    },
                };

                OpenWebDataServiceDefinition serverService = new OpenWebDataServiceDefinition()
                {
                    DataServiceType = typeof(CustomDataContext)
                };

                PlaybackServiceDefinition clientService = new PlaybackServiceDefinition();

                TestUtil.RunCombinations(
                    testCases,
                    (testCase) =>
                    {
                        using (TestWebRequest request = serverService.CreateForInProcess())
                        {
                            request.RequestContentType = testCase.ContentType;
                            request.SetRequestStreamAsText(string.Format(
                                "--{0}\r\n" +
                                "Content-Type: multipart/mixed; boundary=changesetresponse_00000001-0000-0000-0000-000000000000\r\n\r\n" +
                                "--changesetresponse_00000001-0000-0000-0000-000000000000\r\n" +
                                "--changesetresponse_00000001-0000-0000-0000-000000000000--\r\n" +
                                "--{0}--\r\n", testCase.PayloadBatchBoundary));
                            request.RequestUriString = "/$batch";
                            request.HttpMethod = "POST";

                            Exception exception = TestUtil.RunCatching(request.SendRequest);

                            int actualStatusCode = 0;
                            if (exception != null)
                            {
                                actualStatusCode = request.ResponseStatusCode;
                            }
                            else
                            {
                                Assert.AreEqual(202, request.ResponseStatusCode, "Wrong response code for no-exception request.");
                                BatchWebRequest batchResponse = BatchWebRequest.FromResponse(InMemoryWebRequest.FromResponse(request));
                                if (batchResponse.Parts.Count > 0)
                                {
                                    actualStatusCode = batchResponse.Parts[0].ResponseStatusCode;
                                    if (actualStatusCode == 200) actualStatusCode = 0;
                                }
                            }

                            Assert.AreEqual(testCase.ExpectedErrorStatusCode, actualStatusCode, "Wrong status code.");
                        }

                        using (TestWebRequest request = clientService.CreateForInProcessWcf())
                        {
                            request.StartService();

                            clientService.ProcessRequestOverride = clientRequest =>
                            {
                                var clientResponse = new InMemoryWebRequest();
                                clientResponse.SetResponseStatusCode(202);
                                clientResponse.ResponseHeaders["Content-Type"] = testCase.ContentType;
                                clientResponse.SetResponseStreamAsText(string.Format(
                                    "--{0}\r\n" +
                                    "Content-Type: application/http\r\n" +
                                    "Content-Transfer-Encoding: binary\r\n" +
                                    "\r\n" +
                                    "200 OK\r\n" +
                                    "<feed xmlns='http://www.w3.org/2005/Atom'/>\r\n" +
                                    "--{0}--\r\n",
                                    testCase.PayloadBatchBoundary));
                                return clientResponse;
                            };

                            DataServiceContext ctx = new DataServiceContext(request.ServiceRoot);
                            Exception exception = TestUtil.RunCatching(() => ctx.ExecuteBatch(ctx.CreateQuery<Customer>("/Customers")));

                            if (exception != null)
                            {
                                exception = ((DataServiceRequestException)exception).InnerException;
                                Assert.AreEqual(testCase.ExpectedClientErrorMessage, exception.Message, "Unexpected error message.");
                            }
                            else
                            {
                                Assert.IsNull(testCase.ExpectedClientErrorMessage, "Expected exception, but none was thrown.");
                            }
                        }
                    });
            }