/*
* Copyright 2017 ThoughtWorks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.thoughtworks.studios.shine.cruise.stage.details;
import com.thoughtworks.go.domain.DefaultJobPlan;
import com.thoughtworks.go.domain.JobInstance;
import com.thoughtworks.go.domain.XmlWriterContext;
import com.thoughtworks.go.helper.JobInstanceMother;
import com.thoughtworks.go.server.domain.xml.JobXmlViewModel;
import com.thoughtworks.go.server.service.XmlApiService;
import com.thoughtworks.go.util.SystemEnvironment;
import com.thoughtworks.studios.shine.cruise.GoIntegrationException;
import com.thoughtworks.studios.shine.semweb.Graph;
import com.thoughtworks.studios.shine.semweb.grddl.XSLTTransformerRegistry;
import com.thoughtworks.studios.shine.semweb.sesame.InMemoryTempGraphFactory;
import com.thoughtworks.studios.shine.time.Clock;
import com.thoughtworks.studios.shine.xunit.XUnitOntology;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static com.thoughtworks.studios.shine.AssertUtils.assertAskIsFalse;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.hasItem;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class JobResourceImporterTest {
private final SystemEnvironment systemEnvironment = new SystemEnvironment();
private XSLTTransformerRegistry transformerRegistry;
private XmlWriterContext xmlWriterContext;
private DefaultJobPlan jobPlan;
private String baseUri;
private XmlApiService xmlApiService;
@Before
public void setup() {
transformerRegistry = new XSLTTransformerRegistry();
xmlWriterContext = mock(XmlWriterContext.class);
baseUri = "https://localhost:8154/go";
xmlApiService = mock(XmlApiService.class);
}
@After
public void resetClock() {
Clock.reset();
}
@Test
public void testLoadingFileThatDoesNotExist() throws GoIntegrationException, IOException, DocumentException {
Clock.fakeNowUTC(2008, 1, 20, 0, 0, 1);
when(xmlApiService.write(any(JobXmlViewModel.class), eq(baseUri))).thenReturn(docFor(jobWithArtifactsMissing));
JobResourceImporter rdfImporter = new JobResourceImporter("test/data/cruise/artifacts", new InMemoryTempGraphFactory(), transformerRegistry, xmlApiService, systemEnvironment);
Graph jobGraph = rdfImporter.importJob(JobInstanceMother.passed("foo"), "https://localhost:8154/go");
String ask = "PREFIX xunit: <" + XUnitOntology.URI + "> ASK WHERE { [] a xunit:TestCase }";
assertAskIsFalse(jobGraph, ask);
}
private Document docFor(String jobWithArtifactsMissing) throws DocumentException {
return new SAXReader().read(new ByteArrayInputStream(jobWithArtifactsMissing.getBytes()));
}
@Test
public void testArtifactsAreImported() throws Exception {
Clock.fakeNowUTC(2008, 1, 20, 0, 0, 1);
JobInstance failedJob = JobInstanceMother.failed("test");
Document document = docFor(happyJobResourceXML);
document.selectSingleNode("//link[@rel='self']/@href").setText(new JobXmlViewModel(failedJob).httpUrl(baseUri));
when(xmlApiService.write(any(JobXmlViewModel.class), eq(baseUri))).thenReturn(document);
JobResourceImporter rdfImporter = new JobResourceImporter("test/data/cruise/artifacts", new InMemoryTempGraphFactory(), transformerRegistry, xmlApiService, systemEnvironment);
Graph graph = rdfImporter.importJob(failedJob, baseUri);
String testCountSelect = "PREFIX xunit: <" + XUnitOntology.URI + "> SELECT ?testcase WHERE { ?testCase a xunit:TestCase }";
assertEquals(5, graph.select(testCountSelect).size());
}
@Test
public void listFilesOfTypeWhenThereAreNoMatches() {
JobResourceImporter rdfImporter = new JobResourceImporter("test/data/cruise", new InMemoryTempGraphFactory(), transformerRegistry, xmlApiService, systemEnvironment);
File[] files = rdfImporter.getArtifactFilesOfType("artifacts/job2", "junit-reports", "boo");
assertThat(files.length, equalTo(0));
}
@Test
public void listArtifactFilesOfTypeWhenThereAreMatchesWithCaseInSensitiveExtensions() {
JobResourceImporter rdfImporter = new JobResourceImporter("test/data/cruise", new InMemoryTempGraphFactory(), transformerRegistry, xmlApiService, systemEnvironment);
File[] files = rdfImporter.getArtifactFilesOfType("artifacts", "job2", "xml");
assertThat(files.length, equalTo(4));
List<String> actualFileNames = new ArrayList<>();
for (File f : files) {
actualFileNames.add(f.getName());
}
assertThat(actualFileNames, hasItem("junit-report-failed.xml"));
assertThat(actualFileNames, hasItem("junit-report-passed.xml"));
assertThat(actualFileNames, hasItem("junit-report-passed-with-capitalcase-extension.XML"));
assertThat(actualFileNames, hasItem("junit-report-passed-with-mixedcase-extension.Xml"));
}
@Test
public void listArtifactFilesReturnsEmptyListWhenJobArtifactPathIsAFile() {
JobResourceImporter rdfImporter = new JobResourceImporter("test/data/cruise", new InMemoryTempGraphFactory(), transformerRegistry, xmlApiService, systemEnvironment);
File[] files = rdfImporter.getArtifactFilesOfType("artifacts/job2/junit-reports", "junit-report-failed.xml", "xml");
assertThat(files.length, equalTo(0));
}
@Test
public void listArtifactFilesReturnsEmptyListWhenJobArtifactPathIsAGlob() {
JobResourceImporter rdfImporter = new JobResourceImporter("test/data/cruise", new InMemoryTempGraphFactory(), transformerRegistry, xmlApiService, systemEnvironment);
File[] files = rdfImporter.getArtifactFilesOfType("artifacts", "job2/**/*.xml", "xml");
assertThat(files.length, equalTo(0));
}
String jobWithArtifactsMissing = "" +
"<job name='test'>" +
"<link rel='self' href='http://job/1'/>" +
"<result>Passed</result>" +
"<properties>" +
"<property name='cruise_job_id'><![CDATA[111]]></property>" +
"<property name='cruise_timestamp_06_completed'>2008-01-15T16:36:19-08:00</property>" +
"<property name='os'><![CDATA[OpenBSD]]></property>" +
"</properties>" +
"<artifacts baseUrl='http://cruise/missing-artifacts' pathFromArtifactRoot='/do/you/really/care'>" +
" <artifact src='' dest='duh' type='unit' />" +
"</artifacts>" +
"</job>";
String jobMoreThanMonthOldXML = "" +
"<job name='test'>" +
" <link rel='self' href='http://job/4'/>" +
" <result>Passed</result>" +
" <properties>" +
" <property name='cruise_timestamp_06_completed'>2009-01-15T16:36:19-08:00</property>" +
" <property name='cruise_job_id'><![CDATA[110]]></property>" +
" <property name='os'><![CDATA[OpenBSD]]></property>" +
" </properties>" +
" <artifacts baseUrl='http://cruise/' pathFromArtifactRoot='job4'>" +
" <artifact src='' dest='junit-reports' type='unit' />" +
" <artifact src='' dest='' />" +
" </artifacts>" +
"</job>";
String happyJobResourceXML = "" +
"<job name='test'>" +
" <link rel='self' href='http://job/4'/>" +
" <result>Passed</result>" +
" <properties>" +
" <property name='cruise_job_id'><![CDATA[110]]></property>" +
" <property name='cruise_job_duration'><![CDATA[651]]></property>" +
" <property name='cruise_timestamp_06_completed'>2008-01-15T16:36:19-08:00</property>" +
" <property name='os'><![CDATA[OpenBSD]]></property>" +
" </properties>" +
" <artifacts baseUrl='http://cruise/' pathFromArtifactRoot='job4'>" +
" <artifact dest='junit-reports' src='some/**/path' type='unit' />" +
" <artifact dest='' src='simple/path' />" +
" </artifacts>" +
"</job>";
String jobWithOldTimestampFormatXML = "" +
"<job name='test'>" +
" <link rel='self' href='http://job/4'/>" +
" <result>Passed</result>" +
" <properties>" +
" <property name='cruise_job_id'><![CDATA[110]]></property>" +
" <property name='cruise_timestamp_06_completed'>2008-09-19 02:18:39 +0800</property>" +
" <property name='os'><![CDATA[OpenBSD]]></property>" +
" </properties>" +
" <artifacts baseUrl='http://cruise/' pathFromArtifactRoot='job4'>" +
" <artifact dest='junit-reports' type='unit' />" +
" <artifact dest='' />" +
" </artifacts>" +
"</job>";
String jobUnparseableCompletedTimestampXML = "" +
"<job name='test'>" +
" <link rel='self' href='http://job/4'/>" +
" <result>Passed</result>" +
" <properties>" +
" <property name='cruise_timestamp_06_completed'>I_AM_NOT_A_TIMESTAMP</property>" +
" <property name='cruise_job_id'><![CDATA[110]]></property>" +
" <property name='os'><![CDATA[OpenBSD]]></property>" +
" </properties>" +
" <artifacts baseUrl='http://cruise/' pathFromArtifactRoot='job4'>" +
" <artifact dest='junit-reports' type='unit' />" +
" <artifact dest='' />" +
" </artifacts>" +
"</job>";
String jobMissingCompletedTimestampXML = "" +
"<job name='test'>" +
" <link rel='self' href='http://job/4'/>" +
" <result>Passed</result>" +
" <properties>" +
" <property name='cruise_job_id'><![CDATA[110]]></property>" +
" <property name='os'><![CDATA[OpenBSD]]></property>" +
" </properties>" +
" <artifacts baseUrl='http://cruise/' pathFromArtifactRoot='job4'>" +
" <artifact dest='junit-reports' type='unit' />" +
" <artifact dest='' />" +
" </artifacts>" +
"</job>";
}