diff --git a/pom.xml b/pom.xml index 3aa710e5..e57b1aa9 100644 --- a/pom.xml +++ b/pom.xml @@ -233,6 +233,12 @@ + + + src/main/resources + true + + diff --git a/src/main/java/com/lpvs/LicensePreValidationService.java b/src/main/java/com/lpvs/LicensePreValidationService.java index 8cb02330..63d5a3e2 100644 --- a/src/main/java/com/lpvs/LicensePreValidationService.java +++ b/src/main/java/com/lpvs/LicensePreValidationService.java @@ -7,12 +7,12 @@ package com.lpvs; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @@ -32,7 +32,7 @@ public class LicensePreValidationService { /** * The core pool size for the asynchronous task executor. */ - private final int corePoolSize; + private static int corePoolSize = 8; /** * The exit handler for handling application exits. @@ -40,12 +40,12 @@ public class LicensePreValidationService { private static LPVSExitHandler exitHandler; /** - * Constructs a new LicensePreValidationService with the specified core pool size. + * Creates a new instance of {@link SpringApplication} configured to run the {@link LicensePreValidationService} class. * - * @param corePoolSize The core pool size for the asynchronous task executor. + * @return a new instance of {@link SpringApplication} */ - public LicensePreValidationService(@Value("${lpvs.cores:8}") int corePoolSize) { - this.corePoolSize = corePoolSize; + protected SpringApplication createSpringApplication() { + return new SpringApplication(LicensePreValidationService.class); } /** @@ -54,10 +54,25 @@ public LicensePreValidationService(@Value("${lpvs.cores:8}") int corePoolSize) { * @param args The command-line arguments passed to the application. */ public static void main(String[] args) { + new LicensePreValidationService().run(args); + } + + /** + * Runs the {@link LicensePreValidationService} application with the specified command-line arguments. + * + * @param args the command-line arguments to pass to the application + */ + public void run(String[] args) { + SpringApplication app = createSpringApplication(); + app.addInitializers( + applicationContext -> { + ConfigurableEnvironment environment = applicationContext.getEnvironment(); + String version = environment.getProperty("lpvs.version", "Unknown"); + log.info(getEmblem(version)); + corePoolSize = Integer.parseInt(environment.getProperty("lpvs.cores", "8")); + }); try { - log.info(getEmblem()); - ApplicationContext applicationContext = - SpringApplication.run(LicensePreValidationService.class, args); + ApplicationContext applicationContext = app.run(args); exitHandler = applicationContext.getBean(LPVSExitHandler.class); } catch (IllegalArgumentException e) { log.error("An IllegalArgumentException occurred: " + e.getMessage()); @@ -92,33 +107,21 @@ public TaskExecutor getAsyncExecutor() { * * @return the emblem as a String */ - protected static String getEmblem() { - StringBuilder emblem = new StringBuilder(); - emblem.append("\n"); - emblem.append( - " .----------------. .----------------. .----------------. .----------------. \n"); - emblem.append( - " | .--------------. | | .--------------. | | .--------------. | | .--------------. |\n"); - emblem.append( - " | | _____ | | | | ______ | | | | ____ ____ | | | | _______ | |\n"); - emblem.append( - " | | |_ _| | | | | |_ __ \\ | | | ||_ _| |_ _| | | | | / ___ | | |\n"); - emblem.append( - " | | | | | | | | | |__) | | | | | \\ \\ / / | | | | | (__ \\_| | |\n"); - emblem.append( - " | | | | _ | | | | | ___/ | | | | \\ \\ / / | | | | '.___`-. | |\n"); - emblem.append( - " | | _| |__/ | | | | | _| |_ | | | | \\ ' / | | | | |`\\____) | | |\n"); - emblem.append( - " | | |________| | | | | |_____| | | | | \\_/ | | | | |_______.' | |\n"); - emblem.append( - " | | | | | | | | | | | | | | | |\n"); - emblem.append( - " | '--------------' | | '--------------' | | '--------------' | | '--------------' |\n"); - emblem.append( - " '----------------' '----------------' '----------------' '----------------' \n"); - emblem.append( - " :: License Pre-Validation Service :: (v1.5.2)\n"); - return emblem.toString(); + protected static String getEmblem(String version) { + return "\n" + + " .----------------. .----------------. .----------------. .----------------. \n" + + " | .--------------. | | .--------------. | | .--------------. | | .--------------. |\n" + + " | | _____ | | | | ______ | | | | ____ ____ | | | | _______ | |\n" + + " | | |_ _| | | | | |_ __ \\ | | | ||_ _| |_ _| | | | | / ___ | | |\n" + + " | | | | | | | | | |__) | | | | | \\ \\ / / | | | | | (__ \\_| | |\n" + + " | | | | _ | | | | | ___/ | | | | \\ \\ / / | | | | '.___`-. | |\n" + + " | | _| |__/ | | | | | _| |_ | | | | \\ ' / | | | | |`\\____) | | |\n" + + " | | |________| | | | | |_____| | | | | \\_/ | | | | |_______.' | |\n" + + " | | | | | | | | | | | | | | | |\n" + + " | '--------------' | | '--------------' | | '--------------' | | '--------------' |\n" + + " '----------------' '----------------' '----------------' '----------------' \n" + + " :: License Pre-Validation Service :: (v " + + version + + ")\n"; } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8f7e981e..b5986903 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -33,6 +33,8 @@ github.secret=LPVS lpvs.cores=8 # Number of scan attempts lpvs.attempts=4 +# Version of LPVS application (used for versioning) +lpvs.version=@project.version@ # DB Configuration # The name of DB schema diff --git a/src/test/java/com/lpvs/LicensePreValidationServiceTest.java b/src/test/java/com/lpvs/LicensePreValidationServiceTest.java index 87ce7f56..4e28bcab 100644 --- a/src/test/java/com/lpvs/LicensePreValidationServiceTest.java +++ b/src/test/java/com/lpvs/LicensePreValidationServiceTest.java @@ -7,141 +7,130 @@ package com.lpvs; import com.lpvs.util.LPVSExitHandler; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.MockedConstruction; -import org.mockito.MockedStatic; -import org.mockito.Mockito; +import org.mockito.*; import org.springframework.boot.SpringApplication; +import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import java.lang.reflect.Field; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; +import static org.mockito.Mockito.verify; public class LicensePreValidationServiceTest { - final int testNumCores = 42; + LicensePreValidationService licensePreValidationService; - private MockedStatic mockedStatic; + @Mock SpringApplication springApplication; - @BeforeEach - void setUp() { - licensePreValidationService = new LicensePreValidationService(42); - mockedStatic = Mockito.mockStatic(SpringApplication.class); - } - - @AfterEach - public void tearDown() { - if (mockedStatic != null) { - mockedStatic.close(); - } - } + @Mock ConfigurableApplicationContext applicationContext; - @Test - public void testGetAsyncExecutor() { - try (MockedConstruction mocked = - mockConstruction(ThreadPoolTaskExecutor.class)) { - TaskExecutor executor = licensePreValidationService.getAsyncExecutor(); - - assertEquals(1, mocked.constructed().size()); - ThreadPoolTaskExecutor mocked_constructed_executor = mocked.constructed().get(0); + @Mock LPVSExitHandler exitHandler; - // main assert - assertEquals(executor, mocked_constructed_executor); + String[] args = new String[0]; - verify(mocked_constructed_executor, times(1)).setCorePoolSize(testNumCores); - verify(mocked_constructed_executor, times(1)).setThreadNamePrefix("LPVS::"); - verifyNoMoreInteractions(mocked_constructed_executor); - } + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + licensePreValidationService = + new LicensePreValidationService() { + @Override + protected SpringApplication createSpringApplication() { + return springApplication; + } + }; + doNothing().when(springApplication).addInitializers(any()); + when(springApplication.run()).thenReturn(applicationContext); } @Test public void testMain() { - ConfigurableApplicationContext applicationContext = - Mockito.mock(ConfigurableApplicationContext.class); - LPVSExitHandler exitHandler = Mockito.mock(LPVSExitHandler.class); - String[] args = new String[0]; - - mockedStatic - .when(() -> SpringApplication.run(LicensePreValidationService.class, args)) - .thenReturn(applicationContext); Mockito.when(applicationContext.getBean(LPVSExitHandler.class)).thenReturn(exitHandler); - LicensePreValidationService.main(args); + licensePreValidationService.run(args); Mockito.verify(applicationContext).getBean(LPVSExitHandler.class); } @Test - public void testMain_IllegalAccessException_N() - throws NoSuchFieldException, IllegalAccessException { - ConfigurableApplicationContext applicationContext = - Mockito.mock(ConfigurableApplicationContext.class); - LPVSExitHandler exitHandler = Mockito.mock(LPVSExitHandler.class); - String[] args = new String[0]; - - mockedStatic - .when(() -> SpringApplication.run(LicensePreValidationService.class, args)) - .thenReturn(applicationContext); - - Field exitHandlerField = LicensePreValidationService.class.getDeclaredField("exitHandler"); - exitHandlerField.setAccessible(true); - exitHandlerField.set(null, exitHandler); - - Mockito.doThrow(new IllegalArgumentException("Test IllegalArgumentException")) - .when(applicationContext) - .getBean(LPVSExitHandler.class); - LicensePreValidationService.main(args); + public void testMain_IllegalAccessException_N() { + when(applicationContext.getBean(LPVSExitHandler.class)) + .thenReturn(exitHandler) + .thenThrow(new IllegalArgumentException("Test IllegalArgumentException")); + licensePreValidationService.run(args); // First call - initialize exitHandler + licensePreValidationService.run(args); // Second call - IllegalAccessException + Mockito.verify(applicationContext, Mockito.times(2)).getBean(LPVSExitHandler.class); Mockito.verify(exitHandler, Mockito.times(1)).exit(anyInt()); } @Test - public void testMain_IllegalAccessException_ExitHandlerIsNull_N() { - ConfigurableApplicationContext applicationContext = - Mockito.mock(ConfigurableApplicationContext.class); - LPVSExitHandler exitHandler = Mockito.mock(LPVSExitHandler.class); - String[] args = new String[0]; - - mockedStatic - .when(() -> SpringApplication.run(LicensePreValidationService.class, args)) - .thenReturn(applicationContext); - - Mockito.doThrow(new IllegalArgumentException("Test IllegalArgumentException")) + public void testMain_Exception_N() throws NoSuchFieldException, IllegalAccessException { + Mockito.doThrow(new RuntimeException("Test RuntimeException")) .when(applicationContext) .getBean(LPVSExitHandler.class); - LicensePreValidationService.main(args); + licensePreValidationService.run(args); Mockito.verify(exitHandler, Mockito.times(0)).exit(anyInt()); } @Test - public void testMain_Exception_N() throws NoSuchFieldException, IllegalAccessException { - ConfigurableApplicationContext applicationContext = - Mockito.mock(ConfigurableApplicationContext.class); - LPVSExitHandler exitHandler = Mockito.mock(LPVSExitHandler.class); - String[] args = new String[0]; + public void testAddInitializers() { + ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + PrintStream originalOut = System.out; + System.setOut(new PrintStream(outContent)); - mockedStatic - .when(() -> SpringApplication.run(LicensePreValidationService.class, args)) - .thenReturn(applicationContext); + Mockito.when(applicationContext.getBean(LPVSExitHandler.class)).thenReturn(exitHandler); + ArgumentCaptor> captor = + ArgumentCaptor.forClass(ApplicationContextInitializer.class); + ConfigurableEnvironment env = mock(ConfigurableEnvironment.class); + when(applicationContext.getEnvironment()).thenReturn(env); + when(env.getProperty("lpvs.cores", "8")).thenReturn("8"); + when(env.getProperty("lpvs.version", "Unknown")).thenReturn("1.0.0"); - Field exitHandlerField = LicensePreValidationService.class.getDeclaredField("exitHandler"); - exitHandlerField.setAccessible(true); - exitHandlerField.set(null, exitHandler); + licensePreValidationService.run(args); - Mockito.doThrow(new RuntimeException("Test RuntimeException")) - .when(applicationContext) - .getBean(LPVSExitHandler.class); - LicensePreValidationService.main(args); - Mockito.verify(exitHandler, Mockito.times(0)).exit(anyInt()); + verify(springApplication).addInitializers(captor.capture()); + + ApplicationContextInitializer initializer = + captor.getValue(); + initializer.initialize(applicationContext); + + assertTrue(outContent.toString().contains("1.0.0")); + System.setOut(originalOut); + } + + @Test + public void testCreateSpringApplication() { + LicensePreValidationService service = new LicensePreValidationService(); + SpringApplication springApplication = service.createSpringApplication(); + assertNotNull(springApplication); + } + + @Test + public void testGetAsyncExecutor() { + try (MockedConstruction mocked = + mockConstruction(ThreadPoolTaskExecutor.class)) { + LicensePreValidationService lpvs = new LicensePreValidationService(); + TaskExecutor executor = lpvs.getAsyncExecutor(); + + assertEquals(1, mocked.constructed().size()); + ThreadPoolTaskExecutor mocked_constructed_executor = mocked.constructed().get(0); + + assertEquals(executor, mocked_constructed_executor); + verify(mocked_constructed_executor, times(1)).setCorePoolSize(8); + verify(mocked_constructed_executor, times(1)).setThreadNamePrefix("LPVS::"); + verifyNoMoreInteractions(mocked_constructed_executor); + } } @Test public void testGetEmblem() { - String emblem = LicensePreValidationService.getEmblem(); + String emblem = LicensePreValidationService.getEmblem("test"); assertNotNull(emblem); + assertTrue(emblem.contains("test")); } }