Skip to content

Commit

Permalink
Flaky h2 bookstore test #7097 (#7137)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielkec authored Jun 29, 2023
1 parent 4516a81 commit df84c0e
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 290 deletions.
34 changes: 21 additions & 13 deletions tests/apps/bookstore/bookstore-se/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@
<artifactId>helidon-tests-apps-bookstore-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.nima.testing.junit5
</groupId>
<artifactId>helidon-nima-testing-junit5-webserver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand All @@ -101,12 +107,6 @@
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand All @@ -128,13 +128,21 @@
<compilerArg>--enable-preview</compilerArg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
<executions>
<execution>
<id>default-testCompile</id>
<configuration>
<!--
We use HTTP client from tests, and we do not want it as a module dependency
-->
<compilerArgs>
<compilerArg>--enable-preview</compilerArg>
<compilerArg>--add-modules</compilerArg>
<compilerArg>java.net.http</compilerArg>
</compilerArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,29 +73,31 @@ static WebServer startServer() {
* @return the created {@link WebServer} instance
*/
static WebServer startServer(boolean ssl, boolean http2, boolean compression) {
WebServerConfig.Builder serverBuilder = WebServerConfig.builder();
setupServer(serverBuilder, ssl);

WebServer server = serverBuilder.build();
server.start();
String url = (ssl ? "https" : "http") + "://localhost:" + server.port() + SERVICE_PATH;
System.out.println("WEB server is up! " + url + " [ssl=" + ssl + ", http2=" + http2
+ ", compression=" + compression + "]");

return server;
}

static void setupServer(WebServerConfig.Builder serverBuilder, boolean ssl) {
// load logging configuration
LogConfig.configureRuntime();

// By default this will pick up application.yaml from the classpath
Config config = Config.create();

// Build server config based on params
var serverBuilder = WebServer.builder()
serverBuilder
.addRouting(createRouting(config))
.config(config.get("server"))
.update(it -> configureJsonSupport(it, config))
.update(it -> configureSsl(it, ssl));
// .enableCompression(compression);

configureJsonSupport(serverBuilder, config);

WebServer server = serverBuilder.build();
server.start();
String url = (ssl ? "https" : "http") + "://localhost:" + server.port() + SERVICE_PATH;
System.out.println("WEB server is up! " + url + " [ssl=" + ssl + ", http2=" + http2
+ ", compression=" + compression + "]");

return server;
}

static JsonLibrary getJsonLibrary(Config config) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ app:
json-library: jsonp

server:
port: 8080
# Random port
port: -1
host: 0.0.0.0

# ssl:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$
#io.helidon.config.level=INFO
#io.helidon.security.level=INFO
#io.helidon.common.level=INFO
#io.netty.level=INFO
#io.helidon.nima.level=ALL
Original file line number Diff line number Diff line change
Expand Up @@ -16,48 +16,51 @@

package io.helidon.tests.apps.bookstore.se;

import io.helidon.common.configurable.ThreadPoolSupplier;
import io.helidon.nima.testing.junit5.webserver.ServerTest;
import io.helidon.nima.testing.junit5.webserver.SetUpServer;
import io.helidon.nima.webserver.WebServer;
import io.helidon.nima.webserver.WebServerConfig;
import org.junit.jupiter.api.Test;

import javax.net.ssl.SSLContext;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

import io.helidon.common.configurable.ThreadPoolSupplier;

import io.helidon.nima.webserver.WebServer;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import static io.helidon.tests.apps.bookstore.se.TestServer.APPLICATION_JSON;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.fail;

/**
* Tests SSL/TLS with HTTP 2 upgrades and compression.
*/
@Disabled("https://github.com/helidon-io/helidon/issues/7097")
@ServerTest
public class Http2SslTest {

private static WebServer webServer;
private static OkHttpClient client;

@BeforeAll
public static void startServer() throws Exception {
webServer = TestServer.start(true, true, true);
client = TestServer.newOkHttpClient(true, true);
private static HttpClient client;
private final URI baseSslUri;

public Http2SslTest(WebServer server) throws Exception {
SSLContext sslContext = TestServer.setupSSLTrust();
baseSslUri = URI.create("https://localhost:" + server.port());
client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.sslContext(sslContext)
.connectTimeout(Duration.ofSeconds(5))
.build();
}

@AfterAll
public static void stopServer() throws Exception {
TestServer.stop(webServer);
@SetUpServer
static void server(WebServerConfig.Builder server) {
Main.setupServer(server, true);
}

@Test
Expand All @@ -72,74 +75,110 @@ public void testHelloWorldHttp2SslCompression() throws Exception {

@Test
public void testHelloWorldHttp2SslPostFirst() throws Exception {
Request.Builder builder = TestServer.newRequestBuilder(webServer, "/books", true);
Request postBook = builder.post(
RequestBody.create(APPLICATION_JSON, TestServer.getBookAsJson())).build();
try (Response postBookRes = client.newCall(postBook).execute()) {
assertThat(postBookRes.code(), is(200));
assertThat(postBookRes.protocol(), is(Protocol.HTTP_2));
}

builder = TestServer.newRequestBuilder(webServer, "/books/123456", true);
Request deleteBook = builder.delete().build();
try (Response deleteBookRes = client.newCall(deleteBook).execute()) {
assertThat(deleteBookRes.code(), is(200));
assertThat(deleteBookRes.protocol(), is(Protocol.HTTP_2));
}
HttpRequest postBookReq = HttpRequest.newBuilder()
.uri(baseSslUri.resolve("/books"))
.version(HttpClient.Version.HTTP_2)
.setHeader("Accept-Encoding", "gzip")
.POST(HttpRequest.BodyPublishers.ofString(TestServer.getBookAsJson()))
.build();

var postBookRes = client.send(postBookReq, HttpResponse.BodyHandlers.ofString());
assertThat(postBookRes.statusCode(), is(200));
assertThat(postBookRes.version(), is(HttpClient.Version.HTTP_2));

HttpRequest deleteBookReq = HttpRequest.newBuilder()
.uri(baseSslUri.resolve("/books/123456"))
.version(HttpClient.Version.HTTP_2)
.setHeader("Accept-Encoding", "gzip")
.DELETE()
.build();

var deleteBookRes = client.send(deleteBookReq, HttpResponse.BodyHandlers.ofString());
assertThat(deleteBookRes.statusCode(), is(200));
assertThat(deleteBookRes.version(), is(HttpClient.Version.HTTP_2));

}

@Test
public void testHelloWorldHttp2SslConcurrent() throws Exception {
ExecutorService executor = ThreadPoolSupplier.create("test-thread-pool").get();
Request.Builder builder = TestServer.newRequestBuilder(webServer, "/books", true);
Request getBooks = builder.build();

List<Callable<Response>> tasks = Collections.nCopies(10, () -> client.newCall(getBooks).execute());
HttpRequest getBookReq = HttpRequest.newBuilder()
.uri(baseSslUri.resolve("/books"))
.version(HttpClient.Version.HTTP_2)
.setHeader("Accept-Encoding", "gzip")
.GET()
.build();

List<Callable<HttpResponse<String>>> tasks =
Collections.nCopies(10, () -> client.send(getBookReq, HttpResponse.BodyHandlers.ofString()));
executor.invokeAll(tasks).forEach(f -> {
try {
Response r = f.get(1, TimeUnit.SECONDS);
assertThat(r.code(), is(200));
assertThat(r.protocol(), is(Protocol.HTTP_2));
HttpResponse<String> r = f.get(1, TimeUnit.SECONDS);
assertThat(r.statusCode(), is(200));
assertThat(r.version(), is(HttpClient.Version.HTTP_2));
} catch (Exception e) {
fail(e);
}
});
}

private void testHelloWorld(boolean compression) throws Exception {
Request.Builder builder = TestServer.newRequestBuilder(webServer, "/books", true, compression);

Request getBooks = builder.build();
try (Response getBooksRes = client.newCall(getBooks).execute()) {
assertThat(getBooksRes.code(), is(200));
assertThat(getBooksRes.protocol(), is(Protocol.HTTP_2));
}

Request postBook = builder.post(
RequestBody.create(APPLICATION_JSON, TestServer.getBookAsJson())).build();
try (Response postBookRes = client.newCall(postBook).execute()) {
assertThat(postBookRes.code(), is(200));
assertThat(postBookRes.protocol(), is(Protocol.HTTP_2));
}

builder = TestServer.newRequestBuilder(webServer, "/books/123456", true, compression);
Request getBook = builder.build();
try (Response getBookRes = client.newCall(getBook).execute()) {
assertThat(getBookRes.code(), is(200));
assertThat(getBookRes.protocol(), is(Protocol.HTTP_2));
}

Request deleteBook = builder.delete().build();
try (Response deleteBookRes = client.newCall(deleteBook).execute()) {
assertThat(deleteBookRes.code(), is(200));
assertThat(deleteBookRes.protocol(), is(Protocol.HTTP_2));

}

Request getNoBook = builder.build();
try (Response getNoBookRes = client.newCall(getNoBook).execute()) {
assertThat(getNoBookRes.code(), is(404));
assertThat(getNoBookRes.protocol(), is(Protocol.HTTP_2));
}
HttpRequest getBooksReq = HttpRequest.newBuilder()
.uri(baseSslUri.resolve("/books"))
.version(HttpClient.Version.HTTP_2)
.setHeader("Accept-Encoding", compression ? "gzip" : "none")
.GET()
.build();

var getBooksRes = client.send(getBooksReq, HttpResponse.BodyHandlers.ofString());
assertThat(getBooksRes.statusCode(), is(200));
assertThat(getBooksRes.version(), is(HttpClient.Version.HTTP_2));

HttpRequest postBookReq = HttpRequest.newBuilder()
.uri(baseSslUri.resolve("/books"))
.version(HttpClient.Version.HTTP_2)
.setHeader("Accept-Encoding", compression ? "gzip" : "none")
.POST(HttpRequest.BodyPublishers.ofString(TestServer.getBookAsJson()))
.build();

var postBookRes = client.send(postBookReq, HttpResponse.BodyHandlers.ofString());
assertThat(postBookRes.statusCode(), is(200));
assertThat(postBookRes.version(), is(HttpClient.Version.HTTP_2));

HttpRequest getBookReq = HttpRequest.newBuilder()
.uri(baseSslUri.resolve("/books/123456"))
.version(HttpClient.Version.HTTP_2)
.setHeader("Accept-Encoding", compression ? "gzip" : "none")
.GET()
.build();

var getBookRes = client.send(getBookReq, HttpResponse.BodyHandlers.ofString());

assertThat(getBookRes.statusCode(), is(200));
assertThat(getBookRes.version(), is(HttpClient.Version.HTTP_2));

HttpRequest deleteBookReq = HttpRequest.newBuilder()
.uri(baseSslUri.resolve("/books/123456"))
.version(HttpClient.Version.HTTP_2)
.setHeader("Accept-Encoding", compression ? "gzip" : "none")
.DELETE()
.build();

var deleteBookRes = client.send(deleteBookReq, HttpResponse.BodyHandlers.ofString());
assertThat(deleteBookRes.statusCode(), is(200));
assertThat(deleteBookRes.version(), is(HttpClient.Version.HTTP_2));

HttpRequest getNoBookReq = HttpRequest.newBuilder()
.uri(baseSslUri.resolve("/books/123456"))
.version(HttpClient.Version.HTTP_2)
.setHeader("Accept-Encoding", compression ? "gzip" : "none")
.GET()
.build();

var getNoBookRes = client.send(getNoBookReq, HttpResponse.BodyHandlers.ofString());

assertThat(getNoBookRes.statusCode(), is(404));
assertThat(getNoBookRes.version(), is(HttpClient.Version.HTTP_2));
}
}
Loading

0 comments on commit df84c0e

Please sign in to comment.