Skip to content

Commit

Permalink
Fix JIJ output location, add CoreMod to testproject for testing (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
shartte authored Jun 15, 2024
1 parent eeb5534 commit d480632
Show file tree
Hide file tree
Showing 14 changed files with 223 additions and 20 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/build-prs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,42 @@ on:

jobs:
build:
name: Build
uses: neoforged/actions/.github/workflows/build-prs.yml@main
with:
java: 17
gradle_tasks: test
jar_compatibility: false

test-project:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
name: Test on ${{ matrix.os }}
steps:
- name: Checkout project sources
uses: actions/checkout@v4
with:
fetch-depth: 1000
fetch-tags: true

- uses: actions/setup-java@v4
with:
distribution: microsoft
java-version: 21

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Run build
run: ./gradlew build
working-directory: ./testproject

- name: Ensure clean, build and test work in the same run
run: ./gradlew clean build check
working-directory: ./testproject

- name: Ensure runData runs
run: ./gradlew runData
working-directory: ./testproject
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.neoforged.moddevgradle.dsl;

import net.neoforged.moddevgradle.internal.ModDevPlugin;
import net.neoforged.moddevgradle.internal.utils.ExtensionUtils;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.NamedDomainObjectContainer;
Expand Down Expand Up @@ -52,7 +53,7 @@ public NeoForgeExtension(Project project) {
*/
public void addModdingDependenciesTo(SourceSet sourceSet) {
var configurations = project.getConfigurations();
var sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
var sourceSets = ExtensionUtils.getSourceSets(project);
if (!sourceSets.contains(sourceSet)) {
throw new GradleException("Cannot add to the source set in another project.");
}
Expand Down
8 changes: 0 additions & 8 deletions src/main/java/net/neoforged/moddevgradle/dsl/UnitTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import net.neoforged.moddevgradle.internal.ModDevPlugin;
import org.gradle.api.Project;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.provider.Property;

import javax.inject.Inject;
Expand All @@ -16,8 +15,6 @@ public abstract class UnitTest {
@Inject
public UnitTest(Project project) {
this.project = project;

getGameDirectory().convention(project.getLayout().getBuildDirectory().dir("minecraft-junit"));
}

/**
Expand All @@ -33,9 +30,4 @@ public void enable() {
* will be added to that mod at runtime.
*/
public abstract Property<ModModel> getTestedMod();

/**
* The working directory for the unit test.
*/
public abstract DirectoryProperty getGameDirectory();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.neoforged.moddevgradle.dsl.NeoForgeExtension;
import net.neoforged.moddevgradle.dsl.RunModel;
import net.neoforged.moddevgradle.internal.utils.ExtensionUtils;
import net.neoforged.moddevgradle.internal.utils.FileUtils;
import net.neoforged.moddevgradle.internal.utils.IdeDetection;
import net.neoforged.moddevgradle.tasks.JarJar;
import org.gradle.api.GradleException;
Expand All @@ -24,6 +25,7 @@
import org.gradle.api.attributes.java.TargetJvmVersion;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.Directory;
import org.gradle.api.file.RegularFile;
import org.gradle.api.plugins.ExtensionAware;
import org.gradle.api.plugins.JavaLibraryPlugin;
import org.gradle.api.plugins.JavaPlugin;
Expand Down Expand Up @@ -57,6 +59,7 @@
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
Expand All @@ -70,6 +73,12 @@ public class ModDevPlugin implements Plugin<Project> {
private static final Attribute<String> ATTRIBUTE_DISTRIBUTION = Attribute.of("net.neoforged.distribution", String.class);
private static final Attribute<String> ATTRIBUTE_OPERATING_SYSTEM = Attribute.of("net.neoforged.operatingsystem", String.class);

/**
* This must be relative to the project directory since we can only set this to the same project-relative
* directory across all subprojects due to IntelliJ limitations.
*/
private static final String JUNIT_GAME_DIR = "build/minecraft-junit";

private static final String JAR_JAR_GROUP = "jarjar";

private static final String TASK_GROUP = "mod development";
Expand Down Expand Up @@ -544,6 +553,7 @@ private void setupTesting(Project project,
Provider<ConfigurableFileCollection> minecraftClassesArtifact) {
var extension = ExtensionUtils.getExtension(project, NeoForgeExtension.NAME, NeoForgeExtension.class);
var unitTest = extension.getUnitTest();
var gameDirectory = new File(project.getProjectDir(), JUNIT_GAME_DIR);

var tasks = project.getTasks();
var configurations = project.getConfigurations();
Expand Down Expand Up @@ -626,7 +636,7 @@ private void setupTesting(Project project,
var prepareTask = tasks.register("prepareNeoForgeTestFiles", PrepareTest.class, task -> {
task.setGroup(INTERNAL_TASK_GROUP);
task.setDescription("Prepares all files needed to run the JUnit test task.");
task.getGameDirectory().set(unitTest.getGameDirectory());
task.getGameDirectory().set(gameDirectory);
task.getVmArgsFile().set(vmArgsFile);
task.getProgramArgsFile().set(programArgsFile);
task.getLog4jConfigFile().set(log4j2ConfigFile);
Expand Down Expand Up @@ -654,28 +664,48 @@ private void setupTesting(Project project,

project.afterEvaluate(p -> {
// Test tasks don't have a provider-based property for working directory, so we need to afterEvaluate it.
testTask.configure(task -> task.setWorkingDir(unitTest.getGameDirectory()));
testTask.configure(task -> task.setWorkingDir(gameDirectory));

// Write out a separate file that has IDE specific VM args, which include the definition of the output directories.
// For JUnit we have to write this to a separate file due to the Run parameters being shared among all projects.
var intellijVmArgsFile = runArgsDir.map(dir -> dir.file("intellijVmArgs.txt"));
var outputDirectory = RunUtils.getIntellijOutputDirectory(project);
var ideSpecificVmArgs = RunUtils.escapeJvmArg(RunUtils.getIdeaModFoldersProvider(project, outputDirectory, unitTest.getTestedMod().map(Set::of), true).getArgument());
try {
var vmArgsFilePath = intellijVmArgsFile.get().getAsFile().toPath();
Files.createDirectories(vmArgsFilePath.getParent());
FileUtils.writeStringSafe(vmArgsFilePath, ideSpecificVmArgs);
} catch (IOException e) {
throw new GradleException("Failed to write VM args file for IntelliJ unit tests", e);
}

// Configure IntelliJ default JUnit parameters, which are used when the user configures IJ to run tests natively
// IMPORTANT: This affects *all projects*, not just this one. We have to use $MODULE_WORKING_DIR$ to make it work.
var intelliJRunConfigurations = getIntelliJRunConfigurations(p);
if (intelliJRunConfigurations != null) {
var outputDirectory = RunUtils.getIntellijOutputDirectory(p);
intelliJRunConfigurations.defaults(JUnit.class, jUnitDefaults -> {
jUnitDefaults.setWorkingDirectory(unitTest.getGameDirectory().get().getAsFile().getAbsolutePath());
// $MODULE_WORKING_DIR$ is documented here: https://www.jetbrains.com/help/idea/absolute-path-variables.html
jUnitDefaults.setWorkingDirectory("$MODULE_WORKING_DIR$/" + JUNIT_GAME_DIR);
jUnitDefaults.setVmParameters(
// The FML JUnit plugin uses this system property to read a
// file containing the program arguments needed to launch
RunUtils.escapeJvmArg("-Dfml.junit.argsfile=" + programArgsFile.get().getAsFile().getAbsolutePath())
// The FML JUnit plugin uses this system property to read a file containing the program arguments needed to launch
// NOTE: IntelliJ does not support $MODULE_WORKING_DIR$ in VM Arguments
// See https://youtrack.jetbrains.com/issue/IJPL-14230/Add-macro-support-for-VM-options-field-e.g.-expand-ModuleFileDir-properly
// As a workaround, we just use paths relative to the working directory.
RunUtils.escapeJvmArg("-Dfml.junit.argsfile=" + buildRelativePath(programArgsFile, gameDirectory))
+ " "
+ RunUtils.escapeJvmArg(RunUtils.getArgFileParameter(vmArgsFile.get()))
+ RunUtils.escapeJvmArg("@" + buildRelativePath(vmArgsFile, gameDirectory))
+ " "
+ RunUtils.escapeJvmArg(RunUtils.getIdeaModFoldersProvider(p, outputDirectory, unitTest.getTestedMod().map(Set::of), true).getArgument())
+ RunUtils.escapeJvmArg("@" + buildRelativePath(intellijVmArgsFile, gameDirectory))
);
});
}
});
}

private static String buildRelativePath(Provider<RegularFile> file, File workingDirectory) {
return workingDirectory.toPath().relativize(file.get().getAsFile().toPath()).toString().replace("\\", "/");
}

private static void setupJarJar(Project project) {
SourceSetContainer sourceSets = ExtensionUtils.getExtension(project, "sourceSets", SourceSetContainer.class);
sourceSets.configureEach(sourceSet -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public static File getIntellijProjectDir(Project project) {
return getIntellijProjectDir(project.getRootDir());
}

@Nullable
private static File getIntellijProjectDir(File gradleProjectDir) {
var ideaDir = new File(gradleProjectDir, ".idea");
return ideaDir.exists() ? ideaDir : null;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/net/neoforged/moddevgradle/tasks/JarJar.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public abstract class JarJar extends DefaultTask {
@Inject
public JarJar(FileSystemOperations fileSystemOperations) {
this.fileSystemOperations = fileSystemOperations;
this.getOutputDirectory().convention(getProject().getLayout().getBuildDirectory().dir("jarJar/"+getName()));
this.getOutputDirectory().convention(getProject().getLayout().getBuildDirectory().dir("generated/" + getName()));
}

@TaskAction
Expand All @@ -46,7 +46,7 @@ protected void run() {
spec.delete(getOutputDirectory());
});
fileSystemOperations.copy(spec -> {
spec.into(getOutputDirectory());
spec.into(getOutputDirectory().dir("META-INF/jarjar"));
spec.from(
includedJars.stream().map(ResolvedJarJarArtifact::getFile).collect(Collectors.toList())
);
Expand Down
33 changes: 33 additions & 0 deletions testproject/coremod/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
plugins {
id 'java'
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

jar {
manifest {
attributes([
"FMLModType": "LIBRARY"
])
}
}

repositories {
maven {
url = "https://libraries.minecraft.net"
metadataSources{
mavenPom()
}
}
maven {
url = "https://maven.neoforged.net/releases"
}
}

dependencies {
compileOnly 'net.neoforged.fancymodloader:loader:4.0.4'
}
48 changes: 48 additions & 0 deletions testproject/coremod/src/main/java/coremod/CoreMod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package coremod;

import cpw.mods.modlauncher.api.ITransformer;
import cpw.mods.modlauncher.api.ITransformerVotingContext;
import cpw.mods.modlauncher.api.TargetType;
import cpw.mods.modlauncher.api.TransformerVoteResult;
import net.neoforged.neoforgespi.coremod.ICoreMod;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;

import java.util.List;
import java.util.Set;

public class CoreMod implements ICoreMod {
@Override
public Iterable<? extends cpw.mods.modlauncher.api.ITransformer<?>> getTransformers() {
return List.of(
new ITransformer<ClassNode>() {
@Override
public ClassNode transform(ClassNode classNode, ITransformerVotingContext context) {
classNode.visitField(
Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL,
"CORE_MOD_MARKER",
"Z",
null,
true
);
return classNode;
}

@Override
public TransformerVoteResult castVote(ITransformerVotingContext context) {
return TransformerVoteResult.YES;
}

@Override
public Set<Target<ClassNode>> targets() {
return Set.of(Target.targetClass("net.minecraft.world.item.ItemStack"));
}

@Override
public TargetType<ClassNode> getTargetType() {
return TargetType.CLASS;
}
}
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
coremod.CoreMod
Empty file modified testproject/gradlew
100644 → 100755
Empty file.
37 changes: 37 additions & 0 deletions testproject/jijtest/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
plugins {
id 'net.neoforged.moddev'
}

dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
jarJar project(":coremod")
}

test {
useJUnitPlatform()
}

neoForge {
version = project.neoforge_version

runs {
data {
data()
}
}

mods {
jijtest {
sourceSet sourceSets.main
}
coremod {
dependency project(":coremod")
}
}

unitTest {
enable()
testedMod = mods.jijtest
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
modLoader = "javafml"
loaderVersion = "[4,)"
license = "CC0"
[[mods]]
modId = "jijtest"
version = "0.0.0"
displayName = "JIJ Test"
description = '''JIJ Test'''
16 changes: 16 additions & 0 deletions testproject/jijtest/src/test/java/jijtest/CoreModTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package jijtest;

import net.minecraft.world.item.ItemStack;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class CoreModTest {
@Test
void testPresenceOfCoreMod() throws Exception {
var field = assertDoesNotThrow(() -> ItemStack.class.getField("CORE_MOD_MARKER"));
assertTrue(field.getBoolean(null));
}
}
2 changes: 2 additions & 0 deletions testproject/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,7 @@ plugins {
includeBuild '..'
include 'subproject'
include 'common'
include 'jijtest'
include 'coremod'

enableFeaturePreview "STABLE_CONFIGURATION_CACHE"

0 comments on commit d480632

Please sign in to comment.