/// <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)); } }
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)); } }
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(); } }
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(); } }
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)); } }