diff --git a/src/main/java/com/mathworks/ci/MatlabBuilder.java b/src/main/java/com/mathworks/ci/MatlabBuilder.java index 9eb5fb1e..883cd3e3 100644 --- a/src/main/java/com/mathworks/ci/MatlabBuilder.java +++ b/src/main/java/com/mathworks/ci/MatlabBuilder.java @@ -60,6 +60,7 @@ public class MatlabBuilder extends Builder implements SimpleBuildStep { private static final String MATLAB_RUNNER_RESOURCE = "com/mathworks/ci/MatlabBuilder/runMatlabTests.m"; private static final String AUTOMATIC_OPTION = "RunTestsAutomaticallyOption"; + private String nodeSpecificfileSeparator; @DataBoundConstructor @@ -101,6 +102,7 @@ private String getCustomMatlabCommand() { private void setEnv(EnvVars env) { this.env = env; } + @Extension public static class MatlabDescriptor extends BuildStepDescriptor { @@ -190,14 +192,15 @@ public FormValidation getFirstErrorOrWarning( final MatrixPatternResolver resolver = new MatrixPatternResolver(matlabRoot); if (!resolver.hasVariablePattern()) { try { - rel = new MatlabReleaseInfo(matlabRoot); + FilePath matlabRootPath = new FilePath(new File(matlabRoot)); + rel = new MatlabReleaseInfo(matlabRootPath); if (rel.verLessThan(BASE_MATLAB_VERSION_RUNTESTS_SUPPORT)) { return FormValidation .error(Message.getValue("Builder.matlab.test.support.error")); } } catch (MatlabVersionNotFoundException e) { return FormValidation - .error(Message.getValue("Builder.invalid.matlab.root.error")); + .warning(Message.getValue("Builder.invalid.matlab.root.warning")); } } return FormValidation.ok(); @@ -257,7 +260,8 @@ public FormValidation doCheckTaCoberturaChkBx(@QueryParameter boolean taCobertur } Function chkCoberturaSupport = (String matlabRoot) -> { - rel = new MatlabReleaseInfo(matlabRoot); + FilePath matlabRootPath = new FilePath(new File(matlabRoot)); + rel = new MatlabReleaseInfo(matlabRootPath); final MatrixPatternResolver resolver = new MatrixPatternResolver(matlabRoot); if(!resolver.hasVariablePattern()) { try { @@ -266,7 +270,7 @@ public FormValidation doCheckTaCoberturaChkBx(@QueryParameter boolean taCobertur .warning(Message.getValue("Builder.matlab.cobertura.support.warning")); } } catch (MatlabVersionNotFoundException e) { - return FormValidation.error(Message.getValue("Builder.invalid.matlab.root.error")); + return FormValidation.warning(Message.getValue("Builder.invalid.matlab.root.warning")); } } @@ -393,40 +397,44 @@ public String getStringByName(String memberName) { public void perform(@Nonnull Run build, @Nonnull FilePath workspace, @Nonnull Launcher launcher, @Nonnull TaskListener listener) throws InterruptedException, IOException { - final boolean isLinuxLauncher = launcher.isUnix(); + //Set the environment variable specific to the this build + setEnv(build.getEnvironment(listener)); + nodeSpecificfileSeparator = getNodeSpecificFileSeperator(launcher); // Invoke MATLAB command and transfer output to standard // Output Console - buildResult = execMatlabCommand(build, workspace, launcher, listener, isLinuxLauncher); + buildResult = execMatlabCommand(workspace, launcher, listener); if (buildResult != 0) { build.setResult(Result.FAILURE); } } - private synchronized int execMatlabCommand(Run build, FilePath workspace, Launcher launcher, - TaskListener listener, boolean isLinuxLauncher) + private synchronized int execMatlabCommand(FilePath workspace, Launcher launcher, + TaskListener listener) throws IOException, InterruptedException { - setEnv(build.getEnvironment(listener)); - final String testRunMode = this.getTestRunTypeList().getDescriptor().getId(); - - // Copy MATLAB scratch file into the workspace only if Automatic option is selected. - if (testRunMode.contains(AUTOMATIC_OPTION)) { - copyMatlabScratchFileInWorkspace(MATLAB_RUNNER_RESOURCE, MATLAB_RUNNER_TARGET_FILE, - workspace, getClass().getClassLoader()); - } ProcStarter matlabLauncher; try { - MatlabReleaseInfo rel = new MatlabReleaseInfo(getLocalMatlab()); + FilePath nodeSpecificMatlabRoot = new FilePath(launcher.getChannel(),getLocalMatlab()); + MatlabReleaseInfo rel = new MatlabReleaseInfo(nodeSpecificMatlabRoot); matlabLauncher = launcher.launch().pwd(workspace).envs(this.env); if (rel.verLessThan(BASE_MATLAB_VERSION_BATCH_SUPPORT)) { ListenerLogDecorator outStream = new ListenerLogDecorator(listener); - matlabLauncher = matlabLauncher.cmds(constructDefaultMatlabCommand(isLinuxLauncher)).stderr(outStream); + matlabLauncher = matlabLauncher.cmds(constructDefaultMatlabCommand(launcher.isUnix())).stderr(outStream); } else { matlabLauncher = matlabLauncher.cmds(constructMatlabCommandWithBatch()).stdout(listener); } - } catch (MatlabVersionNotFoundException e) { + + //Check the test run mode option selected by user and identify the target workspace to copy the scratch file. + final String testRunMode = this.getTestRunTypeList().getDescriptor().getId(); + + // Copy MATLAB scratch file into the workspace only if Automatic option is selected. + if (testRunMode.contains(AUTOMATIC_OPTION)) { + FilePath targetWorkspace = new FilePath(launcher.getChannel(), workspace.getRemote()); + copyMatlabScratchFileInWorkspace(MATLAB_RUNNER_RESOURCE, MATLAB_RUNNER_TARGET_FILE, targetWorkspace); + } + } catch (Exception e) { listener.getLogger().println(e.getMessage()); return 1; } @@ -450,7 +458,7 @@ public List constructMatlabCommandWithBatch() { } matlabDefaultArgs = - Arrays.asList(getLocalMatlab() + File.separator + "bin" + File.separator + "matlab", + Arrays.asList(getLocalMatlab() + nodeSpecificfileSeparator + "bin" + nodeSpecificfileSeparator + "matlab", "-batch", runCommand); return matlabDefaultArgs; @@ -473,7 +481,7 @@ public List constructDefaultMatlabCommand(boolean isLinuxLauncher) { private String[] getPreRunnerSwitches() { String[] preRunnerSwitches = - {getLocalMatlab() + File.separator + "bin" + File.separator + "matlab", "-nosplash", + {getLocalMatlab() + nodeSpecificfileSeparator + "bin" + nodeSpecificfileSeparator + "matlab", "-nosplash", "-nodesktop", "-noAppIcon"}; return preRunnerSwitches; } @@ -504,13 +512,22 @@ private String[] getRunnerSwitch() { } private void copyMatlabScratchFileInWorkspace(String matlabRunnerResourcePath, - String matlabRunnerTarget, FilePath workspace, ClassLoader classLoader) + String matlabRunnerTarget, FilePath targetWorkspace) throws IOException, InterruptedException { + final ClassLoader classLoader = getClass().getClassLoader(); + FilePath targetFile = + new FilePath(targetWorkspace, Message.getValue(matlabRunnerTarget)); InputStream in = classLoader.getResourceAsStream(matlabRunnerResourcePath); - Path target = - new File(workspace.getRemote(), Message.getValue(matlabRunnerTarget)).toPath(); - Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING); + targetFile.copyFrom(in); + } + + private String getNodeSpecificFileSeperator(Launcher launcher) { + if (launcher.isUnix()) { + return "/"; + } else { + return "\\"; + } } } diff --git a/src/main/java/com/mathworks/ci/MatlabReleaseInfo.java b/src/main/java/com/mathworks/ci/MatlabReleaseInfo.java index eed435ec..79580a9a 100644 --- a/src/main/java/com/mathworks/ci/MatlabReleaseInfo.java +++ b/src/main/java/com/mathworks/ci/MatlabReleaseInfo.java @@ -6,20 +6,25 @@ */ import java.io.File; +import java.io.IOException; import java.nio.file.NotDirectoryException; import java.util.HashMap; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.collections.MapUtils; +import org.jenkinsci.remoting.RoleChecker; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import hudson.FilePath; +import hudson.FilePath.FileCallable; +import hudson.remoting.VirtualChannel; public class MatlabReleaseInfo { - private String matlabRoot; + private FilePath matlabRoot; private static final String VERSION_INFO_FILE = "VersionInfo.xml"; private static final String VERSION_INFO_ROOT_TAG = "MathWorks_version_info"; private static final String RELEASE_TAG = "release"; @@ -34,8 +39,8 @@ public class MatlabReleaseInfo { }; private Map versionInfoCache = new HashMap(); - - public MatlabReleaseInfo(String matlabRoot) { + + public MatlabReleaseInfo(FilePath matlabRoot) { this.matlabRoot = matlabRoot; } @@ -73,12 +78,12 @@ public boolean verLessThan(double version) throws MatlabVersionNotFoundException private Map getVersionInfoFromFile() throws MatlabVersionNotFoundException { if (MapUtils.isEmpty(versionInfoCache)) { try { - File versionFile = new File(this.matlabRoot + File.separator + VERSION_INFO_FILE); - if(versionFile.isFile()) { + FilePath versionFile = new FilePath(this.matlabRoot, VERSION_INFO_FILE); + if(versionFile.exists()) { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - Document doc = dBuilder.parse(versionFile); - + Document doc = dBuilder.parse(versionFile.read()); + doc.getDocumentElement().normalize(); NodeList nList = doc.getElementsByTagName(VERSION_INFO_ROOT_TAG); @@ -99,7 +104,7 @@ private Map getVersionInfoFromFile() throws MatlabVersionNotFoun } } } - else if(!new File(this.matlabRoot).exists()){ + else if(!this.matlabRoot.exists()){ throw new NotDirectoryException("Invalid matlabroot path"); }else { versionInfoCache.putAll(VERSION_OLDER_THAN_17A); @@ -112,4 +117,4 @@ else if(!new File(this.matlabRoot).exists()){ } return versionInfoCache; } -} + } diff --git a/src/main/resources/config.properties b/src/main/resources/config.properties index 1e8effcf..296f77c1 100644 --- a/src/main/resources/config.properties +++ b/src/main/resources/config.properties @@ -3,8 +3,8 @@ Builder.display.name = Run MATLAB Tests Builder.matlab.runner.target.file.name = runMatlabTests.m -Builder.matlab.cobertura.support.warning = To generate a Cobertura report, use MATLAB R2017b or a newer version. -Builder.invalid.matlab.root.error = Unable to launch MATLAB from the specified location. Verify the MATLAB root folder path. +Builder.matlab.cobertura.support.warning = To generate a Cobertura report, use MATLAB R2017b or a newer release. +Builder.invalid.matlab.root.warning = Unable to find MATLAB from the specified location on this system(but perhaps it exists on some agents) Builder.matlab.root.empty.error = Full path to the MATLAB root folder is required. Builder.matlab.test.support.error = To run tests with the Jenkins plugin, use MATLAB R2013a or a newer version. builder.matlab.automatictestoption.display.name = Automatic diff --git a/src/test/java/com/mathworks/ci/MatlabBuilderTest.java b/src/test/java/com/mathworks/ci/MatlabBuilderTest.java index 8e754c17..617ee206 100644 --- a/src/test/java/com/mathworks/ci/MatlabBuilderTest.java +++ b/src/test/java/com/mathworks/ci/MatlabBuilderTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertFalse; import hudson.EnvVars; +import hudson.FilePath; import hudson.model.FreeStyleBuild; import hudson.model.Result; import hudson.slaves.EnvironmentVariablesNodeProperty; @@ -245,7 +246,8 @@ public void verifyBuildStatusWhenTestFails() throws Exception { @Test public void verifyVerlessThan() throws Exception { - MatlabReleaseInfo rel = new MatlabReleaseInfo(getMatlabroot("R2017a")); + FilePath matlabRoot = new FilePath(new File(getMatlabroot("R2017a"))); + MatlabReleaseInfo rel = new MatlabReleaseInfo(matlabRoot); // verLessthan() will check all the versions against 9.2 which is version of R2017a assertFalse(rel.verLessThan(9.1)); @@ -383,7 +385,7 @@ public void verifyInvalidMatlabRootDisplaysError() throws Exception { project.getBuildersList().add(this.matlabBuilder); this.matlabBuilder.setMatlabRoot("/fake/matlab/path"); HtmlPage page = jenkins.createWebClient().goTo("job/test0/configure"); - WebAssert.assertTextPresent(page, TestMessage.getValue("Builder.invalid.matlab.root.error")); + WebAssert.assertTextPresent(page, TestMessage.getValue("Builder.invalid.matlab.root.warning")); } /* @@ -396,7 +398,7 @@ public void verifyValidMatlabRootDoesntDisplayError() throws Exception { project.getBuildersList().add(this.matlabBuilder); this.matlabBuilder.setMatlabRoot(getMatlabroot("R2018b")); HtmlPage page = jenkins.createWebClient().goTo("job/test0/configure"); - WebAssert.assertTextNotPresent(page, TestMessage.getValue("Builder.invalid.matlab.root.error")); + WebAssert.assertTextNotPresent(page, TestMessage.getValue("Builder.invalid.matlab.root.warning")); } /* @@ -429,8 +431,8 @@ public void verifyCoberturaError() throws Exception { coberturaChkBx.setChecked(true); Thread.sleep(2000); String pageText = page.asText(); - String filteredPageText = pageText.replaceFirst(TestMessage.getValue("Builder.invalid.matlab.root.error"), ""); - Assert.assertTrue(filteredPageText.contains(TestMessage.getValue("Builder.invalid.matlab.root.error"))); + String filteredPageText = pageText.replaceFirst(TestMessage.getValue("Builder.invalid.matlab.root.warning"), ""); + Assert.assertTrue(filteredPageText.contains(TestMessage.getValue("Builder.invalid.matlab.root.warning"))); } /* diff --git a/src/test/resources/testconfig.properties b/src/test/resources/testconfig.properties index 603cb72e..246adc14 100644 --- a/src/test/resources/testconfig.properties +++ b/src/test/resources/testconfig.properties @@ -3,6 +3,6 @@ Verify.matlab.invokes.positive = MATLAB is invoking positive tests Verify.build.ignore.test.failure = Build Ignored test failure -Builder.matlab.cobertura.support.warning = To generate a Cobertura report, use MATLAB R2017b or a newer version. -Builder.invalid.matlab.root.error = Unable to launch MATLAB from the specified location. Verify the MATLAB root folder path. +Builder.matlab.cobertura.support.warning = To generate a Cobertura report, use MATLAB R2017b or a newer release. +Builder.invalid.matlab.root.warning = Unable to find MATLAB from the specified location on this system(but perhaps it exists on some agents) Builder.matlab.root.empty.error = Full path to the MATLAB root folder is required. \ No newline at end of file