attempt to stabalize tests on build server

This commit is contained in:
Adrian Cole 2011-04-20 16:21:36 -07:00
parent 2f01afb3cc
commit d0a5278ca0
4 changed files with 136 additions and 114 deletions

View File

@ -24,6 +24,8 @@ import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.getLast; import static com.google.common.collect.Iterables.getLast;
import static com.google.common.io.ByteStreams.toByteArray; import static com.google.common.io.ByteStreams.toByteArray;
import static com.google.common.io.Closeables.closeQuietly; import static com.google.common.io.Closeables.closeQuietly;
import static org.jclouds.io.Payloads.newInputStreamPayload;
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
@ -60,12 +62,10 @@ import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler; import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.io.MutableContentMetadata; import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.RestAnnotationProcessor;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder; import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.io.CountingOutputStream; import com.google.common.io.CountingOutputStream;
@ -107,12 +107,15 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
InputStream in = null; InputStream in = null;
try { try {
in = consumeOnClose(connection.getInputStream()); in = consumeOnClose(connection.getInputStream());
} catch (IOException e) { } catch (Exception e) {
in = bufferAndCloseStream(connection.getErrorStream()); IOException ioe = getFirstThrowableOfType(e, IOException.class);
} catch (RuntimeException e) { if (ioe != null) {
closeQuietly(in); in = bufferAndCloseStream(connection.getErrorStream());
propagate(e); } else {
assert false : "should have propagated exception"; closeQuietly(in);
propagate(e);
assert false : "should have propagated exception";
}
} }
int responseCode = connection.getResponseCode(); int responseCode = connection.getResponseCode();
@ -130,7 +133,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
headerBuilder.putAll(header, connection.getHeaderFields().get(header)); headerBuilder.putAll(header, connection.getHeaderFields().get(header));
} }
ImmutableMultimap<String, String> headers = headerBuilder.build(); ImmutableMultimap<String, String> headers = headerBuilder.build();
Payload payload = in != null ? Payloads.newInputStreamPayload(in) : null; Payload payload = in != null ? newInputStreamPayload(in) : null;
if (payload != null) { if (payload != null) {
payload.getContentMetadata().setPropertiesFromHttpHeaders(headers); payload.getContentMetadata().setPropertiesFromHttpHeaders(headers);
builder.payload(payload); builder.payload(payload);
@ -202,7 +205,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
methodField.set(connection, request.getMethod()); methodField.set(connection, request.getMethod());
} catch (Exception e1) { } catch (Exception e1) {
logger.error(e, "could not set request method: ", request.getMethod()); logger.error(e, "could not set request method: ", request.getMethod());
Throwables.propagate(e1); propagate(e1);
} }
} }
@ -236,7 +239,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
"JDK 1.6 does not support >2GB chunks. Use chunked encoding, if possible."); "JDK 1.6 does not support >2GB chunks. Use chunked encoding, if possible.");
connection.setFixedLengthStreamingMode(length.intValue()); connection.setFixedLengthStreamingMode(length.intValue());
if (length.intValue() > 0) { if (length.intValue() > 0) {
connection.setRequestProperty("Expect", "100-continue"); connection.setRequestProperty("Expect", "100-continue");
} }
} }
CountingOutputStream out = new CountingOutputStream(connection.getOutputStream()); CountingOutputStream out = new CountingOutputStream(connection.getOutputStream());

View File

