diff --git a/java/client/test/org/openqa/selenium/BUILD.bazel b/java/client/test/org/openqa/selenium/BUILD.bazel index ace4f3f31a80b..514fb82112ccd 100644 --- a/java/client/test/org/openqa/selenium/BUILD.bazel +++ b/java/client/test/org/openqa/selenium/BUILD.bazel @@ -59,6 +59,10 @@ java_selenium_test_suite( ["*Test.java"], exclude = SMALL_TESTS, ), + javacopts = [ + "--release", + "11", + ], deps = [ ":helpers", "//java/client/src/org/openqa/selenium/remote", @@ -93,6 +97,10 @@ java_library( ]) + [ "interactions/touch/TouchTestBase.java", ], + javacopts = [ + "--release", + "11", + ], visibility = [ "//java/client/test:__subpackages__", ], diff --git a/java/client/test/org/openqa/selenium/ReferrerTest.java b/java/client/test/org/openqa/selenium/ReferrerTest.java index e1adc948fec99..6b970ebc23f09 100644 --- a/java/client/test/org/openqa/selenium/ReferrerTest.java +++ b/java/client/test/org/openqa/selenium/ReferrerTest.java @@ -18,54 +18,51 @@ package org.openqa.selenium; import com.google.common.base.Joiner; -import com.google.common.base.Objects; import com.google.common.net.HostAndPort; -import com.google.common.net.HttpHeaders; -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.handler.AbstractHandler; +import org.junit.After; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExternalResource; +import org.junit.runner.RunWith; import org.openqa.selenium.environment.webserver.AppServer; -import org.openqa.selenium.internal.Require; -import org.openqa.selenium.net.PortProber; -import org.openqa.selenium.net.UrlChecker; +import org.openqa.selenium.environment.webserver.NettyAppServer; +import org.openqa.selenium.remote.http.Contents; +import org.openqa.selenium.remote.http.HttpHandler; +import org.openqa.selenium.remote.http.HttpRequest; +import org.openqa.selenium.remote.http.HttpResponse; import org.openqa.selenium.support.ui.WebDriverWait; import org.openqa.selenium.testing.Ignore; -import org.openqa.selenium.testing.JUnit4TestBase; import org.openqa.selenium.testing.NeedsLocalEnvironment; import org.openqa.selenium.testing.NotYetImplemented; -import org.openqa.selenium.testing.drivers.WebDriverBuilder; +import org.openqa.selenium.testing.SeleniumTestRule; +import org.openqa.selenium.testing.SeleniumTestRunner; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.UncheckedIOException; import java.io.UnsupportedEncodingException; -import java.net.URL; +import java.net.URI; import java.net.URLEncoder; import java.nio.file.Files; import java.time.Duration; import java.util.List; +import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.TimeUnit; +import static com.google.common.net.HttpHeaders.REFERER; +import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.openqa.selenium.build.InProject.locate; import static org.openqa.selenium.remote.CapabilityType.PROXY; import static org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated; import static org.openqa.selenium.support.ui.ExpectedConditions.titleIs; +import static org.openqa.selenium.testing.Safely.safelyCall; import static org.openqa.selenium.testing.drivers.Browser.CHROME; import static org.openqa.selenium.testing.drivers.Browser.EDGE; import static org.openqa.selenium.testing.drivers.Browser.FIREFOX; import static org.openqa.selenium.testing.drivers.Browser.IE; import static org.openqa.selenium.testing.drivers.Browser.MARIONETTE; -import static org.openqa.selenium.testing.drivers.Browser.SAFARI; /** * Tests that "Referer" headers are generated as expected under various conditions. @@ -91,24 +88,50 @@ *

Note: depending on the condition under test, the various pages may or may * not be served by the same server. */ -@Ignore(SAFARI) -public class ReferrerTest extends JUnit4TestBase { +@RunWith(SeleniumTestRunner.class) +public class ReferrerTest { + @Rule + public SeleniumTestRule seleniumTestRule = new SeleniumTestRule(); + + private static final String PAGE_1 = "/page1.html"; + private static final String PAGE_2 = "/page2.html"; + private static final String PAGE_3 = "/page3.html"; private static String page1; private static String page2; private static String page3; - - @Rule public CustomDriverFactory customDriverFactory = new CustomDriverFactory(); - @Rule public PacFileServerResource pacFileServer = new PacFileServerResource(); - @Rule public ProxyServer proxyServer = new ProxyServer(); - @Rule public TestServer testServer1 = new TestServer(); - @Rule public TestServer testServer2 = new TestServer(); + private TestServer server1; + private TestServer server2; + private ProxyServer proxyServer; @BeforeClass - public static void readPages() throws IOException { - page1 = new String(Files.readAllBytes(locate("common/src/web/proxy/page1.html")), UTF_8); - page2 = new String(Files.readAllBytes(locate("common/src/web/proxy/page2.html")), UTF_8); - page3 = new String(Files.readAllBytes(locate("common/src/web/proxy/page3.html")), UTF_8); + public static void readContents() throws IOException { + page1 = Files.readString(locate("common/src/web/proxy" + PAGE_1)); + page2 = Files.readString(locate("common/src/web/proxy" + PAGE_2)); + page3 = Files.readString(locate("common/src/web/proxy/page3.html")); + } + + @Before + public void startServers() { + server1 = new TestServer(); + server2 = new TestServer(); + proxyServer = new ProxyServer(); + } + + @After + public void stopServers() { + safelyCall(() -> proxyServer.stop()); + safelyCall(() -> server1.stop()); + safelyCall(() -> server2.stop()); + } + + private WebDriver createDriver(String pacUrl) { + Proxy proxy = new Proxy(); + proxy.setProxyAutoconfigUrl(pacUrl); + + Capabilities caps = new ImmutableCapabilities(PROXY, proxy); + + return seleniumTestRule.createNewDriver(caps); } /** @@ -119,18 +142,15 @@ public static void readPages() throws IOException { @NotYetImplemented(EDGE) @NeedsLocalEnvironment public void basicHistoryNavigationWithoutAProxy() { - testServer1.start(); - - String page1Url = buildPage1Url(testServer1, buildPage2Url(testServer1)); - String page2Url = buildPage2Url(testServer1, buildPage3Url(testServer1)); - String page3Url = buildPage3Url(testServer1); + String page1Url = server1.whereIs(PAGE_1 + "?next=" + encode(server1.whereIs(PAGE_2))); + String page2Url = server1.whereIs(PAGE_2 + "?next=" + encode(server1.whereIs(PAGE_3))); - performNavigation(driver, page1Url); + performNavigation(seleniumTestRule.getDriver(), page1Url); - assertThat(testServer1.getRequests()).containsExactly( - new HttpRequest(page1Url, null), - new HttpRequest(page2Url, page1Url), - new HttpRequest(page3Url, page2Url)); + assertThat(server1.getRequests()).containsExactly( + new ExpectedRequest(PAGE_1, null), + new ExpectedRequest(PAGE_2, page1Url), + new ExpectedRequest(PAGE_3, page2Url)); } /** @@ -140,22 +160,17 @@ public void basicHistoryNavigationWithoutAProxy() { @NotYetImplemented(EDGE) @NeedsLocalEnvironment public void crossDomainHistoryNavigationWithoutAProxy() { + String page1Url = server1.whereIs(PAGE_1) + "?next=" + encode(server2.whereIs(PAGE_2)); + String page2Url = server2.whereIs(PAGE_2) + "?next=" + encode(server1.whereIs(PAGE_3)); - testServer1.start(); - testServer2.start(); + performNavigation(seleniumTestRule.getDriver(), page1Url); - String page1Url = buildPage1Url(testServer1, buildPage2Url(testServer2)); - String page2Url = buildPage2Url(testServer2, buildPage3Url(testServer1)); - String page3Url = buildPage3Url(testServer1); - - performNavigation(driver, page1Url); + assertThat(server1.getRequests()).containsExactly( + new ExpectedRequest(PAGE_1, null), + new ExpectedRequest(PAGE_3, page2Url)); - assertThat(testServer1.getRequests()).containsExactly( - new HttpRequest(page1Url, null), - new HttpRequest(page3Url, page2Url)); - - assertThat(testServer2.getRequests()).containsExactly( - new HttpRequest(page2Url, page1Url)); + assertThat(server2.getRequests()).containsExactly( + new ExpectedRequest(PAGE_2, page1Url)); } /** @@ -166,23 +181,19 @@ public void crossDomainHistoryNavigationWithoutAProxy() { @Ignore(EDGE) @NeedsLocalEnvironment public void basicHistoryNavigationWithADirectProxy() { - testServer1.start(); - - pacFileServer.setPacFileContents( - "function FindProxyForURL(url, host) { return 'DIRECT'; }"); - pacFileServer.start(); - WebDriver driver = customDriverFactory.createDriver(pacFileServer.getBaseUrl()); + proxyServer.setPacFileContents("function FindProxyForURL(url, host) { return 'DIRECT'; }"); + WebDriver driver = createDriver(proxyServer.whereIs("/pac.js")); - String page1Url = buildPage1Url(testServer1, buildPage2Url(testServer1)); - String page2Url = buildPage2Url(testServer1, buildPage3Url(testServer1)); - String page3Url = buildPage3Url(testServer1); + String page1Url = server1.whereIs(PAGE_1) + "?next=" + encode(server1.whereIs(PAGE_2)); + String page2Url = server1.whereIs(PAGE_2) + "?next=" + encode(server1.whereIs(PAGE_3)); performNavigation(driver, page1Url); - assertThat(testServer1.getRequests()).containsExactly( - new HttpRequest(page1Url, null), - new HttpRequest(page2Url, page1Url), - new HttpRequest(page3Url, page2Url)); + assertThat(server1.getRequests()) + .containsExactly( + new ExpectedRequest(PAGE_1, null), + new ExpectedRequest(PAGE_2, page1Url), + new ExpectedRequest(PAGE_3, page2Url)); } /** @@ -193,26 +204,20 @@ public void basicHistoryNavigationWithADirectProxy() { @Ignore(EDGE) @NeedsLocalEnvironment public void crossDomainHistoryNavigationWithADirectProxy() { - testServer1.start(); - testServer2.start(); + proxyServer.setPacFileContents("function FindProxyForURL(url, host) { return 'DIRECT'; }"); + WebDriver driver = createDriver(proxyServer.whereIs("/pac.js")); - pacFileServer.setPacFileContents( - "function FindProxyForURL(url, host) { return 'DIRECT'; }"); - pacFileServer.start(); - WebDriver driver = customDriverFactory.createDriver(pacFileServer.getBaseUrl()); - - String page1Url = buildPage1Url(testServer1, buildPage2Url(testServer2)); - String page2Url = buildPage2Url(testServer2, buildPage3Url(testServer1)); - String page3Url = buildPage3Url(testServer1); + String page1Url = server1.whereIs(PAGE_1) + "?next=" + encode(server2.whereIs(PAGE_2)); + String page2Url = server2.whereIs(PAGE_2) + "?next=" + encode(server1.whereIs(PAGE_3)); performNavigation(driver, page1Url); - assertThat(testServer1.getRequests()).containsExactly( - new HttpRequest(page1Url, null), - new HttpRequest(page3Url, page2Url)); + assertThat(server1.getRequests()).containsExactly( + new ExpectedRequest(PAGE_1, null), + new ExpectedRequest(PAGE_3, page2Url)); - assertThat(testServer2.getRequests()).containsExactly( - new HttpRequest(page2Url, page1Url)); + assertThat(server2.getRequests()).containsExactly( + new ExpectedRequest(PAGE_2, page1Url)); } /** @@ -223,31 +228,26 @@ public void crossDomainHistoryNavigationWithADirectProxy() { @Ignore(EDGE) @NeedsLocalEnvironment public void crossDomainHistoryNavigationWithAProxiedHost() { - testServer1.start(); - testServer2.start(); - - pacFileServer.setPacFileContents(Joiner.on('\n').join( - "function FindProxyForURL(url, host) {", - " if (host.indexOf('example') != -1) {", - " return 'PROXY " + testServer2.getHostAndPort() + "';", - " }", - " return 'DIRECT';", - " }")); - pacFileServer.start(); - WebDriver driver = customDriverFactory.createDriver(pacFileServer.getBaseUrl()); + proxyServer.setPacFileContents(Joiner.on('\n').join( + "function FindProxyForURL(url, host) {", + " if (host.indexOf('example') != -1) {", + " return 'PROXY " + server2.getHostAndPort() + "';", + " }", + " return 'DIRECT';", + " }")); + WebDriver driver = createDriver(proxyServer.whereIs("/pac.js")); - String page1Url = buildPage1Url(testServer1, "http://www.example.com" + buildPage2Url()); - String page2Url = buildPage2Url("http://www.example.com", buildPage3Url(testServer1)); - String page3Url = buildPage3Url(testServer1); + String page1Url = server1.whereIs(PAGE_1) + "?next=" + encode("http://www.example.com" + PAGE_2); + String page2Url = "http://www.example.com" + PAGE_2 + "?next=" + encode(server1.whereIs(PAGE_3)); performNavigation(driver, page1Url); - assertThat(testServer1.getRequests()).containsExactly( - new HttpRequest(page1Url, null), - new HttpRequest(page3Url, page2Url)); + assertThat(server1.getRequests()).containsExactly( + new ExpectedRequest(PAGE_1, null), + new ExpectedRequest(PAGE_3, page2Url)); - assertThat(testServer2.getRequests()).containsExactly( - new HttpRequest(page2Url, page1Url)); + assertThat(server2.getRequests()).containsExactly( + new ExpectedRequest("http://www.example.com" + PAGE_2, page1Url)); } /** @@ -259,29 +259,26 @@ public void crossDomainHistoryNavigationWithAProxiedHost() { @Ignore(EDGE) @NeedsLocalEnvironment public void crossDomainHistoryNavigationWhenProxyInterceptsHostRequests() { - testServer1.start(); - proxyServer.start(); proxyServer.setPacFileContents(Joiner.on('\n').join( - "function FindProxyForURL(url, host) {", - " if (host.indexOf('example') != -1) {", - " return 'PROXY " + proxyServer.getHostAndPort() + "';", - " }", - " return 'DIRECT';", - " }")); + "function FindProxyForURL(url, host) {", + " if (host.indexOf('example') != -1) {", + " return 'PROXY " + proxyServer.getHostAndPort() + "';", + " }", + " return 'DIRECT';", + " }")); + WebDriver driver = createDriver(proxyServer.whereIs("/pac.js")); - String page1Url = buildPage1Url(testServer1, "http://www.example.com" + buildPage2Url()); - String page2Url = buildPage2Url("http://www.example.com", buildPage3Url(testServer1)); - String page3Url = buildPage3Url(testServer1); + String page1Url = server1.whereIs(PAGE_1) + "?next=" + encode("http://www.example.com" + PAGE_2); + String page2Url = "http://www.example.com" + PAGE_2 + "?next=" + encode(server1.whereIs(PAGE_3)); - WebDriver driver = customDriverFactory.createDriver(proxyServer.getPacUrl()); performNavigation(driver, page1Url); - assertThat(testServer1.getRequests()).containsExactly( - new HttpRequest(page1Url, null), - new HttpRequest(page3Url, page2Url)); + assertThat(server1.getRequests()).containsExactly( + new ExpectedRequest(PAGE_1, null), + new ExpectedRequest(PAGE_3, page2Url)); assertThat(proxyServer.getRequests()).containsExactly( - new HttpRequest(page2Url, page1Url)); + new ExpectedRequest("http://www.example.com" + PAGE_2, page1Url)); } /** @@ -290,20 +287,13 @@ public void crossDomainHistoryNavigationWhenProxyInterceptsHostRequests() { */ @Test @Ignore(value = IE, - reason = "IEDriver does not disable automatic proxy caching, causing this test to fail, issue 6629") + reason = "IEDriver does not disable automatic proxy caching, causing this test to fail, issue 6629") @Ignore(MARIONETTE) - @Ignore(value = FIREFOX, travis=true) + @Ignore(value = FIREFOX, travis = true) @NeedsLocalEnvironment @Ignore(EDGE) @Ignore(value = CHROME, reason = "Flaky") public void navigationWhenProxyInterceptsASpecificUrl() { - testServer1.start(); - proxyServer.start(); - - String page1Url = buildPage1Url(testServer1, buildPage2Url(testServer1)); - String page2Url = buildPage2Url(testServer1, buildPage3Url(testServer1)); - String page3Url = buildPage3Url(testServer1); - // Have our proxy intercept requests for page 2. proxyServer.setPacFileContents(Joiner.on('\n').join( "function FindProxyForURL(url, host) {", @@ -312,16 +302,28 @@ public void navigationWhenProxyInterceptsASpecificUrl() { " }", " return 'DIRECT';", " }")); + WebDriver driver = createDriver(proxyServer.whereIs("/pac.js")); + + + String page1Url = server1.whereIs(PAGE_1) + "?next=" + encode(server1.whereIs(PAGE_2)); + String page2Url = server1.whereIs(PAGE_2 + "?next=" + encode(server1.whereIs(PAGE_3))); - WebDriver driver = customDriverFactory.createDriver(proxyServer.getPacUrl()); performNavigation(driver, page1Url); - assertThat(testServer1.getRequests()).containsExactly( - new HttpRequest(page1Url, null), - new HttpRequest(page3Url, page2Url)); + assertThat(server1.getRequests()).containsExactly( + new ExpectedRequest(PAGE_1, null), + new ExpectedRequest(PAGE_3, page2Url)); assertThat(proxyServer.getRequests()).containsExactly( - new HttpRequest(page2Url, page1Url)); + new ExpectedRequest(PAGE_2, page1Url)); + } + + private static String encode(String url) { + try { + return URLEncoder.encode(url, UTF_8.name()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8 should always be supported!", e); + } } private void performNavigation(WebDriver driver, String firstUrl) { @@ -343,264 +345,142 @@ private void performNavigation(WebDriver driver, String firstUrl) { wait.until(titleIs("Page 3")); } - private static String buildPage1Url(ServerResource server, String nextUrl) { - return server.getBaseUrl() + "/page1.html?next=" + encode(nextUrl); - } - - private static String buildPage2Url(String server, String nextUrl) { - return server + "/page2.html?next=" + encode(nextUrl); - } - - private static String buildPage2Url(ServerResource server, String nextUrl) { - return server.getBaseUrl() + "/page2.html?next=" + encode(nextUrl); - } - - private static String buildPage2Url() { - return "/page2.html"; // Nothing special here. - } - - private static String buildPage2Url(ServerResource server) { - return server.getBaseUrl() + "/page2.html"; // Nothing special here. - } - - private static String buildPage3Url(ServerResource server) { - return server.getBaseUrl() + "/page3.html"; // Nothing special here. - } + private static class ExpectedRequest { + private final String uri; + private final String referer; - private static String encode(String url) { - try { - return URLEncoder.encode(url, UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("UTF-8 should always be supported!", e); + public ExpectedRequest(HttpRequest request) { + this(request.getUri(), request.getHeader(REFERER)); } - } - - /** - * Manages a custom WebDriver implementation as an {@link ExternalResource} rule. - */ - private static class CustomDriverFactory extends ExternalResource { - WebDriver driver; - - WebDriver createDriver(String pacUrl) { - Proxy proxy = new Proxy(); - proxy.setProxyAutoconfigUrl(pacUrl); - - Capabilities caps = new ImmutableCapabilities(PROXY, proxy); - - return driver = new WebDriverBuilder().get(caps); + public ExpectedRequest(String uri, String referer) { + this.uri = uri; + this.referer = referer; } @Override - protected void after() { - if (driver != null) { - driver.quit(); - } - } - } - - /** - * An {@link ExternalResource} for a basic HTTP server; ensures the server is shutdown when a - * test finishes. - */ - private abstract static class ServerResource extends ExternalResource { - protected final Server server; - private final HostAndPort hostAndPort; - - ServerResource() { - this.server = new Server(); - - ServerConnector http = new ServerConnector(server); - int port = PortProber.findFreePort(); - http.setPort(port); - http.setIdleTimeout(500000); - - this.server.addConnector(http); - - this.hostAndPort = HostAndPort.fromParts(AppServer.detectHostname(), port); - } - - void addHandler(Handler handler) { - this.server.setHandler(handler); - } - - HostAndPort getHostAndPort() { - return Require.state("Host and port", hostAndPort).nonNull(); - } - - String getBaseUrl() { - return "http://" + getHostAndPort(); + public String toString() { + return "ExpectedRequest{" + + "uri='" + uri + '\'' + + ", referer='" + referer + '\'' + + '}'; } - void start() { - try { - server.start(); - new UrlChecker().waitUntilAvailable(10, TimeUnit.SECONDS, new URL(getBaseUrl())); - } catch (Exception e) { - throw new RuntimeException(e); + @Override + public boolean equals(Object o) { + if (!(o instanceof ExpectedRequest)) { + return false; } + ExpectedRequest that = (ExpectedRequest) o; + return this.uri.equals(that.uri) && + Objects.equals(this.referer, that.referer); } @Override - protected void after() { - try { - server.stop(); - } catch (Exception e) { - throw new RuntimeException(e); - } + public int hashCode() { + return Objects.hash(uri, referer); } } - private static class PacFileServerResource extends ServerResource { + private static class RecordingHandler implements HttpHandler { - private String pacFileContents; + private final List requests = new CopyOnWriteArrayList<>(); - PacFileServerResource() { - addHandler(new AbstractHandler() { - @Override - public void handle(String s, Request baseRequest, HttpServletRequest request, - HttpServletResponse response) throws IOException { - response.setContentType("application/x-javascript-config; charset=us-ascii"); - response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().println(getPacFileContents()); - baseRequest.setHandled(true); - } - }); - } - - String getPacFileContents() { - return pacFileContents; - } - - void setPacFileContents(String content) { - pacFileContents = content; - } - } + @Override + public HttpResponse execute(HttpRequest req) throws UncheckedIOException { + if (req.getUri().endsWith("/favicon.ico")) { + return new HttpResponse().setStatus(204); + } - private static class TestServer extends ServerResource { + // Don't record / requests so we can poll the server for availability in start(). + if (!"/".equals(req.getUri())) { + requests.add(new ExpectedRequest(req)); + } - private final List requests; + String responseHtml; + if (req.getUri().contains(PAGE_1)) { + responseHtml = page1; + } else if (req.getUri().contains(PAGE_2)) { + responseHtml = page2; + } else { + responseHtml = page3; + } - TestServer() { - requests = new CopyOnWriteArrayList<>(); - addHandler(new PageRequestHandler(requests)); + return new HttpResponse() + .setHeader("Content-Type", "text/html; charset=utf-8") + .setContent(Contents.utf8String(responseHtml)); } - List getRequests() { - return requests; + public List getRequests() { + return List.copyOf(requests); } } - private static class ProxyServer extends ServerResource { + private static class TestServer { + private final AppServer server; + private final RecordingHandler handler = new RecordingHandler(); - private final List requests; - private String pacFileContents; - - ProxyServer() { - requests = new CopyOnWriteArrayList<>(); - addHandler(new PageRequestHandler(requests) { - @Override - public void handle(String s, Request baseRequest, HttpServletRequest request, - HttpServletResponse response) throws IOException, ServletException { - if (request.getRequestURI().equals("/pac.js")) { - response.setContentType("application/x-javascript-config; charset=us-ascii"); - response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().println(getPacFileContents()); - baseRequest.setHandled(true); - } else { - super.handle(s, baseRequest, request, response); - } - } - }); + public TestServer() { + server = new NettyAppServer(handler); + server.start(); } - String getPacUrl() { - return getBaseUrl() + "/pac.js"; + public String whereIs(String relativeUrl) { + return server.whereIs(relativeUrl); } - List getRequests() { - return requests; + public void stop() { + server.stop(); } - String getPacFileContents() { - return pacFileContents; + public List getRequests() { + return handler.getRequests(); } - void setPacFileContents(String content) { - pacFileContents = content; + public HostAndPort getHostAndPort() { + URI uri = URI.create(server.whereIs("/")); + return HostAndPort.fromParts(uri.getHost(), uri.getPort()); } } - private static class PageRequestHandler extends AbstractHandler { - private final List requests; + private static class ProxyServer { + private final AppServer server; + private final RecordingHandler handler = new RecordingHandler(); + private String pacFileContents; - PageRequestHandler(List requests) { - this.requests = requests; + public ProxyServer() { + server = new NettyAppServer( + req -> { + if (pacFileContents != null && req.getUri().endsWith("/pac.js")) { + return new HttpResponse() + .setHeader("Content-Type", "application/x-javascript-config; charset=us-ascii") + .setContent(Contents.bytes(pacFileContents.getBytes(US_ASCII))); + } + return handler.execute(req); + } + ); + server.start(); } - @Override - public void handle(String s, Request baseRequest, HttpServletRequest request, - HttpServletResponse response) throws IOException, ServletException { - if (request.getRequestURI().endsWith("/favicon.ico")) { - response.setStatus(204); - baseRequest.setHandled(true); - return; - } - - // Don't record / requests so we can poll the server for availability in start(). - if (!"/".equals(request.getRequestURI())) { - requests.add(new HttpRequest( - request.getRequestURL() + (request.getQueryString() == null ? "" : "?" + request.getQueryString()), - request.getHeader(HttpHeaders.REFERER))); - } - - String responseHtml; - if (request.getRequestURI().contains("/page1.html")) { - responseHtml = page1; - } else if (request.getRequestURI().contains("/page2.html")) { - responseHtml = page2; - } else { - responseHtml = page3; - } - - response.setContentType("text/html; charset=utf-8"); - response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().println(responseHtml); - baseRequest.setHandled(true); + public void setPacFileContents(String pacFileContents) { + this.pacFileContents = pacFileContents; } - } - - /** - * Records basic information about a HTTP request. - */ - private static class HttpRequest { - - private final String uri; - private final String referrer; - HttpRequest(String uri, String referrer) { - this.uri = uri; - this.referrer = referrer; + public String whereIs(String relativeUrl) { + return server.whereIs(relativeUrl); } - @Override - public int hashCode() { - return Objects.hashCode(uri, referrer); + public List getRequests() { + return handler.getRequests(); } - @Override - public boolean equals(Object o) { - if (o instanceof HttpRequest) { - HttpRequest that = (HttpRequest) o; - return Objects.equal(this.uri, that.uri) - && Objects.equal(this.referrer, that.referrer); - } - return false; + public void stop() { + server.stop(); } - @Override - public String toString() { - return String.format("[uri=%s, referrer=%s]", uri, referrer); + public HostAndPort getHostAndPort() { + URI uri = URI.create(server.whereIs("/")); + return HostAndPort.fromParts(uri.getHost(), uri.getPort()); } } }