From a5051e559ab3b1cbd26f310d0ca0e62047a50a56 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Mon, 21 Oct 2024 13:41:54 -0500 Subject: [PATCH] CE-1887 Test on QAppJavalinServer --- .../javalin/QApplicationJavalinServer.java | 25 ++- .../QApplicationJavalinServerTest.java | 210 ++++++++++++++++++ 2 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/middleware/javalin/QApplicationJavalinServerTest.java diff --git a/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/middleware/javalin/QApplicationJavalinServer.java b/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/middleware/javalin/QApplicationJavalinServer.java index b8f20c63..d18a6a03 100644 --- a/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/middleware/javalin/QApplicationJavalinServer.java +++ b/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/middleware/javalin/QApplicationJavalinServer.java @@ -74,6 +74,8 @@ public class QApplicationJavalinServer private long millisBetweenHotSwaps = 2500; private Consumer hotSwapCustomizer = null; + private Javalin service; + /******************************************************************************* @@ -94,7 +96,7 @@ public class QApplicationJavalinServer { QInstance qInstance = application.defineValidatedQInstance(); - Javalin service = Javalin.create(config -> + service = Javalin.create(config -> { if(serveFrontendMaterialDashboard) { @@ -187,6 +189,22 @@ public class QApplicationJavalinServer + /*************************************************************************** + ** + ***************************************************************************/ + public void stop() + { + if(this.service == null) + { + LOG.info("Stop called, but there is no javalin service, so noop."); + return; + } + + this.service.stop(); + } + + + /******************************************************************************* ** If there's a qInstanceHotSwapSupplier, and its been a little while, replace ** the qInstance with a new one from the supplier. Meant to be used while doing @@ -440,12 +458,14 @@ public class QApplicationJavalinServer /******************************************************************************* ** Fluent setter for MILLIS_BETWEEN_HOT_SWAPS *******************************************************************************/ - public void withMillisBetweenHotSwaps(long millisBetweenHotSwaps) + public QApplicationJavalinServer withMillisBetweenHotSwaps(long millisBetweenHotSwaps) { this.millisBetweenHotSwaps = millisBetweenHotSwaps; + return (this); } + /******************************************************************************* ** Getter for hotSwapCustomizer *******************************************************************************/ @@ -506,5 +526,4 @@ public class QApplicationJavalinServer return (this); } - } diff --git a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/middleware/javalin/QApplicationJavalinServerTest.java b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/middleware/javalin/QApplicationJavalinServerTest.java new file mode 100644 index 00000000..a1cdf6b2 --- /dev/null +++ b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/middleware/javalin/QApplicationJavalinServerTest.java @@ -0,0 +1,210 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2024. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.middleware.javalin; + + +import java.util.List; +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.instances.AbstractQQQApplication; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.javalin.TestUtils; +import com.kingsrook.qqq.middleware.javalin.specs.v1.MiddlewareVersionV1; +import kong.unirest.HttpResponse; +import kong.unirest.Unirest; +import org.json.JSONObject; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + + +/******************************************************************************* + ** Unit test for QApplicationJavalinServer + *******************************************************************************/ +class QApplicationJavalinServerTest +{ + private static final int PORT = 6265; + + private QApplicationJavalinServer javalinServer; + + + + /******************************************************************************* + ** + *******************************************************************************/ + @AfterEach + void afterEach() + { + javalinServer.stop(); + TestApplication.callCount = 0; + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testWithLegacyImplementation() throws QException + { + javalinServer = new QApplicationJavalinServer(getQqqApplication()) + .withPort(PORT) + .withServeFrontendMaterialDashboard(false); + javalinServer.start(); + + HttpResponse response = Unirest.get("http://localhost:" + PORT + "/metaData").asString(); + assertEquals(200, response.getStatus()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testWithoutLegacyImplementation() throws QException + { + javalinServer = new QApplicationJavalinServer(getQqqApplication()) + .withPort(PORT) + .withServeLegacyUnversionedMiddlewareAPI(false) + .withServeFrontendMaterialDashboard(false); + javalinServer.start(); + + HttpResponse response = Unirest.get("http://localhost:" + PORT + "/metaData").asString(); + assertEquals(404, response.getStatus()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testWithVersionedImplementation() throws QException + { + javalinServer = new QApplicationJavalinServer(getQqqApplication()) + .withPort(PORT) + .withMiddlewareVersionList(List.of(new MiddlewareVersionV1())) + .withServeFrontendMaterialDashboard(false); + javalinServer.start(); + + HttpResponse response = Unirest.get("http://localhost:" + PORT + "/qqq/v1/metaData").asString(); + assertEquals(200, response.getStatus()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testWithoutHotSwap() throws QException + { + testWithOrWithoutHotSwap(false); + } + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testWithHotSwap() throws QException + { + testWithOrWithoutHotSwap(true); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + private void testWithOrWithoutHotSwap(boolean withHotSwap) throws QException + { + System.setProperty("qqq.javalin.hotSwapInstance", String.valueOf(withHotSwap)); + javalinServer = new QApplicationJavalinServer(getQqqApplication()) + .withPort(PORT) + .withMiddlewareVersionList(List.of(new MiddlewareVersionV1())) + .withMillisBetweenHotSwaps(0) + .withServeFrontendMaterialDashboard(false); + javalinServer.start(); + System.clearProperty("qqq.javalin.hotSwapInstance"); + assertThat(TestApplication.callCount).isEqualTo(1); + + HttpResponse response = Unirest.get("http://localhost:" + PORT + "/qqq/v1/metaData").asString(); + assertEquals(200, response.getStatus()); + + response = Unirest.get("http://localhost:" + PORT + "/qqq/v1/metaData").asString(); + assertEquals(200, response.getStatus()); + JSONObject metaData = new JSONObject(response.getBody()); + JSONObject tables = metaData.getJSONObject("tables"); + String aTableName = tables.keySet().iterator().next(); + JSONObject aTable = tables.getJSONObject(aTableName); + + if(withHotSwap) + { + assertThat(aTable.getString("label")).doesNotEndWith("1"); + assertThat(TestApplication.callCount).isGreaterThanOrEqualTo(1); + } + else + { + assertThat(aTable.getString("label")).endsWith("1"); + assertThat(TestApplication.callCount).isEqualTo(1); + } + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + private static AbstractQQQApplication getQqqApplication() + { + return new TestApplication(); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + public static class TestApplication extends AbstractQQQApplication + { + static int callCount = 0; + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public QInstance defineQInstance() throws QException + { + callCount++; + QInstance qInstance = TestUtils.defineInstance(); + + qInstance.getTables().values().forEach(t -> t.setLabel(t.getLabel() + callCount)); + + return (qInstance); + } + } + +} \ No newline at end of file