/// <summary> Helper test to test canceling media upload in the middle.</summary>
        /// <param name="cancelRequest">The request index to cancel.</param>
        private void TestChunkUploadFail_Cancel(int cancelRequest)
        {
            int chunkSize = 100;
            var payload   = Encoding.UTF8.GetBytes(UploadTestData);

            var handler = new MultipleChunksMessageHandler(true, ServerError.None, payload.Length, chunkSize, false);

            handler.CancellationTokenSource = new CancellationTokenSource();
            handler.CancelRequestNum        = cancelRequest;
            using (var service = new MockClientService(new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            }))
            {
                var stream = new MemoryStream(payload);
                var upload = new MockResumableUpload(service, stream, "text/plain");
                upload.ChunkSize = chunkSize;

                try
                {
                    var result = upload.UploadAsync(handler.CancellationTokenSource.Token).Result;
                    Assert.Fail();
                }
                catch (AggregateException ae)
                {
                    Assert.IsInstanceOf <TaskCanceledException>(ae.InnerException);
                }

                Assert.That(handler.Calls, Is.EqualTo(cancelRequest));
            }
        }
        public void TestUploadProgress()
        {
            int chunkSize = 200;
            var payload   = Encoding.UTF8.GetBytes(UploadTestData);

            var handler = new MultipleChunksMessageHandler(true, ServerError.None, payload.Length, chunkSize);

            using (var service = new MockClientService(new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            }))
            {
                var stream = new MemoryStream(payload);
                var upload = new MockResumableUpload(service, stream, "text/plain");
                upload.ChunkSize = chunkSize;

                var progressEvents = new List <IUploadProgress>();
                upload.ProgressChanged += (progress) =>
                {
                    progressEvents.Add(progress);
                };

                upload.Upload();

                // Starting (1) + Uploading (2) + Completed (1)
                Assert.That(progressEvents.Count, Is.EqualTo(4));
                Assert.That(progressEvents[0].Status, Is.EqualTo(UploadStatus.Starting));
                Assert.That(progressEvents[1].Status, Is.EqualTo(UploadStatus.Uploading));
                Assert.That(progressEvents[2].Status, Is.EqualTo(UploadStatus.Uploading));
                Assert.That(progressEvents[3].Status, Is.EqualTo(UploadStatus.Completed));
            }
        }
Exemple #3
0
        public void TestUploadProgress()
        {
            using (var server = new MockResumableUploadServer())
            {
                var payload = Encoding.UTF8.GetBytes(UploadTestData);
                var stream  = new MemoryStream(payload);
                var len     = payload.Length;

                server.ExpectRequest(context =>
                {
                    // Prepare the response.
                    context.Response.Headers.Add(HttpResponseHeader.Location, server.UploadUri.ToString());
                });

                server.ExpectRequest(context =>
                {
                });

                var progressEvents = new Queue <IUploadProgress>();

                var upload = new MockResumableUpload(server, stream, "text/plain");

                upload.ProgressChanged += (progress) => {
                    progressEvents.Enqueue(progress);
                };

                upload.Upload();
            }
        }
        /// <summary> Test helper to test a fail uploading by with the given server error.</summary>
        private void SubtestChunkUploadFail(ServerError error)
        {
            int chunkSize = 100;
            var payload   = Encoding.UTF8.GetBytes(UploadTestData);

            var handler = new MultipleChunksMessageHandler(true, error, payload.Length,
                                                           chunkSize, true);

            using (var service = new MockClientService(new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            }))
            {
                var stream = new MemoryStream(payload);
                var upload = new MockResumableUpload(service, stream, "text/plain");
                upload.ChunkSize = chunkSize;

                IUploadProgress lastProgressStatus = null;
                upload.ProgressChanged += (p) =>
                {
                    lastProgressStatus = p;
                };
                upload.Upload();

                var exepctedCalls = MultipleChunksMessageHandler.ErrorOnCall +
                                    service.HttpClient.MessageHandler.NumTries - 1;
                Assert.That(handler.Calls, Is.EqualTo(exepctedCalls));
                Assert.NotNull(lastProgressStatus);
                Assert.NotNull(lastProgressStatus.Exception);
                Assert.That(lastProgressStatus.Status, Is.EqualTo(UploadStatus.Failed));
            }
        }
