Upload via GUI (67 Dateien)

This commit is contained in:
2026-10-21 16:45:36 +00:00
parent dc19180a77
commit 8385fdabf2
50 changed files with 1948 additions and 0 deletions
@@ -0,0 +1,162 @@
package de.deskhub.minecraft;
import com.sun.net.httpserver.HttpServer;
import de.deskhub.minecraft.bukkit.BukkitPlugin;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockbukkit.mockbukkit.MockBukkit;
import org.mockbukkit.mockbukkit.ServerMock;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CopyOnWriteArrayList;
import static org.junit.jupiter.api.Assertions.*;
/** Spigot/Paper-Teil des fertigen Plugins gegen einen simulierten Server und eine simulierte DeskHub-API. */
class PaperPluginTest {
private static final String KEY = "dh_" + "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4";
private ServerMock server;
private BukkitPlugin plugin;
private HttpServer http;
private final List<String> bodies = new CopyOnWriteArrayList<>();
private final List<String> keys = new CopyOnWriteArrayList<>();
@BeforeEach
void setUp() throws Exception {
http = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
http.createContext("/api/public/v1/tickets.php", ex -> {
keys.add(ex.getRequestHeaders().getFirst("X-API-Key"));
ByteArrayOutputStream b = new ByteArrayOutputStream();
try (InputStream in = ex.getRequestBody()) { in.transferTo(b); }
bodies.add(b.toString(StandardCharsets.UTF_8));
byte[] out = ("{\"number\":\"T-" + bodies.size() + "\",\"status\":\"open\"}").getBytes(StandardCharsets.UTF_8);
ex.sendResponseHeaders(201, out.length);
ex.getResponseBody().write(out);
ex.close();
});
http.start();
server = MockBukkit.mock();
plugin = MockBukkit.load(BukkitPlugin.class);
server.getPluginManager().disablePlugin(plugin);
}
@AfterEach
void tearDown() {
http.stop(0);
MockBukkit.unmock();
}
private void configure(String extra) throws Exception {
String cfg = "deskhub:\n url: \"http://127.0.0.1:" + http.getAddress().getPort() + "\"\n api-key: \"" + KEY + "\"\n requester-email: \"mc@example.de\"\n"
+ "ticket:\n department-id: 4\n priority-id: 3\n" + extra;
Files.writeString(new File(plugin.getDataFolder(), "config.yml").toPath(), cfg);
}
private File heartbeat() {
return new File(plugin.getDataFolder(), "lebenszeichen.properties");
}
private void writeHeartbeat(boolean running, boolean clean, long lastBeat) throws Exception {
Properties p = new Properties();
p.setProperty("running", String.valueOf(running));
p.setProperty("clean", String.valueOf(clean));
p.setProperty("lastBeat", String.valueOf(lastBeat));
try (var out = Files.newOutputStream(heartbeat().toPath())) { p.store(out, null); }
}
private void enable() {
server.getPluginManager().enablePlugin(plugin);
server.getScheduler().waitAsyncTasksFinished();
}
@Test
void startsWithoutConfigAndCreatesNoTicket() {
// Standard-config: URL/Schlüssel fehlen -> Plugin läuft, meldet das Problem, legt nichts an
enable();
assertTrue(plugin.isEnabled());
assertTrue(bodies.isEmpty());
assertTrue(heartbeat().isFile(), "Lebenszeichen wird geschrieben");
}
@Test
void crashOfPreviousRunCreatesTicketOnStart() throws Exception {
configure("");
writeHeartbeat(true, false, System.currentTimeMillis() - 5 * 60_000L);
enable();
assertEquals(1, bodies.size(), "genau ein Ticket");
String b = bodies.get(0);
assertEquals(KEY, keys.get(0));
assertTrue(b.contains("\"departmentId\":4") && b.contains("\"priorityId\":3"), b);
assertTrue(b.contains("war nicht erreichbar"), b);
assertTrue(b.contains("Ausfalldauer: ca. 5 Minuten"), b);
}
@Test
void cleanShutdownCreatesNoTicketOnNextStart() throws Exception {
configure("");
enable();
server.getPluginManager().disablePlugin(plugin); // ordnungsgemäß beenden
assertFalse(Files.readString(heartbeat().toPath()).contains("running=true"));
configure("");
enable();
assertTrue(bodies.isEmpty(), "nach sauberem Beenden kein Ticket");
}
@Test
void firstEverStartCreatesNoTicket() throws Exception {
configure("");
Files.deleteIfExists(heartbeat().toPath());
enable();
assertTrue(bodies.isEmpty());
}
@Test
void crashTicketCanBeSwitchedOff() throws Exception {
configure("backend:\n ticket-on-crash: false\n");
writeHeartbeat(true, false, System.currentTimeMillis() - 60_000L);
enable();
assertTrue(bodies.isEmpty());
}
@Test
void shutdownTicketOnlyWhenEnabled() throws Exception {
configure("backend:\n ticket-on-shutdown: true\n");
enable();
server.getPluginManager().disablePlugin(plugin);
assertEquals(1, bodies.size());
assertTrue(bodies.get(0).contains("heruntergefahren"), bodies.get(0));
}
@Test
void testCommandCreatesTicketAndNeedsPermission() throws Exception {
configure("");
enable();
var op = server.addPlayer();
op.setOp(false);
server.dispatchCommand(op, "deskhubmc test");
server.getScheduler().waitAsyncTasksFinished();
assertTrue(bodies.isEmpty(), "ohne Berechtigung kein Ticket");
server.dispatchCommand(server.getConsoleSender(), "deskhubmc test");
server.getScheduler().waitAsyncTasksFinished();
server.getScheduler().performOneTick();
assertEquals(1, bodies.size());
assertTrue(bodies.get(0).contains("Testticket"), bodies.get(0));
}
@Test
void crashWithBrokenConfigDoesNotCrashPlugin() throws Exception {
Files.writeString(new File(plugin.getDataFolder(), "config.yml").toPath(), "deskhub:\n url: \"\"\n");
writeHeartbeat(true, false, 1);
assertDoesNotThrow(this::enable);
assertTrue(plugin.isEnabled());
assertTrue(bodies.isEmpty());
}
}