org.eclipse.winery.repository.export.CsarExporterTest.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.winery.repository.export.CsarExporterTest.java

Source

/*******************************************************************************
 * Copyright (c) 2017-2018 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0
 * which is available at https://www.apache.org/licenses/LICENSE-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 *******************************************************************************/
package org.eclipse.winery.repository.export;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.eclipse.winery.common.HashingUtil;
import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId;
import org.eclipse.winery.common.ids.definitions.DefinitionsChildId;
import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
import org.eclipse.winery.model.csar.toscametafile.TOSCAMetaFileAttributes;
import org.eclipse.winery.repository.TestWithGitBackedRepository;
import org.eclipse.winery.repository.backend.RepositoryFactory;

import org.apache.commons.io.IOUtils;
import org.eclipse.virgo.util.parser.manifest.ManifestContents;
import org.eclipse.virgo.util.parser.manifest.RecoveringManifestParser;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;

import static org.eclipse.winery.repository.export.CsarExportConfiguration.INCLUDE_HASHES;
import static org.eclipse.winery.repository.export.CsarExportConfiguration.STORE_IMMUTABLY;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class CsarExporterTest extends TestWithGitBackedRepository {

    private ByteArrayInputStream createOutputAndInputStream(String commitId, DefinitionsChildId id,
            Map<String, Object> exportConfiguration) throws Exception {
        setRevisionTo(commitId);
        CsarExporter exporter = new CsarExporter();
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        exporter.writeCsar(RepositoryFactory.getRepository(), id, os, exportConfiguration);
        return new ByteArrayInputStream(os.toByteArray());
    }

    private ManifestContents parseManifest(ZipInputStream zis) throws IOException {
        ZipEntry entry;
        ManifestContents manifestContents = null;

        while ((entry = zis.getNextEntry()) != null) {
            if ("TOSCA-Metadata/TOSCA.meta".equals(entry.getName())) {
                byte[] bytes = IOUtils.toByteArray(zis);
                String s = new String(bytes, StandardCharsets.UTF_8);

                manifestContents = new RecoveringManifestParser().parse(s);
            }
        }

        return manifestContents;
    }

    @Test
    public void csarIsValidZipForArtifactTemplateWithFilesAndSources() throws Exception {
        Map<String, Object> exportConfiguration = new HashMap<>();
        exportConfiguration.put(INCLUDE_HASHES.name(), null);
        try (InputStream inputStream = this.createOutputAndInputStream("origin/plain",
                new ArtifactTemplateId("http://plain.winery.opentosca.org/artifacttemplates",
                        "ArtifactTemplateWithFilesAndSources-ArtifactTypeWithoutProperties", false),
                exportConfiguration); ZipInputStream zis = new ZipInputStream(inputStream)) {
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                String name = entry.getName();
                assertNotNull(name);
                assertFalse(name.contains("\\"), "name contains backslashes");
            }
        }
    }

    @Test
    public void metafileDoesNotContainUnnecessaryFileAttributes() throws Exception {
        // create an empty configuration object
        Map<String, Object> exportConfiguration = new HashMap<>();

        try (InputStream inputStream = this.createOutputAndInputStream("origin/plain",
                new ArtifactTemplateId("http://plain.winery.opentosca.org/artifacttemplates",
                        "ArtifactTemplateWithFilesAndSources-ArtifactTypeWithoutProperties", false),
                exportConfiguration); ZipInputStream zis = new ZipInputStream(inputStream)) {
            ManifestContents manifestContents = parseManifest(zis);

            assertNotNull(manifestContents);

            for (String section : manifestContents.getSectionNames()) {
                assertNull(manifestContents.getAttributesForSection(section).get(TOSCAMetaFileAttributes.HASH));
                assertNull(manifestContents.getAttributesForSection(section)
                        .get(TOSCAMetaFileAttributes.IMMUTABLE_ADDRESS));
            }
        }
    }

    @Test
    public void testCsarFilesAreMentionedInTheManifest() throws Exception {
        Map<String, Object> exportConfiguration = new HashMap<>();
        exportConfiguration.put(INCLUDE_HASHES.name(), null);

        try (InputStream inputStream = this.createOutputAndInputStream("origin/plain",
                new ServiceTemplateId("http://plain.winery.opentosca.org/servicetemplates",
                        "ServiceTemplateWithAllReqCapVariants", false),
                exportConfiguration); ZipInputStream zis = new ZipInputStream(inputStream)) {
            ZipEntry entry;
            List<String> elementsList = new ArrayList<>();
            ManifestContents manifestContents = null;

            while ((entry = zis.getNextEntry()) != null) {
                String name = entry.getName();
                elementsList.add(name);
                assertNotNull(name);
                assertFalse(name.contains("\\"), "name contains backslashes");

                if ("TOSCA-Metadata/TOSCA.meta".equals(name)) {
                    byte[] bytes = IOUtils.toByteArray(zis);
                    String s = new String(bytes, StandardCharsets.UTF_8);

                    manifestContents = new RecoveringManifestParser().parse(s);
                }
            }

            assertNotNull(manifestContents);

            for (String section : manifestContents.getSectionNames()) {
                // ensures that the file is contained in the archive
                assertTrue(elementsList.remove(section), "Contains element " + section);
            }

            // ensures that the manifest was part of the archive
            assertTrue(elementsList.remove("TOSCA-Metadata/TOSCA.meta"));
            // ensures that every file in the archive is listed in the manifest
            assertEquals(0, elementsList.size());
        }
    }

    @Test
    public void testHashesForEachFile() throws Exception {
        Map<String, Object> exportConfiguration = new HashMap<>();
        exportConfiguration.put(INCLUDE_HASHES.name(), null);

        try (InputStream inputStream = this.createOutputAndInputStream(
                // quick fix - should work if eclipse/winery#305 is merged
                "7c8d8c7057403a07fde90dec1f44f0190ae65ae2",
                new ServiceTemplateId("http://plain.winery.opentosca.org/servicetemplates",
                        "ServiceTemplateWithAllReqCapVariants", false),
                exportConfiguration); ZipInputStream zis = new ZipInputStream(inputStream)) {
            ZipEntry entry;
            List<CsarContentProperties> elementsList = new ArrayList<>();
            ManifestContents manifestContents = null;

            while ((entry = zis.getNextEntry()) != null) {
                CsarContentProperties fileProperties = new CsarContentProperties(entry.getName());
                elementsList.add(fileProperties);
                byte[] array = IOUtils.toByteArray(zis);
                ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(array);
                fileProperties
                        .setFileHash(HashingUtil.getChecksum(byteArrayInputStream, TOSCAMetaFileAttributes.HASH));

                if ("TOSCA-Metadata/TOSCA.meta".equals(fileProperties.getPathInsideCsar())) {
                    String s = new String(array, StandardCharsets.UTF_8);
                    manifestContents = new RecoveringManifestParser().parse(s);
                }
            }

            assertNotNull(manifestContents);

            for (CsarContentProperties fileProperties : elementsList) {
                Map<String, String> attributes = manifestContents
                        .getAttributesForSection(fileProperties.getPathInsideCsar());

                if (!"TOSCA-Metadata/TOSCA.meta".equals(fileProperties.getPathInsideCsar())) {
                    // ensure each file has a hash
                    assertTrue(attributes.containsKey(TOSCAMetaFileAttributes.HASH));
                    // ensure that the hashes match
                    assertEquals(fileProperties.getFileHash(), attributes.get(TOSCAMetaFileAttributes.HASH));
                }
            }

            // ensures that every file in the archive has a hash in the manifest
            assertEquals(elementsList.size() - 1, manifestContents.getSectionNames().size());
        }
    }

    @Test
    @EnabledIf("(new java.io.File(\"C:/Ethereum/keystore/UTC--2018-03-05T15-33-22.456000000Z--e4b51a3d4e77d2ce2a9d9ce107ec8ec7cff5571d.json\")).exists()")
    public void csarFilesHaveImmutableStorageAddresses() throws Exception {
        Map<String, Object> exportConfiguration = new HashMap<>();
        exportConfiguration.put(STORE_IMMUTABLY.name(), null);

        try (InputStream inputStream = this.createOutputAndInputStream("origin/plain",
                new ServiceTemplateId("http://plain.winery.opentosca.org/servicetemplates",
                        "ServiceTemplateWithAllReqCapVariants", false),
                exportConfiguration); ZipInputStream zis = new ZipInputStream(inputStream)) {

            ManifestContents manifestContents = parseManifest(zis);

            assertNotNull(manifestContents);

            for (String section : manifestContents.getSectionNames()) {
                assertNotNull(manifestContents.getAttributesForSection(section)
                        .get(TOSCAMetaFileAttributes.IMMUTABLE_ADDRESS));
            }
        }
    }

    @Test
    @EnabledIf("(new java.io.File(\"C:/Ethereum/keystore/UTC--2018-03-05T15-33-22.456000000Z--e4b51a3d4e77d2ce2a9d9ce107ec8ec7cff5571d.json\")).exists()")
    public void testPutCsarInBlockchainAndImmutableStorage() throws Exception {
        setRevisionTo("origin/plain");
        CsarExporter exporter = new CsarExporter();
        DefinitionsChildId id = new ServiceTemplateId("http://plain.winery.opentosca.org/servicetemplates",
                "ServiceTemplateWithAllReqCapVariants", false);
        ByteArrayOutputStream os = new ByteArrayOutputStream();

        CompletableFuture<String> future = exporter
                .writeCsarAndSaveManifestInProvenanceLayer(RepositoryFactory.getRepository(), id, os);
        String transactionHash = future.get();

        assertNotNull(transactionHash);

        try (InputStream inputStream = new ByteArrayInputStream(os.toByteArray());
                ZipInputStream zis = new ZipInputStream(inputStream)) {
            ManifestContents manifestContents = parseManifest(zis);

            assertNotNull(manifestContents);

            for (String section : manifestContents.getSectionNames()) {
                assertNotNull(manifestContents.getAttributesForSection(section)
                        .get(TOSCAMetaFileAttributes.IMMUTABLE_ADDRESS));
            }
        }
    }
}