Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #332 from stefanSchuhbaeck/warningsPlugin
Warnings plugin Issue JENKINS-17787 with docker
  • Loading branch information
uhafner committed Jul 4, 2017
2 parents 876baae + 25eb1b2 commit 572a0e4
Show file tree
Hide file tree
Showing 7 changed files with 484 additions and 33 deletions.
Expand Up @@ -326,6 +326,11 @@ public SortedMap<String, Integer> getWarningsTabContents() {
return getContentsOfVisibleTable(true, false);
}

public SortedMap<String, String> getDetailsTabContents() {
openTab(Tab.DETAILS);
return mapContentsOfHeaderValueRows("details");
}

/**
* Returns the first two columns of the "Warnings"-tab as key => value pairs, skipping the header row.
*
Expand Down Expand Up @@ -360,6 +365,22 @@ private SortedMap<String, Integer> getContentsOfVisibleTable(boolean removeHeade
return mapTableCellsKeyValue(getVisibleTableRows(removeHeader, removeFooter));
}

private SortedMap<String, String> mapContentsOfHeaderValueRows(String tableId) {
List<WebElement> table = all(by.xpath("//div[@id='statistics']/div/div/table[@id='"+tableId+"']"));
final SortedMap<String, String> result = new TreeMap<>();

for(WebElement element : table) {
final List<WebElement> rows = element.findElements(by.xpath("./tbody/tr/td"));
if(rows.size() > 1) {
String key = asTrimmedString(rows.get(0));
String value = asTrimmedString(rows.get(1));
result.put(key, value);
}
}

return result;
}

/**
* This is a generic variant of {@link AnalysisAction#getContentsOfVisibleTable(boolean, boolean)} which does not
* care about the type of the value part as long as it is derived from {@link java.lang.Object}.
Expand Down
257 changes: 224 additions & 33 deletions src/test/java/plugins/WarningsPluginTest.java
@@ -1,40 +1,19 @@
package plugins;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jenkinsci.test.acceptance.junit.SmokeTest;
import org.jenkinsci.test.acceptance.junit.WithPlugins;
import org.jenkinsci.test.acceptance.SshKeyPair;
import org.jenkinsci.test.acceptance.docker.DockerContainerHolder;
import org.jenkinsci.test.acceptance.docker.fixtures.JavaContainer;
import org.jenkinsci.test.acceptance.docker.fixtures.SshdContainer;
import org.jenkinsci.test.acceptance.junit.*;
import org.jenkinsci.test.acceptance.plugins.analysis_core.AnalysisAction;
import org.jenkinsci.test.acceptance.plugins.analysis_core.AnalysisConfigurator;
import org.jenkinsci.test.acceptance.plugins.envinject.EnvInjectConfig;
import org.jenkinsci.test.acceptance.plugins.matrix_auth.MatrixAuthorizationStrategy;
import org.jenkinsci.test.acceptance.plugins.mock_security_realm.MockSecurityRealm;
import org.jenkinsci.test.acceptance.plugins.script_security.ScriptApproval;
import org.jenkinsci.test.acceptance.plugins.warnings.GroovyParser;
import org.jenkinsci.test.acceptance.plugins.warnings.ParsersConfiguration;
import org.jenkinsci.test.acceptance.plugins.warnings.WarningsAction;
import org.jenkinsci.test.acceptance.plugins.warnings.WarningsBuildSettings;
import org.jenkinsci.test.acceptance.plugins.warnings.WarningsColumn;
import org.jenkinsci.test.acceptance.po.Build;
import org.jenkinsci.test.acceptance.po.Container;
import org.jenkinsci.test.acceptance.po.FreeStyleJob;
import org.jenkinsci.test.acceptance.po.FreeStyleMultiBranchJob;
import org.jenkinsci.test.acceptance.po.GlobalSecurityConfig;
import org.jenkinsci.test.acceptance.po.Job;
import org.jenkinsci.test.acceptance.po.ListView;
import org.jenkinsci.test.acceptance.po.MatrixConfiguration;
import org.jenkinsci.test.acceptance.po.MatrixProject;
import org.jenkinsci.test.acceptance.po.Node;
import org.jenkinsci.test.acceptance.po.StringParameter;
import org.jenkinsci.test.acceptance.po.WorkflowJob;
import org.jenkinsci.test.acceptance.plugins.ssh_slaves.SshSlaveLauncher;
import org.jenkinsci.test.acceptance.plugins.warnings.*;
import org.jenkinsci.test.acceptance.po.*;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;
Expand All @@ -43,10 +22,22 @@
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebElement;

import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import javax.inject.Inject;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.jenkinsci.test.acceptance.Matchers.*;
import static org.jenkinsci.test.acceptance.po.PageObject.*;
import static org.jenkinsci.test.acceptance.po.PageObject.createRandomName;
import static org.junit.Assert.assertTrue;

/**
* Tests various aspects of the warnings plug-in. Most tests copy an existing file with several warnings into the
Expand Down Expand Up @@ -86,6 +77,206 @@ public class WarningsPluginTest extends AbstractAnalysisTest<WarningsAction> {
+ "Priority test = Priority.NORMAL;\n"
+ "return new Warning(all, 42, all, all, all);";

private static final String RESOURCE_WARNING_MAIN_JAVA = "WarningMain.java";
private static final String RESOURCE_WARNING_MAIN_JAVA_PATH = "/warnings_plugin/"
+ RESOURCE_WARNING_MAIN_JAVA;

private static final String CMD_WARNING_MAIN_JAVA_CONSOLE = "javac -Xlint:all "
+ RESOURCE_WARNING_MAIN_JAVA;

private static final String RESOURCE_CODE_NARC_REPORT = "CodeNarcXmlReport.xml";
private static final String RESOURCE_CODE_NARC_REPORT_PATH = "/warnings_plugin/jenkins-17787/"
+ RESOURCE_CODE_NARC_REPORT;

@Inject
SshKeyPair keyPair;

@Inject
private DockerContainerHolder<JavaContainer> dockerContainer;

@WithDocker
@Test
public void detailsTabContentTest() throws ExecutionException, InterruptedException {

WarningsAction action = getWarningsAction(resource("/warnings_plugin/WarningMain.java"), "javac -Xlint:all WarningMain.java");

SortedMap<String, String> map = action.getDetailsTabContents();
Set<Map.Entry<String, String>> set = map.entrySet();

assertThat("Assert the proper detail count.", set.size(), is(3));
assertProperDetailsTabWithJavaCompilerAndNormalPrio(map, "redundant cast to TextClass", "WarningMain.java:10");

// removing tested entry from map.
map.remove(map.firstKey());
assertProperDetailsTabWithJavaCompilerAndNormalPrio(map, "redundant cast to TextClass", "WarningMain.java:11");

// removing tested entry from map.
map.remove(map.firstKey());
assertProperDetailsTabWithJavaCompilerAndNormalPrio(map, "division by zero", "WarningMain.java:14");
}

@WithDocker
@Test
public void detailsTabContentWithOneWarningTest() throws ExecutionException, InterruptedException {
WarningsAction action = getWarningsAction(resource("/warnings_plugin/WarningMain2.java"), "javac -Xlint:all WarningMain2.java");

SortedMap<String, String> map = action.getDetailsTabContents();
Set<Map.Entry<String, String>> set = map.entrySet();

assertThat("Assert the proper detail count.", set.size(), is(1));

assertProperDetailsTabWithJavaCompilerAndNormalPrio(map, "redundant cast to TextClass", "WarningMain2.java:9");
}

private WarningsAction getWarningsAction(Resource resource, String command) {
DumbSlave dockerSlave = getDockerSlave(dockerContainer.get());
FreeStyleJob job = prepareDockerSlave(dockerSlave);

job.configure();
job.copyResource(resource);
ShellBuildStep shellBuildStep = job.addBuildStep(ShellBuildStep.class);
shellBuildStep.command(command);
WarningsPublisher warningsPublisher = job.addPublisher(WarningsPublisher.class);
warningsPublisher.addConsoleScanner(JAVA_ID);

job.save();

Build build = buildSuccessfulJob(job);

assertThatActionExists(job, build, "Java Warnings");

WarningsAction action = createJavaResultAction(build);

action.open();
return action;
}

private void assertProperDetailsTabWithJavaCompilerAndNormalPrio(SortedMap<String, String> map, String expectedDetailText, String expectedLineInFile) {
String thirdKey = map.firstKey();
String detailText = map.get(thirdKey);
String[] headerArray = thirdKey.split(",");

assertThat("Assert the proper header array length." , headerArray.length, is(3));
assertThat("Assert the proper file and line." , headerArray[0].trim(), is(expectedLineInFile));
assertThat("Assert the proper parser." , headerArray[1].trim(), is("Java Compiler (javac)"));
assertThat("Assert the proper warning priority." , headerArray[2].trim(), is("Priority: Normal"));
assertThat("Assert the proper detail text" , detailText.trim(), is(expectedDetailText));
}

@WithDocker
@Test
public void dockerMachineTestConsoleScanner() throws ExecutionException, InterruptedException {
DumbSlave dockerSlave = (DumbSlave) getDockerSlave(dockerContainer.get());
FreeStyleJob job = prepareDockerSlave(dockerSlave);

job.configure();
job.copyResource(resource(RESOURCE_WARNING_MAIN_JAVA_PATH));
ShellBuildStep shellBuildStep = job.addBuildStep(ShellBuildStep.class);
shellBuildStep.command(CMD_WARNING_MAIN_JAVA_CONSOLE);
WarningsPublisher warningsPublisher = job.addPublisher(WarningsPublisher.class);
warningsPublisher.addConsoleScanner(JAVA_ID);

job.save();
Build build = job.startBuild().shouldSucceed();

assertThatActionExists(job, build, "Java Warnings");

WarningsAction action = createJavaResultAction(build);
assertThatWarningsCountInSummaryIs(action, 3);

String codeLine = action.getLinkedSourceFileText(AnalysisAction.Tab.DETAILS,"WarningMain.java", 10);

String[] codeLineArr = codeLine.trim().split("\\s+", 2);
assertThat("Warning should be at line",codeLineArr[0], is("10"));
assertThat("Assert failed comparing code line is",codeLineArr[1], is("text = (TextClass) text2;"));
}

@WithDocker
@Test
public void dockerMachineTestFileScanner(){
DumbSlave dockerSlave = getDockerSlave(dockerContainer.get());
FreeStyleJob job = prepareDockerSlave(dockerSlave);

job.configure();
job.copyResource(resource("/warnings_plugin/out.txt"));
job.addPublisher(WarningsPublisher.class).addWorkspaceFileScanner(JAVA_ID, "out.txt");
job.save();

Build build = job.startBuild().shouldSucceed();

assertThatActionExists(job, build, "Java Warnings");

build.open();
assertThat(driver, hasContent("Java Warnings: " + 2));
}

@WithDocker
@Test
@Issue("JENKINS-17787")
@Ignore("Reproduces JENKINS-17787")
public void codenarcParserOnDockerSlave(){
DumbSlave dockerSlave = getDockerSlave(dockerContainer.get());
FreeStyleJob job = prepareDockerSlave(dockerSlave);
assertThatCodeNarcActionExists(job);
}

@Test
public void codenarcParserOnMaster(){
FreeStyleJob job = jenkins.jobs.create();
assertThatCodeNarcActionExists(job);
}

private void assertThatCodeNarcActionExists(FreeStyleJob job){
job.configure();
job.copyResource(resource(RESOURCE_CODE_NARC_REPORT_PATH));

WarningsPublisher warningsPublisher = job.addPublisher(WarningsPublisher.class);
warningsPublisher.addWorkspaceFileScanner("Codenarc", RESOURCE_CODE_NARC_REPORT);

job.save();

Build build = job.startBuild().shouldSucceed();

assertThatActionExists(job, build, "Codenarc Warnings");
}


/**
* Create a Slave with the supplied Docker Container
* @param container SshContainer for Slave to live in
* @return
*/
private DumbSlave getDockerSlave(SshdContainer container){
DumbSlave slave = jenkins.slaves.create(DumbSlave.class);

slave.setExecutors(1);
slave.remoteFS.set("/tmp/");
SshSlaveLauncher launcher = slave.setLauncher(SshSlaveLauncher.class);

launcher.host.set(container.ipBound(22));
launcher.port(container.port(22));
launcher.setSshHostKeyVerificationStrategy(SshSlaveLauncher.NonVerifyingKeyVerificationStrategy.class);
launcher.keyCredentials("test", container.getPrivateKeyString());

slave.save();

slave.waitUntilOnline();

assertTrue(slave.isOnline());

return slave;
}

/**
* Create {@link FreeStyleJob} and build once to create Workspace on Slave
*/
private FreeStyleJob prepareDockerSlave(Slave dockerSlave){
FreeStyleJob job = jenkins.jobs.create();
job.configure();
job.setLabelExpression(dockerSlave.getName());
return job;
}

/**
* Checks that a dynamic parser with only methods from the whitelist correctly detects a warning.
*/
Expand Down
17 changes: 17 additions & 0 deletions src/test/resources/warnings_plugin/WarningMain.java
@@ -0,0 +1,17 @@

public class WarningMain {

private static class TextClass {}

public static void main(String[] args) {
TextClass text = new TextClass();
TextClass text2 = new TextClass();
// useless casting for compiler warning generation
text = (TextClass) text2;
text2 = (TextClass) text;

Integer inte = (int) 123L;
inte = inte/0;
}

}
12 changes: 12 additions & 0 deletions src/test/resources/warnings_plugin/WarningMain2.java
@@ -0,0 +1,12 @@

public class WarningMain2 {

private static class TextClass {}

public static void main(String[] args) {
TextClass text2 = new TextClass();
// useless casting for compiler warning generation
TextClass text = (TextClass) text2;
}

}

0 comments on commit 572a0e4

Please sign in to comment.