@ -63,6 +63,7 @@ import org.testng.annotations.BeforeTest;
import org.testng.annotations.Optional; import org.testng.annotations.Optional;
import org.testng.annotations.Parameters; import org.testng.annotations.Parameters;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -86,7 +87,7 @@ public abstract class BaseJettyTest {
static final Pattern actionPattern = Pattern.compile("/objects/(.*)/action/([a-z]*);?(.*)"); static final Pattern actionPattern = Pattern.compile("/objects/(.*)/action/([a-z]*);?(.*)");
@BeforeTest @BeforeTest
@Parameters({ "test-jetty-port" }) @Parameters( { "test-jetty-port" })
public void setUpJetty(@Optional("8123") final int testPort) throws Exception { public void setUpJetty(@Optional("8123") final int testPort) throws Exception {
this.testPort = testPort; this.testPort = testPort;
@ -96,62 +97,69 @@ public abstract class BaseJettyTest {
Handler server1Handler = new AbstractHandler() { Handler server1Handler = new AbstractHandler() {
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException { throws IOException, ServletException {
if (failIfNoContentLength(request, response)) { InputStream body = request.getInputStream();
return; try {
} else if (target.indexOf("sleep") > 0) { if (failIfNoContentLength(request, response)) {
try { return;
Thread.sleep(100); } else if (target.indexOf("sleep") > 0) {
} catch (InterruptedException e) { try {
propagate(e); Thread.sleep(100);
} } catch (InterruptedException e) {
response.setContentType("text/xml"); propagate(e);
response.setStatus(HttpServletResponse.SC_OK); }
} else if (target.indexOf("redirect") > 0) { response.setContentType("text/xml");
response.sendRedirect("https://localhost:" + (testPort + 1) + "/"); response.setStatus(HttpServletResponse.SC_OK);
} else if (target.indexOf("101constitutions") > 0) { } else if (target.indexOf("redirect") > 0) {
response.setContentType("text/plain"); response.sendRedirect("https://localhost:" + (testPort + 1) + "/");
response.setHeader("Content-MD5", md5); } else if (target.indexOf("101constitutions") > 0) {
response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/plain");
copy(oneHundredOneConstitutions.getInput(), response.getOutputStream()); response.setHeader("Content-MD5", md5);
} else if (request.getMethod().equals("PUT")) { response.setStatus(HttpServletResponse.SC_OK);
if (request.getContentLength() > 0) { copy(oneHundredOneConstitutions.getInput(), response.getOutputStream());
} else if (request.getMethod().equals("PUT")) {
if (request.getContentLength() > 0) {
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(Strings2.toStringAndClose(body) + "PUT");
} else {
response.sendError(500, "no content");
}
} else if (request.getMethod().equals("POST")) {
// don't redirect large objects
if (request.getContentLength() < 10240 && redirectEveryTwentyRequests(request, response))
return;
if (failEveryTenRequests(request, response))
return;
if (request.getContentLength() > 0) {
handlePost(request, response);
} else {
handleAction(request, response);
}
} else if (request.getHeader("range") != null) {
response.sendError(404, "no content");
} else if (request.getHeader("test") != null) {
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("test");
} else if (request.getMethod().equals("HEAD")) {
/*
* NOTE: by HTML specification, HEAD response MUST NOT include a body
*/
response.setContentType("text/xml");
response.setStatus(HttpServletResponse.SC_OK); response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(Strings2.toStringAndClose(request.getInputStream()) + "PUT");
} else { } else {
response.sendError(500, "no content"); if (failEveryTenRequests(request, response))
return;
response.setContentType("text/xml");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(XML);
} }
} else if (request.getMethod().equals("POST")) { ((Request) request).setHandled(true);
// don't redirect large objects } catch (IOException e) {
if (request.getContentLength() < 10240 && redirectEveryTwentyRequests(request, response)) if (body != null)
return; closeQuietly(body);
if (failEveryTenRequests(request, response)) response.sendError(500, Throwables.getStackTraceAsString(e));
return;
if (request.getContentLength() > 0) {
handlePost(request, response);
} else {
handleAction(request, response);
}
} else if (request.getHeader("range") != null) {
response.sendError(404, "no content");
} else if (request.getHeader("test") != null) {
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("test");
} else if (request.getMethod().equals("HEAD")) {
/*
* NOTE: by HTML specification, HEAD response MUST NOT include a body
*/
response.setContentType("text/xml");
response.setStatus(HttpServletResponse.SC_OK);
} else {
if (failEveryTenRequests(request, response))
return;
response.setContentType("text/xml");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(XML);
} }
((Request) request).setHandled(true);
} }
}; };
@ -172,11 +180,12 @@ public abstract class BaseJettyTest {
} }
private static void handlePost(HttpServletRequest request, HttpServletResponse response) throws IOException { private static void handlePost(HttpServletRequest request, HttpServletResponse response) throws IOException {
InputStream body = request.getInputStream();
try { try {
if (request.getHeader("Content-MD5") != null) { if (request.getHeader("Content-MD5") != null) {
String expectedMd5 = request.getHeader("Content-MD5"); String expectedMd5 = request.getHeader("Content-MD5");
String realMd5FromRequest; String realMd5FromRequest;
realMd5FromRequest = CryptoStreams.md5Base64(InputSuppliers.of(request.getInputStream())); realMd5FromRequest = CryptoStreams.md5Base64(InputSuppliers.of(body));
boolean matched = expectedMd5.equals(realMd5FromRequest); boolean matched = expectedMd5.equals(realMd5FromRequest);
if (matched) { if (matched) {
response.setStatus(HttpServletResponse.SC_OK); response.setStatus(HttpServletResponse.SC_OK);
@ -185,52 +194,60 @@ public abstract class BaseJettyTest {
response.sendError(500, "didn't match"); response.sendError(500, "didn't match");
} }
} else { } else {
String responseString = (request.getContentLength() < 10240) ? Strings2.toStringAndClose(body) + "POST"
: "POST";
body = null;
for (String header : new String[] { "Content-Disposition", HttpHeaders.CONTENT_LANGUAGE, for (String header : new String[] { "Content-Disposition", HttpHeaders.CONTENT_LANGUAGE,
HttpHeaders.CONTENT_ENCODING }) HttpHeaders.CONTENT_ENCODING })
if (request.getHeader(header) != null) { if (request.getHeader(header) != null) {
response.addHeader("x-" + header, request.getHeader(header)); response.addHeader("x-" + header, request.getHeader(header));
} }
response.setStatus(HttpServletResponse.SC_OK); response.setStatus(HttpServletResponse.SC_OK);
String responseString = "POST";
if (request.getContentLength() < 10240) {
responseString = Strings2.toStringAndClose(request.getInputStream()) + "POST";
} else {
closeQuietly(request.getInputStream());
}
response.getWriter().println(responseString); response.getWriter().println(responseString);
} }
} catch (IOException e) { } catch (IOException e) {
response.sendError(500, e.toString()); if (body != null)
closeQuietly(body);
response.sendError(500, Throwables.getStackTraceAsString(e));
} }
} }
protected void setupAndStartSSLServer(final int testPort) throws Exception { protected void setupAndStartSSLServer(final int testPort) throws Exception {
Handler server2Handler = new AbstractHandler() { Handler server2Handler = new AbstractHandler() {
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException { throws IOException, ServletException {
if (request.getMethod().equals("PUT")) { InputStream body = request.getInputStream();
if (request.getContentLength() > 0) { try {
if (request.getMethod().equals("PUT")) {
String text = Strings2.toStringAndClose(body);
body = null;
if (request.getContentLength() > 0) {
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(text + "PUTREDIRECT");
}
} else if (request.getMethod().equals("POST")) {
if (request.getContentLength() > 0) {
handlePost(request, response);
} else {
handleAction(request, response);
}
} else if (request.getMethod().equals("HEAD")) {
/*
* NOTE: by HTML specification, HEAD response MUST NOT include a body
*/
response.setContentType("text/xml");
response.setStatus(HttpServletResponse.SC_OK); response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(Strings2.toStringAndClose(request.getInputStream()) + "PUTREDIRECT");
}
} else if (request.getMethod().equals("POST")) {
if (request.getContentLength() > 0) {
handlePost(request, response);
} else { } else {
handleAction(request, response); response.setContentType("text/xml");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(XML2);
} }
} else if (request.getMethod().equals("HEAD")) { ((Request) request).setHandled(true);
/* } catch (IOException e) {
* NOTE: by HTML specification, HEAD response MUST NOT include a body if (body != null)
*/ closeQuietly(body);
response.setContentType("text/xml"); response.sendError(500, Throwables.getStackTraceAsString(e));
response.setStatus(HttpServletResponse.SC_OK);
} else {
response.setContentType("text/xml");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(XML2);
} }
((Request) request).setHandled(true);
} }
}; };
@ -261,12 +278,12 @@ public abstract class BaseJettyTest {
} }
public static RestContextBuilder<IntegrationTestClient, IntegrationTestAsyncClient> newBuilder(int testPort, public static RestContextBuilder<IntegrationTestClient, IntegrationTestAsyncClient> newBuilder(int testPort,
Properties properties, Module... connectionModules) { Properties properties, Module... connectionModules) {
properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
properties.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true"); properties.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
RestContextSpec<IntegrationTestClient, IntegrationTestAsyncClient> contextSpec = contextSpec("test", RestContextSpec<IntegrationTestClient, IntegrationTestAsyncClient> contextSpec = contextSpec("test",
"http://localhost:" + testPort, "1", "", "identity", null, IntegrationTestClient.class, "http://localhost:" + testPort, "1", "", "identity", null, IntegrationTestClient.class,
IntegrationTestAsyncClient.class, ImmutableSet.<Module> copyOf(connectionModules)); IntegrationTestAsyncClient.class, ImmutableSet.<Module> copyOf(connectionModules));
return createContextBuilder(contextSpec, properties); return createContextBuilder(contextSpec, properties);
} }
@ -300,7 +317,7 @@ public abstract class BaseJettyTest {
} }
protected boolean redirectEveryTwentyRequests(HttpServletRequest request, HttpServletResponse response) protected boolean redirectEveryTwentyRequests(HttpServletRequest request, HttpServletResponse response)
throws IOException { throws IOException {
if (cycle.incrementAndGet() % 20 == 0) { if (cycle.incrementAndGet() % 20 == 0) {
response.sendRedirect("http://localhost:" + (testPort + 1) + "/"); response.sendRedirect("http://localhost:" + (testPort + 1) + "/");
((Request) request).setHandled(true); ((Request) request).setHandled(true);

View File

@ -61,37 +61,39 @@ public class BackoffLimitedRetryHandlerTest {
@Test @Test
void testExponentialBackoffDelayDefaultMaxInterval500() throws InterruptedException { void testExponentialBackoffDelayDefaultMaxInterval500() throws InterruptedException {
long acceptableDelay = 25; // Delay to forgive if tests run long. long period = 100;
long acceptableDelay = period - 1;
long startTime = System.nanoTime(); long startTime = System.nanoTime();
handler.imposeBackoffExponentialDelay(1, "TEST FAILURE: 1"); handler.imposeBackoffExponentialDelay(period, 2, 1, 5, "TEST FAILURE: 1");
long elapsedTime = (System.nanoTime() - startTime) / 1000000; long elapsedTime = (System.nanoTime() - startTime) / 1000000;
assert (elapsedTime >= 49) : elapsedTime; assert (elapsedTime >= period - 1) : elapsedTime;
assertTrue(elapsedTime < 50 + acceptableDelay); assertTrue(elapsedTime < period + acceptableDelay);
startTime = System.nanoTime(); startTime = System.nanoTime();
handler.imposeBackoffExponentialDelay(2, "TEST FAILURE: 2"); handler.imposeBackoffExponentialDelay(period, 2, 2, 5, "TEST FAILURE: 2");
elapsedTime = (System.nanoTime() - startTime) / 1000000; elapsedTime = (System.nanoTime() - startTime) / 1000000;
assert (elapsedTime >= 199) : elapsedTime; assert (elapsedTime >= period * 4 - 1) : elapsedTime;
assertTrue(elapsedTime < 200 + acceptableDelay); assertTrue(elapsedTime < period * 9);
startTime = System.nanoTime(); startTime = System.nanoTime();
handler.imposeBackoffExponentialDelay(3, "TEST FAILURE: 3"); handler.imposeBackoffExponentialDelay(period, 2, 3, 5, "TEST FAILURE: 3");
elapsedTime = (System.nanoTime() - startTime) / 1000000; elapsedTime = (System.nanoTime() - startTime) / 1000000;
assert (elapsedTime >= 449) : elapsedTime; assert (elapsedTime >= period * 9 - 1) : elapsedTime;
assertTrue(elapsedTime < 450 + acceptableDelay); assertTrue(elapsedTime < period * 10);
startTime = System.nanoTime(); startTime = System.nanoTime();
handler.imposeBackoffExponentialDelay(4, "TEST FAILURE: 4"); handler.imposeBackoffExponentialDelay(period, 2, 4, 5, "TEST FAILURE: 4");
elapsedTime = (System.nanoTime() - startTime) / 1000000; elapsedTime = (System.nanoTime() - startTime) / 1000000;
assert (elapsedTime >= 499) : elapsedTime; assert (elapsedTime >= period * 10 - 1) : elapsedTime;
assertTrue(elapsedTime < 550 + acceptableDelay * 2); assertTrue(elapsedTime < period * 11);
startTime = System.nanoTime(); startTime = System.nanoTime();
handler.imposeBackoffExponentialDelay(5, "TEST FAILURE: 5"); handler.imposeBackoffExponentialDelay(period, 2, 5, 5, "TEST FAILURE: 5");
elapsedTime = (System.nanoTime() - startTime) / 1000000; elapsedTime = (System.nanoTime() - startTime) / 1000000;
assert (elapsedTime >= 499) : elapsedTime; assert (elapsedTime >= period * 10 - 1) : elapsedTime;
assertTrue(elapsedTime < 550 + acceptableDelay * 2); assertTrue(elapsedTime < period * 11);
} }
TransformingHttpCommandExecutorServiceImpl executorService; TransformingHttpCommandExecutorServiceImpl executorService;

View File

@ -36,7 +36,7 @@ import com.google.common.base.Supplier;
*/ */
@Test(groups = "unit", sequential = true) @Test(groups = "unit", sequential = true)
public class RetryablePredicateTest { public class RetryablePredicateTest {
public static int SLOW_BUILD_SERVER_GRACE = 50; public static int SLOW_BUILD_SERVER_GRACE = 100;
@Test @Test
void testFalseOnIllegalStateExeception() { void testFalseOnIllegalStateExeception() {