preparing for another refactoring...

This commit is contained in:
Relism
2026-03-29 23:16:41 +02:00
parent 2edd68b0aa
commit b5d4481502
69 changed files with 4329 additions and 1076 deletions
@@ -8,22 +8,17 @@ import dev.relism.models.Response;
import dev.relism.models.SimpleHandler;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.*;
class AbstractRouterTest {
// A minimal concrete router for testing base-class functionality
static class DummyRouter extends AbstractRouter {
RequestHandler lastAddedHandler;
HttpMethod lastAddedMethod;
String lastAddedPath;
@Override
public RequestHandler route(Request request) {
return null;
}
public RequestHandler route(Request request) { return null; }
@Override
protected AbstractRouter addRoute(HttpMethod method, String path, RequestHandler handler) {
@@ -34,31 +29,15 @@ class AbstractRouterTest {
}
}
// --- namespace ---
@Test
void setNamespace_updatesStringAndBytes() {
void doRegister_sanitizesPathAndWrapsHandler() {
DummyRouter router = new DummyRouter();
assertEquals("/", router.getNamespace());
router.setNamespace("/api");
assertEquals("/api", router.getNamespace());
assertArrayEquals("/api".getBytes(StandardCharsets.UTF_8), router.getNamespaceBytes());
}
// --- doRegister (infrastructure method used by FlashApp/FlashScope) ---
@Test
void doRegister_lambda_sanitizesPathAndWrapsHandler() {
DummyRouter router = new DummyRouter();
SimpleHandler.FunctionalHandler func = (req, res) -> "OK";
router.doRegister(HttpMethod.GET, "users/", func, new Middleware[0]);
router.doRegister(HttpMethod.GET, "users/", new SimpleHandler((req, res) -> "OK"), new Middleware[0]);
assertEquals(HttpMethod.GET, router.lastAddedMethod);
assertEquals("/users", router.lastAddedPath);
assertNotNull(router.lastAddedHandler);
router.doRegister(HttpMethod.DELETE, "//delete//", func, new Middleware[0]);
router.doRegister(HttpMethod.DELETE, "//delete//", new SimpleHandler((req, res) -> "OK"), new Middleware[0]);
assertEquals(HttpMethod.DELETE, router.lastAddedMethod);
assertEquals("/delete", router.lastAddedPath);
}
@@ -69,17 +48,13 @@ class AbstractRouterTest {
public Object handle(Request request, Response response) { return null; }
}
static class UnannotatedHandler extends RequestHandler {
@Override
public Object handle(Request request, Response response) { return null; }
}
@Test
void doRegister_annotatedHandler_addsRoute() {
void doRegister_classBasedHandler_addsRoute() {
DummyRouter router = new DummyRouter();
ProfileHandler handler = new ProfileHandler();
Route ann = ProfileHandler.class.getAnnotation(Route.class);
router.doRegister(handler, new Middleware[0]);
router.doRegister(ann.method(), ann.path(), handler, new Middleware[0]);
assertEquals(HttpMethod.POST, router.lastAddedMethod);
assertEquals("/profile", router.lastAddedPath);
@@ -87,27 +62,16 @@ class AbstractRouterTest {
}
@Test
void doRegister_unannotatedHandler_doesNothing() {
void defaultNotFoundHandler_returns404() throws Exception {
DummyRouter router = new DummyRouter();
router.doRegister(new UnannotatedHandler(), new Middleware[0]);
assertNull(router.lastAddedMethod);
}
// --- error handlers ---
@Test
void defaultNotFoundHandler_returns404Html() throws Exception {
DummyRouter router = new DummyRouter();
Response res = new Response(200, new byte[0], ContentType.TEXT_PLAIN);
assertNotNull(router.getNotFoundHandler());
router.onNotFound((req, resp) -> "Custom 404");
assertEquals("Custom 404", router.getNotFoundHandler().handle(null, res));
assertEquals("Custom 404", router.getNotFoundHandler().handle(null, null));
}
@Test
void defaultExceptionHandler_canBeOverridden() throws Exception {
void defaultExceptionHandler_canBeOverridden() {
DummyRouter router = new DummyRouter();
assertNotNull(router.getExceptionHandler());
@@ -1,97 +0,0 @@
package dev.relism.routing;
import dev.relism.fpr.core.ByteView;
import dev.relism.http.HttpMethod;
import dev.relism.models.HeaderMap;
import dev.relism.models.Request;
import dev.relism.models.RequestHandler;
import dev.relism.models.RequestLine;
import dev.relism.models.SimpleHandler;
import dev.relism.routing.routers.fastpathrouter.FastPathViews;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.*;
class GlobalRouterTest {
// --- mock ---
static class MockSubRouter extends AbstractRouter {
RequestHandler matchedHandler;
MockSubRouter(RequestHandler handler) {
this.matchedHandler = handler;
}
@Override
public RequestHandler route(Request request) {
return matchedHandler;
}
@Override
protected AbstractRouter addRoute(HttpMethod method, String path, RequestHandler handler) {
return this;
}
}
private Request mockRequest(String path) {
byte[] bytes = path.getBytes(StandardCharsets.UTF_8);
FastPathViews.RequestByteView pathView = new FastPathViews.RequestByteView(bytes, 0, bytes.length);
RequestLine line = new RequestLine(
HttpMethod.GET, pathView, null,
new FastPathViews.RequestByteView("HTTP/1.1".getBytes(StandardCharsets.UTF_8), 0, 8),
new HeaderMap()
);
return new Request(line, new byte[0]);
}
// --- mount & route ---
@Test
void route_delegatesToSubRouterBasedOnLongestPrefix() {
GlobalRouter global = new GlobalRouter();
RequestHandler hApi = new SimpleHandler((req, res) -> "api");
RequestHandler hApiV1 = new SimpleHandler((req, res) -> "apiv1");
global.mount("/api", new MockSubRouter(hApi));
global.mount("/api/v1", new MockSubRouter(hApiV1));
assertEquals(hApiV1, global.route(mockRequest("/api/v1/users")));
assertEquals(hApi, global.route(mockRequest("/api/v2/users")));
}
@Test
void route_fallsBackToInternalRouter() throws Exception {
GlobalRouter global = new GlobalRouter();
global.doRegister(HttpMethod.GET, "/hello", (req, res) -> "internal", new Middleware[0]);
RequestHandler resolved = global.route(mockRequest("/hello"));
assertNotNull(resolved);
assertEquals("internal", resolved.handle(null, null));
}
@Test
void route_noMatch_returnsNotFoundHandler() {
GlobalRouter global = new GlobalRouter();
RequestHandler resolved = global.route(mockRequest("/unknown"));
assertEquals(global.getNotFoundHandler(), resolved);
}
// --- resolveExceptionHandler ---
@Test
void resolveExceptionHandler_returnsScopedHandler() {
GlobalRouter global = new GlobalRouter();
MockSubRouter sub = new MockSubRouter(null);
AbstractRouter.ExceptionHandler customSubHandler = (ex, req, res) -> "sub error";
sub.onException(customSubHandler);
global.mount("/api", sub);
assertEquals(customSubHandler, global.resolveExceptionHandler(mockRequest("/api/fail")));
assertEquals(global.getExceptionHandler(), global.resolveExceptionHandler(mockRequest("/other")));
}
}
@@ -5,6 +5,7 @@ import dev.relism.models.HeaderMap;
import dev.relism.models.Request;
import dev.relism.models.RequestHandler;
import dev.relism.models.RequestLine;
import dev.relism.models.SimpleHandler;
import dev.relism.routing.Middleware;
import org.junit.jupiter.api.Test;
@@ -14,9 +15,7 @@ import static org.junit.jupiter.api.Assertions.*;
class FastPathRouterImplTest {
private static final Middleware[] NO_MIDDLEWARE = new Middleware[0];
// --- helpers ---
private static final Middleware[] NO_MW = new Middleware[0];
private Request mockRequest(HttpMethod method, String path) {
byte[] bytes = path.getBytes(StandardCharsets.UTF_8);
@@ -29,14 +28,11 @@ class FastPathRouterImplTest {
return new Request(line, new byte[0]);
}
// --- route ---
@Test
void route_lazyCompilationAndMatch() throws Exception {
FastPathRouterImpl router = new FastPathRouterImpl();
router.doRegister(HttpMethod.GET, "/a", (req, res) -> "A", NO_MIDDLEWARE);
router.doRegister(HttpMethod.POST, "/b", (req, res) -> "B", NO_MIDDLEWARE);
router.doRegister(HttpMethod.GET, "/a", new SimpleHandler((req, res) -> "A"), NO_MW);
router.doRegister(HttpMethod.POST, "/b", new SimpleHandler((req, res) -> "B"), NO_MW);
RequestHandler res1 = router.route(mockRequest(HttpMethod.GET, "/a"));
assertNotNull(res1);
@@ -50,7 +46,7 @@ class FastPathRouterImplTest {
@Test
void route_noMatch_returnsNull() {
FastPathRouterImpl router = new FastPathRouterImpl();
router.doRegister(HttpMethod.GET, "/a", (req, res) -> "A", NO_MIDDLEWARE);
router.doRegister(HttpMethod.GET, "/a", new SimpleHandler((req, res) -> "A"), NO_MW);
assertNull(router.route(mockRequest(HttpMethod.GET, "/b")));
assertNull(router.route(mockRequest(HttpMethod.POST, "/a")));
@@ -60,7 +56,7 @@ class FastPathRouterImplTest {
void route_extractsPathParams() throws Exception {
FastPathRouterImpl router = new FastPathRouterImpl();
router.doRegister(HttpMethod.GET, "/users/{id}/items/{itemId}",
(req, res) -> "Extract", NO_MIDDLEWARE);
new SimpleHandler((req, res) -> "Extract"), NO_MW);
Request request = mockRequest(HttpMethod.GET, "/users/123/items/456");
RequestHandler handler = router.route(request);