2025-11-24 22:52:51 +03:00

267 lines
11 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.google.common.collect.ImmutableList
* com.google.common.collect.Lists
* com.mojang.logging.LogUtils
* it.unimi.dsi.fastutil.longs.LongArraySet
* org.jspecify.annotations.Nullable
* org.slf4j.Logger
*/
package net.minecraft.gametest.framework;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import net.minecraft.core.Holder;
import net.minecraft.gametest.framework.GameTestBatch;
import net.minecraft.gametest.framework.GameTestBatchFactory;
import net.minecraft.gametest.framework.GameTestBatchListener;
import net.minecraft.gametest.framework.GameTestInfo;
import net.minecraft.gametest.framework.GameTestListener;
import net.minecraft.gametest.framework.GameTestTicker;
import net.minecraft.gametest.framework.MultipleTestTracker;
import net.minecraft.gametest.framework.ReportGameListener;
import net.minecraft.gametest.framework.StructureGridSpawner;
import net.minecraft.gametest.framework.StructureUtils;
import net.minecraft.gametest.framework.TestEnvironmentDefinition;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Util;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.block.entity.TestInstanceBlockEntity;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
public class GameTestRunner {
public static final int DEFAULT_TESTS_PER_ROW = 8;
private static final Logger LOGGER = LogUtils.getLogger();
private final ServerLevel level;
private final GameTestTicker testTicker;
private final List<GameTestInfo> allTestInfos;
private ImmutableList<GameTestBatch> batches;
private final List<GameTestBatchListener> batchListeners = Lists.newArrayList();
private final List<GameTestInfo> scheduledForRerun = Lists.newArrayList();
private final GameTestBatcher testBatcher;
private boolean stopped = true;
private @Nullable Holder<TestEnvironmentDefinition> currentEnvironment;
private final StructureSpawner existingStructureSpawner;
private final StructureSpawner newStructureSpawner;
private final boolean haltOnError;
private final boolean clearBetweenBatches;
protected GameTestRunner(GameTestBatcher batcher, Collection<GameTestBatch> batches, ServerLevel level, GameTestTicker testTicker, StructureSpawner existingStructureSpawner, StructureSpawner newStructureSpawner, boolean haltOnError, boolean clearBetweenBatches) {
this.level = level;
this.testTicker = testTicker;
this.testBatcher = batcher;
this.existingStructureSpawner = existingStructureSpawner;
this.newStructureSpawner = newStructureSpawner;
this.batches = ImmutableList.copyOf(batches);
this.haltOnError = haltOnError;
this.clearBetweenBatches = clearBetweenBatches;
this.allTestInfos = this.batches.stream().flatMap(batch -> batch.gameTestInfos().stream()).collect(Util.toMutableList());
testTicker.setRunner(this);
this.allTestInfos.forEach(info -> info.addListener(new ReportGameListener()));
}
public List<GameTestInfo> getTestInfos() {
return this.allTestInfos;
}
public void start() {
this.stopped = false;
this.runBatch(0);
}
public void stop() {
this.stopped = true;
if (this.currentEnvironment != null) {
this.endCurrentEnvironment();
}
}
public void rerunTest(GameTestInfo info) {
GameTestInfo copy = info.copyReset();
info.getListeners().forEach(listener -> listener.testAddedForRerun(info, copy, this));
this.allTestInfos.add(copy);
this.scheduledForRerun.add(copy);
if (this.stopped) {
this.runScheduledRerunTests();
}
}
private void runBatch(final int batchIndex) {
if (batchIndex >= this.batches.size()) {
this.endCurrentEnvironment();
this.runScheduledRerunTests();
return;
}
if (batchIndex > 0 && this.clearBetweenBatches) {
GameTestBatch lastBatch = (GameTestBatch)this.batches.get(batchIndex - 1);
lastBatch.gameTestInfos().forEach(gameTestInfo -> {
TestInstanceBlockEntity testInstanceBlockEntity = gameTestInfo.getTestInstanceBlockEntity();
StructureUtils.clearSpaceForStructure(testInstanceBlockEntity.getStructureBoundingBox(), this.level);
this.level.destroyBlock(testInstanceBlockEntity.getBlockPos(), false);
});
}
final GameTestBatch currentBatch = (GameTestBatch)this.batches.get(batchIndex);
this.existingStructureSpawner.onBatchStart(this.level);
this.newStructureSpawner.onBatchStart(this.level);
Collection<GameTestInfo> testInfosForThisBatch = this.createStructuresForBatch(currentBatch.gameTestInfos());
LOGGER.info("Running test environment '{}' batch {} ({} tests)...", new Object[]{currentBatch.environment().getRegisteredName(), currentBatch.index(), testInfosForThisBatch.size()});
this.endCurrentEnvironment();
this.currentEnvironment = currentBatch.environment();
this.currentEnvironment.value().setup(this.level);
this.batchListeners.forEach(listener -> listener.testBatchStarting(currentBatch));
final MultipleTestTracker currentBatchTracker = new MultipleTestTracker();
testInfosForThisBatch.forEach(currentBatchTracker::addTestToTrack);
currentBatchTracker.addListener(new GameTestListener(){
private void testCompleted(GameTestInfo testInfo) {
testInfo.getTestInstanceBlockEntity().removeBarriers();
if (currentBatchTracker.isDone()) {
GameTestRunner.this.batchListeners.forEach(listener -> listener.testBatchFinished(currentBatch));
LongArraySet forcedChunks = new LongArraySet(GameTestRunner.this.level.getForceLoadedChunks());
forcedChunks.forEach(pos -> GameTestRunner.this.level.setChunkForced(ChunkPos.getX(pos), ChunkPos.getZ(pos), false));
GameTestRunner.this.runBatch(batchIndex + 1);
}
}
@Override
public void testStructureLoaded(GameTestInfo testInfo) {
}
@Override
public void testPassed(GameTestInfo testInfo, GameTestRunner runner) {
this.testCompleted(testInfo);
}
@Override
public void testFailed(GameTestInfo testInfo, GameTestRunner runner) {
if (GameTestRunner.this.haltOnError) {
GameTestRunner.this.endCurrentEnvironment();
LongArraySet forcedChunks = new LongArraySet(GameTestRunner.this.level.getForceLoadedChunks());
forcedChunks.forEach(pos -> GameTestRunner.this.level.setChunkForced(ChunkPos.getX(pos), ChunkPos.getZ(pos), false));
GameTestTicker.SINGLETON.clear();
testInfo.getTestInstanceBlockEntity().removeBarriers();
} else {
this.testCompleted(testInfo);
}
}
@Override
public void testAddedForRerun(GameTestInfo original, GameTestInfo copy, GameTestRunner runner) {
}
});
testInfosForThisBatch.forEach(this.testTicker::add);
}
private void endCurrentEnvironment() {
if (this.currentEnvironment != null) {
this.currentEnvironment.value().teardown(this.level);
this.currentEnvironment = null;
}
}
private void runScheduledRerunTests() {
if (!this.scheduledForRerun.isEmpty()) {
LOGGER.info("Starting re-run of tests: {}", (Object)this.scheduledForRerun.stream().map(info -> info.id().toString()).collect(Collectors.joining(", ")));
this.batches = ImmutableList.copyOf(this.testBatcher.batch(this.scheduledForRerun));
this.scheduledForRerun.clear();
this.stopped = false;
this.runBatch(0);
} else {
this.batches = ImmutableList.of();
this.stopped = true;
}
}
public void addListener(GameTestBatchListener listener) {
this.batchListeners.add(listener);
}
private Collection<GameTestInfo> createStructuresForBatch(Collection<GameTestInfo> batch) {
return batch.stream().map(this::spawn).flatMap(Optional::stream).toList();
}
private Optional<GameTestInfo> spawn(GameTestInfo testInfo) {
if (testInfo.getTestBlockPos() == null) {
return this.newStructureSpawner.spawnStructure(testInfo);
}
return this.existingStructureSpawner.spawnStructure(testInfo);
}
public static interface GameTestBatcher {
public Collection<GameTestBatch> batch(Collection<GameTestInfo> var1);
}
public static interface StructureSpawner {
public static final StructureSpawner IN_PLACE = testInfo -> Optional.ofNullable(testInfo.prepareTestStructure()).map(e -> e.startExecution(1));
public static final StructureSpawner NOT_SET = testInfo -> Optional.empty();
public Optional<GameTestInfo> spawnStructure(GameTestInfo var1);
default public void onBatchStart(ServerLevel level) {
}
}
public static class Builder {
private final ServerLevel level;
private final GameTestTicker testTicker = GameTestTicker.SINGLETON;
private GameTestBatcher batcher = GameTestBatchFactory.fromGameTestInfo();
private StructureSpawner existingStructureSpawner = StructureSpawner.IN_PLACE;
private StructureSpawner newStructureSpawner = StructureSpawner.NOT_SET;
private final Collection<GameTestBatch> batches;
private boolean haltOnError = false;
private boolean clearBetweenBatches = false;
private Builder(Collection<GameTestBatch> batches, ServerLevel level) {
this.batches = batches;
this.level = level;
}
public static Builder fromBatches(Collection<GameTestBatch> batches, ServerLevel level) {
return new Builder(batches, level);
}
public static Builder fromInfo(Collection<GameTestInfo> tests, ServerLevel level) {
return Builder.fromBatches(GameTestBatchFactory.fromGameTestInfo().batch(tests), level);
}
public Builder haltOnError() {
this.haltOnError = true;
return this;
}
public Builder clearBetweenBatches() {
this.clearBetweenBatches = true;
return this;
}
public Builder newStructureSpawner(StructureSpawner structureSpawner) {
this.newStructureSpawner = structureSpawner;
return this;
}
public Builder existingStructureSpawner(StructureGridSpawner spawner) {
this.existingStructureSpawner = spawner;
return this;
}
public Builder batcher(GameTestBatcher batcher) {
this.batcher = batcher;
return this;
}
public GameTestRunner build() {
return new GameTestRunner(this.batcher, this.batches, this.level, this.testTicker, this.existingStructureSpawner, this.newStructureSpawner, this.haltOnError, this.clearBetweenBatches);
}
}
}