aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuck <git@lucko.me>2024-09-03 00:11:24 +0100
committerLuck <git@lucko.me>2024-09-03 00:11:24 +0100
commit35b557af4fd1bc0ce0a5745716e898cd1300a08c (patch)
tree5927e55839d5dd1a0759db3a2fd54f9f8df5d032
parent55b38397296813b66082ad935f773357c8ad5282 (diff)
downloadspark-35b557af4fd1bc0ce0a5745716e898cd1300a08c.tar.gz
spark-35b557af4fd1bc0ce0a5745716e898cd1300a08c.tar.bz2
spark-35b557af4fd1bc0ce0a5745716e898cd1300a08c.zip
Improve unit tests
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/sampler/AbstractSampler.java4
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/sampler/window/ProfilingWindowUtils.java2
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/sampler/window/ProtoTimeEncoder.java23
-rw-r--r--spark-common/src/test/java/me/lucko/spark/common/SparkPlatformTest.java67
-rw-r--r--spark-common/src/test/java/me/lucko/spark/common/sampler/node/NodeTest.java199
-rw-r--r--spark-common/src/test/java/me/lucko/spark/common/sampler/window/ProfilingWindowUtilsTest.java68
-rw-r--r--spark-common/src/test/java/me/lucko/spark/common/sampler/window/ProtoTimeEncoderTest.java54
-rw-r--r--spark-common/src/test/java/me/lucko/spark/common/tick/TickHookTest.java69
-rw-r--r--spark-common/src/test/java/me/lucko/spark/common/tick/TickReporterTest.java94
-rw-r--r--spark-common/src/test/java/me/lucko/spark/common/util/MethodDisambiguatorTest.java2
-rw-r--r--spark-fabric/src/main/java/me/lucko/spark/fabric/FabricWorldInfoProvider.java2
-rw-r--r--spark-neoforge/src/main/java/me/lucko/spark/neoforge/NeoForgeWorldInfoProvider.java4
-rw-r--r--spark-paper/src/main/java/me/lucko/spark/paper/api/PaperSparkModule.java1
-rw-r--r--spark-sponge7/src/main/java/me/lucko/spark/sponge/Sponge7WorldInfoProvider.java1
14 files changed, 568 insertions, 22 deletions
diff --git a/spark-common/src/main/java/me/lucko/spark/common/sampler/AbstractSampler.java b/spark-common/src/main/java/me/lucko/spark/common/sampler/AbstractSampler.java
index 7453074..20e7973 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/sampler/AbstractSampler.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/sampler/AbstractSampler.java
@@ -23,14 +23,11 @@ package me.lucko.spark.common.sampler;
import me.lucko.spark.common.SparkPlatform;
import me.lucko.spark.common.command.sender.CommandSender;
import me.lucko.spark.common.monitor.memory.GarbageCollectorStatistics;
-import me.lucko.spark.common.platform.MetadataProvider;
import me.lucko.spark.common.platform.SparkMetadata;
-import me.lucko.spark.common.platform.serverconfig.ServerConfigProvider;
import me.lucko.spark.common.sampler.aggregator.DataAggregator;
import me.lucko.spark.common.sampler.node.MergeMode;
import me.lucko.spark.common.sampler.node.ThreadNode;
import me.lucko.spark.common.sampler.source.ClassSourceLookup;
-import me.lucko.spark.common.sampler.source.SourceMetadata;
import me.lucko.spark.common.sampler.window.ProtoTimeEncoder;
import me.lucko.spark.common.sampler.window.WindowStatisticsCollector;
import me.lucko.spark.common.util.classfinder.ClassFinder;
@@ -42,7 +39,6 @@ import me.lucko.spark.proto.SparkSamplerProtos.SamplerMetadata;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
diff --git a/spark-common/src/main/java/me/lucko/spark/common/sampler/window/ProfilingWindowUtils.java b/spark-common/src/main/java/me/lucko/spark/common/sampler/window/ProfilingWindowUtils.java
index be6f08a..ca44b31 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/sampler/window/ProfilingWindowUtils.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/sampler/window/ProfilingWindowUtils.java
@@ -61,7 +61,7 @@ public enum ProfilingWindowUtils {
/**
* Gets a prune predicate that can be passed to {@link DataAggregator#pruneData(IntPredicate)}.
*
- * @return the prune predicate
+ * @return the prune predicate - returns true for windows that should be pruned
*/
public static IntPredicate keepHistoryBefore(int currentWindow) {
// windows that were earlier than (currentWindow minus history size) should be pruned
diff --git a/spark-common/src/main/java/me/lucko/spark/common/sampler/window/ProtoTimeEncoder.java b/spark-common/src/main/java/me/lucko/spark/common/sampler/window/ProtoTimeEncoder.java
index fb4a4fc..db0800d 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/sampler/window/ProtoTimeEncoder.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/sampler/window/ProtoTimeEncoder.java
@@ -20,8 +20,8 @@
package me.lucko.spark.common.sampler.window;
-import me.lucko.spark.common.sampler.async.jfr.Dictionary;
import me.lucko.spark.common.sampler.node.ThreadNode;
+import org.jetbrains.annotations.VisibleForTesting;
import java.util.HashMap;
import java.util.List;
@@ -43,16 +43,10 @@ public class ProtoTimeEncoder {
/** A map of key value -> index in the keys array */
private final Map<Integer, Integer> keysToIndex;
- public ProtoTimeEncoder(LongToDoubleFunction valueTransformer, List<ThreadNode> sourceData) {
+ @VisibleForTesting
+ ProtoTimeEncoder(LongToDoubleFunction valueTransformer, IntStream keys) {
this.valueTransformer = valueTransformer;
-
- // get an array of all keys that show up in the source data
- this.keys = sourceData.stream()
- .map(n -> n.getTimeWindows().stream().mapToInt(i -> i))
- .reduce(IntStream.empty(), IntStream::concat)
- .distinct()
- .sorted()
- .toArray();
+ this.keys = keys.distinct().sorted().toArray();
// construct a reverse index lookup
this.keysToIndex = new HashMap<>(this.keys.length);
@@ -61,6 +55,13 @@ public class ProtoTimeEncoder {
}
}
+ public ProtoTimeEncoder(LongToDoubleFunction valueTransformer, List<ThreadNode> sourceData) {
+ this(valueTransformer, sourceData.stream()
+ .map(n -> n.getTimeWindows().stream().mapToInt(i -> i))
+ .reduce(IntStream.empty(), IntStream::concat)
+ );
+ }
+
/**
* Gets an array of the keys that could be encoded by this encoder.
*
@@ -71,7 +72,7 @@ public class ProtoTimeEncoder {
}
/**
- * Encode a {@link Dictionary} (map) of times/durations into a double array.
+ * Encode a map of times/durations into a double array.
*
* @param times a dictionary of times (unix-time millis -> duration in microseconds)
* @return the times encoded as a double array
diff --git a/spark-common/src/test/java/me/lucko/spark/common/SparkPlatformTest.java b/spark-common/src/test/java/me/lucko/spark/common/SparkPlatformTest.java
index 10da849..fb2ae5e 100644
--- a/spark-common/src/test/java/me/lucko/spark/common/SparkPlatformTest.java
+++ b/spark-common/src/test/java/me/lucko/spark/common/SparkPlatformTest.java
@@ -20,12 +20,20 @@
package me.lucko.spark.common;
+import com.google.common.collect.ImmutableSet;
+import me.lucko.spark.common.command.sender.CommandSender;
import me.lucko.spark.test.plugin.TestSparkPlugin;
+import net.kyori.adventure.text.Component;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class SparkPlatformTest {
@@ -37,4 +45,63 @@ public class SparkPlatformTest {
}
}
+ @Test
+ public void testPermissions(@TempDir Path directory) {
+ try (TestSparkPlugin plugin = new TestSparkPlugin(directory)) {
+ SparkPlatform platform = plugin.platform();
+
+ Set<String> permissions = platform.getAllSparkPermissions();
+ assertEquals(
+ ImmutableSet.of(
+ "spark",
+ "spark.profiler",
+ "spark.tps",
+ "spark.ping",
+ "spark.healthreport",
+ "spark.tickmonitor",
+ "spark.gc",
+ "spark.gcmonitor",
+ "spark.heapsummary",
+ "spark.heapdump",
+ "spark.activity"
+ ),
+ permissions
+ );
+
+ TestCommandSender testSender = new TestCommandSender();
+ assertFalse(platform.hasPermissionForAnyCommand(testSender));
+
+ testSender.permissions.add("spark.tps");
+ assertTrue(platform.hasPermissionForAnyCommand(testSender));
+
+ testSender.permissions.clear();
+ testSender.permissions.add("spark");
+ assertTrue(platform.hasPermissionForAnyCommand(testSender));
+ }
+ }
+
+ private static final class TestCommandSender implements CommandSender {
+ private final Set<String> permissions = new HashSet<>();
+
+ @Override
+ public String getName() {
+ return "Test";
+ }
+
+ @Override
+ public UUID getUniqueId() {
+ return new UUID(0, 0);
+ }
+
+ @Override
+ public void sendMessage(Component message) {
+
+ }
+
+ @Override
+ public boolean hasPermission(String permission) {
+ return this.permissions.contains(permission);
+ }
+ }
+
}
diff --git a/spark-common/src/test/java/me/lucko/spark/common/sampler/node/NodeTest.java b/spark-common/src/test/java/me/lucko/spark/common/sampler/node/NodeTest.java
new file mode 100644
index 0000000..7df9e59
--- /dev/null
+++ b/spark-common/src/test/java/me/lucko/spark/common/sampler/node/NodeTest.java
@@ -0,0 +1,199 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.sampler.node;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import me.lucko.spark.common.sampler.SamplerMode;
+import me.lucko.spark.common.sampler.async.AsyncStackTraceElement;
+import me.lucko.spark.common.sampler.window.ProtoTimeEncoder;
+import me.lucko.spark.common.util.MethodDisambiguator;
+import me.lucko.spark.proto.SparkSamplerProtos;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class NodeTest {
+
+ private static final StackTraceNode.Describer<AsyncStackTraceElement> STACK_TRACE_DESCRIBER = (element, parent) -> new StackTraceNode.Description(element.getClassName(), element.getMethodName(), element.getMethodDescription());
+ private static final int WINDOW = 10;
+
+ private static final AsyncStackTraceElement NODE_0 = new AsyncStackTraceElement("java.lang.Thread", "run", "()V");
+ private static final AsyncStackTraceElement NODE_1_1 = new AsyncStackTraceElement("test.Foo", "run", "()V");
+ private static final AsyncStackTraceElement NODE_1_2_1 = new AsyncStackTraceElement("test.Foo", "example", "()V");
+ private static final AsyncStackTraceElement NODE_2_1 = new AsyncStackTraceElement("test.Bar", "run", "()V");
+ private static final AsyncStackTraceElement NODE_2_2_1 = new AsyncStackTraceElement("test.Bar", "example", "()V");
+
+ private static final AsyncStackTraceElement[] STACK_1 = {NODE_1_2_1, NODE_1_1, NODE_0};
+ private static final AsyncStackTraceElement[] STACK_2 = {NODE_2_2_1, NODE_2_1, NODE_0};
+
+ @Test
+ public void testThreadLabels() {
+ ThreadNode node = new ThreadNode("Test Thread");
+ assertEquals("Test Thread", node.getThreadGroup());
+ assertEquals("Test Thread", node.getThreadLabel());
+
+ node.setThreadLabel("Test");
+ assertEquals("Test", node.getThreadLabel());
+ }
+
+ @Test
+ public void testBasicLog() {
+ ThreadNode threadNode = new ThreadNode("Test Thread");
+ assertEquals(0, threadNode.getTimeWindows().size());
+
+ threadNode.log(STACK_TRACE_DESCRIBER, STACK_1, TimeUnit.SECONDS.toMicros(1), WINDOW);
+
+ Collection<StackTraceNode> children1 = threadNode.getChildren();
+ assertEquals(1, children1.size());
+ assertEquals(ImmutableSet.of(WINDOW), threadNode.getTimeWindows());
+
+ StackTraceNode node1 = children1.iterator().next();
+ assertEquals(ImmutableSet.of(WINDOW), node1.getTimeWindows());
+ assertEquals("java.lang.Thread", node1.getClassName());
+ assertEquals("run", node1.getMethodName());
+ assertEquals("()V", node1.getMethodDescription());
+ assertEquals(StackTraceNode.NULL_LINE_NUMBER, node1.getLineNumber());
+ assertEquals(StackTraceNode.NULL_LINE_NUMBER, node1.getParentLineNumber());
+ assertEquals(TimeUnit.SECONDS.toMicros(1), node1.getTimeAccumulator(WINDOW).longValue());
+
+ threadNode.log(STACK_TRACE_DESCRIBER, STACK_2, TimeUnit.SECONDS.toMicros(1), WINDOW);
+ assertEquals(TimeUnit.SECONDS.toMicros(2), node1.getTimeAccumulator(WINDOW).longValue());
+
+ Collection<StackTraceNode> children2 = node1.getChildren();
+ assertEquals(2, children2.size());
+
+ for (StackTraceNode node2 : children2) {
+ assertEquals(ImmutableSet.of(WINDOW), node2.getTimeWindows());
+ assertEquals(TimeUnit.SECONDS.toMicros(1), node2.getTimeAccumulator(WINDOW).longValue());
+ }
+ }
+
+ @Test
+ public void testToProto() {
+ ThreadNode threadNode = new ThreadNode("Test Thread");
+ threadNode.log(STACK_TRACE_DESCRIBER, STACK_1, TimeUnit.SECONDS.toMicros(1), WINDOW);
+ threadNode.log(STACK_TRACE_DESCRIBER, STACK_1, TimeUnit.SECONDS.toMicros(1), WINDOW + 1);
+ threadNode.log(STACK_TRACE_DESCRIBER, STACK_2, TimeUnit.SECONDS.toMicros(1), WINDOW + 1);
+
+ ProtoTimeEncoder timeEncoder = new ProtoTimeEncoder(SamplerMode.EXECUTION.valueTransformer(), ImmutableList.of(threadNode));
+ int[] keys = timeEncoder.getKeys();
+ assertArrayEquals(new int[]{WINDOW, WINDOW + 1}, keys);
+
+ SparkSamplerProtos.ThreadNode proto = threadNode.toProto(
+ MergeMode.sameMethod(new MethodDisambiguator(null)),
+ timeEncoder
+ );
+
+ SparkSamplerProtos.ThreadNode expected = SparkSamplerProtos.ThreadNode.newBuilder()
+ .setName("Test Thread")
+ .addTimes(1000)
+ .addTimes(2000)
+ .addChildren(SparkSamplerProtos.StackTraceNode.newBuilder()
+ .setClassName("test.Bar")
+ .setMethodDesc("()V")
+ .setMethodName("example")
+ .addTimes(0)
+ .addTimes(1000)
+ )
+ .addChildren(SparkSamplerProtos.StackTraceNode.newBuilder()
+ .setClassName("test.Bar")
+ .setMethodDesc("()V")
+ .setMethodName("run")
+ .addTimes(0)
+ .addTimes(1000)
+ .addChildrenRefs(0)
+ )
+ .addChildren(SparkSamplerProtos.StackTraceNode.newBuilder()
+ .setClassName("test.Foo")
+ .setMethodDesc("()V")
+ .setMethodName("example")
+ .addTimes(1000)
+ .addTimes(1000)
+ )
+ .addChildren(SparkSamplerProtos.StackTraceNode.newBuilder()
+ .setClassName("test.Foo")
+ .setMethodDesc("()V")
+ .setMethodName("run")
+ .addTimes(1000)
+ .addTimes(1000)
+ .addChildrenRefs(2)
+ )
+ .addChildren(SparkSamplerProtos.StackTraceNode.newBuilder()
+ .setClassName("java.lang.Thread")
+ .setMethodDesc("()V")
+ .setMethodName("run")
+ .addTimes(1000)
+ .addTimes(2000)
+ .addChildrenRefs(1)
+ .addChildrenRefs(3)
+ )
+ .addChildrenRefs(4)
+ .build();
+
+ assertEquals(expected, proto);
+ }
+
+ @Test
+ public void testRemoveTimeWindows() {
+ ThreadNode threadNode = new ThreadNode("Test Thread");
+ threadNode.log(STACK_TRACE_DESCRIBER, STACK_1, TimeUnit.SECONDS.toMicros(1), WINDOW);
+ threadNode.log(STACK_TRACE_DESCRIBER, STACK_2, TimeUnit.SECONDS.toMicros(1), WINDOW + 1);
+
+ StackTraceNode threadRunNode = threadNode.getChildren().iterator().next();
+ Collection<StackTraceNode> fooBarNodes = threadRunNode.getChildren();
+
+ assertEquals(2, threadNode.getTimeWindows().size());
+ assertEquals(2, threadRunNode.getChildren().size());
+ assertEquals(2, threadRunNode.getTimeWindows().size());
+
+ for (StackTraceNode node : fooBarNodes) {
+ assertEquals(1, node.getTimeWindows().size());
+ assertEquals(1, node.getChildren().size());
+ assertEquals(1, node.getChildren().iterator().next().getTimeWindows().size());
+ assertEquals(0, node.getChildren().iterator().next().getChildren().size());
+ }
+
+ assertFalse(threadNode.removeTimeWindowsRecursively(w -> w == WINDOW));
+ assertEquals(1, threadNode.getTimeWindows().size());
+ assertEquals(1, threadRunNode.getChildren().size());
+ assertEquals(1, threadRunNode.getTimeWindows().size());
+
+ assertTrue(threadNode.removeTimeWindowsRecursively(w -> w == WINDOW + 1));
+ assertEquals(0, threadNode.getTimeWindows().size());
+ assertEquals(0, threadNode.getChildren().size());
+
+ // doesn't bother updating nested children that have been removed
+ for (StackTraceNode node : fooBarNodes) {
+ assertEquals(1, node.getTimeWindows().size());
+ assertEquals(1, node.getChildren().size());
+ assertEquals(1, node.getChildren().iterator().next().getTimeWindows().size());
+ assertEquals(0, node.getChildren().iterator().next().getChildren().size());
+ }
+ }
+
+}
diff --git a/spark-common/src/test/java/me/lucko/spark/common/sampler/window/ProfilingWindowUtilsTest.java b/spark-common/src/test/java/me/lucko/spark/common/sampler/window/ProfilingWindowUtilsTest.java
new file mode 100644
index 0000000..4161fe9
--- /dev/null
+++ b/spark-common/src/test/java/me/lucko/spark/common/sampler/window/ProfilingWindowUtilsTest.java
@@ -0,0 +1,68 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.sampler.window;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.Month;
+import java.time.ZoneOffset;
+import java.util.concurrent.TimeUnit;
+import java.util.function.IntPredicate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ProfilingWindowUtilsTest {
+
+ @Test
+ public void testMillisToWindow() {
+ int baseWindow = 28532770;
+ Instant baseTime = LocalDateTime.of(2024, Month.APRIL, 1, 10, 10, 0).toInstant(ZoneOffset.UTC);
+
+ assertEquals(TimeUnit.MILLISECONDS.toMinutes(baseTime.toEpochMilli()), baseWindow); // should scale with unix time
+
+ assertEquals(baseWindow, ProfilingWindowUtils.unixMillisToWindow(baseTime.toEpochMilli()));
+ assertEquals(baseWindow, ProfilingWindowUtils.unixMillisToWindow(baseTime.plusMillis(1).toEpochMilli()));
+ assertEquals(baseWindow, ProfilingWindowUtils.unixMillisToWindow(baseTime.plusSeconds(1).toEpochMilli()));
+ assertEquals(baseWindow, ProfilingWindowUtils.unixMillisToWindow(baseTime.plusSeconds(59).toEpochMilli()));
+ assertEquals(baseWindow + 1, ProfilingWindowUtils.unixMillisToWindow(baseTime.plusSeconds(60).toEpochMilli()));
+ assertEquals(baseWindow + 1, ProfilingWindowUtils.unixMillisToWindow(baseTime.plusSeconds(61).toEpochMilli()));
+ assertEquals(baseWindow - 1, ProfilingWindowUtils.unixMillisToWindow(baseTime.minusMillis(1).toEpochMilli()));
+ assertEquals(baseWindow - 1, ProfilingWindowUtils.unixMillisToWindow(baseTime.minusSeconds(1).toEpochMilli()));
+ }
+
+ @Test
+ public void testKeepHistoryBefore() {
+ IntPredicate predicate = ProfilingWindowUtils.keepHistoryBefore(100);
+ assertFalse(predicate.test(99));
+ assertFalse(predicate.test(100));
+ assertFalse(predicate.test(101));
+
+ assertFalse(predicate.test(40));
+ assertTrue(predicate.test(39));
+ assertTrue(predicate.test(0));
+ assertTrue(predicate.test(-10));
+ }
+
+}
diff --git a/spark-common/src/test/java/me/lucko/spark/common/sampler/window/ProtoTimeEncoderTest.java b/spark-common/src/test/java/me/lucko/spark/common/sampler/window/ProtoTimeEncoderTest.java
new file mode 100644
index 0000000..82dcb12
--- /dev/null
+++ b/spark-common/src/test/java/me/lucko/spark/common/sampler/window/ProtoTimeEncoderTest.java
@@ -0,0 +1,54 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.sampler.window;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.atomic.LongAdder;
+import java.util.stream.IntStream;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ProtoTimeEncoderTest {
+
+ @Test
+ public void testSimple() {
+ ProtoTimeEncoder encoder = new ProtoTimeEncoder(l -> l, IntStream.of(7, 1, 3, 5));
+ assertArrayEquals(new int[]{1, 3, 5, 7}, encoder.getKeys());
+
+ assertArrayEquals(new double[]{0, 0, 0, 0}, encoder.encode(ImmutableMap.of()));
+ assertArrayEquals(new double[]{0, 100, 0, 0}, encoder.encode(ImmutableMap.of(3, longAdder(100))));
+ assertArrayEquals(new double[]{0, 100, 200, 0}, encoder.encode(ImmutableMap.of(3, longAdder(100), 5, longAdder(200))));
+
+ RuntimeException ex = assertThrows(RuntimeException.class, () -> encoder.encode(ImmutableMap.of(9, longAdder(300))));
+ assertTrue(ex.getMessage().startsWith("No index for key 9"));
+ }
+
+ private static LongAdder longAdder(long l) {
+ LongAdder longAdder = new LongAdder();
+ longAdder.add(l);
+ return longAdder;
+ }
+
+}
diff --git a/spark-common/src/test/java/me/lucko/spark/common/tick/TickHookTest.java b/spark-common/src/test/java/me/lucko/spark/common/tick/TickHookTest.java
new file mode 100644
index 0000000..f920262
--- /dev/null
+++ b/spark-common/src/test/java/me/lucko/spark/common/tick/TickHookTest.java
@@ -0,0 +1,69 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.tick;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class TickHookTest {
+
+ @Test
+ public void testAbstractHook() {
+ AbstractTickHook hook = new AbstractTickHook() {
+ @Override
+ public void start() {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+ };
+
+ assertEquals(0, hook.getCurrentTick());
+
+ List<Integer> ticks = new ArrayList<>();
+ TickHook.Callback callback = ticks::add;
+
+ hook.addCallback(callback);
+
+ hook.onTick();
+ assertEquals(1, hook.getCurrentTick());
+ assertEquals(ImmutableList.of(0), ticks);
+
+ hook.onTick();
+ assertEquals(2, hook.getCurrentTick());
+ assertEquals(ImmutableList.of(0, 1), ticks);
+
+ hook.removeCallback(callback);
+
+ hook.onTick();
+ assertEquals(3, hook.getCurrentTick());
+ assertEquals(ImmutableList.of(0, 1), ticks);
+ }
+
+}
diff --git a/spark-common/src/test/java/me/lucko/spark/common/tick/TickReporterTest.java b/spark-common/src/test/java/me/lucko/spark/common/tick/TickReporterTest.java
new file mode 100644
index 0000000..f7402c5
--- /dev/null
+++ b/spark-common/src/test/java/me/lucko/spark/common/tick/TickReporterTest.java
@@ -0,0 +1,94 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.tick;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class TickReporterTest {
+
+ @Test
+ public void testAbstractReporter() {
+ AbstractTickReporter reporter = new AbstractTickReporter() {
+ @Override
+ public void start() {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+ };
+
+ List<Double> durations = new ArrayList<>();
+ TickReporter.Callback callback = durations::add;
+
+ reporter.addCallback(callback);
+
+ reporter.onTick(1.0);
+ assertEquals(ImmutableList.of(1.0), durations);
+
+ reporter.onTick(2.0);
+ assertEquals(ImmutableList.of(1.0, 2.0), durations);
+
+ reporter.removeCallback(callback);
+
+ reporter.onTick(3.0);
+ assertEquals(ImmutableList.of(1.0, 2.0), durations);
+ }
+
+ @Test
+ public void testSimpleReporter() {
+ SimpleTickReporter reporter = new SimpleTickReporter() {
+ @Override
+ public void start() {
+
+ }
+ };
+
+ List<Double> durations = new ArrayList<>();
+ TickReporter.Callback callback = durations::add;
+
+ reporter.addCallback(callback);
+
+ reporter.onStart();
+ assertEquals(0, durations.size());
+
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+
+ reporter.onEnd();
+
+ assertEquals(1, durations.size());
+ assertTrue(durations.get(0) > 0);
+ }
+
+}
diff --git a/spark-common/src/test/java/me/lucko/spark/common/util/MethodDisambiguatorTest.java b/spark-common/src/test/java/me/lucko/spark/common/util/MethodDisambiguatorTest.java
index f0bea8f..ad2f1e1 100644
--- a/spark-common/src/test/java/me/lucko/spark/common/util/MethodDisambiguatorTest.java
+++ b/spark-common/src/test/java/me/lucko/spark/common/util/MethodDisambiguatorTest.java
@@ -20,9 +20,9 @@
package me.lucko.spark.common.util;
-import me.lucko.spark.test.TestClass;
import me.lucko.spark.common.util.MethodDisambiguator.MethodDescription;
import me.lucko.spark.common.util.classfinder.FallbackClassFinder;
+import me.lucko.spark.test.TestClass;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricWorldInfoProvider.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricWorldInfoProvider.java
index eae9c86..5486cc2 100644
--- a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricWorldInfoProvider.java
+++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricWorldInfoProvider.java
@@ -21,7 +21,6 @@
package me.lucko.spark.fabric;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
-import java.lang.reflect.Method;
import me.lucko.spark.common.platform.world.AbstractChunkInfo;
import me.lucko.spark.common.platform.world.CountMap;
import me.lucko.spark.common.platform.world.WorldInfoProvider;
@@ -44,6 +43,7 @@ import net.minecraft.world.entity.ClientEntityManager;
import net.minecraft.world.entity.EntityIndex;
import net.minecraft.world.entity.EntityLookup;
+import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
diff --git a/spark-neoforge/src/main/java/me/lucko/spark/neoforge/NeoForgeWorldInfoProvider.java b/spark-neoforge/src/main/java/me/lucko/spark/neoforge/NeoForgeWorldInfoProvider.java
index d172ecf..96a90c2 100644
--- a/spark-neoforge/src/main/java/me/lucko/spark/neoforge/NeoForgeWorldInfoProvider.java
+++ b/spark-neoforge/src/main/java/me/lucko/spark/neoforge/NeoForgeWorldInfoProvider.java
@@ -21,7 +21,6 @@
package me.lucko.spark.neoforge;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
-import java.lang.reflect.Method;
import me.lucko.spark.common.platform.world.AbstractChunkInfo;
import me.lucko.spark.common.platform.world.CountMap;
import me.lucko.spark.common.platform.world.WorldInfoProvider;
@@ -37,10 +36,11 @@ import net.minecraft.world.level.entity.EntityLookup;
import net.minecraft.world.level.entity.LevelEntityGetter;
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
import net.minecraft.world.level.entity.TransientEntitySectionManager;
+import net.neoforged.fml.ModList;
+import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
-import net.neoforged.fml.ModList;
public abstract class NeoForgeWorldInfoProvider implements WorldInfoProvider {
diff --git a/spark-paper/src/main/java/me/lucko/spark/paper/api/PaperSparkModule.java b/spark-paper/src/main/java/me/lucko/spark/paper/api/PaperSparkModule.java
index e796438..ce8b74a 100644
--- a/spark-paper/src/main/java/me/lucko/spark/paper/api/PaperSparkModule.java
+++ b/spark-paper/src/main/java/me/lucko/spark/paper/api/PaperSparkModule.java
@@ -26,7 +26,6 @@ import org.bukkit.command.CommandSender;
import java.util.Collection;
import java.util.List;
-import java.util.Set;
import java.util.logging.Logger;
/**
diff --git a/spark-sponge7/src/main/java/me/lucko/spark/sponge/Sponge7WorldInfoProvider.java b/spark-sponge7/src/main/java/me/lucko/spark/sponge/Sponge7WorldInfoProvider.java
index 426ad47..1ded055 100644
--- a/spark-sponge7/src/main/java/me/lucko/spark/sponge/Sponge7WorldInfoProvider.java
+++ b/spark-sponge7/src/main/java/me/lucko/spark/sponge/Sponge7WorldInfoProvider.java
@@ -34,7 +34,6 @@ import org.spongepowered.api.world.World;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-import java.util.Map;
public class Sponge7WorldInfoProvider implements WorldInfoProvider {
private final Server server;