Exemple #5
0
        public void TestUploadEmptyFile()
        {
            using (var server = new MockResumableUploadServer())
            {
                var stream = new MemoryStream(new byte[0]);

                server.ExpectRequest(context =>
                {
                    Assert.That(context.Request.QueryString["uploadType"], Is.EqualTo("resumable"));
                    Assert.That(context.Request.QueryString["alt"], Is.EqualTo("json"));
                    Assert.That(context.Request.Headers["X-Upload-Content-Type"], Is.EqualTo("text/plain"));
                    Assert.That(context.Request.Headers["X-Upload-Content-Length"], Is.EqualTo("0"));

                    context.Response.Headers.Add(HttpResponseHeader.Location, server.UploadUri.ToString());
                });

                server.ExpectRequest(context =>
                {
                    Assert.That(context.Request.Url.AbsoluteUri, Is.EqualTo(server.UploadUri.ToString()));
                    var range = String.Format("bytes */0");
                    Assert.That(context.Request.Headers["Content-Range"], Is.EqualTo(range));
                });

                var upload = new MockResumableUpload(server, stream, "text/plain");
                upload.Upload();
            }
        }
Exemple #6
0
        public void TestUploadSingleChunk()
        {
            using (var server = new MockResumableUploadServer())
            {
                var stream = new MemoryStream(Encoding.UTF8.GetBytes(UploadTestData));

                server.ExpectRequest(context =>
                {
                    Assert.That(context.Request.QueryString["uploadType"], Is.EqualTo("resumable"));
                    Assert.That(context.Request.QueryString["alt"], Is.EqualTo("json"));
                    Assert.That(context.Request.Headers["X-Upload-Content-Type"], Is.EqualTo("text/plain"));
                    Assert.That(context.Request.Headers["X-Upload-Content-Length"], Is.EqualTo(stream.Length.ToString()));
                    context.Response.Headers.Add(HttpResponseHeader.Location, server.UploadUri.ToString());
                });

                server.ExpectRequest(context =>
                {
                    Assert.That(context.Request.Url.AbsoluteUri, Is.EqualTo(server.UploadUri.ToString()));
                    var range = String.Format("bytes 0-{0}/{1}", UploadTestData.Length - 1,
                                              UploadTestData.Length);
                    Assert.That(context.Request.Headers["Content-Range"], Is.EqualTo(range));
                });

                var upload = new MockResumableUpload(server, stream, "text/plain");
                upload.Upload();
            }
        }
