Skip to content

Commit

Permalink
Add more automated tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lucko committed Jul 29, 2024
1 parent 6e7cc88 commit 1fb00b1
Show file tree
Hide file tree
Showing 11 changed files with 255 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ public long getServerNormalOperationStartTime() {
return this.serverNormalOperationStartTime;
}

public boolean hasEnabled() {
return this.enabled.get();
}

public Path resolveSaveFile(String prefix, String extension) {
Path pluginFolder = this.plugin.getPluginDirectory();
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@

package me.lucko.spark.common.heapdump;

import com.google.common.annotations.VisibleForTesting;
import me.lucko.spark.common.SparkPlatform;
import me.lucko.spark.common.command.sender.CommandSender;
import me.lucko.spark.proto.SparkHeapProtos.HeapData;
import me.lucko.spark.proto.SparkHeapProtos.HeapEntry;
import me.lucko.spark.proto.SparkHeapProtos.HeapMetadata;
import org.jetbrains.annotations.VisibleForTesting;
import org.objectweb.asm.Type;

import javax.management.JMX;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@

package me.lucko.spark.common.monitor.net;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import me.lucko.spark.common.monitor.LinuxProc;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.VisibleForTesting;

import java.util.Arrays;
import java.util.Collections;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,10 @@ public static synchronized AsyncProfilerAccess getInstance(SparkPlatform platfor

try {
profiler = load(platform);

if (isEventSupported(profiler, ProfilingEvent.ALLOC, false)) {
allocationProfilingEvent = ProfilingEvent.ALLOC;
}

if (isEventSupported(profiler, ProfilingEvent.CPU, false)) {
profilingEvent = ProfilingEvent.CPU;
} else if (isEventSupported(profiler, ProfilingEvent.WALL, true)) {
if (isEventSupported(profiler, ProfilingEvent.WALL, true)) {
profilingEvent = ProfilingEvent.WALL;
}
} catch (Exception e) {
Expand Down Expand Up @@ -213,8 +209,7 @@ private static boolean isEventSupported(AsyncProfiler profiler, ProfilingEvent e
return false;
}

enum ProfilingEvent {
CPU(Events.CPU),
public enum ProfilingEvent {
WALL(Events.WALL),
ALLOC(Events.ALLOC);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

package me.lucko.spark.common.util;

import com.google.common.annotations.VisibleForTesting;
import org.jetbrains.annotations.VisibleForTesting;

public class JavaVersion {
public enum JavaVersion {
;

private static final int JAVA_VERSION;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,21 @@

package me.lucko.spark.common;

import me.lucko.spark.test.plugin.TestCommandSender;
import me.lucko.spark.test.plugin.TestSparkPlugin;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.assertTrue;

public class SparkPlatformTest {

@Test
public void testEnableDisable(@TempDir Path directory) {
System.setProperty("spark.backgroundProfiler", "false");

SparkPlatform platform = new SparkPlatform(new TestSparkPlugin(directory));
platform.enable();

platform.executeCommand(TestCommandSender.INSTANCE, new String[]{"help"}).join();
platform.executeCommand(TestCommandSender.INSTANCE, new String[]{"profiler", "info"}).join();
platform.executeCommand(TestCommandSender.INSTANCE, new String[]{"health"}).join();

platform.disable();
try (TestSparkPlugin plugin = new TestSparkPlugin(directory)) {
assertTrue(plugin.platform().hasEnabled());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,14 @@

package me.lucko.spark.common.heapdump;

import me.lucko.spark.proto.SparkHeapProtos;
import me.lucko.spark.test.TestClass;
import me.lucko.spark.test.plugin.TestCommandSender;
import me.lucko.spark.test.plugin.TestSparkPlugin;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.nio.file.Path;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
Expand All @@ -31,7 +36,7 @@
public class HeapDumpSummaryTest {

@Test
public void testHeapDumpSummary() throws Exception {
public void testHeapDumpSummary(@TempDir Path directory) throws Exception {
TestClass testClass1 = new TestClass();
TestClass testClass2 = new TestClass();

Expand All @@ -42,6 +47,17 @@ public void testHeapDumpSummary() throws Exception {
assertNotNull(thisClassEntry);
assertEquals(2, thisClassEntry.getInstances());
assertEquals(32, thisClassEntry.getBytes());

SparkHeapProtos.HeapData proto;
try (TestSparkPlugin plugin = new TestSparkPlugin(directory)) {
proto = dump.toProto(plugin.platform(), TestCommandSender.INSTANCE.toData());
}
assertNotNull(proto);

SparkHeapProtos.HeapEntry protoEntry = proto.getEntriesList().stream().filter(entry -> entry.getType().equals(TestClass.class.getName())).findAny().orElse(null);
assertNotNull(protoEntry);
assertEquals(2, protoEntry.getInstances());
assertEquals(32, protoEntry.getSize());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package me.lucko.spark.common.platform;

import me.lucko.spark.proto.SparkProtos;
import me.lucko.spark.test.plugin.TestSparkPlugin;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.assertNotNull;

public class PlatformStatisticsProviderTest {

@Test
public void testSystemStatistics(@TempDir Path directory) {
try (TestSparkPlugin plugin = new TestSparkPlugin(directory)) {
SparkProtos.SystemStatistics systemStatistics = new PlatformStatisticsProvider(plugin.platform()).getSystemStatistics();
assertNotNull(systemStatistics);
}
}

@Test
public void testPlatformStatistics(@TempDir Path directory) {
try (TestSparkPlugin plugin = new TestSparkPlugin(directory)) {
SparkProtos.PlatformStatistics platformStatistics = new PlatformStatisticsProvider(plugin.platform()).getPlatformStatistics(null, true);
assertNotNull(platformStatistics);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* This file is part of spark.
*
* Copyright (c) lucko (Luck) <[email protected]>
* 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;

import me.lucko.spark.common.sampler.async.AsyncSampler;
import me.lucko.spark.common.sampler.java.JavaSampler;
import me.lucko.spark.common.sampler.node.MergeMode;
import me.lucko.spark.common.sampler.source.ClassSourceLookup;
import me.lucko.spark.common.util.MethodDisambiguator;
import me.lucko.spark.proto.SparkSamplerProtos;
import me.lucko.spark.test.TestClass2;
import me.lucko.spark.test.plugin.TestCommandSender;
import me.lucko.spark.test.plugin.TestSparkPlugin;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

import java.nio.file.Path;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

public class SamplerTest {

@ParameterizedTest
@EnumSource
public void testSampler(ProfilerType profilerType, @TempDir Path directory) {
if (profilerType == ProfilerType.ASYNC) {
String os = System.getProperty("os.name").toLowerCase(Locale.ROOT).replace(" ", "");
assumeTrue(os.equals("linux") || os.equals("macosx"), "async profiler is only supported on Linux and macOS");
}

Thread thread = new Thread(new TestClass2(), "Test Thread");
thread.start();

try (TestSparkPlugin plugin = new TestSparkPlugin(directory)) {
Sampler sampler = new SamplerBuilder()
.threadDumper(new ThreadDumper.Specific(thread))
.threadGrouper(ThreadGrouper.BY_POOL)
.samplingInterval(10)
.forceJavaSampler(profilerType == ProfilerType.JAVA)
.completeAfter(2, TimeUnit.SECONDS)
.start(plugin.platform());

assertInstanceOf(profilerType.expectedClass, sampler);

assertNotEquals(-1, sampler.getAutoEndTime());
sampler.getFuture().join();

Sampler.ExportProps exportProps = new Sampler.ExportProps()
.creator(TestCommandSender.INSTANCE.toData())
.mergeMode(() -> MergeMode.sameMethod(new MethodDisambiguator(plugin.platform().createClassFinder())))
.classSourceLookup(() -> ClassSourceLookup.create(plugin.platform()));

SparkSamplerProtos.SamplerData proto = sampler.toProto(plugin.platform(), exportProps);
assertNotNull(proto);

List<SparkSamplerProtos.ThreadNode> threads = proto.getThreadsList();
assertEquals(1, threads.size());

SparkSamplerProtos.ThreadNode protoThread = threads.get(0);
assertEquals("Test Thread", protoThread.getName());
assertTrue(protoThread.getChildrenList().stream().anyMatch(n -> n.getClassName().equals("me.lucko.spark.test.TestClass2") && n.getMethodName().equals("test")));
assertTrue(protoThread.getChildrenList().stream().anyMatch(n -> n.getClassName().equals("me.lucko.spark.test.TestClass2") && n.getMethodName().equals("testA")));
assertTrue(protoThread.getChildrenList().stream().anyMatch(n -> n.getClassName().equals("me.lucko.spark.test.TestClass2") && n.getMethodName().equals("testB")));
}
}

public enum ProfilerType {
JAVA(JavaSampler.class),
ASYNC(AsyncSampler.class);

private final Class<? extends Sampler> expectedClass;

ProfilerType(Class<? extends Sampler> expectedClass) {
this.expectedClass = expectedClass;
}
}

}
52 changes: 52 additions & 0 deletions spark-common/src/test/java/me/lucko/spark/test/TestClass2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* This file is part of spark.
*
* Copyright (c) lucko (Luck) <[email protected]>
* 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.test;

public class TestClass2 implements Runnable {

@Override
public void run() {
while (true) {
try {
test();
} catch (InterruptedException e) {
return;
}
}
}

public void test() throws InterruptedException {
for (int i = 0; i < 10; i++) {
testA();
Thread.sleep(100);
testB();
}
}

public void testA() throws InterruptedException {
Thread.sleep(100);
}

public void testB() throws InterruptedException {
Thread.sleep(100);

}
}
Loading

0 comments on commit 1fb00b1

Please sign in to comment.