blob: 688ec149d41c9e1dff22d2f84136afffafe9a6d7 [file] [log] [blame]
// Copyright 2015 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.singlejar;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertThrows;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.singlejar.FakeZipFile.ByteValidator;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.jar.JarFile;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Unit tests for {@link SingleJar}.
*/
@RunWith(JUnit4.class)
public class SingleJarTest {
public static final byte[] EXTRA_FOR_META_INF = new byte[] {(byte) 0xFE, (byte) 0xCA, 0x00, 0x00};
static final Joiner LINE_JOINER = Joiner.on("\r\n");
static final Joiner LINEFEED_JOINER = Joiner.on("\n");
static enum EntryMode {
DONT_CARE, EXPECT_DEFLATE, EXPECT_STORED;
}
public static final class BuildInfoValidator implements ByteValidator {
private final List<String> buildInfoLines;
public BuildInfoValidator(List<String> buildInfoLines) {
this.buildInfoLines = buildInfoLines;
}
@Override
public void validate(byte[] content) {
String actualBuildInfo = new String(content, StandardCharsets.UTF_8);
List<String> expectedBuildInfos = new ArrayList<>();
for (String line : buildInfoLines) { // the character : is escaped
expectedBuildInfos.add(line.replace(":", "\\:"));
}
Collections.sort(expectedBuildInfos);
String[] actualBuildInfos = actualBuildInfo.split("\n");
Arrays.sort(actualBuildInfos);
assertThat(LINEFEED_JOINER.join(actualBuildInfos))
.isEqualTo(LINEFEED_JOINER.join(expectedBuildInfos));
}
}
// Manifest file line ordering is dependent of the ordering in HashMap (Attributes class) so
// we do a sorted comparison for Manifest.
public static final class ManifestValidator implements ByteValidator {
private final List<String> manifestLines;
public ManifestValidator(List<String> manifestLines) {
this.manifestLines = new ArrayList<>(manifestLines);
Collections.sort(this.manifestLines);
}
public ManifestValidator(String... manifestLines) {
this.manifestLines = Arrays.asList(manifestLines);
Collections.sort(this.manifestLines);
}
@Override
public void validate(byte[] content) {
String actualManifest = new String(content, StandardCharsets.UTF_8);
String[] actualManifestLines = actualManifest.trim().split("\r\n");
Arrays.sort(actualManifestLines);
assertThat(LINEFEED_JOINER.join(actualManifestLines))
.isEqualTo(LINEFEED_JOINER.join(manifestLines));
}
}
private BuildInfoValidator redactedBuildData(String outputJar) {
return new BuildInfoValidator(ImmutableList.of("build.target=" + outputJar));
}
private BuildInfoValidator redactedBuildData(String outputJar, String mainClass) {
return new BuildInfoValidator(
ImmutableList.of("build.target=" + outputJar, "main.class=" + mainClass));
}
static List<String> getBuildInfo() {
return ImmutableList.of("build.build_id=11111-222-33333",
"build.version=12659499",
"build.location=user@machine.domain.com:/home/user/source",
"build.target=output.jar",
"build.time=Fri Jan 2 02:17:36 1970 (123456)",
"build.timestamp=Fri Jan 2 02:17:36 1970 (123456)",
"build.timestamp.as.int=123456"
);
}
private byte[] sampleZip() {
ZipFactory factory = new ZipFactory();
factory.addFile("hello.txt", "Hello World!");
return factory.toByteArray();
}
private byte[] sampleUncompressedZip() {
ZipFactory factory = new ZipFactory();
factory.addFile("hello.txt", "Hello World!", false);
return factory.toByteArray();
}
private byte[] sampleZipWithSF() {
ZipFactory factory = new ZipFactory();
factory.addFile("hello.SF", "Hello World!");
return factory.toByteArray();
}
private byte[] sampleZipWithSubdirs() {
ZipFactory factory = new ZipFactory();
factory.addFile("dir1/file1", "contents11");
factory.addFile("dir1/file2", "contents12");
factory.addFile("dir2/file1", "contents21");
factory.addFile("dir3/file1", "contents31");
return factory.toByteArray();
}
private void assertStripFirstLine(String expected, String testCase) {
byte[] result = SingleJar.stripFirstLine(testCase.getBytes(StandardCharsets.UTF_8));
assertThat(new String(result, UTF_8)).isEqualTo(expected);
}
@Test
public void testStripFirstLine() {
assertStripFirstLine("", "");
assertStripFirstLine("", "no linefeed");
assertStripFirstLine(LINEFEED_JOINER.join("toto", "titi"),
LINEFEED_JOINER.join("# timestamp comment", "toto", "titi"));
assertStripFirstLine(LINE_JOINER.join("toto", "titi"),
LINE_JOINER.join("# timestamp comment", "toto", "titi"));
}
@Test
public void testEmptyJar() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar"))
.addEntry("build-data.properties", redactedBuildData("output.jar"));
expectedResult.assertSame(mockFs.toByteArray());
}
// Test that two identical calls at different time actually returns identical results
@Test
public void testDeterministicJar() throws IOException, InterruptedException {
MockSimpleFileSystem mockFs1 = new MockSimpleFileSystem("output.jar");
SingleJar singleJar1 = new SingleJar(mockFs1);
singleJar1.run(ImmutableList.of("--output", "output.jar", "--extra_build_info", "toto=titi",
"--normalize"));
Thread.sleep(1000); // ensure that we are not at the same seconds
MockSimpleFileSystem mockFs2 = new MockSimpleFileSystem("output.jar");
SingleJar singleJar2 = new SingleJar(mockFs2);
singleJar2.run(ImmutableList.of("--output", "output.jar", "--extra_build_info", "toto=titi",
"--normalize"));
FakeZipFile.assertSame(mockFs1.toByteArray(), mockFs2.toByteArray());
}
@Test
public void testExtraManifestContent() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--deploy_manifest_lines",
"Main-Class: SomeClass", "X-Other: Duh"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar",
"Main-Class: SomeClass",
"X-Other: Duh"))
.addEntry("build-data.properties", redactedBuildData("output.jar"));
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testMultipleExtraManifestContent() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--deploy_manifest_lines", "X-Other: Duh",
"--output", "output.jar",
"--deploy_manifest_lines", "Main-Class: SomeClass"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar",
"Main-Class: SomeClass",
"X-Other: Duh"))
.addEntry("build-data.properties", redactedBuildData("output.jar"));
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testMainClass() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--main_class", "SomeClass"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar",
"Main-Class: SomeClass"))
.addEntry("build-data.properties", redactedBuildData("output.jar", "SomeClass"));
expectedResult.assertSame(mockFs.toByteArray());
}
// These four tests test all combinations of compressed/uncompressed input and output.
@Test
public void testSimpleZip() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("test.jar", sampleZip());
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--sources", "test.jar"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF, false)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar"), false)
.addEntry("build-data.properties", redactedBuildData("output.jar"), false)
.addEntry("hello.txt", "Hello World!", false);
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testSimpleZipExpectCompressedOutput() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("test.jar", sampleZip());
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--sources", "test.jar",
"--compression"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF, false)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar"), true)
.addEntry("build-data.properties", redactedBuildData("output.jar"), true)
.addEntry("hello.txt", "Hello World!", true);
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testSimpleUncompressedZip() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("test.jar", sampleUncompressedZip());
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--sources", "test.jar"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF, false)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(ImmutableList.of(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar")), false)
.addEntry("build-data.properties", redactedBuildData("output.jar"), false)
.addEntry("hello.txt", "Hello World!", false);
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testSimpleUncompressedZipExpectCompressedOutput() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("test.jar", sampleUncompressedZip());
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--sources", "test.jar",
"--compression"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF, false)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar"), true)
.addEntry("build-data.properties", redactedBuildData("output.jar"), true)
.addEntry("hello.txt", "Hello World!", true);
expectedResult.assertSame(mockFs.toByteArray());
}
// Integration test for option file expansion.
@Test
public void testOptionFile() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("input.jar", sampleZip());
mockFs.addFile("options", "--output output.jar --sources input.jar");
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("@options"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar"))
.addEntry("build-data.properties", redactedBuildData("output.jar"))
.addEntry("hello.txt", "Hello World!");
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testSkipsSignatureFiles() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("input.jar", sampleZipWithSF());
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--sources", "input.jar"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar"))
.addEntry("build-data.properties", redactedBuildData("output.jar"));
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testSkipsUsingInputPrefixes() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("input.jar", sampleZipWithSubdirs());
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--sources",
"input.jar", "--include_prefixes", "dir1", "dir2"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar"))
.addEntry("build-data.properties", redactedBuildData("output.jar"))
.addEntry("dir1/file1", "contents11")
.addEntry("dir1/file2", "contents12")
.addEntry("dir2/file1", "contents21");
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testSkipsUsingMultipleInputPrefixes() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("input.jar", sampleZipWithSubdirs());
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--include_prefixes", "dir2",
"--sources", "input.jar", "--include_prefixes", "dir1"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar"))
.addEntry("build-data.properties", redactedBuildData("output.jar"))
.addEntry("dir1/file1", "contents11")
.addEntry("dir1/file2", "contents12")
.addEntry("dir2/file1", "contents21");
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testNormalize() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("input.jar", sampleZip());
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--sources", "input.jar",
"--normalize"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF, false)
.addEntry(JarFile.MANIFEST_NAME, ZipCombiner.DOS_EPOCH, new ManifestValidator(
"Manifest-Version: 1.0", "Created-By: blaze-singlejar"), false)
.addEntry("build-data.properties", ZipCombiner.DOS_EPOCH,
redactedBuildData("output.jar"), false)
.addEntry("hello.txt", ZipCombiner.DOS_EPOCH, "Hello World!", false);
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testNormalizeAndCompress() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("input.jar", sampleZip());
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--sources", "input.jar",
"--normalize", "--compression"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF, false)
.addEntry(JarFile.MANIFEST_NAME, ZipCombiner.DOS_EPOCH, new ManifestValidator(
"Manifest-Version: 1.0", "Created-By: blaze-singlejar"), true)
.addEntry("build-data.properties", ZipCombiner.DOS_EPOCH,
redactedBuildData("output.jar"), true)
.addEntry("hello.txt", ZipCombiner.DOS_EPOCH, "Hello World!", true);
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testAddBuildInfoProperties() throws IOException {
List<String> buildInfo = getBuildInfo();
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF, false)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0", "Created-By: blaze-singlejar"), false)
.addEntry("build-data.properties", new BuildInfoValidator(buildInfo),
false);
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
SingleJar singleJar = new SingleJar(mockFs);
List<String> args = new ArrayList<>();
args.add("--output");
args.add("output.jar");
args.addAll(infoPropertyArguments(buildInfo));
singleJar.run(args);
expectedResult.assertSame(mockFs.toByteArray());
}
private static List<String> infoPropertyArguments(List<String> buildInfoLines) {
List<String> args = new ArrayList<>();
for (String s : buildInfoLines) {
if (!s.isEmpty()) {
args.add("--extra_build_info");
args.add(s);
}
}
return args;
}
@Test
public void testAddBuildInfoPropertiesFile() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
SingleJar singleJar = new SingleJar(mockFs);
doTestAddBuildInfoPropertiesFile(mockFs, "output.jar", singleJar);
}
public static void doTestAddBuildInfoPropertiesFile(MockSimpleFileSystem mockFs, String target,
SingleJar singleJar) throws IOException {
List<String> buildInfo = getBuildInfo();
mockFs.addFile("my.properties", makePropertyFileFromBuildInfo(buildInfo));
singleJar.run(ImmutableList.of("--output", target, "--build_info_file", "my.properties"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF, false)
.addEntry(JarFile.MANIFEST_NAME,
new ManifestValidator("Manifest-Version: 1.0", "Created-By: blaze-singlejar"), false)
.addEntry("build-data.properties", new BuildInfoValidator(buildInfo),
false);
expectedResult.assertSame(mockFs.toByteArray());
}
private static String makePropertyFileFromBuildInfo(List<String> buildInfo) {
return LINEFEED_JOINER.join(buildInfo).replace(":", "\\:");
}
@Test
public void testAddBuildInfoPropertiesFiles() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
SingleJar singleJar = new SingleJar(mockFs);
doTestAddBuildInfoPropertiesFiles(mockFs, "output.jar", singleJar);
}
public static void doTestAddBuildInfoPropertiesFiles(MockSimpleFileSystem mockFs, String target,
SingleJar singleJar) throws IOException {
List<String> buildInfo = getBuildInfo();
mockFs.addFile("my1.properties", makePropertyFileFromBuildInfo(buildInfo.subList(0, 4)));
mockFs.addFile("my2.properties",
makePropertyFileFromBuildInfo(buildInfo.subList(4, buildInfo.size())));
singleJar.run(ImmutableList.of("--output", target,
"--build_info_file", "my1.properties",
"--build_info_file", "my2.properties"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF, false)
.addEntry(JarFile.MANIFEST_NAME,
new ManifestValidator("Manifest-Version: 1.0", "Created-By: blaze-singlejar"), false)
.addEntry("build-data.properties", new BuildInfoValidator(buildInfo),
false);
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testAddBuildInfoPropertiesAndFiles() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
SingleJar singleJar = new SingleJar(mockFs);
doTestAddBuildInfoPropertiesAndFiles(mockFs, "output.jar", singleJar);
}
public static void doTestAddBuildInfoPropertiesAndFiles(MockSimpleFileSystem mockFs,
String target, SingleJar singleJar) throws IOException {
List<String> buildInfo = getBuildInfo();
mockFs.addFile("my1.properties", makePropertyFileFromBuildInfo(buildInfo.subList(0, 4)));
mockFs.addFile("my2.properties", makePropertyFileFromBuildInfo(
buildInfo.subList(4, buildInfo.size())));
List<String> args = ImmutableList.<String>builder()
.add("--output").add(target)
.add("--build_info_file").add("my1.properties")
.add("--build_info_file").add("my2.properties")
.addAll(infoPropertyArguments(buildInfo.subList(4, buildInfo.size())))
.build();
singleJar.run(args);
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF, false)
.addEntry(JarFile.MANIFEST_NAME,
new ManifestValidator("Manifest-Version: 1.0", "Created-By: blaze-singlejar"), false)
.addEntry("build-data.properties", new BuildInfoValidator(buildInfo),
false);
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testExcludeBuildData() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
SingleJar singleJar = new SingleJar(mockFs);
doTestExcludeBuildData(mockFs, "output.jar", singleJar);
}
public static void doTestExcludeBuildData(MockSimpleFileSystem mockFs, String target,
SingleJar singleJar) throws IOException {
singleJar.run(ImmutableList.of("--output", target, "--exclude_build_data"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar"));
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testResourceMapping() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("a/b/c", "Test");
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--exclude_build_data",
"--resources", "a/b/c:c/b/a"));
FakeZipFile expectedResult = new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(JarFile.MANIFEST_NAME, new ManifestValidator(
"Manifest-Version: 1.0",
"Created-By: blaze-singlejar"))
.addEntry("c/", (String) null)
.addEntry("c/b/", (String) null)
.addEntry("c/b/a", "Test");
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testResourceMappingIdentity() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("a/b/c", "Test");
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--exclude_build_data",
"--resources", "a/b/c"));
FakeZipFile expectedResult =
new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(
JarFile.MANIFEST_NAME,
new ManifestValidator("Manifest-Version: 1.0", "Created-By: blaze-singlejar"))
.addEntry("a/", (String) null)
.addEntry("a/b/", (String) null)
.addEntry("a/b/c", "Test");
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testResourceMappingDuplicateError() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("a/b/c", "Test");
SingleJar singleJar = new SingleJar(mockFs);
IllegalArgumentException e =
assertThrows(
IllegalArgumentException.class,
() ->
singleJar.run(
ImmutableList.of(
"--output",
"output.jar",
"--exclude_build_data",
"--resources",
"a/b/c",
"a/b/c")));
assertThat(e).hasMessageThat().contains("already contains a file named 'a/b/c'.");
}
@Test
public void testResourceMappingDuplicateWarning() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
mockFs.addFile("a/b/c", "Test");
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar", "--exclude_build_data",
"--warn_duplicate_resources", "--resources", "a/b/c", "a/b/c"));
FakeZipFile expectedResult =
new FakeZipFile()
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(
JarFile.MANIFEST_NAME,
new ManifestValidator("Manifest-Version: 1.0", "Created-By: blaze-singlejar"))
.addEntry("a/", (String) null)
.addEntry("a/b/", (String) null)
.addEntry("a/b/c", "Test");
expectedResult.assertSame(mockFs.toByteArray());
}
@Test
public void testCanAddPreamble() throws IOException {
MockSimpleFileSystem mockFs = new MockSimpleFileSystem("output.jar");
String preamble = "WeThePeople";
mockFs.addFile(preamble, preamble.getBytes(UTF_8));
SingleJar singleJar = new SingleJar(mockFs);
singleJar.run(ImmutableList.of("--output", "output.jar",
"--java_launcher", preamble,
"--main_class", "SomeClass"));
FakeZipFile expectedResult =
new FakeZipFile()
.addPreamble(preamble.getBytes(UTF_8))
.addEntry("META-INF/", EXTRA_FOR_META_INF)
.addEntry(
JarFile.MANIFEST_NAME,
new ManifestValidator("Manifest-Version: 1.0", "Created-By: blaze-singlejar",
"Main-Class: SomeClass"))
.addEntry("build-data.properties", redactedBuildData("output.jar", "SomeClass"));
expectedResult.assertSame(mockFs.toByteArray());
}
}