Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SkTest #6

Open
wants to merge 5 commits into
base: dev/dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import ch.njol.skript.ScriptLoader;
import ch.njol.skript.Skript;
import ch.njol.skript.SkriptAddon;
import ch.njol.skript.command.ScriptCommand;
import ch.njol.skript.hooks.VaultHook;
import ch.njol.skript.hooks.regions.RegionsPlugin;
Expand All @@ -15,6 +16,7 @@
import me.glicz.skanalyzer.AnalyzerFlag;
import me.glicz.skanalyzer.SkAnalyzer;
import me.glicz.skanalyzer.bridge.log.CachingLogHandler;
import me.glicz.skanalyzer.bridge.log.TestLogHandler;
import me.glicz.skanalyzer.bridge.util.FilesUtil;
import me.glicz.skanalyzer.result.ScriptAnalyzeResult;
import me.glicz.skanalyzer.result.ScriptAnalyzeResults;
Expand All @@ -36,6 +38,7 @@

public class MockSkriptBridgeImpl extends MockSkriptBridge {
private Executor mainThreadExecutor;
private SkriptAddon skriptAddon;

public MockSkriptBridgeImpl(SkAnalyzer skAnalyzer) {
super(skAnalyzer);
Expand All @@ -49,6 +52,13 @@ public void onLoad() {
@Override
public void onEnable() {
mainThreadExecutor = getServer().getScheduler().getMainThreadExecutor(this);

skriptAddon = Skript.registerAddon(this);
try {
skriptAddon.loadClasses("me.glicz.skanalyzer.bridge.sktest");
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public void parseFlags() {
Expand Down Expand Up @@ -97,7 +107,7 @@ public CompletableFuture<ScriptAnalyzeResults> parseScript(String path, boolean
.thenApply(info -> {
ScriptAnalyzeResults results = new ScriptAnalyzeResults(buildAnalyzeResults(files, logHandler));
if (!load) {
unloadScript(path);
unloadScript0(file);
}
return results;
})
Expand All @@ -107,14 +117,46 @@ public CompletableFuture<ScriptAnalyzeResults> parseScript(String path, boolean
);
}

@Override
public void testScripts(String path) {
File file = new File(path);
if (!file.exists() || !file.getName().endsWith(".sktest")) {
skAnalyzer.getLogger().error("Invalid file path");
return;
}

CompletableFuture.supplyAsync(
() -> {
TestLogHandler logHandler = new TestLogHandler().start();
return ScriptLoader.loadScripts(file, logHandler)
.handle((info, throwable) -> {
if (throwable != null) {
skAnalyzer.getLogger().error("Something went wrong while trying to parse '%s'".formatted(path), throwable);
throw new RuntimeException(throwable);
}
return info;
})
.thenApply(info -> {
unloadScript0(file);
return null;
})
.join();
},
mainThreadExecutor
);
}

@Override
public boolean unloadScript(String path) {
File file = new File(path);
if (!file.exists() || !file.getName().endsWith(".sk")) {
skAnalyzer.getLogger().error("Invalid file path");
return false;
}
return unloadScript0(file);
}

private boolean unloadScript0(File file) {
Script script = ScriptLoader.getScript(file);
if (script != null) {
ScriptLoader.unloadScript(script);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package me.glicz.skanalyzer.bridge.log;

import ch.njol.skript.log.LogEntry;
import ch.njol.skript.log.SkriptLogger;
import me.glicz.skanalyzer.bridge.log.entry.TestLogEntry;
import org.jetbrains.annotations.NotNull;

public class TestLogHandler extends CachingLogHandler {
@Override
public @NotNull LogResult log(@NotNull LogEntry entry) {
if (entry instanceof TestLogEntry testLogEntry) {
System.out.printf("Test \"%s\": %s%n", testLogEntry.getTestName(), testLogEntry.message);
return LogResult.CACHED;
}

return super.log(entry);
}

@Override
public @NotNull TestLogHandler start() {
return SkriptLogger.startLogHandler(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package me.glicz.skanalyzer.bridge.log.entry;

import ch.njol.skript.log.LogEntry;
import ch.njol.skript.log.SkriptLogger;
import lombok.Getter;

import java.util.logging.Level;

@Getter
public class TestLogEntry extends LogEntry {
private final String testName;

public TestLogEntry(String testName, String message) {
super(Level.INFO, message, SkriptLogger.getNode());
this.testName = testName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package me.glicz.skanalyzer.bridge.sktest;

import ch.njol.skript.log.SkriptLogger;
import me.glicz.skanalyzer.bridge.log.entry.TestLogEntry;

public interface SkTestLogger {
String testName();

default void testLog(String message) {
SkriptLogger.log(new TestLogEntry(testName(), message));
}

default void testLog(String message, Object... args) {
testLog(message.formatted(args));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package me.glicz.skanalyzer.bridge.sktest.bukkit.event;

import be.seeseemelk.mockbukkit.WorldMock;
import be.seeseemelk.mockbukkit.entity.PlayerMock;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
import me.glicz.skanalyzer.bridge.sktest.SkTestLogger;
import me.glicz.skanalyzer.mockbukkit.AnalyzerServer;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;

import java.util.HashSet;
import java.util.Set;

@Accessors(fluent = true)
@RequiredArgsConstructor
public class TestEvent extends Event implements SkTestLogger {
@Getter
private static final HandlerList handlerList = new HandlerList();
private final Set<PlayerMock> playerMocks = new HashSet<>();
private final Set<WorldMock> worldMocks = new HashSet<>();
@Getter
private final AnalyzerServer server;
@Getter
private final String testName;

@Override
public @NotNull HandlerList getHandlers() {
return handlerList;
}

public void registerPlayerMock(PlayerMock playerMock) {
playerMocks.add(playerMock);
server.addPlayer(playerMock);
}

public void registerWorldMock(WorldMock worldMock) {
worldMocks.add(worldMock);
server.addWorld(worldMock);
}

public void postTest() {
playerMocks.removeIf(playerMock -> {
playerMock.disconnect();
return true;
});

worldMocks.removeIf(worldMock -> {
server.removeWorld(worldMock);
return true;
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package me.glicz.skanalyzer.bridge.sktest.effect;

import ch.njol.skript.Skript;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser;
import ch.njol.util.Kleenean;
import me.glicz.skanalyzer.bridge.sktest.bukkit.event.TestEvent;
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull;

public class EffDebug extends Effect {
static {
Skript.registerEffect(EffDebug.class, "debug %-string%");
}

private Expression<String> text = null;

@SuppressWarnings("unchecked")
@Override
public boolean init(Expression<?> @NotNull [] expressions, int matchedPattern, @NotNull Kleenean isDelayed, SkriptParser.@NotNull ParseResult parseResult) {
this.text = (Expression<String>) expressions[0];
return true;
}

@Override
protected void execute(@NotNull Event event) {
if (event instanceof TestEvent e) {
e.testLog(text.getSingle(event));
}
}

@Override
public @NotNull String toString(Event event, boolean debug) {
return "debug " + text.toString(event, debug);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package me.glicz.skanalyzer.bridge.sktest.event;

import ch.njol.skript.Skript;
import ch.njol.skript.lang.Literal;
import ch.njol.skript.lang.SkriptEvent;
import ch.njol.skript.lang.SkriptParser;
import lombok.Getter;
import lombok.experimental.Accessors;
import me.glicz.skanalyzer.bridge.sktest.SkTestLogger;
import me.glicz.skanalyzer.bridge.sktest.bukkit.event.TestEvent;
import me.glicz.skanalyzer.mockbukkit.AnalyzerServer;
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull;

@Getter
@Accessors(fluent = true)
public class EvtTest extends SkriptEvent implements SkTestLogger {
static {
Skript.registerEvent("*Test", EvtTest.class, TestEvent.class, "test %-string%");
}

private String testName = null;

@Override
public boolean init(Literal<?> @NotNull [] args, int matchedPattern, SkriptParser.@NotNull ParseResult parseResult) {
this.testName = (String) args[0].getSingle();
return true;
}

@Override
public boolean preLoad() {
if (false) { // TODO
Skript.error("Test structure can be only used in .'sktest' file!");
return false;
}
return super.preLoad();
}

@Override
public boolean postLoad() {
testLog("Running test");

TestEvent event = new TestEvent((AnalyzerServer) Bukkit.getServer(), testName);

boolean result = trigger.forceExecute(event);
if (result) {
testLog("Test succeeded");
} else {
testLog("Test failed");
}

event.postTest();

return true;
}

@Override
public boolean check(@NotNull Event event) {
throw new UnsupportedOperationException();
}

@Override
public boolean isEventPrioritySupported() {
return false;
}

@Override
public @NotNull String toString(Event event, boolean debug) {
return "test " + testName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package me.glicz.skanalyzer.bridge.sktest.expression;

import be.seeseemelk.mockbukkit.entity.PlayerMock;
import ch.njol.skript.Skript;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptParser;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.util.Kleenean;
import me.glicz.skanalyzer.bridge.sktest.bukkit.event.TestEvent;
import me.glicz.skanalyzer.mockbukkit.AnalyzerPlayer;
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull;

public class ExprNewPlayerMock extends SimpleExpression<PlayerMock> {
static {
Skript.registerExpression(ExprNewPlayerMock.class, PlayerMock.class, ExpressionType.SIMPLE, "new player mock");
}

@Override
public boolean init(Expression<?> @NotNull [] expressions, int matchedPattern, @NotNull Kleenean isDelayed, SkriptParser.@NotNull ParseResult parseResult) {
return true;
}

@Override
protected PlayerMock @NotNull [] get(@NotNull Event event) {
if (event instanceof TestEvent e) {
AnalyzerPlayer player = e.server().addPlayer((p, message) ->
e.testLog("%s received: (%s) %s", p.getName(), message.type(), message.rawValue())
);

e.registerPlayerMock(player);
e.registerWorldMock(player.getWorld());

return new PlayerMock[]{player};
}
return new PlayerMock[]{null};
}

@Override
public boolean isSingle() {
return true;
}

@Override
public @NotNull Class<? extends PlayerMock> getReturnType() {
return PlayerMock.class;
}

@Override
public @NotNull String toString(Event event, boolean debug) {
return "new player mock";
}
}
Loading