This is an automated email from the ASF dual-hosted git repository. jamesbognar pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/juneau.git
commit 7e4ca741b63b453f65c21b8c315a75de9754a98c Author: James Bognar <[email protected]> AuthorDate: Tue Jul 28 17:44:42 2026 -0400 test: add the permanent fake-McpRevision architecture acceptance test A revision written from scratch in the core module's own test tree serves a full request through both the servlet-subclass and mixin paths. Its classpath-isolation assertion is disabled until core's dependency on the v1 bean module is dropped. Co-authored-by: Cursor <[email protected]> --- .../rest/server/mcp/FakeMcpRevision_Test.java | 115 +++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/juneau-rest/juneau-rest-server-mcp/src/test/java/org/apache/juneau/rest/server/mcp/FakeMcpRevision_Test.java b/juneau-rest/juneau-rest-server-mcp/src/test/java/org/apache/juneau/rest/server/mcp/FakeMcpRevision_Test.java new file mode 100644 index 0000000000..80ec9c80de --- /dev/null +++ b/juneau-rest/juneau-rest-server-mcp/src/test/java/org/apache/juneau/rest/server/mcp/FakeMcpRevision_Test.java @@ -0,0 +1,115 @@ +package org.apache.juneau.rest.server.mcp; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.bean.jsonrpc.*; +import org.apache.juneau.commons.inject.*; +import org.apache.juneau.marshall.json.*; +import org.apache.juneau.rest.mock.classic.*; +import org.apache.juneau.rest.server.*; +import org.apache.juneau.rest.server.servlet.*; +import org.junit.jupiter.api.*; + +/** + * The architecture acceptance test for the revision-neutral core. + * + * <p> + * A revision implementation written entirely from scratch, inside the core module's own test tree, + * with no access to any revision-specific module, must be able to serve a full MCP request through + * both integration paths. If this ever stops compiling or stops passing, some revision-specific + * assumption has leaked into the core — which is precisely the regression this test exists to catch. + * Keep it permanently. + */ +@SuppressWarnings({ + "resource" // MockRestClient is a Closeable test helper; lifetime is bounded by the test method. +}) +class FakeMcpRevision_Test extends TestBase { + + /** Records what it received and returns a canned response. */ + static class FakeRevision implements McpRevision { + McpExchange lastExchange; + McpServerConfig lastConfig; + BeanStore lastCtx; + int calls; + + @Override + public String protocolVersion() { + return "0000-00-00"; + } + + @Override + public JsonRpcResponse dispatch(McpExchange exchange, McpServerConfig config, BeanStore ctx) { + calls++; + lastExchange = exchange; + lastConfig = config; + lastCtx = ctx; + return JsonRpcResponse.ok(exchange.request().getId(), Map.of("fake", protocolVersion())); + } + + @Override + public int errorCode(McpErrorKind kind) { + return -1; + } + } + + static final FakeRevision SERVLET_REVISION = new FakeRevision(); + static final FakeRevision MIXIN_REVISION = new FakeRevision(); + + @Rest(serializers = JsonSerializer.class, parsers = JsonParser.class, defaultAccept = "application/json") + public static class A extends McpRestServlet { + private static final long serialVersionUID = 1L; + @Override protected McpServerConfig createMcpConfig() { return new McpServerConfig().setInstructions("fake"); } + @Override protected McpRevision revision() { return SERVLET_REVISION; } + } + + @Rest(path = "/api", serializers = JsonSerializer.class, parsers = JsonParser.class, defaultAccept = "application/json") + public static class B extends BasicRestServlet implements McpEndpoint { + private static final long serialVersionUID = 1L; + @Override public McpServerConfig getMcpConfig() { return new McpServerConfig().setInstructions("fake-mixin"); } + @Override public McpRevision revision() { return MIXIN_REVISION; } + } + + @Test + void a01_servletPath_reachesTheFakeRevision() throws Exception { + var c = MockRestClient.create(A.class).json().contentType("application/json").accept("application/json").build(); + var res = c.post("/").contentString("{\"jsonrpc\":\"2.0\",\"id\":9,\"method\":\"anything\"}").run() + .assertStatus(200).getContent().asString(); + assertTrue(res.contains("0000-00-00"), res); + assertEquals(1, SERVLET_REVISION.calls); + assertEquals("anything", SERVLET_REVISION.lastExchange.request().getMethod()); + assertEquals("fake", SERVLET_REVISION.lastConfig.getInstructions()); + assertTrue(SERVLET_REVISION.lastCtx.getBean(RestRequest.class).isPresent()); + } + + @Test + void a02_mixinPath_reachesTheFakeRevision() throws Exception { + var c = MockRestClient.create(B.class).json().contentType("application/json").accept("application/json").build(); + var res = c.post("/mcp").contentString("{\"jsonrpc\":\"2.0\",\"id\":9,\"method\":\"anything\"}").run() + .assertStatus(200).getContent().asString(); + assertTrue(res.contains("0000-00-00"), res); + assertEquals(1, MIXIN_REVISION.calls); + assertEquals("fake-mixin", MIXIN_REVISION.lastConfig.getInstructions()); + } + + @Test + void a03_headerAccessorReachesTheHttpHeaders() throws Exception { + var c = MockRestClient.create(A.class).json().contentType("application/json").accept("application/json").build(); + c.post("/").contentString("{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"anything\"}").header("Mcp-Method", "tools/call").run().assertStatus(200); + assertEquals("tools/call", SERVLET_REVISION.lastExchange.header("Mcp-Method")); + assertNull(SERVLET_REVISION.lastExchange.header("Absent-Header")); + } + + @Test + @org.junit.jupiter.api.Disabled("Enabled by the task that drops core's dependency on juneau-bean-mcp-2025-06-18.") + void a04_coreTestTreeSeesNoRevisionModule() { + assertThrows(ClassNotFoundException.class, + () -> Class.forName("org.apache.juneau.rest.server.mcp.v20250618.Mcp20250618Revision"), + "the core module's test classpath must not contain any revision adapter"); + assertThrows(ClassNotFoundException.class, + () -> Class.forName("org.apache.juneau.bean.mcp.v20250618.Tool"), + "the core module's test classpath must not contain any revision's wire beans"); + } +}
