mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-15 12:40:30 +00:00
Switch to Forge's game test system
It's now impossible to run the client tests (tests are still there, but none of the other infrastructure is). We've not run these for months now due to their severe flakiness :(.
This commit is contained in:
parent
6735cfd12e
commit
52df7cb8a4
62
build.gradle
62
build.gradle
@ -88,26 +88,8 @@ minecraft {
|
|||||||
args '--mod', 'computercraft', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
|
args '--mod', 'computercraft', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
|
||||||
}
|
}
|
||||||
|
|
||||||
testClient {
|
gameTestServer {
|
||||||
workingDirectory project.file('test-files/client')
|
|
||||||
parent runs.client
|
|
||||||
|
|
||||||
mods {
|
|
||||||
cctest {
|
|
||||||
source sourceSets.testMod
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lazyToken('minecraft_classpath') {
|
|
||||||
(configurations.shade.copyRecursive().resolve() + configurations.testModExtra.copyRecursive().resolve())
|
|
||||||
.collect { it.absolutePath }
|
|
||||||
.join(File.pathSeparator)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
testServer {
|
|
||||||
workingDirectory project.file('test-files/server')
|
workingDirectory project.file('test-files/server')
|
||||||
parent runs.server
|
|
||||||
|
|
||||||
mods {
|
mods {
|
||||||
cctest {
|
cctest {
|
||||||
@ -374,38 +356,23 @@ task licenseFormatAPI(type: LicenseFormat)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task setupServer(type: Copy) {
|
tasks.register("testServer", JavaExec.class).configure {
|
||||||
group "test server"
|
|
||||||
description "Sets up the environment for the test server."
|
|
||||||
|
|
||||||
from("src/testMod/server-files") {
|
|
||||||
include "eula.txt"
|
|
||||||
include "server.properties"
|
|
||||||
}
|
|
||||||
into "test-files/server"
|
|
||||||
}
|
|
||||||
|
|
||||||
["Client", "Server"].forEach { name ->
|
|
||||||
tasks.register("test$name", JavaExec.class).configure {
|
|
||||||
it.group('In-game tests')
|
it.group('In-game tests')
|
||||||
it.description("Runs tests on a temporary Minecraft instance.")
|
it.description("Runs tests on a temporary Minecraft instance.")
|
||||||
it.dependsOn(setupServer, "prepareRunTest$name", "cleanTest$name", 'compileTestModJava')
|
it.dependsOn("prepareRunGameTestServer", "cleanTestServer", 'compileTestModJava')
|
||||||
|
|
||||||
// Copy from runTestServer. We do it in this slightly odd way as runTestServer
|
// Copy from runTestServer. We do it in this slightly odd way as runTestServer
|
||||||
// isn't created until the task is configured (which is no good for us).
|
// isn't created until the task is configured (which is no good for us).
|
||||||
JavaExec exec = tasks.getByName("runTest$name")
|
JavaExec exec = tasks.getByName("runGameTestServer")
|
||||||
exec.copyTo(it)
|
exec.copyTo(it)
|
||||||
it.setClasspath(exec.getClasspath())
|
it.setClasspath(exec.getClasspath())
|
||||||
it.mainClass = exec.mainClass
|
it.mainClass = exec.mainClass
|
||||||
it.setArgs(exec.getArgs())
|
it.setArgs(exec.getArgs())
|
||||||
|
|
||||||
it.systemProperty('forge.logging.console.level', 'info')
|
|
||||||
it.systemProperty('cctest.run', 'true')
|
|
||||||
|
|
||||||
// Jacoco and modlauncher don't play well together as the classes loaded in-game don't
|
// Jacoco and modlauncher don't play well together as the classes loaded in-game don't
|
||||||
// match up with those written to disk. We get Jacoco to dump all classes to disk, and
|
// match up with those written to disk. We get Jacoco to dump all classes to disk, and
|
||||||
// use that when generating the report.
|
// use that when generating the report.
|
||||||
def coverageOut = new File(buildDir, "jacocoClassDump/test$name")
|
def coverageOut = new File(buildDir, "jacocoClassDump/testServer")
|
||||||
jacoco.applyTo(it)
|
jacoco.applyTo(it)
|
||||||
it.jacoco.setIncludes(["dan200.computercraft.*"])
|
it.jacoco.setIncludes(["dan200.computercraft.*"])
|
||||||
it.jacoco.setClassDumpDir(coverageOut)
|
it.jacoco.setClassDumpDir(coverageOut)
|
||||||
@ -413,28 +380,21 @@ task setupServer(type: Copy) {
|
|||||||
// Older versions of modlauncher don't include a protection domain (and thus no code
|
// Older versions of modlauncher don't include a protection domain (and thus no code
|
||||||
// source). Jacoco skips such classes by default, so we need to explicitly include them.
|
// source). Jacoco skips such classes by default, so we need to explicitly include them.
|
||||||
it.jacoco.setIncludeNoLocationClasses(true)
|
it.jacoco.setIncludeNoLocationClasses(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("jacocoTest${name}Report", JacocoReport.class).configure {
|
tasks.register("jacocoTestServerReport", JacocoReport.class).configure {
|
||||||
it.group('In-game')
|
it.group('In-game')
|
||||||
it.description("Generate coverage reports for test$name")
|
it.description("Generate coverage reports for testServer")
|
||||||
it.dependsOn("test$name")
|
it.dependsOn("testServer")
|
||||||
|
|
||||||
it.executionData(new File(buildDir, "jacoco/test${name}.exec"))
|
it.executionData(new File(buildDir, "jacoco/testServer.exec"))
|
||||||
it.sourceDirectories.from(sourceSets.main.allJava.srcDirs)
|
it.sourceDirectories.from(sourceSets.main.allJava.srcDirs)
|
||||||
it.classDirectories.from(new File(buildDir, "jacocoClassDump/test$name"))
|
it.classDirectories.from(new File(buildDir, "jacocoClassDump/testServer"))
|
||||||
|
|
||||||
it.reports {
|
it.reports {
|
||||||
xml.enabled true
|
xml.enabled true
|
||||||
html.enabled true
|
html.enabled true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (name != "Client" || project.findProperty('cc.tweaked.clientTests') == 'true') {
|
|
||||||
// Don't run client tests unless explicitly opted into them. They're a bit of a faff
|
|
||||||
// to run and pretty flakey.
|
|
||||||
check.dependsOn("jacocoTest${name}Report")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
package dan200.computercraft.ingame
|
package dan200.computercraft.ingame
|
||||||
|
|
||||||
import dan200.computercraft.ingame.api.*
|
import dan200.computercraft.ComputerCraft
|
||||||
|
import dan200.computercraft.ingame.api.modifyBlock
|
||||||
|
import dan200.computercraft.ingame.api.sequence
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.gametest.framework.GameTest
|
import net.minecraft.gametest.framework.GameTest
|
||||||
import net.minecraft.gametest.framework.GameTestHelper
|
import net.minecraft.gametest.framework.GameTestHelper
|
||||||
import net.minecraft.world.level.block.LeverBlock
|
import net.minecraft.world.level.block.LeverBlock
|
||||||
import net.minecraft.world.level.block.RedstoneLampBlock
|
import net.minecraft.world.level.block.RedstoneLampBlock
|
||||||
|
import net.minecraftforge.gametest.GameTestHolder
|
||||||
|
|
||||||
|
@GameTestHolder(ComputerCraft.MOD_ID)
|
||||||
class Computer_Test {
|
class Computer_Test {
|
||||||
/**
|
/**
|
||||||
* Ensures redstone signals do not travel through computers.
|
* Ensures redstone signals do not travel through computers.
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package dan200.computercraft.ingame
|
package dan200.computercraft.ingame
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft
|
||||||
import dan200.computercraft.ingame.api.sequence
|
import dan200.computercraft.ingame.api.sequence
|
||||||
import dan200.computercraft.ingame.api.thenComputerOk
|
import dan200.computercraft.ingame.api.thenComputerOk
|
||||||
import net.minecraft.gametest.framework.GameTest
|
import net.minecraft.gametest.framework.GameTest
|
||||||
import net.minecraft.gametest.framework.GameTestHelper
|
import net.minecraft.gametest.framework.GameTestHelper
|
||||||
|
import net.minecraftforge.gametest.GameTestHolder
|
||||||
|
|
||||||
|
@GameTestHolder(ComputerCraft.MOD_ID)
|
||||||
class CraftOs_Test {
|
class CraftOs_Test {
|
||||||
/**
|
/**
|
||||||
* Sends a rednet message to another a computer and back again.
|
* Sends a rednet message to another a computer and back again.
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package dan200.computercraft.ingame
|
package dan200.computercraft.ingame
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft
|
||||||
import dan200.computercraft.ingame.api.sequence
|
import dan200.computercraft.ingame.api.sequence
|
||||||
import dan200.computercraft.ingame.api.thenComputerOk
|
import dan200.computercraft.ingame.api.thenComputerOk
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.gametest.framework.GameTest
|
import net.minecraft.gametest.framework.GameTest
|
||||||
import net.minecraft.gametest.framework.GameTestHelper
|
import net.minecraft.gametest.framework.GameTestHelper
|
||||||
import net.minecraft.world.item.Items
|
import net.minecraft.world.item.Items
|
||||||
|
import net.minecraftforge.gametest.GameTestHolder
|
||||||
|
|
||||||
|
@GameTestHolder(ComputerCraft.MOD_ID)
|
||||||
class Disk_Drive_Test {
|
class Disk_Drive_Test {
|
||||||
/**
|
/**
|
||||||
* Ensure audio disks exist and we can play them.
|
* Ensure audio disks exist and we can play them.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package dan200.computercraft.ingame
|
package dan200.computercraft.ingame
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft
|
||||||
import dan200.computercraft.ingame.api.sequence
|
import dan200.computercraft.ingame.api.sequence
|
||||||
import dan200.computercraft.ingame.api.thenComputerOk
|
import dan200.computercraft.ingame.api.thenComputerOk
|
||||||
import dan200.computercraft.shared.Registry
|
import dan200.computercraft.shared.Registry
|
||||||
@ -7,7 +8,9 @@ import dan200.computercraft.shared.peripheral.modem.wired.BlockCable
|
|||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.gametest.framework.GameTest
|
import net.minecraft.gametest.framework.GameTest
|
||||||
import net.minecraft.gametest.framework.GameTestHelper
|
import net.minecraft.gametest.framework.GameTestHelper
|
||||||
|
import net.minecraftforge.gametest.GameTestHolder
|
||||||
|
|
||||||
|
@GameTestHolder(ComputerCraft.MOD_ID)
|
||||||
class Modem_Test {
|
class Modem_Test {
|
||||||
@GameTest(timeoutTicks = TIMEOUT)
|
@GameTest(timeoutTicks = TIMEOUT)
|
||||||
fun Have_peripherals(helper: GameTestHelper) = helper.sequence { thenComputerOk() }
|
fun Have_peripherals(helper: GameTestHelper) = helper.sequence { thenComputerOk() }
|
||||||
|
@ -2,7 +2,6 @@ package dan200.computercraft.ingame
|
|||||||
|
|
||||||
import dan200.computercraft.ComputerCraft
|
import dan200.computercraft.ComputerCraft
|
||||||
import dan200.computercraft.ingame.api.*
|
import dan200.computercraft.ingame.api.*
|
||||||
import dan200.computercraft.ingame.api.Timeouts.CLIENT_TIMEOUT
|
|
||||||
import dan200.computercraft.shared.Capabilities
|
import dan200.computercraft.shared.Capabilities
|
||||||
import dan200.computercraft.shared.Registry
|
import dan200.computercraft.shared.Registry
|
||||||
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer
|
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer
|
||||||
@ -13,8 +12,10 @@ import net.minecraft.gametest.framework.GameTest
|
|||||||
import net.minecraft.gametest.framework.GameTestHelper
|
import net.minecraft.gametest.framework.GameTestHelper
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.world.level.block.Blocks
|
import net.minecraft.world.level.block.Blocks
|
||||||
|
import net.minecraftforge.gametest.GameTestHolder
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@GameTestHolder(ComputerCraft.MOD_ID)
|
||||||
class Monitor_Test {
|
class Monitor_Test {
|
||||||
@GameTest
|
@GameTest
|
||||||
fun Ensures_valid_on_place(context: GameTestHelper) = context.sequence {
|
fun Ensures_valid_on_place(context: GameTestHelper) = context.sequence {
|
||||||
@ -67,16 +68,16 @@ class Monitor_Test {
|
|||||||
.thenScreenshot()
|
.thenScreenshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
@GameTest(batch = "client:Monitor_Test.Looks_acceptable", timeoutTicks = CLIENT_TIMEOUT, template = LOOKS_ACCEPTABLE)
|
// @GameTest(batch = "Monitor_Test.Looks_acceptable", template = LOOKS_ACCEPTABLE)
|
||||||
fun Looks_acceptable(helper: GameTestHelper) = looksAcceptable(helper, renderer = MonitorRenderer.TBO)
|
fun Looks_acceptable(helper: GameTestHelper) = looksAcceptable(helper, renderer = MonitorRenderer.TBO)
|
||||||
|
|
||||||
@GameTest(batch = "client:Monitor_Test.Looks_acceptable_dark", timeoutTicks = CLIENT_TIMEOUT, template = LOOKS_ACCEPTABLE_DARK)
|
// @GameTest(batch = "Monitor_Test.Looks_acceptable_dark", template = LOOKS_ACCEPTABLE_DARK)
|
||||||
fun Looks_acceptable_dark(helper: GameTestHelper) = looksAcceptable(helper, renderer = MonitorRenderer.TBO)
|
fun Looks_acceptable_dark(helper: GameTestHelper) = looksAcceptable(helper, renderer = MonitorRenderer.TBO)
|
||||||
|
|
||||||
@GameTest(batch = "client:Monitor_Test.Looks_acceptable_vbo", timeoutTicks = CLIENT_TIMEOUT, template = LOOKS_ACCEPTABLE)
|
// @GameTest(batch = "Monitor_Test.Looks_acceptable_vbo", template = LOOKS_ACCEPTABLE)
|
||||||
fun Looks_acceptable_vbo(helper: GameTestHelper) = looksAcceptable(helper, renderer = MonitorRenderer.VBO)
|
fun Looks_acceptable_vbo(helper: GameTestHelper) = looksAcceptable(helper, renderer = MonitorRenderer.VBO)
|
||||||
|
|
||||||
@GameTest(batch = "client:Monitor_Test.Looks_acceptable_dark_vbo", timeoutTicks = CLIENT_TIMEOUT, template = LOOKS_ACCEPTABLE_DARK)
|
// @GameTest(batch = "Monitor_Test.Looks_acceptable_dark_vbo", template = LOOKS_ACCEPTABLE_DARK)
|
||||||
fun Looks_acceptable_dark_vbo(helper: GameTestHelper) = looksAcceptable(helper, renderer = MonitorRenderer.VBO)
|
fun Looks_acceptable_dark_vbo(helper: GameTestHelper) = looksAcceptable(helper, renderer = MonitorRenderer.VBO)
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
package dan200.computercraft.ingame
|
package dan200.computercraft.ingame
|
||||||
|
|
||||||
import dan200.computercraft.ingame.api.Timeouts
|
|
||||||
import dan200.computercraft.ingame.api.positionAtArmorStand
|
import dan200.computercraft.ingame.api.positionAtArmorStand
|
||||||
import dan200.computercraft.ingame.api.sequence
|
import dan200.computercraft.ingame.api.sequence
|
||||||
import dan200.computercraft.ingame.api.thenScreenshot
|
import dan200.computercraft.ingame.api.thenScreenshot
|
||||||
import net.minecraft.gametest.framework.GameTest
|
|
||||||
import net.minecraft.gametest.framework.GameTestHelper
|
import net.minecraft.gametest.framework.GameTestHelper
|
||||||
|
|
||||||
class PrintoutTest {
|
class PrintoutTest {
|
||||||
@GameTest(batch = "client:Printout_Test.In_frame_at_night", timeoutTicks = Timeouts.CLIENT_TIMEOUT)
|
// @GameTest(batch = "Printout_Test.In_frame_at_night", timeoutTicks = Timeouts.CLIENT_TIMEOUT)
|
||||||
fun In_frame_at_night(helper: GameTestHelper) = helper.sequence {
|
fun In_frame_at_night(helper: GameTestHelper) = helper.sequence {
|
||||||
this
|
this
|
||||||
.thenExecute { helper.positionAtArmorStand() }
|
.thenExecute { helper.positionAtArmorStand() }
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package dan200.computercraft.ingame
|
package dan200.computercraft.ingame
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft
|
||||||
import dan200.computercraft.ingame.api.Timeouts.COMPUTER_TIMEOUT
|
import dan200.computercraft.ingame.api.Timeouts.COMPUTER_TIMEOUT
|
||||||
import dan200.computercraft.ingame.api.sequence
|
import dan200.computercraft.ingame.api.sequence
|
||||||
import dan200.computercraft.ingame.api.thenComputerOk
|
import dan200.computercraft.ingame.api.thenComputerOk
|
||||||
import net.minecraft.gametest.framework.GameTest
|
import net.minecraft.gametest.framework.GameTest
|
||||||
import net.minecraft.gametest.framework.GameTestHelper
|
import net.minecraft.gametest.framework.GameTestHelper
|
||||||
|
import net.minecraftforge.gametest.GameTestHolder
|
||||||
|
|
||||||
|
@GameTestHolder(ComputerCraft.MOD_ID)
|
||||||
class Turtle_Test {
|
class Turtle_Test {
|
||||||
@GameTest(timeoutTicks = COMPUTER_TIMEOUT)
|
@GameTest(timeoutTicks = COMPUTER_TIMEOUT)
|
||||||
fun Unequip_refreshes_peripheral(helper: GameTestHelper) = helper.sequence { thenComputerOk() }
|
fun Unequip_refreshes_peripheral(helper: GameTestHelper) = helper.sequence { thenComputerOk() }
|
||||||
|
@ -11,7 +11,10 @@ import net.minecraft.ChatFormatting;
|
|||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.gametest.framework.*;
|
import net.minecraft.gametest.framework.GameTestRegistry;
|
||||||
|
import net.minecraft.gametest.framework.StructureUtils;
|
||||||
|
import net.minecraft.gametest.framework.TestCommand;
|
||||||
|
import net.minecraft.gametest.framework.TestFunction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.chat.TextComponent;
|
import net.minecraft.network.chat.TextComponent;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
@ -23,7 +26,6 @@ import net.minecraft.world.level.block.entity.StructureBlockEntity;
|
|||||||
import net.minecraft.world.level.storage.LevelResource;
|
import net.minecraft.world.level.storage.LevelResource;
|
||||||
import net.minecraftforge.fml.loading.FMLLoader;
|
import net.minecraftforge.fml.loading.FMLLoader;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
|
|
||||||
@ -133,35 +135,6 @@ class CCTestCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Callback implements GameTestListener
|
|
||||||
{
|
|
||||||
private final CommandSourceStack source;
|
|
||||||
private final MultipleTestTracker result;
|
|
||||||
|
|
||||||
Callback( CommandSourceStack source, MultipleTestTracker result )
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
this.result = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testStructureLoaded( @Nonnull GameTestInfo tracker )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testFailed( @Nonnull GameTestInfo tracker )
|
|
||||||
{
|
|
||||||
TestHooks.writeResults( source, result );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testPassed( @Nonnull GameTestInfo tracker )
|
|
||||||
{
|
|
||||||
TestHooks.writeResults( source, result );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int error( CommandSourceStack source, String message )
|
private static int error( CommandSourceStack source, String message )
|
||||||
{
|
{
|
||||||
source.sendFailure( new TextComponent( message ).withStyle( ChatFormatting.RED ) );
|
source.sendFailure( new TextComponent( message ).withStyle( ChatFormatting.RED ) );
|
||||||
|
@ -6,45 +6,26 @@
|
|||||||
package dan200.computercraft.ingame.mod;
|
package dan200.computercraft.ingame.mod;
|
||||||
|
|
||||||
import dan200.computercraft.ingame.api.Times;
|
import dan200.computercraft.ingame.api.Times;
|
||||||
import net.minecraft.ChatFormatting;
|
|
||||||
import net.minecraft.SharedConstants;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.gametest.framework.*;
|
|
||||||
import net.minecraft.network.chat.TextComponent;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.GameRules;
|
import net.minecraft.world.level.GameRules;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Rotation;
|
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
|
||||||
import net.minecraftforge.event.RegisterCommandsEvent;
|
import net.minecraftforge.event.RegisterCommandsEvent;
|
||||||
import net.minecraftforge.event.TickEvent;
|
|
||||||
import net.minecraftforge.event.server.ServerStartedEvent;
|
import net.minecraftforge.event.server.ServerStartedEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.loading.FMLLoader;
|
|
||||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
@Mod.EventBusSubscriber( modid = TestMod.MOD_ID )
|
@Mod.EventBusSubscriber( modid = TestMod.MOD_ID )
|
||||||
public class TestHooks
|
public class TestHooks
|
||||||
{
|
{
|
||||||
private static final Logger LOG = LogManager.getLogger( TestHooks.class );
|
private static final Logger LOG = LogManager.getLogger( TestHooks.class );
|
||||||
|
|
||||||
private static MultipleTestTracker runningTests = null;
|
|
||||||
private static boolean shutdown = false;
|
|
||||||
private static int countdown = 20;
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onRegisterCommands( RegisterCommandsEvent event )
|
public static void onRegisterCommands( RegisterCommandsEvent event )
|
||||||
{
|
{
|
||||||
LOG.info( "Starting server, registering command helpers." );
|
LOG.info( "Starting server, registering command helpers." );
|
||||||
TestCommand.register( event.getDispatcher() );
|
|
||||||
CCTestCommand.register( event.getDispatcher() );
|
CCTestCommand.register( event.getDispatcher() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,124 +35,15 @@ public class TestHooks
|
|||||||
MinecraftServer server = event.getServer();
|
MinecraftServer server = event.getServer();
|
||||||
GameRules rules = server.getGameRules();
|
GameRules rules = server.getGameRules();
|
||||||
rules.getRule( GameRules.RULE_DAYLIGHT ).set( false, server );
|
rules.getRule( GameRules.RULE_DAYLIGHT ).set( false, server );
|
||||||
rules.getRule( GameRules.RULE_WEATHER_CYCLE ).set( false, server );
|
|
||||||
rules.getRule( GameRules.RULE_DOMOBSPAWNING ).set( false, server );
|
|
||||||
|
|
||||||
ServerLevel world = event.getServer().getLevel( Level.OVERWORLD );
|
ServerLevel world = event.getServer().getLevel( Level.OVERWORLD );
|
||||||
if( world != null ) world.setDayTime( Times.NOON );
|
if( world != null ) world.setDayTime( Times.NOON );
|
||||||
|
|
||||||
LOG.info( "Cleaning up after last run" );
|
// LOG.info( "Cleaning up after last run" );
|
||||||
CommandSourceStack source = server.createCommandSourceStack();
|
// CommandSourceStack source = server.createCommandSourceStack();
|
||||||
GameTestRunner.clearAllTests( source.getLevel(), getStart( source ), GameTestTicker.SINGLETON, 200 );
|
// GameTestRunner.clearAllTests( source.getLevel(), getStart( source ), GameTestTicker.SINGLETON, 200 );
|
||||||
|
|
||||||
LOG.info( "Importing files" );
|
LOG.info( "Importing files" );
|
||||||
CCTestCommand.importFiles( server );
|
CCTestCommand.importFiles( server );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
|
||||||
public static void onServerTick( TickEvent.ServerTickEvent event )
|
|
||||||
{
|
|
||||||
if( event.phase != TickEvent.Phase.START ) return;
|
|
||||||
|
|
||||||
// Let the world settle a bit before starting tests.
|
|
||||||
countdown--;
|
|
||||||
if( countdown == 0 && System.getProperty( "cctest.run", "false" ).equals( "true" ) ) startTests();
|
|
||||||
|
|
||||||
if( !SharedConstants.IS_RUNNING_IN_IDE ) GameTestTicker.SINGLETON.tick();
|
|
||||||
|
|
||||||
if( runningTests != null && runningTests.isDone() ) finishTests();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MultipleTestTracker runTests()
|
|
||||||
{
|
|
||||||
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
|
|
||||||
CommandSourceStack source = server.createCommandSourceStack();
|
|
||||||
Collection<TestFunction> tests = GameTestRegistry.getAllTestFunctions();
|
|
||||||
|
|
||||||
LOG.info( "Running {} tests...", tests.size() );
|
|
||||||
|
|
||||||
return new MultipleTestTracker( GameTestRunner.runTests(
|
|
||||||
tests, getStart( source ), Rotation.NONE, source.getLevel(), GameTestTicker.SINGLETON, 8
|
|
||||||
) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeResults( CommandSourceStack source, MultipleTestTracker result )
|
|
||||||
{
|
|
||||||
if( !result.isDone() ) return;
|
|
||||||
|
|
||||||
say( source, "Finished tests - " + result.getTotalCount() + " tests were run", ChatFormatting.WHITE );
|
|
||||||
if( result.hasFailedRequired() )
|
|
||||||
{
|
|
||||||
say( source, result.getFailedRequiredCount() + " required tests failed :(", ChatFormatting.RED );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
say( source, "All required tests passed :)", ChatFormatting.GREEN );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( result.hasFailedOptional() )
|
|
||||||
{
|
|
||||||
say( source, result.getFailedOptionalCount() + " optional tests failed", ChatFormatting.GRAY );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void startTests()
|
|
||||||
{
|
|
||||||
runningTests = runTests();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void finishTests()
|
|
||||||
{
|
|
||||||
if( shutdown ) return;
|
|
||||||
shutdown = true;
|
|
||||||
writeResults( ServerLifecycleHooks.getCurrentServer().createCommandSourceStack(), runningTests );
|
|
||||||
|
|
||||||
if( FMLLoader.getDist().isDedicatedServer() )
|
|
||||||
{
|
|
||||||
shutdownServer();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shutdownClient();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BlockPos getStart( CommandSourceStack source )
|
|
||||||
{
|
|
||||||
BlockPos pos = new BlockPos( source.getPosition() );
|
|
||||||
return new BlockPos( pos.getX(), source.getLevel().getHeightmapPos( Heightmap.Types.WORLD_SURFACE, pos ).getY(), pos.getZ() + 3 );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void shutdownCommon()
|
|
||||||
{
|
|
||||||
System.exit( runningTests.hasFailedRequired() ? 1 : 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void shutdownServer()
|
|
||||||
{
|
|
||||||
// We can't exit normally as Minecraft registers a shutdown hook which results in a deadlock.
|
|
||||||
LOG.info( "Stopping server." );
|
|
||||||
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
|
|
||||||
new Thread( () -> {
|
|
||||||
server.halt( true );
|
|
||||||
shutdownCommon();
|
|
||||||
}, "Background shutdown" ).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void shutdownClient()
|
|
||||||
{
|
|
||||||
Minecraft minecraft = Minecraft.getInstance();
|
|
||||||
minecraft.execute( () -> {
|
|
||||||
LOG.info( "Stopping client." );
|
|
||||||
minecraft.level.disconnect();
|
|
||||||
minecraft.clearLevel();
|
|
||||||
minecraft.stop();
|
|
||||||
shutdownCommon();
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void say( CommandSourceStack source, String message, ChatFormatting colour )
|
|
||||||
{
|
|
||||||
source.sendFailure( new TextComponent( message ).withStyle( colour ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
||||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
|
||||||
*/
|
|
||||||
package dan200.computercraft.ingame.mod;
|
|
||||||
|
|
||||||
import net.minecraft.gametest.framework.GameTest;
|
|
||||||
import net.minecraft.gametest.framework.GameTestRegistry;
|
|
||||||
import net.minecraftforge.fml.ModList;
|
|
||||||
import net.minecraftforge.fml.loading.FMLLoader;
|
|
||||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads methods annotated with {@link GameTest} and adds them to the {@link GameTestRegistry}.
|
|
||||||
*/
|
|
||||||
class TestLoader
|
|
||||||
{
|
|
||||||
private static final Type gameTest = Type.getType( GameTest.class );
|
|
||||||
|
|
||||||
public static void setup()
|
|
||||||
{
|
|
||||||
ModList.get().getAllScanData().stream()
|
|
||||||
.flatMap( x -> x.getAnnotations().stream() )
|
|
||||||
.filter( x -> x.annotationType().equals( gameTest ) )
|
|
||||||
.forEach( TestLoader::loadTest );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void loadTest( ModFileScanData.AnnotationData annotation )
|
|
||||||
{
|
|
||||||
Class<?> klass;
|
|
||||||
Method method;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
klass = TestLoader.class.getClassLoader().loadClass( annotation.clazz().getClassName() );
|
|
||||||
|
|
||||||
// We don't know the exact signature (could suspend or not), so find something with the correct descriptor instead.
|
|
||||||
String methodName = annotation.memberName();
|
|
||||||
method = Arrays.stream( klass.getMethods() ).filter( x -> (x.getName() + Type.getMethodDescriptor( x )).equals( methodName ) ).findFirst()
|
|
||||||
.orElseThrow( () -> new NoSuchMethodException( "No method " + annotation.clazz().getClassName() + "." + annotation.memberName() ) );
|
|
||||||
}
|
|
||||||
catch( ReflectiveOperationException e )
|
|
||||||
{
|
|
||||||
throw new RuntimeException( e );
|
|
||||||
}
|
|
||||||
|
|
||||||
GameTest test = method.getAnnotation( GameTest.class );
|
|
||||||
if( test.batch().startsWith( "client" ) && !FMLLoader.getDist().isClient() ) return;
|
|
||||||
|
|
||||||
GameTestRegistry.register( method );
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,7 +27,6 @@ public class TestMod
|
|||||||
{
|
{
|
||||||
log.info( "CC: Test initialised" );
|
log.info( "CC: Test initialised" );
|
||||||
ComputerCraftAPI.registerAPIFactory( TestAPI::new );
|
ComputerCraftAPI.registerAPIFactory( TestAPI::new );
|
||||||
TestLoader.setup();
|
|
||||||
|
|
||||||
StructureUtils.testStructuresDir = sourceDir.resolve( "structures" ).toString();
|
StructureUtils.testStructuresDir = sourceDir.resolve( "structures" ).toString();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user