/** * Copyright 2010 Mirko Friedenhagen */ package hudson.plugins.jobConfigHistory; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertThat; import static org.junit.matchers.JUnitMatchers.containsString; import hudson.security.AccessControlled; import hudson.security.HudsonPrivateSecurityRealm; import hudson.security.LegacyAuthorizationStrategy; import java.io.File; import java.io.IOException; import java.net.URLEncoder; import org.jvnet.hudson.test.Bug; import org.xml.sax.SAXException; import com.gargoylesoftware.htmlunit.ElementNotFoundException; import com.gargoylesoftware.htmlunit.TextPage; import com.gargoylesoftware.htmlunit.html.HtmlForm; import com.gargoylesoftware.htmlunit.html.HtmlPage; import hudson.security.Permission; /** * @author mfriedenhagen * */ public class JobConfigHistoryBaseActionTest extends AbstractHudsonTestCaseDeletingInstanceDir { private WebClient webClient; private final File file1 = new File("old/config.xml"); private final File file2 = new File("new/config.xml"); private String oldLineSeparator; @Override protected void setUp() throws Exception { super.setUp(); webClient = createWebClient(); oldLineSeparator = System.getProperty("line.separator"); System.setProperty("line.separator", "\n"); } @Override protected void tearDown() throws Exception { super.tearDown(); System.setProperty("line.separator", oldLineSeparator); } /** * Test method for {@link hudson.plugins.jobConfigHistory.JobConfigHistoryBaseAction#getDiffFile(java.lang.String, java.lang.String)}. */ public void testGetDiffFileStringStringSameLineLength() { final JobConfigHistoryBaseAction action = new JobConfigHistoryBaseAction() { @Override protected AccessControlled getAccessControlledObject() { return getHudson(); } @Override protected void checkConfigurePermission() { getAccessControlledObject().checkPermission(Permission.CONFIGURE); } @Override protected boolean hasConfigurePermission() { return getAccessControlledObject().hasPermission(Permission.CONFIGURE); } }; final String s1 = "123\n346"; final String s2 = "123\n3467"; assertEquals("--- old/config.xml\n+++ new/config.xml\n@@ -1,2 +1,2 @@\n 123\n-346\n+3467\n", makeResultPlatformIndependant(action.getDiff(file1, file2, s1.split("\n"), s2.split("\n")))); } /** * Test method for {@link hudson.plugins.jobConfigHistory.JobConfigHistoryBaseAction#getDiffFile(java.lang.String, java.lang.String)}. */ public void testGetDiffFileStringStringEmpty() { final JobConfigHistoryBaseAction action = new JobConfigHistoryBaseAction() { @Override protected AccessControlled getAccessControlledObject() { return getHudson(); } @Override protected void checkConfigurePermission() { getAccessControlledObject().checkPermission(Permission.CONFIGURE); } @Override protected boolean hasConfigurePermission() { return getAccessControlledObject().hasPermission(Permission.CONFIGURE); } }; assertEquals("--- old/config.xml\n+++ new/config.xml\n", makeResultPlatformIndependant(action.getDiff(file1, file2, new String[0], new String[0]))); } /** * Test method for {@link hudson.plugins.jobConfigHistory.JobConfigHistoryBaseAction#getDiffFile(java.lang.String, java.lang.String)}. */ public void testGetDiffFileStringStringDifferentLineLength() { final JobConfigHistoryBaseAction action = new JobConfigHistoryBaseAction() { @Override protected AccessControlled getAccessControlledObject() { return getHudson(); } @Override protected void checkConfigurePermission() { getAccessControlledObject().checkPermission(Permission.CONFIGURE); } @Override protected boolean hasConfigurePermission() { return getAccessControlledObject().hasPermission(Permission.CONFIGURE); } }; assertEquals("--- old/config.xml\n+++ new/config.xml\n", makeResultPlatformIndependant(action.getDiff(file1, file2, "123\n346".split("\n"), "123\n346\n".split("\n")))); assertEquals("--- old/config.xml\n+++ new/config.xml\n@@ -1,2 +1,3 @@\n 123\n 346\n+123\n", makeResultPlatformIndependant(action.getDiff(file1, file2, "123\n346".split("\n"), "123\n346\n123".split("\n")))); } private String makeResultPlatformIndependant(final String result) { return result.replace("\\", "/"); } public void testGetConfigXmlIllegalArgumentExceptionNoConfigHistory() throws IOException, SAXException { // config-history not in diffDir testGetConfigXmlIllegalArgumentException(hudson.getRootDir().getAbsolutePath()); } public void testGetConfigXmlIllegalArgumentExceptionNoHudsonHome() throws IOException, SAXException { // HUDSON_HOME not in diffDir testGetConfigXmlIllegalArgumentException("/etc/config-history/"); } public void testGetConfigXmlIllegalArgumentExceptionHasDoubleDots() throws IOException, SAXException { // diffDir has double dots. testGetConfigXmlIllegalArgumentException(hudson.getRootDir().getAbsolutePath() + "/../config-history/2010_02_09"); } public void testGetConfigXmlIllegalArgumentExceptionNull() { testGetConfigXmlIllegalArgumentException(null); } public void testGetConfigXmlIllegalArgumentExceptionNotUnderConfigRoot() throws IOException, SAXException { // request file not under historyRootDir when historyRootDir is configured try { HtmlForm form = webClient.goTo("configure").getFormByName("config"); form.getInputByName("historyRootDir").setValueAttribute("jobConfigHistory"); form.getInputByName("saveSystemConfiguration").setChecked(true); submit(form); } catch (Exception e) { fail("Unable to configure historyRootDir" + e); } // request outside of configured history root //testGetConfigXmlIllegalArgumentException(hudson.getRootDir().getParent()); testGetConfigXmlIllegalArgumentException(hudson.getRootDir().getPath()); // request contains '..' testGetConfigXmlIllegalArgumentException(hudson.getRootDir() + "/jobConfigHistory/../jobs/"); // request for non-history directory final File baseDir = new File(hudson.getRootDir(), "jobConfigHistory"); TextPage page = (TextPage) webClient.goTo("jobConfigHistory/configOutput?type=raw&file=" + URLEncoder.encode(baseDir.getPath(),"UTF-8"),"text/plain"); assertTrue("Verify empty return on non-history directory request.", page.getContent().trim().isEmpty()); // request for non-existent directory final File invalidDir = new File(baseDir, "no_such_dir"); page = (TextPage) webClient.goTo("jobConfigHistory/configOutput?type=raw&file=" + URLEncoder.encode(invalidDir.getPath(),"UTF-8"),"text/plain"); assertTrue("Verify empty return on non-existent directory request.", page.getContent().trim().isEmpty()); } private void testGetConfigXmlIllegalArgumentException(final String diffDir) { final JobConfigHistoryBaseAction action = new JobConfigHistoryBaseAction() { @Override protected AccessControlled getAccessControlledObject() { return getHudson(); } @Override protected void checkConfigurePermission() { getAccessControlledObject().checkPermission(Permission.CONFIGURE); } @Override protected boolean hasConfigurePermission() { return getAccessControlledObject().hasPermission(Permission.CONFIGURE); } }; try { action.getConfigXml(diffDir); fail("Expected for " + diffDir + " " + IllegalArgumentException.class); } catch (IllegalArgumentException e) { System.err.println(e); } } @Bug(5534) public void testSecuredAccessToJobConfigHistoryPage() throws IOException, SAXException { // without security the jobConfigHistory-badge should show. final HtmlPage withoutSecurity = webClient.goTo("/"); assertThat(withoutSecurity.asXml(), containsString(JobConfigHistoryConsts.ICONFILENAME)); withoutSecurity.getAnchorByHref("/" + JobConfigHistoryConsts.URLNAME); // with security enabled the jobConfigHistory-badge should not show anymore. hudson.setSecurityRealm(new HudsonPrivateSecurityRealm(false)); hudson.setAuthorizationStrategy(new LegacyAuthorizationStrategy()); final HtmlPage withSecurityEnabled = webClient.goTo("/"); assertThat(withSecurityEnabled.asXml(), not(containsString(JobConfigHistoryConsts.ICONFILENAME))); try { withSecurityEnabled.getAnchorByHref("/" + JobConfigHistoryConsts.URLNAME); fail("Expected a " + ElementNotFoundException.class + " to be thrown"); } catch (ElementNotFoundException e) { System.err.println(e); } } }