Exemple #7
0
        public void TestUploadMultipleChunk()
        {
            using (var server = new MockResumableUploadServer())
            {
                var       payload   = Encoding.UTF8.GetBytes(UploadTestData);
                var       stream    = new MemoryStream(payload);
                const int chunkSize = 100;

                var len = payload.Length;

                server.ExpectRequest(context =>
                {
                    // Validate the request
                    Assert.That(context.Request.QueryString["uploadType"], Is.EqualTo("resumable"));
                    Assert.That(context.Request.QueryString["alt"], Is.EqualTo("json"));
                    Assert.That(context.Request.Headers["X-Upload-Content-Type"], Is.EqualTo("text/plain"));
                    Assert.That(context.Request.Headers["X-Upload-Content-Length"], Is.EqualTo(stream.Length.ToString()));

                    // Prepare the response.
                    context.Response.Headers.Add(HttpResponseHeader.Location, server.UploadUri.ToString());
                });

                MemoryStream dataStream = new MemoryStream();

                int chunkStart = 0;
                while (chunkStart < len)
                {
                    var chunkEnd = Math.Min(len, chunkStart + chunkSize) - 1;
                    var range    = String.Format("bytes {0}-{1}/{2}", chunkStart, chunkEnd, UploadTestData.Length);
                    server.ExpectRequest(context =>
                    {
                        var buffer = new byte[100];
                        while (true)
                        {
                            int x = context.Request.InputStream.Read(buffer, 0, buffer.Length);
                            if (x == 0)
                            {
                                break;
                            }
                            dataStream.Write(buffer, 0, x);
                        }
                        Assert.That(context.Request.Url.AbsoluteUri, Is.EqualTo(server.UploadUri.ToString()));
                        Assert.That(context.Request.Headers["Content-Range"], Is.EqualTo(range));
                    });
                    chunkStart += chunkSize;
                }

                var upload = new MockResumableUpload(server, stream, "text/plain");
                upload.ChunkSize = chunkSize;
                upload.Upload();
                Assert.That(payload, Is.EqualTo(dataStream.ToArray()));
            }
        }
        private void SubtestTestChunkUpload(bool knownSize, ServerError error = ServerError.None)
        {
            // -If error is none - there isn't any error, so there should be 6 calls (1 to initialize and 5 successful
            // upload requests.
            // -If error isn't supported by the media upload (4xx) - the upload fails.
            // Otherwise, we simulate server 503 error or exception, as following:
            // On the 4th chunk (when server received bytes 300-399), we mimic an error.
            // In the next request we expect the client to send the content range header with "bytes */[size]", and
            // server return that the upload was interrupted after 299 bytes. From that point the server works as
            // expected, and received the last chunks successfully
            int chunkSize = 100;
            var payload   = Encoding.UTF8.GetBytes(UploadTestData);

            var handler = new MultipleChunksMessageHandler(knownSize, error, payload.Length, chunkSize);

            using (var service = new MockClientService(new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            }))
            {
                var stream = knownSize ? new MemoryStream(payload) : new UnknownSizeMemoryStream(payload);
                var upload = new MockResumableUpload(service, stream, "text/plain");
                upload.ChunkSize = chunkSize;

                IUploadProgress lastProgress = null;
                upload.ProgressChanged += (p) => lastProgress = p;
                upload.Upload();

                Assert.NotNull(lastProgress);

                if (error == ServerError.NotFound)
                {
                    // upload fails
                    Assert.That(lastProgress.Status, Is.EqualTo(UploadStatus.Failed));
                    Assert.That(handler.Calls, Is.EqualTo(MultipleChunksMessageHandler.ErrorOnCall));
                    Assert.True(lastProgress.Exception.Message.Contains(
                                    @"Message[Login Required] Location[Authorization - header] Reason[required] Domain[global]"),
                                "Error message is invalid");
                }
                else
                {
                    Assert.That(lastProgress.Status, Is.EqualTo(UploadStatus.Completed));
                    Assert.That(payload, Is.EqualTo(handler.ReceivedData.ToArray()));
                    // if server doesn't supports errors there should be 6 request - 1 initialize request and 5
                    // requests to upload data (the whole data send is divided to 5 chunks).
                    // if server supports errors, there should be an additional 2 requests (1 to query where the upload
                    // was interrupted and 1 to resend the data)
                    Assert.That(handler.Calls, error != ServerError.None ? Is.EqualTo(8) : Is.EqualTo(6));
                }
            }
        }
        /// <summary>Test helper to test a fail uploading by with the given server error.</summary>
        /// <param name="error">The error kind.</param>
        /// <param name="resume">Whether we should resume uploading the stream after the failure.</param>
        /// <param name="errorOnResume">Whether the first call after resuming should fail.</param>
        private void SubtestChunkUploadFail(ServerError error, bool resume = false, bool errorOnResume = false)
        {
            int chunkSize = 100;
            var payload   = Encoding.UTF8.GetBytes(UploadTestData);

            var handler = new MultipleChunksMessageHandler(true, error, payload.Length, chunkSize, true);

            using (var service = new MockClientService(new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            }))
            {
                var stream = new MemoryStream(payload);
                var upload = new MockResumableUpload(service, stream, "text/plain");
                upload.chunkSize = chunkSize;

                IUploadProgress lastProgressStatus = null;
                upload.ProgressChanged += (p) =>
                {
                    lastProgressStatus = p;
                };
                upload.Upload();

                // Upload should fail.
                var exepctedCalls = MultipleChunksMessageHandler.ErrorOnCall +
                                    service.HttpClient.MessageHandler.NumTries - 1;
                Assert.That(handler.Calls, Is.EqualTo(exepctedCalls));
                Assert.NotNull(lastProgressStatus);
                Assert.NotNull(lastProgressStatus.Exception);
                Assert.That(lastProgressStatus.Status, Is.EqualTo(UploadStatus.Failed));

                if (resume)
                {
                    // Hack the handler, so when calling the resume method the upload should succeeded.
                    handler.ResumeFromCall = exepctedCalls + 1;
                    handler.ErrorOnResume  = errorOnResume;

                    upload.Resume();

                    // The first request after resuming is to query the server where the media upload was interrupted.
                    // If errorOnResume is true, the server's first response will be 503.
                    exepctedCalls += MultipleChunksMessageHandler.CallAfterResume + 1 + (errorOnResume ? 1 : 0);
                    Assert.That(handler.Calls, Is.EqualTo(exepctedCalls));
                    Assert.NotNull(lastProgressStatus);
                    Assert.Null(lastProgressStatus.Exception);
                    Assert.That(lastProgressStatus.Status, Is.EqualTo(UploadStatus.Completed));
                    Assert.That(payload, Is.EqualTo(handler.ReceivedData.ToArray()));
                }
            }
        }
        public void TestUploadEmptyFile()
        {
            var handler = new EmptyFileMessageHandler();

            using (var service = new MockClientService(new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            }))
            {
                var stream = new MemoryStream(new byte[0]);
                var upload = new MockResumableUpload(service, stream, "text/plain");
                upload.Upload();
            }

            Assert.That(handler.Calls, Is.EqualTo(2));
        }
        /// <summary>Tests a single upload request.</summary>
        /// <param name="knownSize">Defines if the stream size is known</param>
        /// <param name="expectedCalls">How many HTTP calls should be made to the server</param>
        /// <param name="error">Defines the type of error this test tests. The default value is none</param>
        /// <param name="chunkSize">Defines the size of a chunk</param>
        /// <param name="readBytesOnError">How many bytes the server reads when it returns 5xx</param>
        private void SubtestTestChunkUpload(bool knownSize, int expectedCalls, ServerError error = ServerError.None,
                                            int chunkSize = 100, int readBytesOnError = 0)
        {
            // If an error isn't supported by the media upload (4xx) - the upload fails.
            // Otherwise, we simulate server 503 error or exception, as following:
            // On the 3th chunk (4th chunk including the initial request), we mimic an error.
            // In the next request we expect the client to send the content range header with "bytes */[size]", and
            // server return that the upload was interrupted after x bytes.
            // From that point the server works as expected, and received the last chunks successfully
            var payload = Encoding.UTF8.GetBytes(UploadTestData);

            var handler = new MultipleChunksMessageHandler(knownSize, error, payload.Length, chunkSize);

            handler.ReadBytesOnError = readBytesOnError;
            using (var service = new MockClientService(new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            }))
            {
                var stream = knownSize ? new MemoryStream(payload) : new UnknownSizeMemoryStream(payload);
                var upload = new MockResumableUpload(service, stream, "text/plain");
                upload.chunkSize = chunkSize;

                IUploadProgress lastProgress = null;
                upload.ProgressChanged += (p) => lastProgress = p;
                upload.Upload();

                Assert.NotNull(lastProgress);

                if (error == ServerError.NotFound)
                {
                    // Upload fails.
                    Assert.That(lastProgress.Status, Is.EqualTo(UploadStatus.Failed));
                    Assert.True(lastProgress.Exception.Message.Contains(
                                    @"Message[Login Required] Location[Authorization - header] Reason[required] Domain[global]"),
                                "Error message is invalid");
                }
                else
                {
                    Assert.That(lastProgress.Status, Is.EqualTo(UploadStatus.Completed));
                    Assert.That(payload, Is.EqualTo(handler.ReceivedData.ToArray()));
                }
                Assert.That(handler.Calls, Is.EqualTo(expectedCalls));
            }
        }
        public void TestUploadSingleChunk_ExactChunkSize()
        {
            var stream  = new MemoryStream(Encoding.UTF8.GetBytes(UploadTestData));
            var handler = new SingleChunkMessageHandler()
            {
                StreamLength = stream.Length
            };

            using (var service = new MockClientService(new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            }))
            {
                // Chunk size is the exact size we are sending.
                var upload = new MockResumableUpload(service, "", "POST", stream, "text/plain", UploadTestData.Length);
                upload.Upload();
            }

            Assert.That(handler.Calls, Is.EqualTo(2));
        }
        private void SubtestTestChunkUpload_ServerRecievedPartOfRequest(bool knownSize)
        {
            int chunkSize = 400;
            var payload   = Encoding.UTF8.GetBytes(UploadTestData);

            var handler = new ReadPartialMessageHandler(knownSize, payload.Length, chunkSize);

            using (var service = new MockClientService(new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            }))
            {
                var stream = knownSize ? new MemoryStream(payload) : new UnknownSizeMemoryStream(payload);
                var upload = new MockResumableUpload(service, stream, "text/plain", chunkSize);
                upload.Upload();

                Assert.That(payload, Is.EqualTo(handler.ReceivedData.ToArray()));
                // 1 initialization request and 2 uploads requests.
                Assert.That(handler.Calls, Is.EqualTo(3));
            }
        }