From 56a77f90deee51bf5f19c33f5cf51b58c520ccba Mon Sep 17 00:00:00 2001 From: kaah Date: Thu, 11 Dec 2025 14:01:08 +0100 Subject: [PATCH 1/2] Initial migration from TestNG to JUnit 5 - Added JUnit 5 annotations to BitrepositoryTestSuite - Added GlobalSuiteExtension to implement JUnit 5 extension points for suite-level setup and teardown. - Ensured consistency and correctness of test suite configuration and setup methods. This commit updates the test suite configuration to use JUnit 5 annotations, allowing for more flexible and powerful test suite management. --- .../protocol/BitrepositoryTestSuite.java | 63 ++++++ .../protocol/GlobalSuiteExtension.java | 208 ++++++++++++++++++ .../protocol/IntegrationTest.java | 5 + .../protocol/bus/ActiveMQMessageBusTest.java | 31 ++- ...MessageBusNumberOfListenersStressTest.java | 16 +- pom.xml | 63 ++++-- 6 files changed, 351 insertions(+), 35 deletions(-) create mode 100644 bitrepository-core/src/test/java/org/bitrepository/protocol/BitrepositoryTestSuite.java create mode 100644 bitrepository-core/src/test/java/org/bitrepository/protocol/GlobalSuiteExtension.java diff --git a/bitrepository-core/src/test/java/org/bitrepository/protocol/BitrepositoryTestSuite.java b/bitrepository-core/src/test/java/org/bitrepository/protocol/BitrepositoryTestSuite.java new file mode 100644 index 000000000..e31f8f4a0 --- /dev/null +++ b/bitrepository-core/src/test/java/org/bitrepository/protocol/BitrepositoryTestSuite.java @@ -0,0 +1,63 @@ +package org.bitrepository.protocol; + +import org.junit.platform.suite.api.ExcludeTags; +import org.junit.platform.suite.api.IncludeTags; +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.SelectPackages; +import org.junit.platform.suite.api.Suite; +import org.junit.jupiter.api.extension.ExtendWith; +import org.bitrepository.protocol.GlobalSuiteExtension; + +/** + * BitrepositoryTestSuite is a JUnit 5 suite class that groups and configures multiple test classes + * for the BitRepository project. This suite uses JUnit 5 annotations to select test classes, packages, + * and tags, and extend the suite with custom extensions. + * + *

JUnit 5 Annotations Used:

+ * + * + *

Options in a JUnit 5 Suite:

+ * + * + *

Example Usage:

+ *
+ * {@code
+ * @Suite
+ * @SelectClasses({IntegrationTest.class})  // List your test classes here
+ * @SelectPackages("org.bitrepository.protocol")  // List your test packages here
+ * @IncludeTags("integration")  // List your include tags here
+ * @ExcludeTags("slow")  // List your exclude tags here
+ * @ExtendWith(GlobalSuiteExtension.class)
+ * public class BitrepositoryTestSuite {
+ *     // No need for methods here; this just groups and extends
+ * }
+ * }
+ * 
+ */ +@Suite +@SelectClasses({IntegrationTest.class}) // List your test classes here +@ExtendWith(GlobalSuiteExtension.class) +public class BitrepositoryTestSuite { + // No need for methods here; this just groups and extends +} + diff --git a/bitrepository-core/src/test/java/org/bitrepository/protocol/GlobalSuiteExtension.java b/bitrepository-core/src/test/java/org/bitrepository/protocol/GlobalSuiteExtension.java new file mode 100644 index 000000000..8b8754b74 --- /dev/null +++ b/bitrepository-core/src/test/java/org/bitrepository/protocol/GlobalSuiteExtension.java @@ -0,0 +1,208 @@ +package org.bitrepository.protocol; + +import org.bitrepository.common.settings.Settings; +import org.bitrepository.common.settings.TestSettingsProvider; +import org.bitrepository.common.utils.SettingsUtils; +import org.bitrepository.common.utils.TestFileHelper; +import org.bitrepository.protocol.bus.LocalActiveMQBroker; +import org.bitrepository.protocol.bus.MessageReceiver; +import org.bitrepository.protocol.fileexchange.HttpServerConfiguration; +import org.bitrepository.protocol.http.EmbeddedHttpServer; +import org.bitrepository.protocol.messagebus.MessageBus; +import org.bitrepository.protocol.messagebus.MessageBusManager; +import org.bitrepository.protocol.messagebus.SimpleMessageBus; +import org.bitrepository.protocol.security.DummySecurityManager; +import org.bitrepository.protocol.security.SecurityManager; +import org.jaccept.TestEventManager; +import org.junit.jupiter.api.extension.*; + +import javax.jms.JMSException; +import java.net.MalformedURLException; +import java.net.URL; + +public class GlobalSuiteExtension implements BeforeAllCallback, AfterAllCallback { + + private static boolean initialized = false; + protected static TestEventManager testEventManager = TestEventManager.getInstance(); + public static LocalActiveMQBroker broker; + public static EmbeddedHttpServer server; + public static HttpServerConfiguration httpServerConfiguration; + public static MessageBus messageBus; + private MessageReceiverManager receiverManager; + protected static String alarmDestinationID; + protected static MessageReceiver alarmReceiver; + protected static SecurityManager securityManager; + protected static Settings settingsForCUT; + protected static Settings settingsForTestClient; + protected static String collectionID; + protected String NON_DEFAULT_FILE_ID; + protected static String DEFAULT_FILE_ID; + protected static URL DEFAULT_FILE_URL; + protected static String DEFAULT_DOWNLOAD_FILE_ADDRESS; + protected static String DEFAULT_UPLOAD_FILE_ADDRESS; + protected String DEFAULT_AUDIT_INFORMATION; + protected String testMethodName; + + @Override + public void beforeAll(ExtensionContext context) { + if (!initialized) { + initialized = true; + settingsForCUT = loadSettings(getComponentID()); + settingsForTestClient = loadSettings("TestSuiteInitialiser"); + makeUserSpecificSettings(settingsForCUT); + makeUserSpecificSettings(settingsForTestClient); + httpServerConfiguration = new HttpServerConfiguration(settingsForTestClient.getReferenceSettings().getFileExchangeSettings()); + collectionID = settingsForTestClient.getCollections().get(0).getID(); + + securityManager = createSecurityManager(); + DEFAULT_FILE_ID = "DefaultFile"; + try { + DEFAULT_FILE_URL = httpServerConfiguration.getURL(TestFileHelper.DEFAULT_FILE_ID); + DEFAULT_DOWNLOAD_FILE_ADDRESS = DEFAULT_FILE_URL.toExternalForm(); + DEFAULT_UPLOAD_FILE_ADDRESS = DEFAULT_FILE_URL.toExternalForm() + "-" + DEFAULT_FILE_ID; + } catch (MalformedURLException e) { + throw new RuntimeException("Never happens"); + } + } + } + + @Override + public void afterAll(ExtensionContext context) { + if (initialized) { + teardownMessageBus(); + teardownHttpServer(); + } + } + + /** + * May be extended by subclasses needing to have their receivers managed. Remember to still call + * super.registerReceivers() when overriding + */ + protected void registerMessageReceivers() { + alarmReceiver = new MessageReceiver(settingsForCUT.getAlarmDestination(), testEventManager); + addReceiver(alarmReceiver); + } + + protected void addReceiver(MessageReceiver receiver) { + receiverManager.addReceiver(receiver); + } + protected void initializeCUT() {} + + /** + * Purges all messages from the receivers. + */ + protected void clearReceivers() { + receiverManager.clearMessagesInReceivers(); + } + + /** + * May be overridden by specific tests wishing to do stuff. Remember to call super if this is overridden. + */ + protected void shutdownCUT() {} + + /** + * Initializes the settings. Will postfix the alarm and collection topics with '-${user.name} + */ + protected void setupSettings() { + settingsForCUT = loadSettings(getComponentID()); + makeUserSpecificSettings(settingsForCUT); + SettingsUtils.initialize(settingsForCUT); + + alarmDestinationID = settingsForCUT.getRepositorySettings().getProtocolSettings().getAlarmDestination(); + + settingsForTestClient = loadSettings(testMethodName); + makeUserSpecificSettings(settingsForTestClient); + } + + + protected Settings loadSettings(String componentID) { + return TestSettingsProvider.reloadSettings(componentID); + } + + private void makeUserSpecificSettings(Settings settings) { + settings.getRepositorySettings().getProtocolSettings() + .setCollectionDestination(settings.getCollectionDestination() + getTopicPostfix()); + settings.getRepositorySettings().getProtocolSettings().setAlarmDestination(settings.getAlarmDestination() + getTopicPostfix()); + } + + /** + * Indicated whether an embedded active MQ should be started and used + */ + public boolean useEmbeddedMessageBus() { + return System.getProperty("useEmbeddedMessageBus", "true").equals("true"); + } + + /** + * Indicated whether an embedded http server should be started and used + */ + public boolean useEmbeddedHttpServer() { + return System.getProperty("useEmbeddedHttpServer", "false").equals("true"); + } + + /** + * Hooks up the message bus. + */ + protected void setupMessageBus() { + if (useEmbeddedMessageBus()) { + if (messageBus == null) { + messageBus = new SimpleMessageBus(); + } + } + } + + /** + * Shutdown the message bus. + */ + private void teardownMessageBus() { + MessageBusManager.clear(); + if (messageBus != null) { + try { + messageBus.close(); + messageBus = null; + } catch (JMSException e) { + throw new RuntimeException(e); + } + } + + if (broker != null) { + try { + broker.stop(); + broker = null; + } catch (Exception e) { + // No reason to pollute the test output with this + } + } + } + + /** + * Shutdown the embedded http server if any. + */ + protected void teardownHttpServer() { + if (useEmbeddedHttpServer()) { + server.stop(); + } + } + + /** + * Returns the postfix string to use when accessing user specific topics, which is the mechanism we use in the + * bit repository tests. + * + * @return The string to postfix all topix names with. + */ + protected String getTopicPostfix() { + return "-" + System.getProperty("user.name"); + } + + protected String getComponentID() { + return getClass().getSimpleName(); + } + + protected String createDate() { + return Long.toString(System.currentTimeMillis()); + } + + protected SecurityManager createSecurityManager() { + return new DummySecurityManager(); + } + +} \ No newline at end of file diff --git a/bitrepository-core/src/test/java/org/bitrepository/protocol/IntegrationTest.java b/bitrepository-core/src/test/java/org/bitrepository/protocol/IntegrationTest.java index ece1da863..2d9c82ff4 100644 --- a/bitrepository-core/src/test/java/org/bitrepository/protocol/IntegrationTest.java +++ b/bitrepository-core/src/test/java/org/bitrepository/protocol/IntegrationTest.java @@ -81,6 +81,10 @@ public abstract class IntegrationTest extends ExtendedTestCase { @BeforeSuite(alwaysRun = true) public void initializeSuite(ITestContext testContext) { + // + } + + private void initializationMethod() { settingsForCUT = loadSettings(getComponentID()); settingsForTestClient = loadSettings("TestSuiteInitialiser"); makeUserSpecificSettings(settingsForCUT); @@ -114,6 +118,7 @@ protected void addReceiver(MessageReceiver receiver) { @BeforeClass(alwaysRun = true) public void initMessagebus() { + initializationMethod(); setupMessageBus(); } diff --git a/bitrepository-core/src/test/java/org/bitrepository/protocol/bus/ActiveMQMessageBusTest.java b/bitrepository-core/src/test/java/org/bitrepository/protocol/bus/ActiveMQMessageBusTest.java index d5b9bf884..6b284a415 100644 --- a/bitrepository-core/src/test/java/org/bitrepository/protocol/bus/ActiveMQMessageBusTest.java +++ b/bitrepository-core/src/test/java/org/bitrepository/protocol/bus/ActiveMQMessageBusTest.java @@ -8,12 +8,12 @@ * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 2.1 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 General Lesser Public License for more details. - * + * * You should have received a copy of the GNU General Lesser Public * License along with this program. If not, see * . @@ -27,7 +27,9 @@ import org.bitrepository.protocol.ProtocolComponentFactory; import org.bitrepository.protocol.activemq.ActiveMQMessageBus; import org.bitrepository.protocol.message.ExampleMessageFactory; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; import javax.jms.Message; import javax.jms.MessageListener; @@ -36,14 +38,7 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; -import static org.testng.Assert.assertEquals; - -/** - * Runs the GeneralMessageBusTest using a LocalActiveMQBroker (if useEmbeddedMessageBus is true) and a suitable - * MessageBus based on settingsForTestClient. Regression tests utilized that uses JAccept to generate reports. - */ - -public class ActiveMQMessageBusTest extends GeneralMessageBusTest { +public class ActiveMQMessageBusTest extends GeneralMessageBusTest { // Assuming it extends a base class @Override protected void setupMessageBus() { @@ -53,10 +48,10 @@ protected void setupMessageBus() { } messageBus = new MessageBusWrapper(ProtocolComponentFactory.getInstance().getMessageBus( settingsForTestClient, securityManager), testEventManager); - } - @Test(groups = {"regressiontest"}) + @Test + @Tag("regressiontest") public final void collectionFilterTest() throws Exception { addDescription("Test that message bus filters identify requests to other collection, eg. ignores these."); addStep("Send an identify request with a undefined 'Collection' header property, " + @@ -90,7 +85,8 @@ public final void collectionFilterTest() throws Exception { collectionReceiver.checkNoMessageIsReceived(IdentifyPillarsForDeleteFileRequest.class); } - @Test(groups = {"regressiontest"}) + @Test + @Tag("regressiontest") public final void sendMessageToSpecificComponentTest() throws Exception { addDescription("Test that message bus correct uses the 'to' header property to indicated that the message " + "is meant for a specific component"); @@ -113,10 +109,11 @@ public void onMessage(Message message) { messageToSend.setTo(receiverID); messageBus.sendMessage(messageToSend); Message receivedMessage = messageList.poll(3, TimeUnit.SECONDS); - assertEquals(receivedMessage.getStringProperty(ActiveMQMessageBus.MESSAGE_TO_KEY), receiverID); + Assertions.assertEquals(receivedMessage.getStringProperty(ActiveMQMessageBus.MESSAGE_TO_KEY), receiverID); // Assertion update } - @Test(groups = {"regressiontest"}) + @Test + @Tag("regressiontest") public final void toFilterTest() throws Exception { addDescription("Test that message bus filters identify requests to other components, eg. ignores these."); addStep("Send an identify request with a undefined 'To' header property, " + @@ -174,4 +171,4 @@ public final void toFilterTest() throws Exception { rawMessagebus.sendMessage(settingsForTestClient.getCollectionDestination(), rq); collectionReceiver.waitForMessage(DeleteFileRequest.class); } -} +} \ No newline at end of file diff --git a/bitrepository-core/src/test/java/org/bitrepository/protocol/performancetest/MessageBusNumberOfListenersStressTest.java b/bitrepository-core/src/test/java/org/bitrepository/protocol/performancetest/MessageBusNumberOfListenersStressTest.java index 066c4eb50..696098426 100644 --- a/bitrepository-core/src/test/java/org/bitrepository/protocol/performancetest/MessageBusNumberOfListenersStressTest.java +++ b/bitrepository-core/src/test/java/org/bitrepository/protocol/performancetest/MessageBusNumberOfListenersStressTest.java @@ -39,9 +39,13 @@ import org.bitrepository.protocol.security.SecurityManager; import org.bitrepository.settings.repositorysettings.MessageBusConfiguration; import org.jaccept.structure.ExtendedTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; import org.testng.Assert; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; +//import org.testng.Assert; +//import org.testng.annotations.BeforeMethod; +//import org.testng.annotations.Test; import java.io.File; import java.io.FileOutputStream; @@ -110,7 +114,7 @@ public class MessageBusNumberOfListenersStressTest extends ExtendedTestCase { private static boolean sendMoreMessages = true; private Settings settings; - @BeforeMethod + @BeforeEach public void initializeSettings() { settings = TestSettingsProvider.getSettings(getClass().getSimpleName()); } @@ -121,7 +125,8 @@ public void initializeSettings() { * * @throws Exception Can possibly throw an exception. */ - @Test(groups = {"StressTest"}) + @Test + @Tag("StressTest") public void testManyListenersOnLocalMessageBus() throws Exception { addDescription("Tests how many messages can be handled within a given timeframe when a given number of " + "listeners are receiving them."); @@ -155,7 +160,8 @@ public void testManyListenersOnLocalMessageBus() throws Exception { } } - @Test(groups = {"StressTest"}) + @Test + @Tag("StressTest") public void testManyListenersOnDistributedMessageBus() throws Exception { addDescription("Tests how many messages can be handled within a given timeframe when a given number of " + "listeners are receiving them."); diff --git a/pom.xml b/pom.xml index d74adb031..de63482f3 100644 --- a/pom.xml +++ b/pom.xml @@ -173,13 +173,50 @@ runtime + + org.glassfish.jaxb + jaxb-runtime + 2.3.6 + runtime + + + + + + + + + + org.mockito + mockito-junit-jupiter + 5.12.0 + test + + + org.junit.jupiter + junit-jupiter + 5.10.3 + test + + + + org.slf4j + jul-to-slf4j + ${slf4j.version} + + org.testng testng 7.1.0 test - + + org.junit.platform + junit-platform-suite-engine + 1.10.3 + test + org.mockito mockito-core 3.3.3 @@ -415,33 +452,33 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.1.0 + 3.4.5 org.apache.maven.plugins maven-checkstyle-plugin - 3.1.1 + 3.6.0 sonarCheckstyle.xml - - com.github.spotbugs - spotbugs-maven-plugin - 4.0.0 - - false - - + + + + + + + + org.jacoco jacoco-maven-plugin - 0.8.5 + 0.8.12 org.apache.maven.plugins maven-pmd-plugin - 3.13.0 + 3.26.0 From 7ec116cc80e60d2c2e5f3f52920e5d6dc73f31bc Mon Sep 17 00:00:00 2001 From: kaah Date: Tue, 16 Dec 2025 11:41:09 +0100 Subject: [PATCH 2/2] Changes due to PR --- .../protocol/GlobalSuiteExtension.java | 2 +- pom.xml | 61 +++++++------------ 2 files changed, 22 insertions(+), 41 deletions(-) diff --git a/bitrepository-core/src/test/java/org/bitrepository/protocol/GlobalSuiteExtension.java b/bitrepository-core/src/test/java/org/bitrepository/protocol/GlobalSuiteExtension.java index 8b8754b74..886419ac8 100644 --- a/bitrepository-core/src/test/java/org/bitrepository/protocol/GlobalSuiteExtension.java +++ b/bitrepository-core/src/test/java/org/bitrepository/protocol/GlobalSuiteExtension.java @@ -61,7 +61,7 @@ public void beforeAll(ExtensionContext context) { DEFAULT_DOWNLOAD_FILE_ADDRESS = DEFAULT_FILE_URL.toExternalForm(); DEFAULT_UPLOAD_FILE_ADDRESS = DEFAULT_FILE_URL.toExternalForm() + "-" + DEFAULT_FILE_ID; } catch (MalformedURLException e) { - throw new RuntimeException("Never happens"); + throw new RuntimeException("Never happens", e); } } } diff --git a/pom.xml b/pom.xml index de63482f3..16992397f 100644 --- a/pom.xml +++ b/pom.xml @@ -173,37 +173,18 @@ runtime - - org.glassfish.jaxb - jaxb-runtime - 2.3.6 - runtime - - - - - - - - - - org.mockito - mockito-junit-jupiter - 5.12.0 - test - - - org.junit.jupiter - junit-jupiter - 5.10.3 - test - - - - org.slf4j - jul-to-slf4j - ${slf4j.version} - + + org.mockito + mockito-junit-jupiter + 5.12.0 + test + + + org.junit.jupiter + junit-jupiter + 5.10.3 + test + org.testng @@ -462,14 +443,14 @@ sonarCheckstyle.xml - - - - - - - - + + com.github.spotbugs + spotbugs-maven-plugin + 4.0.0 + + false + + org.jacoco jacoco-maven-plugin @@ -478,7 +459,7 @@ org.apache.maven.plugins maven-pmd-plugin - 3.26.0 + 3.28.0