mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-18 22:44:09 +00:00
VolmLib pin removal
- The build resolves VolmLib master-SNAPSHOT when no sibling checkout is substituted - The native runtime manifest, roots and keep rules come from the embedded natives - The packed jar natives are verified against the embedded provider shas - Every jar carries META-INF/volmit/volmlib.properties - The build logs the resolved VolmLib once - publishedNativeRuntime, the loader coordinate flags, mavenLocal and publish-volmlib are gone
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.artifacts.ModuleIdentifier;
|
||||
import org.gradle.api.artifacts.component.ComponentIdentifier;
|
||||
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.tukaani.xz.LZMA2Options;
|
||||
import org.tukaani.xz.XZOutputStream;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -15,122 +18,149 @@ import java.util.HexFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.TreeMap;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class NativeRuntimeArtifactsTest {
|
||||
@Test
|
||||
public void acceptsOnlyRequestedPublishedCoordinates() {
|
||||
File common = new File("common.jar");
|
||||
File provider = new File("provider.jar");
|
||||
Map<ComponentIdentifier, File> resolved = Map.of(
|
||||
module("native-common", "revision"), common,
|
||||
module("native-v26_2_R1", "revision"), provider);
|
||||
assertEquals(Map.of("native-common", common, "native-v26_2_R1", provider),
|
||||
NativeRuntimeArtifacts.publishedArtifacts(resolved,
|
||||
List.of("native-common", "native-v26_2_R1"), "revision"));
|
||||
}
|
||||
private static final List<String> MODULES = List.of("native-common", "native-v26_2_R1");
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporary = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void rejectsCompositeProjectArtifacts() {
|
||||
ComponentIdentifier project = () -> "project :VolmLib:native-common";
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.publishedArtifacts(
|
||||
Map.of(project, new File("native-common-local-SNAPSHOT.jar")), List.of("native-common"), "revision"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectsUnexpectedCoordinates() {
|
||||
List<ComponentIdentifier> invalid = List.of(
|
||||
new PublishedModule("other.group", "native-common", "revision"),
|
||||
module("native-common", "other-revision"),
|
||||
module("native-v26_3_R1", "revision"));
|
||||
for (ComponentIdentifier component : invalid) {
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.publishedArtifacts(
|
||||
Map.of(component, new File("provider.jar")), List.of("native-common"), "revision"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectsMissingProviders() {
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.publishedArtifacts(
|
||||
Map.of(module("native-common", "revision"), new File("common.jar")),
|
||||
List.of("native-common", "native-v26_2_R1"), "revision"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recordsExactDependenciesAndRetainsSharedProviderReferences() throws Exception {
|
||||
Path directory = Files.createTempDirectory("native-artifacts");
|
||||
File provider = directory.resolve("provider.jar").toFile();
|
||||
ClassWriter writer = new ClassWriter(0);
|
||||
writer.visit(Opcodes.V17, Opcodes.ACC_PUBLIC, "art/arcane/volmlib/nativelib/v26_2_R1/terrain/Provider", null,
|
||||
"art/arcane/volmlib/util/collection/KList", null);
|
||||
writer.visitEnd();
|
||||
try (JarOutputStream jar = new JarOutputStream(Files.newOutputStream(provider.toPath()))) {
|
||||
jar.putNextEntry(new JarEntry("art/arcane/volmlib/nativelib/v26_2_R1/terrain/Provider.class"));
|
||||
jar.write(writer.toByteArray());
|
||||
jar.closeEntry();
|
||||
}
|
||||
File rules = directory.resolve("keep.pro").toFile();
|
||||
NativeRuntimeArtifacts.generate(Map.of("native-common", provider, "native-v26_2_R1", provider),
|
||||
"revision", directory.toFile(), rules);
|
||||
public void describesTheEmbeddedProvidersAndRetainsTheirSharedReferences() throws Exception {
|
||||
Map<String, File> natives = natives();
|
||||
File output = temporary.newFolder("generated");
|
||||
File rules = new File(output, "keep.pro");
|
||||
NativeRuntimeArtifacts.generate(natives, MODULES, output, rules);
|
||||
Properties manifest = new Properties();
|
||||
try (Reader reader = Files.newBufferedReader(directory.resolve(NativeRuntimeArtifacts.MANIFEST))) {
|
||||
try (Reader reader = Files.newBufferedReader(output.toPath().resolve(NativeRuntimeArtifacts.MANIFEST))) {
|
||||
manifest.load(reader);
|
||||
}
|
||||
String digest = HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256")
|
||||
.digest(Files.readAllBytes(provider.toPath())));
|
||||
assertEquals(digest, manifest.getProperty("native-common.sha256"));
|
||||
assertEquals(digest, manifest.getProperty("native-v26_2_R1.sha256"));
|
||||
assertEquals("native-common,native-v26_2_R1", manifest.getProperty("modules"));
|
||||
assertEquals("embedded", manifest.getProperty("storage"));
|
||||
assertFalse(manifest.containsKey("repository"));
|
||||
for (String module : MODULES) {
|
||||
String digest = digest(Files.readAllBytes(natives.get(module).toPath()));
|
||||
assertEquals(digest, manifest.getProperty(module + ".sha256"));
|
||||
assertEquals("com.github.VolmitSoftware.VolmLib:" + module + ":embedded-" + digest,
|
||||
manifest.getProperty(module + ".coordinate"));
|
||||
}
|
||||
assertTrue(Files.readString(rules.toPath()).contains("-keep class art.arcane.volmlib.util.collection.KList { *; }"));
|
||||
File plugin = directory.resolve("plugin.jar").toFile();
|
||||
try (JarOutputStream jar = new JarOutputStream(Files.newOutputStream(plugin.toPath()))) {
|
||||
jar.putNextEntry(new JarEntry(NativeRuntimeArtifacts.MANIFEST));
|
||||
Files.copy(directory.resolve(NativeRuntimeArtifacts.MANIFEST), jar);
|
||||
jar.closeEntry();
|
||||
}
|
||||
NativeRuntimeArtifacts.verify(plugin, List.of("v26_2_R1"), "revision");
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.verify(plugin, List.of("v26_3_R1"), "revision"));
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.verify(plugin, List.of("v26_2_R1"), "other"));
|
||||
assertEquals(List.of("art/arcane/volmlib/util/collection/KList"),
|
||||
Files.readAllLines(output.toPath().resolve("META-INF/volmit/runtime-roots.list")));
|
||||
}
|
||||
|
||||
private static ModuleComponentIdentifier module(String module, String version) {
|
||||
return new PublishedModule("com.github.VolmitSoftware.VolmLib", module, version);
|
||||
@Test
|
||||
public void rejectsAProviderSetThatDiffersFromTheRuntimeModules() throws Exception {
|
||||
Map<String, File> natives = natives();
|
||||
natives.remove("native-v26_2_R1");
|
||||
File output = temporary.newFolder("generated");
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.generate(natives, MODULES, output,
|
||||
new File(output, "keep.pro")));
|
||||
}
|
||||
|
||||
private record PublishedModule(String group, String module, String version)
|
||||
implements ModuleComponentIdentifier, ModuleIdentifier {
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
@Test
|
||||
public void verifiesThePluginManifestAgainstTheProvidersBeingEmbedded() throws Exception {
|
||||
Map<String, File> natives = natives();
|
||||
File plugin = plugin(natives, Map.of());
|
||||
NativeRuntimeArtifacts.verify(plugin, MODULES, natives);
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.verify(plugin,
|
||||
List.of("native-common", "native-v26_3_R1"), natives));
|
||||
Map<String, File> rebuilt = new TreeMap<>(natives);
|
||||
rebuilt.put("native-v26_2_R1", provider("rebuilt.jar", "art/arcane/volmlib/util/collection/KMap"));
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.verify(plugin, MODULES, rebuilt));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModule() {
|
||||
return module;
|
||||
}
|
||||
@Test
|
||||
public void rejectsProviderImplementationsBundledOutsideTheEmbeddedJars() throws Exception {
|
||||
Map<String, File> natives = natives();
|
||||
File plugin = plugin(natives, Map.of("art/arcane/volmlib/nativelib/v26_2_R1/terrain/Provider.class", new byte[0]));
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.verify(plugin, MODULES, natives));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
@Test
|
||||
public void verifiesTheEmbeddedProviderBytesInsideThePackedRuntime() throws Exception {
|
||||
Map<String, File> natives = natives();
|
||||
Map<String, byte[]> runtime = runtime(natives, natives);
|
||||
NativeRuntimeArtifacts.verifyPacked(packed(runtime), MODULES, natives);
|
||||
NativeRuntimeArtifacts.verifyPacked(jar("ordinary.jar", runtime), MODULES, natives);
|
||||
Map<String, File> rebuilt = new TreeMap<>(natives);
|
||||
rebuilt.put("native-v26_2_R1", provider("rebuilt.jar", "art/arcane/volmlib/util/collection/KMap"));
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.verifyPacked(packed(runtime(natives, rebuilt)),
|
||||
MODULES, natives));
|
||||
Map<String, byte[]> missing = new TreeMap<>(runtime);
|
||||
missing.remove(NativeRuntimeArtifacts.RESOURCES + "native-v26_2_R1.jar");
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.verifyPacked(packed(missing), MODULES, natives));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleIdentifier getModuleIdentifier() {
|
||||
return this;
|
||||
}
|
||||
private Map<String, File> natives() throws IOException {
|
||||
Map<String, File> natives = new TreeMap<>();
|
||||
natives.put("native-common", provider("common.jar", "java/lang/Object"));
|
||||
natives.put("native-v26_2_R1", provider("v26_2_R1.jar", "art/arcane/volmlib/util/collection/KList"));
|
||||
return natives;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return module;
|
||||
}
|
||||
private File provider(String name, String superclass) throws IOException {
|
||||
ClassWriter writer = new ClassWriter(0);
|
||||
writer.visit(Opcodes.V17, Opcodes.ACC_PUBLIC, "art/arcane/volmlib/nativelib/v26_2_R1/terrain/Provider", null,
|
||||
superclass, null);
|
||||
writer.visitEnd();
|
||||
return jar(name, Map.of("art/arcane/volmlib/nativelib/v26_2_R1/terrain/Provider.class", writer.toByteArray()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return group + ":" + module + ":" + version;
|
||||
private File plugin(Map<String, File> natives, Map<String, byte[]> extra) throws IOException {
|
||||
File generated = temporary.newFolder();
|
||||
NativeRuntimeArtifacts.generate(natives, MODULES, generated, new File(generated, "keep.pro"));
|
||||
Map<String, byte[]> contents = new TreeMap<>(extra);
|
||||
contents.put(NativeRuntimeArtifacts.MANIFEST,
|
||||
Files.readAllBytes(generated.toPath().resolve(NativeRuntimeArtifacts.MANIFEST)));
|
||||
return jar("plugin.jar", contents);
|
||||
}
|
||||
|
||||
private Map<String, byte[]> runtime(Map<String, File> described, Map<String, File> embedded) throws IOException {
|
||||
File generated = temporary.newFolder();
|
||||
NativeRuntimeArtifacts.generate(described, MODULES, generated, new File(generated, "keep.pro"));
|
||||
Map<String, byte[]> contents = new TreeMap<>();
|
||||
contents.put(NativeRuntimeArtifacts.MANIFEST,
|
||||
Files.readAllBytes(generated.toPath().resolve(NativeRuntimeArtifacts.MANIFEST)));
|
||||
for (Map.Entry<String, File> provider : embedded.entrySet()) {
|
||||
contents.put(NativeRuntimeArtifacts.RESOURCES + provider.getKey() + ".jar",
|
||||
Files.readAllBytes(provider.getValue().toPath()));
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
private File packed(Map<String, byte[]> runtime) throws IOException {
|
||||
ByteArrayOutputStream compressed = new ByteArrayOutputStream();
|
||||
try (XZOutputStream xz = new XZOutputStream(compressed, new LZMA2Options(1))) {
|
||||
xz.write(Files.readAllBytes(jar("payload.jar", runtime).toPath()));
|
||||
}
|
||||
Map<String, byte[]> outer = new TreeMap<>();
|
||||
outer.put(NativeRuntimeArtifacts.MANIFEST, runtime.get(NativeRuntimeArtifacts.MANIFEST));
|
||||
outer.put("META-INF/volmit/runtime.jar.xz", compressed.toByteArray());
|
||||
return jar("packed.jar", outer);
|
||||
}
|
||||
|
||||
private File jar(String name, Map<String, byte[]> contents) throws IOException {
|
||||
Path file = temporary.newFolder().toPath().resolve(name);
|
||||
try (JarOutputStream jar = new JarOutputStream(Files.newOutputStream(file))) {
|
||||
for (Map.Entry<String, byte[]> entry : contents.entrySet()) {
|
||||
jar.putNextEntry(new JarEntry(entry.getKey()));
|
||||
jar.write(entry.getValue());
|
||||
jar.closeEntry();
|
||||
}
|
||||
}
|
||||
return file.toFile();
|
||||
}
|
||||
|
||||
private static String digest(byte[] bytes) throws Exception {
|
||||
return HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256").digest(bytes));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user