Provide JUnit5 compatible alternative for RoundTripAbstractTest and RestartableJenkinsRule (#2623)
Co-authored-by: strangelookingnerd <strangelookingnerd@users.noreply.github.com>
This commit is contained in:
parent
01e7b59d2a
commit
036b5ae1f1
|
|
@ -2,38 +2,52 @@ package io.jenkins.plugins.casc;
|
|||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import javaposse.jobdsl.plugin.GlobalJobDslSecurityConfiguration;
|
||||
import jenkins.model.GlobalConfiguration;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.jvnet.hudson.test.Issue;
|
||||
import org.jvnet.hudson.test.RestartableJenkinsRule;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
|
||||
|
||||
/**
|
||||
* Created by odavid on 23/12/2017.
|
||||
*/
|
||||
public class JobDslGlobalSecurityConfigurationTest {
|
||||
|
||||
@Rule
|
||||
public RestartableJenkinsRule j = new RestartableJenkinsRule();
|
||||
@WithJenkins
|
||||
class JobDslGlobalSecurityConfigurationTest {
|
||||
|
||||
@Test
|
||||
public void test_global_dsl_security_can_be_applied() {
|
||||
j.addStep(validateGlobalDSLSecurity);
|
||||
void test_global_dsl_security_can_be_applied(@SuppressWarnings("unused") JenkinsRule j) {
|
||||
GlobalJobDslSecurityConfiguration dslSecurity = getGlobalJobDslSecurityConfiguration();
|
||||
dslSecurity.setUseScriptSecurity(true);
|
||||
|
||||
assertThat("ScriptSecurity", dslSecurity.isUseScriptSecurity(), is(true));
|
||||
configure();
|
||||
assertThat("ScriptSecurity", dslSecurity.isUseScriptSecurity(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Issue("#253")
|
||||
public void test_global_dsl_security_can_be_reapplied_after_restart() {
|
||||
j.addStep(validateGlobalDSLSecurity);
|
||||
j.addStep(validateGlobalDSLSecurityAfterRestart, true);
|
||||
void test_global_dsl_security_can_be_reapplied_after_restart(JenkinsRule j) throws Throwable {
|
||||
GlobalJobDslSecurityConfiguration dslSecurity = getGlobalJobDslSecurityConfiguration();
|
||||
dslSecurity.setUseScriptSecurity(true);
|
||||
|
||||
assertThat("ScriptSecurity", dslSecurity.isUseScriptSecurity(), is(true));
|
||||
configure();
|
||||
assertThat("ScriptSecurity", dslSecurity.isUseScriptSecurity(), is(false));
|
||||
|
||||
j.restart();
|
||||
|
||||
dslSecurity = getGlobalJobDslSecurityConfiguration();
|
||||
|
||||
assertThat("ScriptSecurity", dslSecurity.isUseScriptSecurity(), is(false));
|
||||
configure();
|
||||
assertThat("ScriptSecurity", dslSecurity.isUseScriptSecurity(), is(false));
|
||||
}
|
||||
|
||||
private GlobalJobDslSecurityConfiguration getGlobalJobDslSecurityConfiguration() {
|
||||
final GlobalJobDslSecurityConfiguration dslSecurity =
|
||||
GlobalJobDslSecurityConfiguration dslSecurity =
|
||||
GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class);
|
||||
assertNotNull(dslSecurity);
|
||||
return dslSecurity;
|
||||
|
|
@ -45,34 +59,4 @@ public class JobDslGlobalSecurityConfigurationTest {
|
|||
.getResource("JobDslGlobalSecurityConfigurationTest.yml")
|
||||
.toExternalForm());
|
||||
}
|
||||
|
||||
private Statement validateGlobalDSLSecurity = new Statement() {
|
||||
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
final GlobalJobDslSecurityConfiguration dslSecurity = getGlobalJobDslSecurityConfiguration();
|
||||
|
||||
dslSecurity.setUseScriptSecurity(true);
|
||||
assertThat("ScriptSecurity", dslSecurity.isUseScriptSecurity(), is(true));
|
||||
|
||||
configure();
|
||||
|
||||
assertThat("ScriptSecurity", dslSecurity.isUseScriptSecurity(), is(false));
|
||||
}
|
||||
};
|
||||
|
||||
private Statement validateGlobalDSLSecurityAfterRestart = new Statement() {
|
||||
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
final GlobalJobDslSecurityConfiguration dslSecurity = getGlobalJobDslSecurityConfiguration();
|
||||
|
||||
// step 1 configuration still applies
|
||||
assertThat("ScriptSecurity", dslSecurity.isUseScriptSecurity(), is(false));
|
||||
|
||||
configure();
|
||||
|
||||
assertThat("ScriptSecurity", dslSecurity.isUseScriptSecurity(), is(false));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
package io.jenkins.plugins.casc;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import hudson.tasks.Mailer;
|
||||
import io.jenkins.plugins.casc.misc.RoundTripAbstractTest;
|
||||
import io.jenkins.plugins.casc.misc.junit.jupiter.AbstractRoundTripTest;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.jvnet.hudson.test.RestartableJenkinsRule;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
|
||||
|
||||
public class RoundTripMailerTest extends RoundTripAbstractTest {
|
||||
@WithJenkins
|
||||
class RoundTripMailerTest extends AbstractRoundTripTest {
|
||||
@Override
|
||||
protected void assertConfiguredAsExpected(RestartableJenkinsRule j, String configContent) {
|
||||
protected void assertConfiguredAsExpected(JenkinsRule j, String configContent) {
|
||||
final Jenkins jenkins = Jenkins.get();
|
||||
final Mailer.DescriptorImpl descriptor = (Mailer.DescriptorImpl) jenkins.getDescriptor(Mailer.class);
|
||||
assertEquals("4441", descriptor.getSmtpPort());
|
||||
|
|
|
|||
2
pom.xml
2
pom.xml
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.jenkins-ci.plugins</groupId>
|
||||
<artifactId>plugin</artifactId>
|
||||
<version>5.5</version>
|
||||
<version>5.6</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ import org.jvnet.hudson.test.RestartableJenkinsRule;
|
|||
* text configured.
|
||||
*
|
||||
* @since 1.20
|
||||
* @deprecated Consider migrating to JUnit5 and use {@link io.jenkins.plugins.casc.misc.junit.jupiter.AbstractRoundTripTest} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class RoundTripAbstractTest {
|
||||
@Rule
|
||||
public RestartableJenkinsRule r = new RestartableJenkinsRule();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,211 @@
|
|||
package io.jenkins.plugins.casc.misc.junit.jupiter;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.htmlunit.HttpMethod.POST;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import io.jenkins.plugins.casc.ConfigurationAsCode;
|
||||
import io.jenkins.plugins.casc.ConfiguratorException;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.htmlunit.WebRequest;
|
||||
import org.htmlunit.WebResponse;
|
||||
import org.htmlunit.util.NameValuePair;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
import org.jvnet.hudson.test.LogRecorder;
|
||||
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
|
||||
|
||||
/**
|
||||
* Base test to check a complete test of each plugin configuration.
|
||||
* <p>
|
||||
* What it does:
|
||||
* <ol>
|
||||
* <li>Configure the instance with the {@link #configResource()} implemented.</li>
|
||||
* <li>Check it was configured correctly.</li>
|
||||
* <li>Check the configuration is valid via Web UI.</li>
|
||||
* <li>Apply the configuration via Web UI.</li>
|
||||
* <li>Write the configuration to $JENKINS_HOME/jenkins.yaml.</li>
|
||||
* <li>Restart Jenkins.</li>
|
||||
* <li>Check the {@link #stringInLogExpected()} is set during the restart.</li>
|
||||
* <li>Check it is still configured correctly after the restart</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* All the plugin author needs to do is override the methods providing:
|
||||
* <ol>
|
||||
* <li>The resource with the yaml configuration of the plugin in case they use their own name for the file.</li>
|
||||
* <li>A way to validate the configuration is established.</li>
|
||||
* <li>A string that should be present in the logs (casc logger) that guarantees the config is loaded. Usually a weird text configured.</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* This is the JUnit5 equivalent of {@link io.jenkins.plugins.casc.misc.RoundTripAbstractTest}
|
||||
*
|
||||
* @see io.jenkins.plugins.casc.misc.RoundTripAbstractTest
|
||||
*/
|
||||
@WithJenkins
|
||||
public abstract class AbstractRoundTripTest {
|
||||
|
||||
@TempDir
|
||||
public Path tempFolder;
|
||||
|
||||
/**
|
||||
* A method to assert if the configuration was correctly loaded. The Jenkins rule and the
|
||||
* content of the config supposedly loaded are passed.
|
||||
*
|
||||
* @param j a JenkinsRule instance.
|
||||
* @param configContent expected configuration.
|
||||
*/
|
||||
protected abstract void assertConfiguredAsExpected(JenkinsRule j, String configContent);
|
||||
|
||||
/**
|
||||
* Return the resource path (yaml file) to be loaded. i.e: If the resource is in the same
|
||||
* package of the implementor class, then: my-config.yaml
|
||||
*
|
||||
* @return the resource name and path.
|
||||
*/
|
||||
protected String configResource() {
|
||||
return "configuration-as-code.yaml";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the string that should be in the logs of the JCasC logger to verify it's configured
|
||||
* after a restart. This string should be unique to avoid interpreting that it was configured
|
||||
* successfully, but it wasn't.
|
||||
*
|
||||
* @return the unique string to be in the logs to certify the configuration was done
|
||||
* successfully.
|
||||
*/
|
||||
protected abstract String stringInLogExpected();
|
||||
|
||||
/**
|
||||
* 1. Configure the instance with the {@link #configResource()} implemented. 2. Check it was
|
||||
* configured correctly. 3. Check the configuration is valid via Web UI. 4. Apply the
|
||||
* configuration via Web UI. 5. Write the configuration to $JENKINS_HOME/jenkins.yaml. 6.
|
||||
* Restart Jenkins. 7. Check the {@link #stringInLogExpected()} is set during the restart.
|
||||
*
|
||||
* @throws IOException If an exception is thrown managing resources or files.
|
||||
*/
|
||||
@Test
|
||||
public void roundTripTest(JenkinsRule r) throws Throwable {
|
||||
String resourcePath = configResource();
|
||||
String resourceContent = getResourceContent(resourcePath);
|
||||
|
||||
assertNotNull(resourcePath);
|
||||
assertNotNull(resourceContent);
|
||||
|
||||
// Configure and validate
|
||||
configureWithResource(resourcePath);
|
||||
assertConfiguredAsExpected(r, resourceContent);
|
||||
|
||||
// Check config is valid via Web UI
|
||||
String jenkinsConf = getResourceContent(resourcePath);
|
||||
assertConfigViaWebUI(r, jenkinsConf);
|
||||
|
||||
// Apply configuration via Web UI
|
||||
applyConfigViaWebUI(r, jenkinsConf);
|
||||
assertConfiguredAsExpected(r, resourceContent);
|
||||
|
||||
// Configure Jenkins default JCasC file with the config file. It's already established, we check if applied
|
||||
// looking at the logs.
|
||||
putConfigInHome(r, jenkinsConf);
|
||||
|
||||
// Start recording the logs just before restarting, to avoid capture the previous startup. We're look there
|
||||
// if the "magic token" is there
|
||||
try (LogRecorder recorder =
|
||||
new LogRecorder().record("io.jenkins.plugins.casc", Level.FINER).capture(2048)) {
|
||||
// Restart the testing instance
|
||||
r.restart();
|
||||
|
||||
// Verify the log shows it's configured
|
||||
assertLogAsExpected(recorder, stringInLogExpected());
|
||||
}
|
||||
|
||||
// Verify the configuration set at home/jenkins.yaml is loaded
|
||||
assertConfiguredAsExpected(r, resourceContent);
|
||||
}
|
||||
|
||||
private void configureWithResource(String config) throws ConfiguratorException {
|
||||
ConfigurationAsCode.get().configure(this.getClass().getResource(config).toExternalForm());
|
||||
}
|
||||
|
||||
private String getResourceContent(String resourcePath) throws IOException {
|
||||
return IOUtils.toString(getClass().getResourceAsStream(resourcePath), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private void writeToFile(String text, String path) throws FileNotFoundException {
|
||||
File file = new File(path);
|
||||
try (PrintWriter out = new PrintWriter(file)) {
|
||||
out.print(text);
|
||||
}
|
||||
}
|
||||
|
||||
private void putConfigInHome(JenkinsRule r, String config) throws Exception {
|
||||
File configFile = new File(r.getWebAppRoot(), ConfigurationAsCode.DEFAULT_JENKINS_YAML_PATH);
|
||||
|
||||
writeToFile(config, configFile.getAbsolutePath());
|
||||
assertTrue(configFile.exists(), ConfigurationAsCode.DEFAULT_JENKINS_YAML_PATH + " should be created");
|
||||
}
|
||||
|
||||
private void assertConfigViaWebUI(JenkinsRule r, String jenkinsConfig) throws Exception {
|
||||
// The UI requires the path to the config file
|
||||
File f = File.createTempFile("junit", null, tempFolder.toFile());
|
||||
writeToFile(jenkinsConfig, f.getAbsolutePath());
|
||||
|
||||
// Call the check url
|
||||
JenkinsRule.WebClient client = r.createWebClient();
|
||||
WebRequest request = new WebRequest(client.createCrumbedUrl("configuration-as-code/checkNewSource"), POST);
|
||||
NameValuePair param = new NameValuePair("newSource", f.toURI().toURL().toExternalForm());
|
||||
request.setRequestParameters(Collections.singletonList(param));
|
||||
WebResponse response = client.loadWebResponse(request);
|
||||
assertEquals(
|
||||
200,
|
||||
response.getStatusCode(),
|
||||
"Failed to POST to " + request.getUrl().toString());
|
||||
String res = response.getContentAsString();
|
||||
assertThat(res, containsString("The configuration can be applied"));
|
||||
}
|
||||
|
||||
private void applyConfigViaWebUI(JenkinsRule r, String jenkinsConfig) throws Exception {
|
||||
// The UI requires the path to the config file
|
||||
File f = File.createTempFile("junit", null, tempFolder.toFile());
|
||||
writeToFile(jenkinsConfig, f.getAbsolutePath());
|
||||
|
||||
// Call the replace url
|
||||
JenkinsRule.WebClient client = r.createWebClient();
|
||||
WebRequest request = new WebRequest(client.createCrumbedUrl("configuration-as-code/replace"), POST);
|
||||
NameValuePair param = new NameValuePair("_.newSource", f.toURI().toURL().toExternalForm());
|
||||
request.setRequestParameters(Collections.singletonList(param));
|
||||
request.setRequestParameters(Collections.singletonList(param));
|
||||
WebResponse response = client.loadWebResponse(request);
|
||||
assertEquals(
|
||||
200,
|
||||
response.getStatusCode(),
|
||||
"Failed to POST to " + request.getUrl().toString());
|
||||
String res = response.getContentAsString();
|
||||
/* The result page has:
|
||||
Configuration loaded from :
|
||||
<ul>
|
||||
<li>path</li>
|
||||
</ul>
|
||||
path is the file used to store the configuration.
|
||||
*/
|
||||
assertThat(res, containsString(f.toURI().toURL().toExternalForm()));
|
||||
}
|
||||
|
||||
private void assertLogAsExpected(LogRecorder recorder, String uniqueText) {
|
||||
assertTrue(
|
||||
recorder.getMessages().stream().anyMatch(m -> m.contains(uniqueText)),
|
||||
"The log should have '" + uniqueText + "'");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue