/*
* ProActive Parallel Suite(TM):
* The Open Source library for parallel and distributed
* Workflows & Scheduling, Orchestration, Cloud Automation
* and Big Data Analysis on Enterprise Grids & Clouds.
*
* Copyright (c) 2007 - 2017 ActiveEon
* Contact: contact@activeeon.com
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation: version 3 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* If needed, contact us to obtain a release under GPL Version 2 or 3
* or a different license than the AGPL.
*/
package org.ow2.proactive_grid_cloud_portal.dataspace.util;
import static com.google.common.truth.Truth.assertThat;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.zip.ZipEntry;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.VFS;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.ow2.proactive_grid_cloud_portal.dataspace.FileSystem;
import org.zeroturnaround.zip.ZipEntryCallback;
import org.zeroturnaround.zip.ZipUtil;
/**
* Unit tests related to {@link org.ow2.proactive_grid_cloud_portal.dataspace.util.VFSZipper.ZIP}.
*
* @author ActiveEon Team
*/
public class VFSZipperZIPTest {
private static final String DEFAULT_ARCHIVE_NAME = "archive.zip";
private static final int HIERARCHY_DEPTH = 10;
private static final int HIERARCHY_CODEPOINT_ROOT = 'a';
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private Path archivePath;
private Path outputPath;
private FileSystemManager fileSystemManager;
private Path temporaryPath;
@Before
public void setUp() throws IOException {
fileSystemManager = VFS.getManager();
temporaryPath = temporaryFolder.newFolder().toPath();
archivePath = getArchivePath();
outputPath = getOutputPath();
}
@Test
public void testZipFolderWithFileHierarchy() throws IOException {
createFileHierarchy(temporaryPath);
testZip(temporaryPath);
assertZipWithFileHierarchy(archivePath);
}
@Test
public void testZipEmptyFolder() throws IOException {
testZip(temporaryPath);
assertThat(Files.exists(archivePath)).isTrue();
}
@Test
public void testUnzipArchiveWithFileHierarchy() throws IOException {
createFileHierarchy(temporaryPath);
// Zips using third-party library that is tested and known to work as expected
ZipUtil.pack(temporaryPath.toFile(), archivePath.toFile());
testUnzip(outputPath);
}
@Test
public void testUnzipEmptyContent() throws IOException, InterruptedException {
Files.createFile(archivePath);
FileSystemManager fsManager = VFS.getManager();
VFSZipper.ZIP.unzip(Files.newInputStream(archivePath), fsManager.resolveFile(outputPath.toUri()));
assertThat(outputPath.toFile().listFiles()).isNull();
}
@Test
public void testZipUnzipZipUnzip() throws IOException, InterruptedException {
Path pathToZip = temporaryPath;
Path resultPath = outputPath;
createFileHierarchy(temporaryPath);
for (int i = 0; i < 2; i++) {
testZip(pathToZip);
assertZipWithFileHierarchy(archivePath);
testUnzip(resultPath);
assertUnzippedFileHierarchy(resultPath);
pathToZip = resultPath;
resultPath = temporaryPath.resolve("output" + (i + 1));
Files.delete(archivePath);
}
}
/**
* Creates the following file hierarchy from the specified root:
* .
* ├── a.txt
* └── folder0
* ├── b.txt
* └── folder...
* ├── ....txt
* └── folderN
* └── N_{ascii}.txt
* <p>
* where N is the equals to HIERARCHY_DEPTH.
*/
private void createFileHierarchy(Path root) throws IOException {
int codepoint = HIERARCHY_CODEPOINT_ROOT;
createFile(root, codepoint);
for (int i = 0; i < HIERARCHY_DEPTH; i++) {
codepoint++;
Path folder = createFolder(root, "folder" + i);
createFile(folder, codepoint);
root = folder;
}
}
private void testZip(Path pathToZip) throws IOException {
List<FileObject> files = FileSystem.findFiles(fileSystemManager.resolveFile(pathToZip.toUri()), null, null);
VFSZipper.ZIP.zip(fileSystemManager.resolveFile(pathToZip.toUri()), files, Files.newOutputStream(archivePath));
}
private void assertZipWithFileHierarchy(Path archivePath) {
final int[] nbEntries = { 0 };
// Reads ZIP content using a third-party library
ZipUtil.iterate(archivePath.toFile(), new ZipEntryCallback() {
@Override
public void process(InputStream in, ZipEntry zipEntry) throws IOException {
nbEntries[0]++;
}
});
assertThat(nbEntries[0]).isEqualTo(HIERARCHY_DEPTH + 1);
}
private void testUnzip(Path resultPath) throws IOException {
VFSZipper.ZIP.unzip(Files.newInputStream(archivePath), fileSystemManager.resolveFile(resultPath.toUri()));
assertUnzippedFileHierarchy(outputPath);
}
private void assertUnzippedFileHierarchy(Path root) {
int codepoint = HIERARCHY_CODEPOINT_ROOT;
Path file = getFile(root, codepoint);
assertThat(Files.exists(file)).isTrue();
for (int i = 0; i < HIERARCHY_DEPTH; i++) {
root = root.resolve("folder" + i);
assertThat(Files.exists(root)).isTrue();
}
}
private Path getArchivePath() {
return temporaryPath.getParent().resolve(DEFAULT_ARCHIVE_NAME);
}
private Path getOutputPath() throws IOException {
return temporaryPath.resolve("output");
}
private Path createFile(Path root, int codepoint) throws IOException {
return Files.createFile(getFile(root, codepoint));
}
private Path getFile(Path root, int codepoint) {
return root.resolve(Character.toString((char) codepoint) + ".txt");
}
private Path createFolder(Path root, String name) throws IOException {
Path folder = root.resolve(name);
Files.createDirectories(folder);
return folder;
}
}