Skip to content

Commit ff39e90

Browse files
committed
Get testing working, add tests for blockstate cache rebuilds
1 parent 03b2395 commit ff39e90

File tree

9 files changed

+120
-41
lines changed

9 files changed

+120
-41
lines changed

common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public void clearCache() {
2525
cacheInvalid = true;
2626
}
2727

28+
@Override
29+
public boolean isCacheInvalid() {
30+
return cacheInvalid;
31+
}
32+
2833
private BlockBehaviour.BlockStateBase.Cache generateCache(BlockBehaviour.BlockStateBase base) {
2934
if(cacheInvalid) {
3035
// Ensure that only one block's cache is built at a time

common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -316,19 +316,21 @@ public Option getEffectiveOptionForMixin(String mixinClassName) {
316316
public static ModernFixEarlyConfig load(File file) {
317317
ModernFixEarlyConfig config = new ModernFixEarlyConfig(file);
318318
Properties props = new Properties();
319-
if(file.exists()) {
320-
try (FileInputStream fin = new FileInputStream(file)){
321-
props.load(fin);
322-
} catch (IOException e) {
323-
throw new RuntimeException("Could not load config file", e);
319+
if(!Boolean.getBoolean("modernfix.ignoreConfigForTesting")) {
320+
if(file.exists()) {
321+
try (FileInputStream fin = new FileInputStream(file)){
322+
props.load(fin);
323+
} catch (IOException e) {
324+
throw new RuntimeException("Could not load config file", e);
325+
}
326+
config.readProperties(props);
324327
}
325-
config.readProperties(props);
326-
}
327328

328-
try {
329-
config.save();
330-
} catch (IOException e) {
331-
LOGGER.warn("Could not write configuration file", e);
329+
try {
330+
config.save();
331+
} catch (IOException e) {
332+
LOGGER.warn("Could not write configuration file", e);
333+
}
332334
}
333335

334336
return config;

common/src/main/java/org/embeddedt/modernfix/duck/IBlockState.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33

44
public interface IBlockState {
55
void clearCache();
6+
boolean isCacheInvalid();
67
}

fabric/build.gradle

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
plugins {
22
id "com.github.johnrengelman.shadow" version "7.1.2"
3+
id 'com.adarshr.test-logger' version '3.2.0'
34
}
45

56
architectury {
@@ -44,8 +45,8 @@ dependencies {
4445
// Remove the next line if you don't want to depend on the API
4546
// modApi "me.shedaniel:architectury-fabric:${rootProject.architectury_version}"
4647

47-
testImplementation(common(project(path: ":common", configuration: "namedElements"))) { transitive false }
48-
shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false }
48+
common(project(path: ":common", configuration: "namedElements")) { transitive false }
49+
testImplementation(shadowCommon(project(path: ":common", configuration: "transformProductionFabric"))) { transitive false }
4950

5051
testImplementation(platform("org.junit:junit-bom:${project.junit_version}"))
5152
testImplementation("org.junit.jupiter:junit-jupiter-api")
@@ -66,6 +67,7 @@ test {
6667
runDir.mkdir()
6768
}
6869
workingDir = runDir
70+
systemProperty 'modernfix.ignoreConfigForTesting', 'true'
6971

7072
// inject our custom agent to fix #817
7173
FileCollection agentFile = configurations.getByName("testAgent")

fabric/src/main/java/org/embeddedt/modernfix/ModernFixPreLaunchFabric.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
public class ModernFixPreLaunchFabric implements PreLaunchEntrypoint {
1010
@Override
1111
public void onPreLaunch() {
12+
if(ModernFixMixinPlugin.instance == null) {
13+
System.err.println("Mixin plugin not loaded yet");
14+
return;
15+
}
1216
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnFabric")) {
1317
CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.start("launch"), "Failed to start profiler");
1418
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package net.minecraft.world.level.block.state;
2+
3+
import net.minecraft.core.BlockPos;
4+
import net.minecraft.world.level.EmptyBlockGetter;
5+
import net.minecraft.world.level.block.Blocks;
6+
import org.embeddedt.modernfix.duck.IBlockState;
7+
import org.embeddedt.modernfix.testing.util.BootstrapMinecraft;
8+
import org.junit.jupiter.api.*;
9+
10+
import static org.junit.jupiter.api.Assertions.*;
11+
12+
@BootstrapMinecraft
13+
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
14+
public class BlockStateCacheTest {
15+
@BeforeEach
16+
public void rebuildCache() {
17+
Blocks.rebuildCache();
18+
}
19+
20+
/**
21+
* Initially, the cache should be invalid, and null.
22+
*/
23+
@Test
24+
@Order(1)
25+
public void testCacheNullInitially() {
26+
BlockState stoneBlock = Blocks.STONE.defaultBlockState();
27+
assertTrue(((IBlockState)stoneBlock).isCacheInvalid());
28+
assertNull(stoneBlock.cache);
29+
}
30+
31+
/**
32+
* When an API that needs the cache is called, it should be built and the invalid flag
33+
* becomes false.
34+
*/
35+
@Test
36+
@Order(2)
37+
public void testCacheBuiltByRequest() {
38+
BlockState stoneBlock = Blocks.STONE.defaultBlockState();
39+
stoneBlock.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
40+
assertFalse(((IBlockState)stoneBlock).isCacheInvalid());
41+
assertNotNull(stoneBlock.cache);
42+
}
43+
44+
/**
45+
* When a second rebuild occurs, the invalid flag should be set to true, but the old cache
46+
* is not set to null, in order to prevent NPEs if a second thread is accessing the cache
47+
* when this takes place.
48+
*/
49+
@Test
50+
@Order(3)
51+
public void testCacheInvalidatedByLateRebuild() {
52+
BlockState stoneBlock = Blocks.STONE.defaultBlockState();
53+
stoneBlock.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
54+
Blocks.rebuildCache();
55+
assertTrue(((IBlockState)stoneBlock).isCacheInvalid());
56+
assertNotNull(stoneBlock.cache);
57+
}
58+
}

fabric/src/test/java/org/embeddedt/modernfix/blocks/BlockStateCacheTest.java

Lines changed: 0 additions & 28 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.embeddedt.modernfix.testing.util;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
import org.junit.jupiter.api.extension.ExtendWith;
9+
10+
@Retention(RetentionPolicy.RUNTIME)
11+
@Target(ElementType.TYPE)
12+
@ExtendWith({ BootstrapMinecraftExtension.class })
13+
public @interface BootstrapMinecraft {
14+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.embeddedt.modernfix.testing.util;
2+
3+
import net.minecraft.DetectedVersion;
4+
import net.minecraft.server.Bootstrap;
5+
import org.junit.jupiter.api.extension.AfterAllCallback;
6+
import org.junit.jupiter.api.extension.BeforeAllCallback;
7+
import org.junit.jupiter.api.extension.Extension;
8+
import org.junit.jupiter.api.extension.ExtensionContext;
9+
10+
public class BootstrapMinecraftExtension implements Extension, BeforeAllCallback, AfterAllCallback {
11+
@Override
12+
public void beforeAll(ExtensionContext context) throws Exception {
13+
DetectedVersion.tryDetectVersion();
14+
Bootstrap.bootStrap();
15+
}
16+
17+
@Override
18+
public void afterAll(ExtensionContext context) throws Exception {
19+
20+
}
21+
}

0 commit comments

Comments
 (0)