diff --git a/src/main/java/com/xceptance/xlt/engine/XltWebClient.java b/src/main/java/com/xceptance/xlt/engine/XltWebClient.java index 49c0f10be..08cc65307 100644 --- a/src/main/java/com/xceptance/xlt/engine/XltWebClient.java +++ b/src/main/java/com/xceptance/xlt/engine/XltWebClient.java @@ -314,38 +314,9 @@ public XltWebClient(final BrowserVersion browserVersion, final boolean javaScrip cssMode = CssMode.getMode(props.getProperty("com.xceptance.xlt.css.download.images")); // JavaScript - if (javaScriptEngineEnabled) - { - // setup JavaScript engine - int optimizationLevel = props.getProperty("com.xceptance.xlt.js.compiler.optimizationLevel", -1); - if (optimizationLevel < -1 || optimizationLevel > 9) - { - XltLogger.runTimeLogger.warn("Property 'com.xceptance.xlt.js.compiler.optimizationLevel' is set to an invalid value. Will use -1 instead."); - optimizationLevel = -1; - } - - final boolean takeMeasurements = props.getProperty("com.xceptance.xlt.js.takeMeasurements", false); - - setJavaScriptEngine(new XltJavaScriptEngine(this, optimizationLevel, takeMeasurements)); - getOptions().setJavaScriptEnabled(props.getProperty("com.xceptance.xlt.javaScriptEnabled", false)); - getOptions().setThrowExceptionOnScriptError(props.getProperty("com.xceptance.xlt.stopTestOnJavaScriptErrors", false)); - - // setup JavaScript debugger - if (props.getProperty("com.xceptance.xlt.js.debugger.enabled", false)) - { - setJavaScriptDebuggerEnabled(true); - - // create JS beautifying response processor only when needed - if (props.getProperty("com.xceptance.xlt.js.debugger.beautifyDownloadedJavaScript", true)) - { - jsBeautifier = new JSBeautifingResponseProcessor(); - } - } - } - else - { - getOptions().setJavaScriptEnabled(false); - } + getOptions().setJavaScriptEnabled(props.getProperty("com.xceptance.xlt.javaScriptEnabled", false)); + getOptions().setThrowExceptionOnScriptError(props.getProperty("com.xceptance.xlt.stopTestOnJavaScriptErrors", false)); + configureJavaScriptEngine(props); // default user authentication final String userName = props.getProperty("com.xceptance.xlt.auth.userName"); @@ -448,36 +419,30 @@ public XltWebClient(final BrowserVersion browserVersion, final boolean javaScrip getOptions().setHistorySizeLimit(historySizeLimit); // set web connection - final WebConnection underlyingWebConnection; - if (props.getProperty("com.xceptance.xlt.http.offline", false)) - { - // we are in offline mode and return fixed responses - underlyingWebConnection = new XltOfflineWebConnection(); - } - else - { - final String client = props.getProperty("com.xceptance.xlt.http.client"); - final boolean collectTargetIpAddress = ((XltPropertiesImpl) props).collectUsedIpAddress(); - if ("okhttp3".equals(client)) - { - final boolean http2Enabled = props.getProperty("com.xceptance.xlt.http.client.okhttp3.http2Enabled", true); - underlyingWebConnection = new OkHttp3WebConnection(this, http2Enabled, collectTargetIpAddress); - } - else - { - // the default connection - underlyingWebConnection = new XltApacheHttpWebConnection(this, collectTargetIpAddress); - } - } + configureWebConnection(props); - XltLogger.runTimeLogger.debug("Using web connection class: " + underlyingWebConnection.getClass().getName()); + // load key/trust material for client/server authentication + configureKeyStore(props); + configureTrustStore(props); + } - final XltHttpWebConnection connection = new XltHttpWebConnection(this, underlyingWebConnection); - setWebConnection(connection); + /** + * {@inheritDoc} + */ + @Override + public void reset() + { + super.reset(); - // load key/trust material for client/server authentication - setUpKeyStore(props); - setUpTrustStore(props); + final XltProperties props = XltProperties.getInstance(); + + // create a new instance of "our" JavaScript engine if needed + configureJavaScriptEngine(props); + + // create a new instance of "our" web connection + configureWebConnection(props); + + pageLocalCache.clear(); } /** @@ -2059,6 +2024,78 @@ else if (s.equals("resync")) } } + /** + * Sets up the JavaScript engine to be used by this web client. + * + * @param props + * the configuration + */ + private void configureJavaScriptEngine(final XltProperties props) + { + if (isJavaScriptEngineEnabled()) + { + // setup JavaScript engine + int optimizationLevel = props.getProperty("com.xceptance.xlt.js.compiler.optimizationLevel", -1); + if (optimizationLevel < -1 || optimizationLevel > 9) + { + XltLogger.runTimeLogger.warn("Property 'com.xceptance.xlt.js.compiler.optimizationLevel' is set to an invalid value. Will use -1 instead."); + optimizationLevel = -1; + } + + final boolean takeMeasurements = props.getProperty("com.xceptance.xlt.js.takeMeasurements", false); + + setJavaScriptEngine(new XltJavaScriptEngine(this, optimizationLevel, takeMeasurements)); + + // setup JavaScript debugger + if (props.getProperty("com.xceptance.xlt.js.debugger.enabled", false)) + { + setJavaScriptDebuggerEnabled(true); + + // create JS beautifying response processor only when needed + if (props.getProperty("com.xceptance.xlt.js.debugger.beautifyDownloadedJavaScript", true)) + { + jsBeautifier = new JSBeautifingResponseProcessor(); + } + } + } + } + + /** + * Sets up the web connection to be used by this web client. + * + * @param props + * the configuration + */ + private void configureWebConnection(final XltProperties props) + { + final WebConnection underlyingWebConnection; + if (props.getProperty("com.xceptance.xlt.http.offline", false)) + { + // we are in offline mode and return fixed responses + underlyingWebConnection = new XltOfflineWebConnection(); + } + else + { + final String client = props.getProperty("com.xceptance.xlt.http.client"); + final boolean collectTargetIpAddress = ((XltPropertiesImpl) props).collectUsedIpAddress(); + if ("okhttp3".equals(client)) + { + final boolean http2Enabled = props.getProperty("com.xceptance.xlt.http.client.okhttp3.http2Enabled", true); + underlyingWebConnection = new OkHttp3WebConnection(this, http2Enabled, collectTargetIpAddress); + } + else + { + // the default connection + underlyingWebConnection = new XltApacheHttpWebConnection(this, collectTargetIpAddress); + } + } + + XltLogger.runTimeLogger.debug("Using web connection class: " + underlyingWebConnection.getClass().getName()); + + final XltHttpWebConnection connection = new XltHttpWebConnection(this, underlyingWebConnection); + setWebConnection(connection); + } + /** * Sets up the key store with the client key to be used by this web client. The store is read from a file specified * in the test suite configuration. @@ -2066,7 +2103,7 @@ else if (s.equals("resync")) * @param props * the configuration */ - private void setUpKeyStore(final XltProperties props) + private void configureKeyStore(final XltProperties props) { final String storeFilePath = props.getProperty("com.xceptance.xlt.tls.keyStore.file"); if (StringUtils.isNotBlank(storeFilePath)) @@ -2086,7 +2123,7 @@ private void setUpKeyStore(final XltProperties props) * @param props * the configuration */ - private void setUpTrustStore(final XltProperties props) + private void configureTrustStore(final XltProperties props) { final String storeFilePath = props.getProperty("com.xceptance.xlt.tls.trustStore.file"); if (StringUtils.isNotBlank(storeFilePath)) diff --git a/src/test/java/com/xceptance/xlt/engine/XltWebClientTest.java b/src/test/java/com/xceptance/xlt/engine/XltWebClientTest.java index bbf5660ce..74939ca05 100644 --- a/src/test/java/com/xceptance/xlt/engine/XltWebClientTest.java +++ b/src/test/java/com/xceptance/xlt/engine/XltWebClientTest.java @@ -22,7 +22,9 @@ import org.htmlunit.BrowserVersion; import org.htmlunit.MockWebConnection; +import org.htmlunit.WebConnection; import org.htmlunit.WebResponse; +import org.htmlunit.javascript.AbstractJavaScriptEngine; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; @@ -203,16 +205,42 @@ private void checkBrowserVersion(final String key, final BrowserVersion expected } } + @Test + public void testReset() + { + try (final XltWebClient webClient = new XltWebClient(BrowserVersion.BEST_SUPPORTED, true)) + { + // prevalidation + final WebConnection webConnection = webClient.getWebConnection(); + final AbstractJavaScriptEngine javaScriptEngine = webClient.getJavaScriptEngine(); + + Assert.assertEquals("Unexpected WebConnection class", XltHttpWebConnection.class, webConnection.getClass()); + Assert.assertEquals("Unexpected JavaScriptEngine class", XltJavaScriptEngine.class, javaScriptEngine.getClass()); + + // reset + webClient.reset(); + + // validate that web connection and javascript engine are still XLT classes, but different objects + final WebConnection newWebConnection = webClient.getWebConnection(); + final AbstractJavaScriptEngine newJavaScriptEngine = webClient.getJavaScriptEngine(); + + Assert.assertEquals("Unexpected WebConnection class", XltHttpWebConnection.class, newWebConnection.getClass()); + Assert.assertEquals("Unexpected JavaScriptEngine class", XltJavaScriptEngine.class, newJavaScriptEngine.getClass()); + + Assert.assertNotEquals("WebConnection is the same as before", webConnection, newWebConnection); + Assert.assertNotEquals("JavaScriptEngine is the same as before", javaScriptEngine, newJavaScriptEngine); + } + } + /** * Response processor which simple stores the request URLs. */ static class URLCollector implements ResponseProcessor { /** - * Collected URLs. - * This has to be a synchronized set because some of the processing runs in another thread and hence - * we might experiencene false sharing otherwise, mainly because a response processor is not designed - * to be a data collector + * Collected URLs. This has to be a synchronized set because some of the processing runs in another thread and + * hence we might experiencene false sharing otherwise, mainly because a response processor is not designed to + * be a data collector */ private final Set urls = Collections.synchronizedSet(new HashSet());