mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-03-28 04:07:01 -05:00
Add basic unit tests for SpecContext (#1377)
This commit is contained in:
@@ -38,22 +38,18 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.attributes.Usage;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.RemapConfigurationSettings;
|
||||
import net.fabricmc.loom.api.processor.SpecContext;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets;
|
||||
import net.fabricmc.loom.util.AsyncCache;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJson;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJsonFactory;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJsonHelpers;
|
||||
import net.fabricmc.loom.util.gradle.GradleUtils;
|
||||
|
||||
/**
|
||||
* @param modDependencies External mods that are depended on
|
||||
@@ -65,20 +61,24 @@ public record SpecContextImpl(
|
||||
List<FabricModJson> localMods,
|
||||
List<ModHolder> compileRuntimeMods) implements SpecContext {
|
||||
public static SpecContextImpl create(Project project) {
|
||||
AsyncCache<List<FabricModJson>> fmjCache = new AsyncCache<List<FabricModJson>>();
|
||||
return create(new SpecContextProjectView.Impl(project, LoomGradleExtension.get(project)));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static SpecContextImpl create(SpecContextProjectView projectView) {
|
||||
AsyncCache<List<FabricModJson>> fmjCache = new AsyncCache<>();
|
||||
return new SpecContextImpl(
|
||||
getDependentMods(project, fmjCache),
|
||||
FabricModJsonHelpers.getModsInProject(project),
|
||||
getCompileRuntimeMods(project, fmjCache)
|
||||
getDependentMods(projectView, fmjCache),
|
||||
projectView.getMods(),
|
||||
getCompileRuntimeMods(projectView, fmjCache)
|
||||
);
|
||||
}
|
||||
|
||||
// Reruns a list of mods found on both the compile and/or runtime classpaths
|
||||
private static List<FabricModJson> getDependentMods(Project project, AsyncCache<List<FabricModJson>> fmjCache) {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
private static List<FabricModJson> getDependentMods(SpecContextProjectView projectView, AsyncCache<List<FabricModJson>> fmjCache) {
|
||||
var futures = new ArrayList<CompletableFuture<List<FabricModJson>>>();
|
||||
|
||||
for (RemapConfigurationSettings entry : extension.getRemapConfigurations()) {
|
||||
for (RemapConfigurationSettings entry : projectView.extension().getRemapConfigurations()) {
|
||||
final Set<File> artifacts = entry.getSourceConfiguration().get().resolve();
|
||||
|
||||
for (File artifact : artifacts) {
|
||||
@@ -90,10 +90,9 @@ public record SpecContextImpl(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO provide a project isolated way of doing this.
|
||||
if (!extension.isProjectIsolationActive() && !GradleUtils.getBooleanProperty(project, Constants.Properties.DISABLE_PROJECT_DEPENDENT_MODS)) {
|
||||
if (!projectView.disableProjectDependantMods()) {
|
||||
// Add all the dependent projects
|
||||
for (Project dependentProject : getDependentProjects(project).toList()) {
|
||||
for (Project dependentProject : getDependentProjects(projectView).toList()) {
|
||||
futures.add(fmjCache.get(dependentProject.getPath(), () -> FabricModJsonHelpers.getModsInProject(dependentProject)));
|
||||
}
|
||||
}
|
||||
@@ -101,19 +100,19 @@ public record SpecContextImpl(
|
||||
return sorted(AsyncCache.joinList(futures));
|
||||
}
|
||||
|
||||
private static Stream<Project> getDependentProjects(Project project) {
|
||||
final Stream<Project> runtimeProjects = getLoomProjectDependencies(project, project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME));
|
||||
final Stream<Project> compileProjects = getLoomProjectDependencies(project, project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME));
|
||||
private static Stream<Project> getDependentProjects(SpecContextProjectView projectView) {
|
||||
final Stream<Project> runtimeProjects = projectView.getLoomProjectDependencies(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
|
||||
final Stream<Project> compileProjects = projectView.getLoomProjectDependencies(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME);
|
||||
|
||||
return Stream.concat(runtimeProjects, compileProjects)
|
||||
.distinct();
|
||||
}
|
||||
|
||||
// Returns a list of mods that are on both to compile and runtime classpath
|
||||
private static List<ModHolder> getCompileRuntimeMods(Project project, AsyncCache<List<FabricModJson>> fmjCache) {
|
||||
var mods = new ArrayList<>(getCompileRuntimeModsFromRemapConfigs(project, fmjCache));
|
||||
private static List<ModHolder> getCompileRuntimeMods(SpecContextProjectView projectView, AsyncCache<List<FabricModJson>> fmjCache) {
|
||||
var mods = new ArrayList<>(getCompileRuntimeModsFromRemapConfigs(projectView, fmjCache));
|
||||
|
||||
for (Project dependentProject : getCompileRuntimeProjectDependencies(project).toList()) {
|
||||
for (Project dependentProject : getCompileRuntimeProjectDependencies(projectView).toList()) {
|
||||
List<FabricModJson> projectMods = fmjCache.getBlocking(dependentProject.getPath(), () -> {
|
||||
return FabricModJsonHelpers.getModsInProject(dependentProject);
|
||||
});
|
||||
@@ -127,49 +126,49 @@ public record SpecContextImpl(
|
||||
}
|
||||
|
||||
// Returns a list of jar mods that are found on the compile and runtime remapping configurations
|
||||
private static List<ModHolder> getCompileRuntimeModsFromRemapConfigs(Project project, AsyncCache<List<FabricModJson>> fmjCache) {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
|
||||
private static List<ModHolder> getCompileRuntimeModsFromRemapConfigs(SpecContextProjectView projectView, AsyncCache<List<FabricModJson>> fmjCache) {
|
||||
// A set of mod ids from all remap configurations that are considered for dependency transforms.
|
||||
final Set<String> runtimeModIds = getModIds(
|
||||
project,
|
||||
projectView,
|
||||
fmjCache,
|
||||
extension.getRuntimeRemapConfigurations().stream()
|
||||
projectView.extension().getRuntimeRemapConfigurations().stream()
|
||||
.filter(settings -> settings.getApplyDependencyTransforms().get())
|
||||
);
|
||||
|
||||
// A set of mod ids that are found on one or more remap configurations that target the common source set.
|
||||
// Null when split source sets are not enabled, meaning all mods are common.
|
||||
final Set<String> commonModIds = extension.areEnvironmentSourceSetsSplit() ? getModIds(
|
||||
project,
|
||||
final Set<String> commonRuntimeModIds = projectView.extension().areEnvironmentSourceSetsSplit() ? getModIds(
|
||||
projectView,
|
||||
fmjCache,
|
||||
extension.getRuntimeRemapConfigurations().stream()
|
||||
projectView.extension().getRuntimeRemapConfigurations().stream()
|
||||
.filter(settings -> settings.getSourceSet().map(sourceSet -> !sourceSet.getName().equals(MinecraftSourceSets.Split.CLIENT_ONLY_SOURCE_SET_NAME)).get())
|
||||
.filter(settings -> settings.getApplyDependencyTransforms().get()))
|
||||
: null;
|
||||
|
||||
return getMods(
|
||||
project,
|
||||
Stream<FabricModJson> compileMods = getMods(
|
||||
projectView,
|
||||
fmjCache,
|
||||
extension.getCompileRemapConfigurations().stream()
|
||||
.filter(settings -> settings.getApplyDependencyTransforms().get()))
|
||||
projectView.extension().getCompileRemapConfigurations().stream()
|
||||
.filter(settings -> settings.getApplyDependencyTransforms().get()));
|
||||
|
||||
return compileMods
|
||||
// Only check based on the modid, as there may be differing versions used between the compile and runtime classpath.
|
||||
// We assume that the version used at runtime will be binary compatible with the version used to compile against.
|
||||
// It's not perfect but better than silently not supplying the mod, and this could happen with regular API that you compile against anyway.
|
||||
.filter(fabricModJson -> runtimeModIds.contains(fabricModJson.getId()))
|
||||
.sorted(Comparator.comparing(FabricModJson::getId))
|
||||
.map(fabricModJson -> new ModHolder(fabricModJson, commonModIds == null || commonModIds.contains(fabricModJson.getId())))
|
||||
.map(fabricModJson -> new ModHolder(fabricModJson, commonRuntimeModIds == null || commonRuntimeModIds.contains(fabricModJson.getId())))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private static Stream<FabricModJson> getMods(Project project, AsyncCache<List<FabricModJson>> fmjCache, Stream<RemapConfigurationSettings> stream) {
|
||||
return stream.flatMap(resolveArtifacts(project, true))
|
||||
private static Stream<FabricModJson> getMods(SpecContextProjectView projectView, AsyncCache<List<FabricModJson>> fmjCache, Stream<RemapConfigurationSettings> stream) {
|
||||
return stream.flatMap(projectView.resolveArtifacts(true))
|
||||
.map(modFromZip(fmjCache))
|
||||
.filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
private static Set<String> getModIds(Project project, AsyncCache<List<FabricModJson>> fmjCache, Stream<RemapConfigurationSettings> stream) {
|
||||
return getMods(project, fmjCache, stream)
|
||||
private static Set<String> getModIds(SpecContextProjectView projectView, AsyncCache<List<FabricModJson>> fmjCache, Stream<RemapConfigurationSettings> stream) {
|
||||
return getMods(projectView, fmjCache, stream)
|
||||
.map(FabricModJson::getId)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
@@ -185,43 +184,19 @@ public record SpecContextImpl(
|
||||
};
|
||||
}
|
||||
|
||||
private static Function<RemapConfigurationSettings, Stream<Path>> resolveArtifacts(Project project, boolean runtime) {
|
||||
final Usage usage = project.getObjects().named(Usage.class, runtime ? Usage.JAVA_RUNTIME : Usage.JAVA_API);
|
||||
|
||||
return settings -> {
|
||||
final Configuration configuration = settings.getSourceConfiguration().get().copyRecursive();
|
||||
configuration.setCanBeConsumed(false);
|
||||
configuration.attributes(attributes -> attributes.attribute(Usage.USAGE_ATTRIBUTE, usage));
|
||||
return configuration.resolve().stream().map(File::toPath);
|
||||
};
|
||||
}
|
||||
|
||||
// Returns a list of Loom Projects found in both the runtime and compile classpath
|
||||
private static Stream<Project> getCompileRuntimeProjectDependencies(Project project) {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
|
||||
// TODO provide a project isolated way of doing this.
|
||||
if (extension.isProjectIsolationActive()
|
||||
|| GradleUtils.getBooleanProperty(project, Constants.Properties.DISABLE_PROJECT_DEPENDENT_MODS)) {
|
||||
private static Stream<Project> getCompileRuntimeProjectDependencies(SpecContextProjectView projectView) {
|
||||
if (projectView.disableProjectDependantMods()) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
final Stream<Project> runtimeProjects = getLoomProjectDependencies(project, project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME));
|
||||
final List<Project> compileProjects = getLoomProjectDependencies(project, project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME)).toList();
|
||||
final Stream<Project> runtimeProjects = projectView.getLoomProjectDependencies(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
|
||||
final List<Project> compileProjects = projectView.getLoomProjectDependencies(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME).toList();
|
||||
|
||||
return runtimeProjects
|
||||
.filter(compileProjects::contains); // Use the intersection of the two configurations.
|
||||
}
|
||||
|
||||
// Returns a list of Loom Projects found in the provided Configuration
|
||||
private static Stream<Project> getLoomProjectDependencies(Project project, Configuration configuration) {
|
||||
return configuration.getAllDependencies()
|
||||
.withType(ProjectDependency.class)
|
||||
.stream()
|
||||
.map((d) -> project.project(d.getPath()))
|
||||
.filter(GradleUtils::isLoomProject);
|
||||
}
|
||||
|
||||
// Sort to ensure stable caching
|
||||
private static List<FabricModJson> sorted(List<FabricModJson> mods) {
|
||||
return mods.stream().sorted(Comparator.comparing(FabricModJson::getId)).toList();
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2025 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.processors;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.attributes.Usage;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.RemapConfigurationSettings;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJson;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJsonHelpers;
|
||||
import net.fabricmc.loom.util.gradle.GradleUtils;
|
||||
|
||||
// Used to abstract out the Gradle API usage to ease unit testing.
|
||||
public interface SpecContextProjectView {
|
||||
LoomGradleExtension extension();
|
||||
|
||||
// Returns a list of Loom Projects found in the specified Configuration
|
||||
Stream<Project> getLoomProjectDependencies(String name);
|
||||
|
||||
Function<RemapConfigurationSettings, Stream<Path>> resolveArtifacts(boolean runtime);
|
||||
|
||||
List<FabricModJson> getMods();
|
||||
|
||||
boolean disableProjectDependantMods();
|
||||
|
||||
record Impl(Project project, LoomGradleExtension extension) implements SpecContextProjectView {
|
||||
@Override
|
||||
public Stream<Project> getLoomProjectDependencies(String name) {
|
||||
final Configuration configuration = project.getConfigurations().getByName(name);
|
||||
return configuration.getAllDependencies()
|
||||
.withType(ProjectDependency.class)
|
||||
.stream()
|
||||
.map((d) -> project.project(d.getPath()))
|
||||
.filter(GradleUtils::isLoomProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<RemapConfigurationSettings, Stream<Path>> resolveArtifacts(boolean runtime) {
|
||||
final Usage usage = project.getObjects().named(Usage.class, runtime ? Usage.JAVA_RUNTIME : Usage.JAVA_API);
|
||||
|
||||
return settings -> {
|
||||
final Configuration configuration = settings.getSourceConfiguration().get().copyRecursive();
|
||||
configuration.setCanBeConsumed(false);
|
||||
configuration.attributes(attributes -> attributes.attribute(Usage.USAGE_ATTRIBUTE, usage));
|
||||
return configuration.resolve().stream().map(File::toPath);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FabricModJson> getMods() {
|
||||
return FabricModJsonHelpers.getModsInProject(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disableProjectDependantMods() {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
// TODO provide a project isolated way of doing this.
|
||||
return extension.isProjectIsolationActive()
|
||||
|| GradleUtils.getBooleanProperty(project, Constants.Properties.DISABLE_PROJECT_DEPENDENT_MODS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2025 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.test.unit
|
||||
|
||||
import java.nio.file.Path
|
||||
import java.util.function.Function
|
||||
import java.util.stream.Stream
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.gradle.api.NamedDomainObjectList
|
||||
import org.gradle.api.NamedDomainObjectProvider
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import spock.lang.Specification
|
||||
import spock.lang.TempDir
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension
|
||||
import net.fabricmc.loom.api.RemapConfigurationSettings
|
||||
import net.fabricmc.loom.api.fmj.FabricModJsonV1Spec
|
||||
import net.fabricmc.loom.configuration.processors.SpecContextImpl
|
||||
import net.fabricmc.loom.configuration.processors.SpecContextProjectView
|
||||
import net.fabricmc.loom.test.util.GradleTestUtil
|
||||
import net.fabricmc.loom.util.ZipUtils
|
||||
import net.fabricmc.loom.util.fmj.gen.FabricModJsonV1Generator
|
||||
|
||||
import static org.mockito.Mockito.mock
|
||||
import static org.mockito.Mockito.when
|
||||
|
||||
@SuppressWarnings('ExplicitCallToModMethod')
|
||||
class SpecContextTest extends Specification {
|
||||
@TempDir
|
||||
Path tempDir
|
||||
|
||||
Project project
|
||||
LoomGradleExtension extension
|
||||
SpecContextProjectView projectView
|
||||
NamedDomainObjectList<RemapConfigurationSettings> remapConfigurations
|
||||
|
||||
RemapConfigurationSettings implementation
|
||||
RemapConfigurationSettings runtimeOnly
|
||||
RemapConfigurationSettings compileOnly
|
||||
|
||||
Map<RemapConfigurationSettings, List<Path>> runtimeArtifacts = [:]
|
||||
Map<RemapConfigurationSettings, List<Path>> apiArtifacts = [:]
|
||||
|
||||
void setup() {
|
||||
project = GradleTestUtil.mockProject()
|
||||
extension = LoomGradleExtension.get(project)
|
||||
projectView = mock(SpecContextProjectView.class)
|
||||
remapConfigurations = project.getObjects().namedDomainObjectList(RemapConfigurationSettings.class)
|
||||
|
||||
when(projectView.extension()).thenReturn(extension)
|
||||
when(extension.getRemapConfigurations()).thenReturn(remapConfigurations)
|
||||
when(projectView.resolveArtifacts(true)).thenReturn(resolve(runtimeArtifacts))
|
||||
when(projectView.resolveArtifacts(false)).thenReturn(resolve(apiArtifacts))
|
||||
|
||||
implementation = createConfigurationSettings("implementation")
|
||||
runtimeOnly = createConfigurationSettings("runtimeOnly")
|
||||
compileOnly = createConfigurationSettings("compileOnly")
|
||||
remapConfigurations.addAll([
|
||||
implementation,
|
||||
runtimeOnly,
|
||||
compileOnly
|
||||
])
|
||||
|
||||
when(extension.getCompileRemapConfigurations()).thenReturn([implementation, compileOnly])
|
||||
when(extension.getRuntimeRemapConfigurations()).thenReturn([implementation, runtimeOnly])
|
||||
}
|
||||
|
||||
def "Empty"() {
|
||||
setup:
|
||||
dependencies(
|
||||
implementation: [],
|
||||
runtimeOnly: [],
|
||||
compileOnly: []
|
||||
)
|
||||
|
||||
when:
|
||||
def specContext = SpecContextImpl.create(projectView)
|
||||
|
||||
then:
|
||||
specContext.modDependencies().size() == 0
|
||||
specContext.localMods().size() == 0
|
||||
specContext.modDependenciesCompileRuntime().size() == 0
|
||||
specContext.modDependenciesCompileRuntimeClient().size() == 0
|
||||
specContext.allMods().size() == 0
|
||||
}
|
||||
|
||||
def "implementation dependency"() {
|
||||
setup:
|
||||
dependencies(
|
||||
implementation: [mod("test1")],
|
||||
runtimeOnly: [],
|
||||
compileOnly: []
|
||||
)
|
||||
|
||||
when:
|
||||
def specContext = SpecContextImpl.create(projectView)
|
||||
|
||||
then:
|
||||
specContext.modDependencies().size() == 1
|
||||
specContext.localMods().size() == 0
|
||||
specContext.modDependenciesCompileRuntime().size() == 1
|
||||
specContext.modDependenciesCompileRuntimeClient().size() == 0
|
||||
specContext.allMods().size() == 1
|
||||
}
|
||||
|
||||
def "runtime only dependency"() {
|
||||
setup:
|
||||
dependencies(
|
||||
implementation: [],
|
||||
runtimeOnly: [mod("test1")],
|
||||
compileOnly: []
|
||||
)
|
||||
|
||||
when:
|
||||
def specContext = SpecContextImpl.create(projectView)
|
||||
|
||||
then:
|
||||
specContext.modDependencies().size() == 1
|
||||
specContext.localMods().size() == 0
|
||||
specContext.modDependenciesCompileRuntime().size() == 0
|
||||
specContext.modDependenciesCompileRuntimeClient().size() == 0
|
||||
specContext.allMods().size() == 1
|
||||
}
|
||||
|
||||
def "compile only dependency"() {
|
||||
setup:
|
||||
dependencies(
|
||||
implementation: [],
|
||||
runtimeOnly: [],
|
||||
compileOnly: [mod("test1")]
|
||||
)
|
||||
|
||||
when:
|
||||
def specContext = SpecContextImpl.create(projectView)
|
||||
|
||||
then:
|
||||
specContext.modDependencies().size() == 1
|
||||
specContext.localMods().size() == 0
|
||||
specContext.modDependenciesCompileRuntime().size() == 0
|
||||
specContext.modDependenciesCompileRuntimeClient().size() == 0
|
||||
specContext.allMods().size() == 1
|
||||
}
|
||||
|
||||
// TODO I believe this test is testing broken behaviour
|
||||
def "compile only runtime only dependency"() {
|
||||
setup:
|
||||
def test1 = mod("test1")
|
||||
dependencies(
|
||||
implementation: [],
|
||||
runtimeOnly: [test1],
|
||||
compileOnly: [test1]
|
||||
)
|
||||
|
||||
when:
|
||||
def specContext = SpecContextImpl.create(projectView)
|
||||
|
||||
then:
|
||||
specContext.modDependencies().size() == 2
|
||||
specContext.localMods().size() == 0
|
||||
specContext.modDependenciesCompileRuntime().size() == 0
|
||||
specContext.modDependenciesCompileRuntimeClient().size() == 0
|
||||
specContext.allMods().size() == 2
|
||||
}
|
||||
|
||||
private void dependencies(Map<Object, List<Path>> files) {
|
||||
configureDependencies(files.implementation, this.implementation)
|
||||
configureDependencies(files.runtimeOnly, this.runtimeOnly)
|
||||
configureDependencies(files.compileOnly, this.compileOnly)
|
||||
|
||||
runtimeArtifacts[this.implementation].addAll(files.implementation)
|
||||
runtimeArtifacts[this.runtimeOnly].addAll(files.runtimeOnly)
|
||||
apiArtifacts[this.implementation].addAll(files.implementation)
|
||||
apiArtifacts[this.compileOnly].addAll(files.compileOnly)
|
||||
}
|
||||
|
||||
private static void configureDependencies(List<Path> files, RemapConfigurationSettings settings) {
|
||||
def configuration = mock(Configuration.class)
|
||||
when(configuration.resolve()).thenReturn(files*.toFile() as Set)
|
||||
|
||||
def provider = mock(NamedDomainObjectProvider.class)
|
||||
when(provider.get()).thenReturn(configuration)
|
||||
|
||||
when(settings.getSourceConfiguration()).thenReturn(provider)
|
||||
}
|
||||
|
||||
private Path mod(String modId) {
|
||||
def zip = tempDir.resolve("${modId}.zip")
|
||||
|
||||
def spec = project.objects.newInstance(FabricModJsonV1Spec.class)
|
||||
spec.modId.set(modId)
|
||||
spec.version.set("1.0.0")
|
||||
def json = FabricModJsonV1Generator.INSTANCE.generate(spec)
|
||||
ZipUtils.add(zip, "fabric.mod.json", json)
|
||||
|
||||
return zip
|
||||
}
|
||||
|
||||
private RemapConfigurationSettings createConfigurationSettings(String name) {
|
||||
def settings = project.getObjects().newInstance(RemapConfigurationSettings.class, name)
|
||||
settings.applyDependencyTransforms.set(true)
|
||||
|
||||
runtimeArtifacts.put(settings, [])
|
||||
apiArtifacts.put(settings, [])
|
||||
|
||||
return settings
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
private static Function<RemapConfigurationSettings, Stream<Path>> resolve(Map<RemapConfigurationSettings, List<Path>> artifacts) {
|
||||
return { settings ->
|
||||
def paths = artifacts.get(settings)
|
||||
return paths != null ? paths.stream() : Stream.empty()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
package net.fabricmc.loom.test.util
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.ConfigurationContainer
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.api.file.RegularFile
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
@@ -47,6 +48,7 @@ import net.fabricmc.loom.util.download.Download
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any
|
||||
import static org.mockito.Mockito.*
|
||||
import static org.mockito.Mockito.mock
|
||||
|
||||
class GradleTestUtil {
|
||||
static <T> Property<T> mockProperty(T value) {
|
||||
@@ -64,17 +66,19 @@ class GradleTestUtil {
|
||||
}
|
||||
|
||||
static Project mockProject() {
|
||||
def mock = mock(Project.class)
|
||||
def serviceRegistry = TestServiceFactory.createServiceRegistry(mock)
|
||||
def project = mock(Project.class)
|
||||
def serviceRegistry = TestServiceFactory.createServiceRegistry(project)
|
||||
def objectFactory = serviceRegistry.get(ObjectFactory)
|
||||
def providerFactory = serviceRegistry.get(ProviderFactory)
|
||||
def extensions = mockExtensionContainer()
|
||||
when(mock.getExtensions()).thenReturn(extensions)
|
||||
when(mock.getObjects()).thenReturn(objectFactory)
|
||||
when(mock.provider(any())).thenAnswer {
|
||||
def configurationContainer = mock(ConfigurationContainer.class)
|
||||
when(project.getExtensions()).thenReturn(extensions)
|
||||
when(project.getObjects()).thenReturn(objectFactory)
|
||||
when(project.provider(any())).thenAnswer {
|
||||
providerFactory.provider(it.getArgument(0))
|
||||
}
|
||||
return mock
|
||||
when(project.getConfigurations()).thenReturn(configurationContainer)
|
||||
return project
|
||||
}
|
||||
|
||||
static ExtensionContainer mockExtensionContainer() {
|
||||
|
||||
Reference in New Issue
Block a user