// Copyright 2016 The Bazel Authors. All rights reserved. // // 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.google.devtools.build.lib.rules.repository; import static com.google.common.truth.Truth.assertThat; import com.google.devtools.build.lib.bazel.repository.CompressedTarFunction; import com.google.devtools.build.lib.bazel.repository.DecompressorDescriptor; import com.google.devtools.build.lib.bazel.repository.TarGzFunction; import com.google.devtools.build.lib.testutil.BlazeTestUtils; import com.google.devtools.build.lib.testutil.TestConstants; import com.google.devtools.build.lib.testutil.TestUtils; import com.google.devtools.build.lib.unix.UnixFileSystem; import com.google.devtools.build.lib.util.OS; import com.google.devtools.build.lib.vfs.FileSystem; import com.google.devtools.build.lib.vfs.JavaIoFileSystem; import com.google.devtools.build.lib.vfs.Path; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.util.zip.GZIPInputStream; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** Tests decompressing archives. */ @RunWith(JUnit4.class) public class CompressedTarFunctionTest { /* Regular file */ private static final String REGULAR_FILE_NAME = "regularFile"; /* Hard link file, created by ln <REGULAR_FILE_NAME> <HARD_LINK_FILE_NAME> */ private static final String HARD_LINK_FILE_NAME = "hardLinkFile"; /* Symbolic(Soft) link file, created by ln -s <REGULAR_FILE_NAME> <SYMBOLIC_LINK_FILE_NAME> */ private static final String RELATIVE_SYMBOLIC_LINK_FILE_NAME = "relativeSymbolicLinkFile"; private static final String ABSOLUTE_SYMBOLIC_LINK_FILE_NAME = "absoluteSymbolicLinkFile"; private static final String PATH_TO_TEST_ARCHIVE = "/com/google/devtools/build/lib/rules/repository/"; private static final String ROOT_FOLDER_NAME = "root_folder"; private static final String INNER_FOLDER_NAME = "another_folder"; /* Tarball, created by * tar -czf <ARCHIVE_NAME> <REGULAR_FILE_NAME> <HARD_LINK_FILE_NAME> <SYMBOLIC_LINK_FILE_NAME> * * The tarball has the following structure * * root_folder/ * another_folder/ * regularFile * hardLinkFile hardlink to root_folder/another_folder/regularFile * relativeSymbolicLinkFile -> regularFile * absoluteSymbolicLinkFile -> /root_folder/another_folder/regularFile */ private static final String ARCHIVE_NAME = "test_decompress_archive.tar.gz"; private FileSystem testFS; private Path workingDir; private Path tarballPath; private Path outDir; private DecompressorDescriptor.Builder descriptorBuilder; @Before public void setUpFs() throws Exception { testFS = OS.getCurrent() == OS.WINDOWS ? new JavaIoFileSystem() : new UnixFileSystem(); tarballPath = testFS .getPath(BlazeTestUtils.runfilesDir()) .getRelative(TestConstants.JAVATESTS_ROOT + PATH_TO_TEST_ARCHIVE + ARCHIVE_NAME); workingDir = testFS.getPath(new File(TestUtils.tmpDir()).getCanonicalPath()); outDir = workingDir.getRelative("out"); descriptorBuilder = DecompressorDescriptor.builder() .setDecompressor(TarGzFunction.INSTANCE) .setRepositoryPath(outDir) .setArchivePath(tarballPath); } /** * Test decompressing a tar.gz file with hard link file and symbolic link file inside without * stripping a prefix * * @throws Exception */ @Test public void testDecompressWithoutPrefix() throws Exception { Path outputDir = new CompressedTarFunction() { @Override protected InputStream getDecompressorStream(DecompressorDescriptor descriptor) throws IOException { return new GZIPInputStream(new FileInputStream(descriptor.archivePath().getPathFile())); } }.decompress(descriptorBuilder.build()); assertOutputFiles(outputDir.getRelative(ROOT_FOLDER_NAME).getRelative(INNER_FOLDER_NAME)); } /** * Test decompressing a tar.gz file with hard link file and symbolic link file inside and * stripping a prefix * * @throws Exception */ @Test public void testDecompressWithPrefix() throws Exception { descriptorBuilder.setPrefix(ROOT_FOLDER_NAME); Path outputDir = new CompressedTarFunction() { @Override protected InputStream getDecompressorStream(DecompressorDescriptor descriptor) throws IOException { return new GZIPInputStream(new FileInputStream(descriptor.archivePath().getPathFile())); } }.decompress(descriptorBuilder.build()); assertOutputFiles(outputDir.getRelative(INNER_FOLDER_NAME)); } /** Validate the content of the output directory */ private void assertOutputFiles(Path outputDir) throws Exception { assertThat(outputDir.exists()).isTrue(); assertThat(outputDir.getRelative(REGULAR_FILE_NAME).exists()).isTrue(); assertThat(outputDir.getRelative(REGULAR_FILE_NAME).getFileSize()).isNotEqualTo(0); assertThat(outputDir.getRelative(REGULAR_FILE_NAME).isSymbolicLink()).isFalse(); assertThat(outputDir.getRelative(HARD_LINK_FILE_NAME).exists()).isTrue(); assertThat(outputDir.getRelative(HARD_LINK_FILE_NAME).getFileSize()).isNotEqualTo(0); assertThat(outputDir.getRelative(HARD_LINK_FILE_NAME).isSymbolicLink()).isFalse(); assertThat(outputDir.getRelative(RELATIVE_SYMBOLIC_LINK_FILE_NAME).exists()).isTrue(); assertThat(outputDir.getRelative(RELATIVE_SYMBOLIC_LINK_FILE_NAME).getFileSize()) .isNotEqualTo(0); assertThat(outputDir.getRelative(RELATIVE_SYMBOLIC_LINK_FILE_NAME).isSymbolicLink()).isTrue(); assertThat(outputDir.getRelative(ABSOLUTE_SYMBOLIC_LINK_FILE_NAME).exists()).isTrue(); assertThat(outputDir.getRelative(ABSOLUTE_SYMBOLIC_LINK_FILE_NAME).getFileSize()) .isNotEqualTo(0); assertThat(outputDir.getRelative(ABSOLUTE_SYMBOLIC_LINK_FILE_NAME).isSymbolicLink()).isTrue(); assertThat( Files.isSameFile( java.nio.file.Paths.get(outputDir.getRelative(REGULAR_FILE_NAME).toString()), java.nio.file.Paths.get(outputDir.getRelative(HARD_LINK_FILE_NAME).toString()))) .isTrue(); assertThat( Files.isSameFile( java.nio.file.Paths.get(outputDir.getRelative(REGULAR_FILE_NAME).toString()), java.nio.file.Paths.get( outputDir.getRelative(RELATIVE_SYMBOLIC_LINK_FILE_NAME).toString()))) .isTrue(); assertThat( Files.isSameFile( java.nio.file.Paths.get(outputDir.getRelative(REGULAR_FILE_NAME).toString()), java.nio.file.Paths.get( outputDir.getRelative(ABSOLUTE_SYMBOLIC_LINK_FILE_NAME).toString()))) .isTrue(); } }