Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for supplying input zip files next to directories #1544

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import io.qameta.allure.summary.SummaryPlugin;
import io.qameta.allure.tags.TagsPlugin;
import io.qameta.allure.timeline.TimelinePlugin;
import io.qameta.allure.zip.ZipResultsSourcePlugin;

import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -107,7 +108,8 @@ public ConfigurationBuilder useDefault() {
new Allure1Plugin(),
new Allure1EnvironmentPlugin(),
new Allure2Plugin(),
new GaPlugin()
new GaPlugin(),
new ZipResultsSourcePlugin()
));
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import io.qameta.allure.summary.SummaryPlugin;
import io.qameta.allure.tags.TagsPlugin;
import io.qameta.allure.timeline.TimelinePlugin;
import io.qameta.allure.zip.ZipResultsSourcePlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -110,6 +111,7 @@ public final class DummyReportGenerator {
new Allure1Plugin(),
new Allure1EnvironmentPlugin(),
new Allure2Plugin(),
new ZipResultsSourcePlugin(),
new ReportWebPlugin() {
@Override
public void aggregate(final Configuration configuration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import io.qameta.allure.core.Configuration;
import io.qameta.allure.core.LaunchResults;
import io.qameta.allure.zip.ZipResultsSourcePlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -67,6 +68,7 @@ private void generate(final Path outputDirectory, final Stream<Path> resultsDire
.filter(this::isValidResultsDirectory)
.map(this::readResults)
.collect(Collectors.toList());

aggregate(results, outputDirectory);
}

Expand All @@ -75,10 +77,14 @@ private boolean isValidResultsDirectory(final Path resultsDirectory) {
LOGGER.warn("{} does not exist", resultsDirectory);
return false;
}
if (!Files.isDirectory(resultsDirectory)) {
LOGGER.warn("{} is not a directory", resultsDirectory);

final boolean isDirectory = Files.isDirectory(resultsDirectory);
final boolean isZip = ZipResultsSourcePlugin.isZip(resultsDirectory);
if (!isDirectory && !isZip) {
LOGGER.warn("{} is neither a directory nor a zip file", resultsDirectory);
return false;
}

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ public class Allure2Plugin implements Reader {
public void readResults(final Configuration configuration,
final ResultsVisitor visitor,
final Path resultsDirectory) {
if (!Files.isDirectory(resultsDirectory)) {
return;
}

final RandomUidContext context = configuration.requireContext(RandomUidContext.class);
final List<TestResultContainer> groups = readTestResultsContainers(resultsDirectory)
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright 2019 Qameta Software OÜ
*
* 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 io.qameta.allure.zip;

import io.qameta.allure.Reader;
import io.qameta.allure.core.Configuration;
import io.qameta.allure.core.ResultsVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;

public class ZipResultsSourcePlugin implements Reader {

private static final Logger LOGGER = LoggerFactory.getLogger(ZipResultsSourcePlugin.class);

@Override
public void readResults(final Configuration configuration,
final ResultsVisitor visitor,
final Path directory) {
if (!isZip(directory)) {
return;
}


try (FileSystem zipFile = FileSystems.newFileSystem(directory, (ClassLoader) null)) {
final Stream<Reader> otherReaders = configuration
.getReaders()
.stream()
.filter(this::isNotZipResultsSourcePlugin);

zipFile.getRootDirectories().forEach(directoryInZip ->
otherReaders.forEach(reader -> reader.readResults(configuration, visitor, directoryInZip))
);

} catch (IOException e) {
LOGGER.warn("Failed to create zip file system from {}", directory, e);
}
}

private boolean isNotZipResultsSourcePlugin(final Reader reader) {
return !getClass().isInstance(reader);
}

public static boolean isZip(final Path path) {
boolean isZip = false;

try {
isZip = "application/zip".equals(Files.probeContentType(path));
} catch (IOException e) {
LOGGER.trace("Failed to probe content type", e);
}

if (!isZip) {
try (RandomAccessFile raf = new RandomAccessFile(path.toFile(), "r")) {
final int fileSignature = raf.readInt();
isZip = fileSignature == 0x504B0304 || fileSignature == 0x504B0506 || fileSignature == 0x504B0708;
} catch (IOException | UnsupportedOperationException e) {
LOGGER.trace("Failed to read {}", path, e);
}
}


return isZip;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Copyright 2019 Qameta Software OÜ
*
* 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 io.qameta.allure.zip;

import io.qameta.allure.ConfigurationBuilder;
import io.qameta.allure.DefaultResultsVisitor;
import io.qameta.allure.core.Configuration;
import io.qameta.allure.core.LaunchResults;
import io.qameta.allure.entity.StageResult;
import io.qameta.allure.entity.TestResult;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static org.assertj.core.api.Assertions.assertThat;

class ZipResultsSourcePluginTest {

private Path zipFile;

@BeforeEach
void setUp() throws IOException {
this.zipFile = Files.createTempFile("zip-results-source", ".zip");
}

@Test
void shouldRunOtherPlugins() throws Exception {
Set<TestResult> testResults = zipAndRunPlugin(
new ResourceToZipEntry("allure2/simple-testcase.json", "simple-testcase-result.json"),
new ResourceToZipEntry("allure2/first-testgroup.json", "first-testgroup-container.json"),
new ResourceToZipEntry("allure2/second-testgroup.json", "second-testgroup-container.json")
).getResults();

assertThat(testResults)
.hasSize(1)
.flatExtracting(TestResult::getBeforeStages)
.hasSize(2)
.extracting(StageResult::getName)
.containsExactlyInAnyOrder("mockAuthorization", "loadTestConfiguration");
}

@Test
void shouldIgnoreEmptyZipFile() throws Exception {
Set<TestResult> testResults = zipAndRunPlugin().getResults();

assertThat(testResults).isEmpty();
}

@Test
void shouldIgnoreNonZipFile() throws Exception {
zipFile = Files.createTempDirectory("regular-dir");

Set<TestResult> testResults = runPlugin().getResults();

assertThat(testResults).isEmpty();
}

private LaunchResults zipAndRunPlugin(ResourceToZipEntry... strings) throws IOException {
try (ZipOutputStream zout = new ZipOutputStream(Files.newOutputStream(zipFile))) {
for (ResourceToZipEntry file : strings) {
copyFile(zout, file);
}
}
return runPlugin();
}

private LaunchResults runPlugin() {
ZipResultsSourcePlugin reader = new ZipResultsSourcePlugin();
final Configuration configuration = new ConfigurationBuilder().useDefault().build();
final DefaultResultsVisitor resultsVisitor = new DefaultResultsVisitor(configuration);
reader.readResults(configuration, resultsVisitor, zipFile);
return resultsVisitor.getLaunchResults();
}

private void copyFile(ZipOutputStream zipFile, ResourceToZipEntry resource) throws IOException {
try (InputStream is = getClass().getClassLoader().getResourceAsStream(resource.getResourceName())) {
ZipEntry zipEntry = new ZipEntry(resource.getZipEntry());
zipFile.putNextEntry(zipEntry);
IOUtils.copy(Objects.requireNonNull(is), zipFile);
zipFile.closeEntry();
}
}

private static String generateTestResultName() {
return UUID.randomUUID() + "-result.json";
}

private static String generateTestResultContainerName() {
return UUID.randomUUID() + "-container.json";
}

static class ResourceToZipEntry {
private final String resourceName;
private final String zipEntry;

public ResourceToZipEntry(String resourceName, String zipEntry) {
this.resourceName = resourceName;
this.zipEntry = zipEntry;
}

public String getResourceName() {
return resourceName;
}

public String getZipEntry() {
return zipEntry;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
Expand Down Expand Up @@ -126,12 +127,12 @@ public void readResults(final Configuration configuration, final ResultsVisitor

private void parseRootElement(final Path resultsDirectory, final Path parsedFile,
final RandomUidContext context, final ResultsVisitor visitor) {
try {
try (InputStream is = Files.newInputStream(parsedFile)) {
LOGGER.debug("Parsing file {}", parsedFile);
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();

final XmlElement rootElement = new XmlElement(builder.parse(parsedFile.toFile()).getDocumentElement());
final XmlElement rootElement = new XmlElement(builder.parse(is).getDocumentElement());
final String elementName = rootElement.getName();

if (TEST_SUITE_ELEMENT_NAME.equals(elementName)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -102,12 +103,12 @@ public void readResults(final Configuration configuration,
}

protected void parseTestRun(final Path parsedFile, final RandomUidContext context, final ResultsVisitor visitor) {
try {
LOGGER.debug("Parsing file {}", parsedFile);

try (InputStream is = Files.newInputStream(parsedFile)) {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document document = builder.parse(parsedFile.toFile());
LOGGER.debug("Parsing file {}", parsedFile);

final Document document = builder.parse(is);
final XmlElement testRunElement = new XmlElement(document.getDocumentElement());
final String elementName = testRunElement.getName();
if (!TEST_RUN_ELEMENT_NAME.equals(elementName)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import xmlwise.XmlParseException;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -77,9 +78,11 @@ public void readResults(final Configuration configuration,
}

private void readSummaries(final Path directory, final Path testSummariesPath, final ResultsVisitor visitor) {
try {
try (InputStream is = Files.newInputStream(testSummariesPath)) {
final Path plist = Files.createTempFile("plist-from-stream", "plist");
Files.copy(is, plist);
LOGGER.info("Parse file {}", testSummariesPath);
final Map<String, Object> loaded = Plist.load(testSummariesPath.toFile());
final Map<String, Object> loaded = Plist.load(plist.toFile());
final List<?> summaries = asList(loaded.getOrDefault(TESTABLE_SUMMARIES, emptyList()));
summaries.forEach(summary -> parseSummary(directory, summary, visitor));
} catch (XmlParseException | IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
Expand Down Expand Up @@ -91,11 +92,11 @@ public void readResults(final Configuration configuration,
}

private void parseAssemblies(final Path parsedFile, final RandomUidContext context, final ResultsVisitor visitor) {
try {
try (InputStream is = Files.newInputStream(parsedFile)) {
LOGGER.debug("Parsing file {}", parsedFile);
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document document = builder.parse(parsedFile.toFile());
final Document document = builder.parse(is);
final XmlElement assembliesElement = new XmlElement(document.getDocumentElement());
final String elementName = assembliesElement.getName();
if (!ASSEMBLIES_ELEMENT_NAME.equals(elementName)) {
Expand Down