Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for custom prefix #924

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ public final class RealJenkinsRule implements TestRule {
private SSLSocketFactory sslSocketFactory;
private X509Certificate rootCA;

@NonNull
private String prefix = "/jenkins";

public RealJenkinsRule() {
home = new AtomicReference<>();
}
Expand Down Expand Up @@ -390,6 +393,26 @@ public RealJenkinsRule withHost(String host) {
return this;
}

/**
* Sets a custom prefix for the Jenkins root URL.
* <p>
* By default, the prefix defaults to {@code /jenkins}.
* <p>
* If not empty, must start with '/' and not end with '/'.
*/
public RealJenkinsRule withPrefix(@NonNull String prefix) {
if (!prefix.isEmpty()) {
if (!prefix.startsWith("/")) {
throw new IllegalArgumentException("Prefix must start with a leading slash.");
}
if (prefix.endsWith("/")) {
throw new IllegalArgumentException("Prefix must not end with a trailing slash.");
}
}
this.prefix = prefix;
return this;
}

/**
* Sets a custom WAR file to be used by the rule instead of the one in the path or {@code war/target/jenkins.war} in case of core.
*/
Expand Down Expand Up @@ -820,12 +843,14 @@ public <T extends Serializable> T then(Step2<T> s) throws Throwable {

/**
* Similar to {@link JenkinsRule#getURL}. Requires Jenkins to be started before using {@link #startJenkins()}.
* <p>
* Always ends with a '/'.
*/
public URL getUrl() throws MalformedURLException {
if (port == 0) {
throw new IllegalStateException("This method must be called after calling #startJenkins.");
}
return new URL(https ? "https" : "http", host, port, "/jenkins/");
return new URL(https ? "https" : "http", host, port, prefix + "/");
}

/**
Expand Down Expand Up @@ -1008,8 +1033,10 @@ public void startJenkins() throws Throwable {
argv.addAll(List.of(
"-jar", war.getAbsolutePath(),
"--enable-future-java",
"--httpListenAddress=" + httpListenAddress,
"--prefix=/jenkins"));
"--httpListenAddress=" + httpListenAddress));
if (!prefix.isEmpty()) {
argv.add("--prefix=" + prefix);
}
argv.addAll(getPortOptions());
if (https) {
argv.add("--httpsKeyStore=" + keyStoreManager.getPath().toAbsolutePath());
Expand Down
36 changes: 32 additions & 4 deletions src/test/java/org/jvnet/hudson/test/RealJenkinsRuleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.emptyString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
Expand All @@ -36,6 +38,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
Expand Down Expand Up @@ -75,7 +78,6 @@
import javax.servlet.ServletResponse;
import jenkins.model.Jenkins;
import jenkins.model.JenkinsLocationConfiguration;
import static org.junit.Assume.assumeThat;
import org.junit.AssumptionViolatedException;
import org.junit.Ignore;
import org.junit.Rule;
Expand All @@ -100,15 +102,41 @@ private static void _smokes(JenkinsRule r) throws Throwable {

@Test public void testReturnObject() throws Throwable {
rr.startJenkins();
assertEquals(rr.getUrl().toExternalForm(), rr.runRemotely(RealJenkinsRuleTest::_getJenkinsUrlFromRemote));
assertThatLocalAndRemoteUrlEquals();
}

@Test public void customPrefix() throws Throwable {
rr.withPrefix("/foo").startJenkins();
assertThat(rr.getUrl().getPath(), equalTo("/foo/"));
assertThatLocalAndRemoteUrlEquals();
}

@Test public void complexPrefix() throws Throwable {
rr.withPrefix("/foo/bar").startJenkins();
assertThat(rr.getUrl().getPath(), equalTo("/foo/bar/"));
assertThatLocalAndRemoteUrlEquals();
}

@Test public void noPrefix() throws Throwable {
rr.withPrefix("").startJenkins();
assertThat(rr.getUrl().getPath(), equalTo("/"));
assertThatLocalAndRemoteUrlEquals();
}

@Test public void invalidPrefixes() {
assertThrows(IllegalArgumentException.class, () -> rr.withPrefix("foo"));
assertThrows(IllegalArgumentException.class, () -> rr.withPrefix("/foo/"));
}

@Test public void ipv6() throws Throwable {
// Use -Djava.net.preferIPv6Addresses=true if dualstack
assumeThat(InetAddress.getLoopbackAddress(), instanceOf(Inet6Address.class));
rr.withHost("::1").startJenkins();
var externalForm = rr.getUrl().toExternalForm();
assertEquals(externalForm, rr.runRemotely(RealJenkinsRuleTest::_getJenkinsUrlFromRemote));
assertThatLocalAndRemoteUrlEquals();
}

private void assertThatLocalAndRemoteUrlEquals() throws Throwable {
assertEquals(rr.getUrl().toExternalForm(), rr.runRemotely(RealJenkinsRuleTest::_getJenkinsUrlFromRemote));
}

@Test public void testThrowsException() {
Expand Down