/* * The MIT License * * Copyright (c) <2011> <Bruno P. Kinoshita> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package jenkins.plugins.testopia.result; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.model.BuildListener; import hudson.model.AbstractBuild; import hudson.remoting.VirtualChannel; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import jenkins.plugins.testopia.TestopiaSite; import jenkins.plugins.testopia.util.Messages; import org.kohsuke.stapler.DataBoundConstructor; import org.mozilla.testopia.model.Status; import org.tap4j.consumer.TapConsumer; import org.tap4j.consumer.TapConsumerFactory; import org.tap4j.model.Directive; import org.tap4j.model.TestResult; import org.tap4j.model.TestSet; import org.tap4j.util.DirectiveValues; /** * <p>Seeks for test results matching each TAP file name with the key * custom field.</p> * * <p>Skips TAP Streams that were skipped.</p> * * @author Bruno P. Kinoshita - http://www.kinoshita.eti.br * @since 0.1 */ public class TAPFileNameResultSeeker extends ResultSeeker { private static final long serialVersionUID = 3068999690225092293L; protected static final String TEXT_PLAIN_CONTENT_TYPE = "text/plain"; /** * @param includePattern */ @DataBoundConstructor public TAPFileNameResultSeeker(String includePattern) { super(includePattern); } @Extension public static class DescriptorImpl extends ResultSeekerDescriptor { /* * (non-Javadoc) * @see hudson.model.Descriptor#getDisplayName() */ @Override public String getDisplayName() { return Messages.Testopia_TAP_TAPFileName(); } } /* * (non-Javadoc) * @see jenkins.plugins.testopia.result.ResultSeeker#seek(org.mozilla.testopia.model.TestCase[], hudson.model.AbstractBuild, hudson.Launcher, hudson.model.BuildListener, jenkins.plugins.testopia.TestopiaSite) */ @Override public void seek(final TestCaseWrapper[] automatedTestCases, AbstractBuild<?, ?> build, Launcher launcher, final BuildListener listener, TestopiaSite testopia) throws ResultSeekerException { listener.getLogger().println( Messages.Testopia_TAP_LookingForTAPFileName() ); try { final Map<String, TestSet> testSets = build.getWorkspace().act(new FilePath.FileCallable<Map<String, TestSet>>() { private static final long serialVersionUID = 1L; private Map<String, TestSet> testSets; public Map<String, TestSet> invoke(File workspace, VirtualChannel channel) throws IOException, InterruptedException { final String[] tapFiles = TAPFileNameResultSeeker.this.scan(workspace, includePattern, listener); testSets = new HashMap<String, TestSet>(tapFiles.length); for(String tapFile : tapFiles) { final File input = new File(workspace, tapFile); final TapConsumer tapConsumer = TapConsumerFactory.makeTap13YamlConsumer(); final TestSet testSet = tapConsumer.load(input); testSets.put(input.getName(), testSet); } return testSets; } }); for(String key : testSets.keySet()) { for(TestCaseWrapper automatedTestCase : automatedTestCases) { String value = automatedTestCase.getAlias(); String tapFileNameWithoutExtension = key; int extensionIndex = tapFileNameWithoutExtension.lastIndexOf('.'); if ( extensionIndex != -1 ) { tapFileNameWithoutExtension = tapFileNameWithoutExtension.substring(0, tapFileNameWithoutExtension.lastIndexOf('.')); } if(tapFileNameWithoutExtension.equals(value)) { final Status status = this.getExecutionStatus(testSets.get(key)); automatedTestCase.setStatusId(status.getValue()); //listener.getLogger().println( Messages.Testopia_ResultSeeker_UpdateAutomatedTestCases() ); testopia.updateTestCase(automatedTestCase); } } } } catch (IOException e) { throw new ResultSeekerException(e); } catch (InterruptedException e) { throw new ResultSeekerException(e); } } /** * Gets execution status for a Test Set. * @param testSet * @return */ protected Status getExecutionStatus(TestSet testSet) { Status status = Status.PASSED; if (isSkipped(testSet)) { status = Status.BLOCKED; } else if (isFailed(testSet)) { status = Status.FAILED; } return status; } /** * Checks if a test set contains a plan with skip directive or any test case * with the same. */ private boolean isSkipped(TestSet testSet) { boolean r = false; if (testSet.getPlan().isSkip()) { r = true; } else { for (TestResult testResult : testSet.getTestResults()) { final Directive directive = testResult.getDirective(); if (directive != null && directive.getDirectiveValue() == DirectiveValues.SKIP) { r = true; break; } } } return r; } /** * Checks if a test set contains not ok's, bail out!'s or a TO-DO directive. */ private boolean isFailed(TestSet testSet) { boolean r = false; if (testSet.containsNotOk() || testSet.containsBailOut()) { r = true; } else { for (TestResult testResult : testSet.getTestResults()) { final Directive directive = testResult.getDirective(); if (directive != null && directive.getDirectiveValue() == DirectiveValues.TODO) { r = true; break; } } } return r; } }