Loading plugins/test.sh +3 −1 Changes for plugins/test.sh: 3 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -43,7 +43,9 @@ # fake proxy and a stub felis-api — a refresh registers, moves and drops # backends and lets go of a renamed subdomain, the login gate and host routing # admit only linked players, each wake refusal reaches the player as its own # message, felis:control acts only for the connection's player and holds its # message (the stub answers a wake from the server's state in felis-api's own # order, so it cannot hand the router an answer the real API never gives), # felis:control acts only for the connection's player and holds its # frame budget. They ride the module's verified dependency set, which is why # they live in Gradle rather than in the javac mains above. # Loading plugins/velocity/test/best/lolicon/felis/velocity/ControlChannelTest.java +24 −8 Changes for plugins/velocity/test/best/lolicon/felis/velocity/ControlChannelTest.java: 24 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -216,20 +216,32 @@ public final class ControlChannelTest { } private static void wakeAndTransfer() { // A WakeRequest parks the player; when the backend is ready the lobby hears // TransferReady just before the proxy moves them. // A WakeRequest for a stopped server parks the player; when the backend is ready // the lobby hears TransferReady just before the proxy moves them. Fakes.FakePlayer p = player(true); p.current = lobby; message(p.on(lobby), ControlChannel.CHANNEL, Control.encode(ControlFrame.wakeRequest("forged-name", "beta"))); Fakes.await("beta woken", () -> api.count("POST " + SERVERS + "beta/wake") == 1); message(p.on(lobby), ControlChannel.CHANNEL, Control.encode(ControlFrame.wakeRequest("forged-name", "gamma"))); Fakes.await("gamma woken", () -> api.count("POST " + SERVERS + "gamma/wake") == 1); Fakes.await("waker queued", () -> router.waitingCount() == 2); api.ready.put("beta", true); api.ready.put("gamma", true); router.tick(); List<ControlFrame> r = frames(p); assertEq("one frame to the lobby", 1, r.size()); assertEq("transfer ready", ControlFrame.TRANSFER_READY + " " + p.name + " beta", assertEq("transfer ready", ControlFrame.TRANSFER_READY + " " + p.name + " gamma", r.get(0).type() + " " + r.get(0).player() + " " + r.get(0).server()); assertEq("then moved", List.of("beta"), List.copyOf(p.connects)); assertEq("then moved", List.of("gamma"), List.copyOf(p.connects)); // For a running one it is a join: TransferReady and the move at once, no wake. Fakes.FakePlayer j = player(true); j.current = lobby; message(j.on(lobby), ControlChannel.CHANNEL, Control.encode(ControlFrame.wakeRequest(j.name, "beta"))); Fakes.await("running server joined", () -> j.connects.size() == 1); List<ControlFrame> jr = frames(j); assertEq("running server: one frame to the lobby", 1, jr.size()); assertEq("running server: transfer ready", ControlFrame.TRANSFER_READY + " " + j.name + " beta", jr.get(0).type() + " " + jr.get(0).player() + " " + jr.get(0).server()); assertEq("running server: moved", List.of("beta"), List.copyOf(j.connects)); assertEq("running server: never woken", 0, api.count("POST " + SERVERS + "beta/wake")); } private static void budget() { Loading Loading @@ -295,8 +307,12 @@ public final class ControlChannelTest { // Shaped like the operator's status: up is direct at addr; down is the fallback, // whose name ("login") sits in the address field. // view is a server as GET /servers lists it, and the stub API's status, menu and // wake answer for the same state: up at addr, or down on the "login" fallback. private static ServerView view(String name, boolean ready, String addr) { return new ServerView(name, name, ready ? "Running" : "Stopped", ready, "ownerOnly", api.ready.put(name, ready); api.address.put(name, addr); return new ServerView(name, name, ready ? "Running" : "Stopped", ready, "public", "Running", ready ? "direct" : "fallback", ready ? addr : "login", 0, 20); } Loading plugins/velocity/test/best/lolicon/felis/velocity/Fakes.java +73 −12 Changes for plugins/velocity/test/best/lolicon/felis/velocity/Fakes.java: 73 added lines, 12 removed lines. Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BooleanSupplier; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Fakes are the test doubles the routing tests run the real proxy classes against: Loading Loading @@ -432,13 +434,18 @@ final class Fakes { /** * Api is a stub felis-api internal face: link status from {@link #linked}, server * status from {@link #ready}, wake answering 202 unless {@link #wakeError} holds an * answer for the server, and join-events recorded. {@link #linkDown} makes the * link-status route answer 500. * status, menu and wake from one server state ({@link #ready}, {@link #phase}, * {@link #desired}, {@link #gaveUp}, {@link #policy}, {@link #owner}), and * join-events recorded. {@link #linkDown} makes the link-status route answer 500. * * <p>Status replies carry the endpoint the way the operator writes it: a server that * is up reports {@code direct} and its {@link #address}; one that is not reports * {@code fallback} with the fallback server's NAME, "login", in the address field. * * <p>The wake follows handleInternalWake step for step, so a test cannot give the * router an answer the real API never gives: an up server is 202 ready for anyone, * 403 and 409 start_failed come from the state, and {@link #wakeError} only holds * what the state cannot say (a cooldown, the running cap, maintenance, a fault). */ static final class Api implements AutoCloseable { final Set<UUID> linked = ConcurrentHashMap.newKeySet(); Loading @@ -455,9 +462,19 @@ final class Fakes { final Map<String, String> desired = new ConcurrentHashMap<>(); final Map<String, Integer> restarts = new ConcurrentHashMap<>(); final Set<String> gaveUp = ConcurrentHashMap.newKeySet(); /** * policy is a server's autostartPolicy, public unless set, and owner the player * who owns it. Only public or the owner passes the wake's gate: ownerOnly, and an * allowlist the stub keeps empty, refuse everyone else. */ final Map<String, String> policy = new ConcurrentHashMap<>(); final Map<String, UUID> owner = new ConcurrentHashMap<>(); /** statusDown makes the status route answer 500. */ volatile boolean statusDown; /** wakeError maps a server to "status code" (e.g. "403 forbidden"). */ /** * wakeError maps a server to "status code" (e.g. "429 cooldown"), answered where * the real wake reaches its cooldown: after the gate and the start_failed check. */ final Map<String, String> wakeError = new ConcurrentHashMap<>(); volatile int joinStatus = 204; /** claimable names the servers the menu route reports as claimable. */ Loading Loading @@ -511,16 +528,13 @@ final class Fakes { reply(ex, 200, status(name, ready.getOrDefault(name, false))); return; case "POST wake": if (!error(ex, wakeError.get(name))) { // The real wake reply is this subset of the view: no endpoint. reply(ex, 202, "{\"name\":\"" + name + "\",\"desiredState\":\"Running\"," + "\"phase\":\"Stopped\",\"ready\":false}"); } wake(ex, name, bodies.get(method + " " + path)); return; case "GET menu": if (!error(ex, menuError.get(name))) { reply(ex, 200, "{\"name\":\"" + name + "\",\"phase\":\"Stopped\",\"ready\":false," + "\"playersOnline\":3,\"playersMax\":20,\"claimable\":" + claimable.contains(name) + "}"); reply(ex, 200, "{\"name\":\"" + name + "\",\"phase\":\"" + phaseOf(name) + "\",\"ready\":" + ready.getOrDefault(name, false) + ",\"playersOnline\":3,\"playersMax\":20,\"claimable\":" + claimable.contains(name) + "}"); } return; case "POST claim": Loading Loading @@ -548,6 +562,52 @@ final class Fakes { return true; } // wake answers the way handleInternalWake does, in its order: a server that is up // and meant to stay up is 202 ready with no gate, nothing flipped; then the // autostartPolicy gate on the body's mc_uuid; then 409 start_failed for a start // whose retries are spent; then the cooldown and the rest of wakeError; then the // flip to Running and a 202 with the phase as it stands. private void wake(HttpExchange ex, String name, String body) throws IOException { boolean up = ready.getOrDefault(name, false); String want = desired.getOrDefault(name, "Running"); if (up && "Running".equals(want)) { reply(ex, 202, wakeReply(name, want, true)); return; } UUID waker = mcUuid(body); if (!"public".equals(policy.getOrDefault(name, "public")) && (waker == null || !waker.equals(owner.get(name)))) { error(ex, "403 forbidden"); return; } if (gaveUp.contains(name) && "Running".equals(want)) { error(ex, "409 start_failed"); return; } if (error(ex, wakeError.get(name))) { return; } desired.put(name, "Running"); reply(ex, 202, wakeReply(name, "Running", up)); } // The real wake reply is this subset of the view: no endpoint. private String wakeReply(String name, String desiredState, boolean up) { return "{\"name\":\"" + name + "\",\"desiredState\":\"" + desiredState + "\",\"phase\":\"" + phaseOf(name) + "\",\"ready\":" + up + "}"; } private static final Pattern MC_UUID = Pattern.compile("\"mc_uuid\"\\s*:\\s*\"([^\"]+)\""); private static UUID mcUuid(String body) { Matcher m = MC_UUID.matcher(body == null ? "" : body); return m.find() ? UUID.fromString(m.group(1)) : null; } private String phaseOf(String name) { return ready.getOrDefault(name, false) ? "Running" : phase.getOrDefault(name, "Stopped"); } private String status(String name, boolean up) { String addr = address.get(name); String endpoint = up Loading @@ -556,7 +616,8 @@ final class Fakes { // Like the real ServerInfo, autoRestarts and startGaveUp are left out at 0/false. int restarts = this.restarts.getOrDefault(name, 0); return "{\"name\":\"" + name + "\",\"subdomain\":\"" + name + "\",\"phase\":\"" + (up ? "Running" : phase.getOrDefault(name, "Stopped")) + "\",\"ready\":" + up + phaseOf(name) + "\",\"ready\":" + up + ",\"autostartPolicy\":\"" + policy.getOrDefault(name, "public") + "\"" + ",\"desiredState\":\"" + desired.getOrDefault(name, "Running") + "\"" + (restarts == 0 ? "" : ",\"autoRestarts\":" + restarts) + (gaveUp.contains(name) ? ",\"startGaveUp\":true" : "") Loading plugins/velocity/test/best/lolicon/felis/velocity/LegacyForwardingTest.java +1 −1 Changes for plugins/velocity/test/best/lolicon/felis/velocity/LegacyForwardingTest.java: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -162,7 +162,7 @@ public final class LegacyForwardingTest { } private static ServerView view(String name, boolean legacy) { return new ServerView(name, name, "Running", true, null, "Running", "ClusterIP", "10.43.0.9:25565", 0, 20, legacy); return new ServerView(name, name, "Running", true, null, "Running", "direct", "10.43.0.9:25565", 0, 20, legacy); } private static void assertEq(String what, Object want, Object got) { Loading plugins/velocity/test/best/lolicon/felis/velocity/ServerListSourceTest.java +7 −7 Changes for plugins/velocity/test/best/lolicon/felis/velocity/ServerListSourceTest.java: 7 added lines, 7 removed lines. Original line number Diff line number Diff line Loading @@ -31,9 +31,9 @@ public final class ServerListSourceTest { private static volatile List<ServerView> answer; private static final ServerView LOGIN = new ServerView("login", null, "Running", true, null, "Running", "ClusterIP", "10.43.0.17:25565", 0, 0); null, "Running", "direct", "10.43.0.17:25565", 0, 0); private static final ServerView SURVIVAL = new ServerView("survival", "Survival", "Stopped", false, "Anyone", "Stopped", "ClusterIP", "10.43.9.2:25565", 3, 20); "public", "Stopped", "fallback", "login", 3, 20); public static void main(String[] args) throws Exception { Path dir = Files.createTempDirectory("felis-server-list"); Loading Loading @@ -84,10 +84,10 @@ public final class ServerListSourceTest { assertEq("survival subdomain", "Survival", s.subdomain()); assertEq("survival phase", "Stopped", s.phase()); assertEq("survival ready", false, s.ready()); assertEq("survival policy", "Anyone", s.autostartPolicy()); assertEq("survival policy", "public", s.autostartPolicy()); assertEq("survival desired", "Stopped", s.desiredState()); assertEq("survival mode", "ClusterIP", s.endpointMode()); assertEq("survival address", "10.43.9.2:25565", s.endpointAddress()); assertEq("survival mode", "fallback", s.endpointMode()); assertEq("survival address", "login", s.endpointAddress()); assertEq("survival online", 3, s.playersOnline()); assertEq("survival max", 20, s.playersMax()); } Loading Loading @@ -154,7 +154,7 @@ public final class ServerListSourceTest { private static void theLegacyForwardingMarkIsSaved(Path dir) throws Exception { Path file = fresh(dir); ServerView legacy = new ServerView("legacy18", "old", "Running", true, null, "Running", "ClusterIP", "10.43.7.1:25565", 0, 20, true); null, "Running", "direct", "10.43.7.1:25565", 0, 20, true); answer = List.of(legacy, SURVIVAL); new ServerListSource(ServerListSourceTest::fetch, file).next(); answer = null; Loading @@ -167,7 +167,7 @@ public final class ServerListSourceTest { // The exact shape GET /api/v1/servers answers with, extra fields included. private static void theApiEnvelopeParses() { List<ServerView> v = ServerView.listFromJson("{\"servers\":[{\"name\":\"lobby\",\"subdomain\":\"\"," + "\"phase\":\"Running\",\"ready\":true,\"desiredState\":\"Running\",\"endpointMode\":\"ClusterIP\"," + "\"phase\":\"Running\",\"ready\":true,\"desiredState\":\"Running\",\"endpointMode\":\"direct\"," + "\"endpointAddress\":\"10.43.1.5:25565\",\"playersOnline\":1,\"playersMax\":100," + "\"owner\":\"x\"},\"junk\",{\"name\":\"legacy18\",\"legacyForwarding\":true}]}"); assertEq("non-object entries skipped", 2, v.size()); Loading Loading
plugins/test.sh +3 −1 Changes for plugins/test.sh: 3 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -43,7 +43,9 @@ # fake proxy and a stub felis-api — a refresh registers, moves and drops # backends and lets go of a renamed subdomain, the login gate and host routing # admit only linked players, each wake refusal reaches the player as its own # message, felis:control acts only for the connection's player and holds its # message (the stub answers a wake from the server's state in felis-api's own # order, so it cannot hand the router an answer the real API never gives), # felis:control acts only for the connection's player and holds its # frame budget. They ride the module's verified dependency set, which is why # they live in Gradle rather than in the javac mains above. # Loading
plugins/velocity/test/best/lolicon/felis/velocity/ControlChannelTest.java +24 −8 Changes for plugins/velocity/test/best/lolicon/felis/velocity/ControlChannelTest.java: 24 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -216,20 +216,32 @@ public final class ControlChannelTest { } private static void wakeAndTransfer() { // A WakeRequest parks the player; when the backend is ready the lobby hears // TransferReady just before the proxy moves them. // A WakeRequest for a stopped server parks the player; when the backend is ready // the lobby hears TransferReady just before the proxy moves them. Fakes.FakePlayer p = player(true); p.current = lobby; message(p.on(lobby), ControlChannel.CHANNEL, Control.encode(ControlFrame.wakeRequest("forged-name", "beta"))); Fakes.await("beta woken", () -> api.count("POST " + SERVERS + "beta/wake") == 1); message(p.on(lobby), ControlChannel.CHANNEL, Control.encode(ControlFrame.wakeRequest("forged-name", "gamma"))); Fakes.await("gamma woken", () -> api.count("POST " + SERVERS + "gamma/wake") == 1); Fakes.await("waker queued", () -> router.waitingCount() == 2); api.ready.put("beta", true); api.ready.put("gamma", true); router.tick(); List<ControlFrame> r = frames(p); assertEq("one frame to the lobby", 1, r.size()); assertEq("transfer ready", ControlFrame.TRANSFER_READY + " " + p.name + " beta", assertEq("transfer ready", ControlFrame.TRANSFER_READY + " " + p.name + " gamma", r.get(0).type() + " " + r.get(0).player() + " " + r.get(0).server()); assertEq("then moved", List.of("beta"), List.copyOf(p.connects)); assertEq("then moved", List.of("gamma"), List.copyOf(p.connects)); // For a running one it is a join: TransferReady and the move at once, no wake. Fakes.FakePlayer j = player(true); j.current = lobby; message(j.on(lobby), ControlChannel.CHANNEL, Control.encode(ControlFrame.wakeRequest(j.name, "beta"))); Fakes.await("running server joined", () -> j.connects.size() == 1); List<ControlFrame> jr = frames(j); assertEq("running server: one frame to the lobby", 1, jr.size()); assertEq("running server: transfer ready", ControlFrame.TRANSFER_READY + " " + j.name + " beta", jr.get(0).type() + " " + jr.get(0).player() + " " + jr.get(0).server()); assertEq("running server: moved", List.of("beta"), List.copyOf(j.connects)); assertEq("running server: never woken", 0, api.count("POST " + SERVERS + "beta/wake")); } private static void budget() { Loading Loading @@ -295,8 +307,12 @@ public final class ControlChannelTest { // Shaped like the operator's status: up is direct at addr; down is the fallback, // whose name ("login") sits in the address field. // view is a server as GET /servers lists it, and the stub API's status, menu and // wake answer for the same state: up at addr, or down on the "login" fallback. private static ServerView view(String name, boolean ready, String addr) { return new ServerView(name, name, ready ? "Running" : "Stopped", ready, "ownerOnly", api.ready.put(name, ready); api.address.put(name, addr); return new ServerView(name, name, ready ? "Running" : "Stopped", ready, "public", "Running", ready ? "direct" : "fallback", ready ? addr : "login", 0, 20); } Loading
plugins/velocity/test/best/lolicon/felis/velocity/Fakes.java +73 −12 Changes for plugins/velocity/test/best/lolicon/felis/velocity/Fakes.java: 73 added lines, 12 removed lines. Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BooleanSupplier; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Fakes are the test doubles the routing tests run the real proxy classes against: Loading Loading @@ -432,13 +434,18 @@ final class Fakes { /** * Api is a stub felis-api internal face: link status from {@link #linked}, server * status from {@link #ready}, wake answering 202 unless {@link #wakeError} holds an * answer for the server, and join-events recorded. {@link #linkDown} makes the * link-status route answer 500. * status, menu and wake from one server state ({@link #ready}, {@link #phase}, * {@link #desired}, {@link #gaveUp}, {@link #policy}, {@link #owner}), and * join-events recorded. {@link #linkDown} makes the link-status route answer 500. * * <p>Status replies carry the endpoint the way the operator writes it: a server that * is up reports {@code direct} and its {@link #address}; one that is not reports * {@code fallback} with the fallback server's NAME, "login", in the address field. * * <p>The wake follows handleInternalWake step for step, so a test cannot give the * router an answer the real API never gives: an up server is 202 ready for anyone, * 403 and 409 start_failed come from the state, and {@link #wakeError} only holds * what the state cannot say (a cooldown, the running cap, maintenance, a fault). */ static final class Api implements AutoCloseable { final Set<UUID> linked = ConcurrentHashMap.newKeySet(); Loading @@ -455,9 +462,19 @@ final class Fakes { final Map<String, String> desired = new ConcurrentHashMap<>(); final Map<String, Integer> restarts = new ConcurrentHashMap<>(); final Set<String> gaveUp = ConcurrentHashMap.newKeySet(); /** * policy is a server's autostartPolicy, public unless set, and owner the player * who owns it. Only public or the owner passes the wake's gate: ownerOnly, and an * allowlist the stub keeps empty, refuse everyone else. */ final Map<String, String> policy = new ConcurrentHashMap<>(); final Map<String, UUID> owner = new ConcurrentHashMap<>(); /** statusDown makes the status route answer 500. */ volatile boolean statusDown; /** wakeError maps a server to "status code" (e.g. "403 forbidden"). */ /** * wakeError maps a server to "status code" (e.g. "429 cooldown"), answered where * the real wake reaches its cooldown: after the gate and the start_failed check. */ final Map<String, String> wakeError = new ConcurrentHashMap<>(); volatile int joinStatus = 204; /** claimable names the servers the menu route reports as claimable. */ Loading Loading @@ -511,16 +528,13 @@ final class Fakes { reply(ex, 200, status(name, ready.getOrDefault(name, false))); return; case "POST wake": if (!error(ex, wakeError.get(name))) { // The real wake reply is this subset of the view: no endpoint. reply(ex, 202, "{\"name\":\"" + name + "\",\"desiredState\":\"Running\"," + "\"phase\":\"Stopped\",\"ready\":false}"); } wake(ex, name, bodies.get(method + " " + path)); return; case "GET menu": if (!error(ex, menuError.get(name))) { reply(ex, 200, "{\"name\":\"" + name + "\",\"phase\":\"Stopped\",\"ready\":false," + "\"playersOnline\":3,\"playersMax\":20,\"claimable\":" + claimable.contains(name) + "}"); reply(ex, 200, "{\"name\":\"" + name + "\",\"phase\":\"" + phaseOf(name) + "\",\"ready\":" + ready.getOrDefault(name, false) + ",\"playersOnline\":3,\"playersMax\":20,\"claimable\":" + claimable.contains(name) + "}"); } return; case "POST claim": Loading Loading @@ -548,6 +562,52 @@ final class Fakes { return true; } // wake answers the way handleInternalWake does, in its order: a server that is up // and meant to stay up is 202 ready with no gate, nothing flipped; then the // autostartPolicy gate on the body's mc_uuid; then 409 start_failed for a start // whose retries are spent; then the cooldown and the rest of wakeError; then the // flip to Running and a 202 with the phase as it stands. private void wake(HttpExchange ex, String name, String body) throws IOException { boolean up = ready.getOrDefault(name, false); String want = desired.getOrDefault(name, "Running"); if (up && "Running".equals(want)) { reply(ex, 202, wakeReply(name, want, true)); return; } UUID waker = mcUuid(body); if (!"public".equals(policy.getOrDefault(name, "public")) && (waker == null || !waker.equals(owner.get(name)))) { error(ex, "403 forbidden"); return; } if (gaveUp.contains(name) && "Running".equals(want)) { error(ex, "409 start_failed"); return; } if (error(ex, wakeError.get(name))) { return; } desired.put(name, "Running"); reply(ex, 202, wakeReply(name, "Running", up)); } // The real wake reply is this subset of the view: no endpoint. private String wakeReply(String name, String desiredState, boolean up) { return "{\"name\":\"" + name + "\",\"desiredState\":\"" + desiredState + "\",\"phase\":\"" + phaseOf(name) + "\",\"ready\":" + up + "}"; } private static final Pattern MC_UUID = Pattern.compile("\"mc_uuid\"\\s*:\\s*\"([^\"]+)\""); private static UUID mcUuid(String body) { Matcher m = MC_UUID.matcher(body == null ? "" : body); return m.find() ? UUID.fromString(m.group(1)) : null; } private String phaseOf(String name) { return ready.getOrDefault(name, false) ? "Running" : phase.getOrDefault(name, "Stopped"); } private String status(String name, boolean up) { String addr = address.get(name); String endpoint = up Loading @@ -556,7 +616,8 @@ final class Fakes { // Like the real ServerInfo, autoRestarts and startGaveUp are left out at 0/false. int restarts = this.restarts.getOrDefault(name, 0); return "{\"name\":\"" + name + "\",\"subdomain\":\"" + name + "\",\"phase\":\"" + (up ? "Running" : phase.getOrDefault(name, "Stopped")) + "\",\"ready\":" + up + phaseOf(name) + "\",\"ready\":" + up + ",\"autostartPolicy\":\"" + policy.getOrDefault(name, "public") + "\"" + ",\"desiredState\":\"" + desired.getOrDefault(name, "Running") + "\"" + (restarts == 0 ? "" : ",\"autoRestarts\":" + restarts) + (gaveUp.contains(name) ? ",\"startGaveUp\":true" : "") Loading
plugins/velocity/test/best/lolicon/felis/velocity/LegacyForwardingTest.java +1 −1 Changes for plugins/velocity/test/best/lolicon/felis/velocity/LegacyForwardingTest.java: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -162,7 +162,7 @@ public final class LegacyForwardingTest { } private static ServerView view(String name, boolean legacy) { return new ServerView(name, name, "Running", true, null, "Running", "ClusterIP", "10.43.0.9:25565", 0, 20, legacy); return new ServerView(name, name, "Running", true, null, "Running", "direct", "10.43.0.9:25565", 0, 20, legacy); } private static void assertEq(String what, Object want, Object got) { Loading
plugins/velocity/test/best/lolicon/felis/velocity/ServerListSourceTest.java +7 −7 Changes for plugins/velocity/test/best/lolicon/felis/velocity/ServerListSourceTest.java: 7 added lines, 7 removed lines. Original line number Diff line number Diff line Loading @@ -31,9 +31,9 @@ public final class ServerListSourceTest { private static volatile List<ServerView> answer; private static final ServerView LOGIN = new ServerView("login", null, "Running", true, null, "Running", "ClusterIP", "10.43.0.17:25565", 0, 0); null, "Running", "direct", "10.43.0.17:25565", 0, 0); private static final ServerView SURVIVAL = new ServerView("survival", "Survival", "Stopped", false, "Anyone", "Stopped", "ClusterIP", "10.43.9.2:25565", 3, 20); "public", "Stopped", "fallback", "login", 3, 20); public static void main(String[] args) throws Exception { Path dir = Files.createTempDirectory("felis-server-list"); Loading Loading @@ -84,10 +84,10 @@ public final class ServerListSourceTest { assertEq("survival subdomain", "Survival", s.subdomain()); assertEq("survival phase", "Stopped", s.phase()); assertEq("survival ready", false, s.ready()); assertEq("survival policy", "Anyone", s.autostartPolicy()); assertEq("survival policy", "public", s.autostartPolicy()); assertEq("survival desired", "Stopped", s.desiredState()); assertEq("survival mode", "ClusterIP", s.endpointMode()); assertEq("survival address", "10.43.9.2:25565", s.endpointAddress()); assertEq("survival mode", "fallback", s.endpointMode()); assertEq("survival address", "login", s.endpointAddress()); assertEq("survival online", 3, s.playersOnline()); assertEq("survival max", 20, s.playersMax()); } Loading Loading @@ -154,7 +154,7 @@ public final class ServerListSourceTest { private static void theLegacyForwardingMarkIsSaved(Path dir) throws Exception { Path file = fresh(dir); ServerView legacy = new ServerView("legacy18", "old", "Running", true, null, "Running", "ClusterIP", "10.43.7.1:25565", 0, 20, true); null, "Running", "direct", "10.43.7.1:25565", 0, 20, true); answer = List.of(legacy, SURVIVAL); new ServerListSource(ServerListSourceTest::fetch, file).next(); answer = null; Loading @@ -167,7 +167,7 @@ public final class ServerListSourceTest { // The exact shape GET /api/v1/servers answers with, extra fields included. private static void theApiEnvelopeParses() { List<ServerView> v = ServerView.listFromJson("{\"servers\":[{\"name\":\"lobby\",\"subdomain\":\"\"," + "\"phase\":\"Running\",\"ready\":true,\"desiredState\":\"Running\",\"endpointMode\":\"ClusterIP\"," + "\"phase\":\"Running\",\"ready\":true,\"desiredState\":\"Running\",\"endpointMode\":\"direct\"," + "\"endpointAddress\":\"10.43.1.5:25565\",\"playersOnline\":1,\"playersMax\":100," + "\"owner\":\"x\"},\"junk\",{\"name\":\"legacy18\",\"legacyForwarding\":true}]}"); assertEq("non-object entries skipped", 2, v.size()); Loading