diff --git a/core/src/test/java/org/jclouds/http/BaseHttpCommandExecutorServiceIntegrationTest.java b/core/src/test/java/org/jclouds/http/BaseHttpCommandExecutorServiceIntegrationTest.java index cddb9b4e25..03bf98d07c 100644 --- a/core/src/test/java/org/jclouds/http/BaseHttpCommandExecutorServiceIntegrationTest.java +++ b/core/src/test/java/org/jclouds/http/BaseHttpCommandExecutorServiceIntegrationTest.java @@ -20,6 +20,10 @@ package org.jclouds.http; import static org.testng.Assert.assertEquals; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.net.MalformedURLException; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -125,6 +129,35 @@ public abstract class BaseHttpCommandExecutorServiceIntegrationTest extends Base } } + /** + * Tests sending a big file to the server. + * Note: this is a heavy test, takes several minutes to finish. + * @throws java.io.IOException + */ + @Test + public void testUploadBigFile() throws IOException { + String filename = "jclouds"; + OutputStream os = null; + File f = null; + try { + //create a file, twice big as free heap memory + f = File.createTempFile(filename, "tmp"); + f.deleteOnExit(); + long length = Runtime.getRuntime().freeMemory() * 2; + os = new FileOutputStream(f.getAbsolutePath()); + for(long i = 0; i < length; i++) os.write('a'); + os.flush(); + os.close(); + + //upload and verify the response + assertEquals(client.postWithMd5("fileso", f).trim(), "created"); + + } finally { + if(os != null) os.close(); + if(f != null && f.exists()) f.delete(); + } + } + protected AtomicInteger postFailures = new AtomicInteger(); @BeforeTest diff --git a/core/src/test/java/org/jclouds/http/BaseJettyTest.java b/core/src/test/java/org/jclouds/http/BaseJettyTest.java index 17f7886588..6eae4c75d9 100644 --- a/core/src/test/java/org/jclouds/http/BaseJettyTest.java +++ b/core/src/test/java/org/jclouds/http/BaseJettyTest.java @@ -39,6 +39,8 @@ import javax.ws.rs.core.HttpHeaders; import org.jclouds.PropertiesBuilder; import org.jclouds.concurrent.internal.SyncProxy; import org.jclouds.encryption.EncryptionService; +import org.jclouds.encryption.internal.Base64; +import org.jclouds.encryption.internal.JCEEncryptionService; import org.jclouds.lifecycle.Closer; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.RestClientFactory; @@ -188,9 +190,20 @@ public abstract class BaseJettyTest { if (failEveryTenRequests(request, response)) return; if (request.getContentLength() > 0) { - response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().println( + if(request.getHeader("Content-MD5") != null) { + String expectedMd5 = request.getHeader("Content-MD5"); + String realMd5FromRequest = Base64.encodeBytes(new JCEEncryptionService().md5(request.getInputStream())); + boolean matched = expectedMd5.equals(realMd5FromRequest); + if(matched) { + response.setContentType("text/xml"); + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().println("created"); + } + } else { + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().println( Utils.toStringAndClose(request.getInputStream()) + "POST"); + } } else { handleAction(request, response); } @@ -227,9 +240,20 @@ public abstract class BaseJettyTest { } } else if (request.getMethod().equals("POST")) { if (request.getContentLength() > 0) { - response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().println( + if(request.getHeader("Content-MD5") != null) { + String expectedMd5 = request.getHeader("Content-MD5"); + String realMd5FromRequest = Base64.encodeBytes(new JCEEncryptionService().md5(request.getInputStream())); + boolean matched = expectedMd5.equals(realMd5FromRequest); + if(matched) { + response.setContentType("text/xml"); + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().println("created"); + } + } else { + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().println( Utils.toStringAndClose(request.getInputStream()) + "POST"); + } } else { handleAction(request, response); } @@ -300,7 +324,7 @@ public abstract class BaseJettyTest { /** * Fails every 10 requests. - * + * * @param request * @param response * @return diff --git a/core/src/test/java/org/jclouds/http/IntegrationTestAsyncClient.java b/core/src/test/java/org/jclouds/http/IntegrationTestAsyncClient.java index 2fe82cc22a..b8ff78d56f 100644 --- a/core/src/test/java/org/jclouds/http/IntegrationTestAsyncClient.java +++ b/core/src/test/java/org/jclouds/http/IntegrationTestAsyncClient.java @@ -18,7 +18,11 @@ */ package org.jclouds.http; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.io.InputStream; +import java.util.Collections; import java.util.Map; import javax.ws.rs.GET; @@ -28,9 +32,16 @@ import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.core.HttpHeaders; +import com.google.common.base.Charsets; +import com.google.common.base.Throwables; +import com.google.common.io.ByteStreams; +import org.jclouds.encryption.internal.Base64; +import org.jclouds.encryption.internal.JCEEncryptionService; import org.jclouds.http.functions.ParseSax; import org.jclouds.http.options.HttpRequestOptions; +import org.jclouds.rest.Binder; import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.ExceptionParser; @@ -49,7 +60,7 @@ import com.google.common.util.concurrent.ListenableFuture; /** * Sample test for the behaviour of our Integration Test jetty server. - * + * * @author Adrian Cole */ @Endpoint(Localhost.class) @@ -113,6 +124,23 @@ public interface IntegrationTestAsyncClient { } } + @POST + @Path("objects/{id}") + ListenableFuture postWithMd5(@PathParam("id") String id, + @BinderParam(BindToFilePayload.class) File file); + + static class BindToFilePayload implements Binder { + @Override + public void bindToRequest(HttpRequest request, Object payload) { + File f = (File) payload; + if (request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE) == null) + request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "application/unknown"); + request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH, Collections.singletonList(f.length() + "")); + request.getHeaders().replaceValues("Content-MD5", Collections.singletonList(Base64.encodeBytes(new JCEEncryptionService().md5(f)))); + request.setPayload(f); + } + } + @POST @Path("objects/{id}") @MapBinder(BindToJsonPayload.class) diff --git a/core/src/test/java/org/jclouds/http/IntegrationTestClient.java b/core/src/test/java/org/jclouds/http/IntegrationTestClient.java index da2d6b31be..8b8db881a3 100644 --- a/core/src/test/java/org/jclouds/http/IntegrationTestClient.java +++ b/core/src/test/java/org/jclouds/http/IntegrationTestClient.java @@ -18,6 +18,7 @@ */ package org.jclouds.http; +import java.io.File; import java.io.InputStream; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -51,6 +52,8 @@ public interface IntegrationTestClient { String postAsInputStream(String id, String toPut); + String postWithMd5(String id, File file); + String postJson(String id, String toPut); String action(String id, String action, Map options);