diff --git a/appserver/tests/pom.xml b/appserver/tests/pom.xml index b414f050c59..06cb2208138 100755 --- a/appserver/tests/pom.xml +++ b/appserver/tests/pom.xml @@ -54,6 +54,11 @@ pom GlassFish Tests related modules + + test-micro-jar + + + ci diff --git a/appserver/tests/test-micro-jar/README.md b/appserver/tests/test-micro-jar/README.md new file mode 100644 index 00000000000..095b556e133 --- /dev/null +++ b/appserver/tests/test-micro-jar/README.md @@ -0,0 +1,27 @@ +# Payara Micro Jar Based Integration Tests + +This module provides plain JUnit tests that use `payara-micro.jar` as only +compile and runtime dependency (+ junit itself). + +The setup makes sure the actual delivery is tested and keeps the setup simple +and minimal. Tests do the programmtic equivalent of: + + java -jar payara-micro.jar + +The `payara-micro.jar` is referenced using a relative path to the module that +generates the jar. Should the jar not exist run: + + cd $PAYARA_HOME/appserver/extras/payara-micro/payara-micro-distribution + mvn install + +Depending on the status of the build artifacts a full build might be required. + +Except from being dependent on a generated jar file the tests in this module +are plain old JUnit tests that can be run using `mvn integration-test` +(or `mvn verify`) or in the IDE as every other JUnit tests. + +While this takes full advantage of the simplicity Payara Micro has to offer for +the user it comes with the downside of not having further APIs and internals +available at compile time. +Instead reflection has to be used if internal should be verified. +This module offers the `BeanProxy` utility class to ease reflection usage. diff --git a/appserver/tests/test-micro-jar/pom.xml b/appserver/tests/test-micro-jar/pom.xml new file mode 100644 index 00000000000..d4f6d56d56e --- /dev/null +++ b/appserver/tests/test-micro-jar/pom.xml @@ -0,0 +1,122 @@ + + + + + 4.0.0 + + org.glassfish.main.tests + tests + 5.191-SNAPSHOT + ../pom.xml + + + test-micro-jar + + Integration Tests based on payara-micro.jar file + NOTE: this module is dependent on the payara-micro-distribution being run previously + but it cannot have a dependency on this module as this would mess up the classpath for test execution + as some classes get in from the modules that have to be taken only from the generated jar file. + + The idea is to test the actual artifact created. + This is not suitable for all kinds of tests as the accessible API is the minumal payara micro API. + + + + + + fish.payara.extras + payara-micro + ${project.version} + pom + + + junit + junit + test + + + + fish.payara.extras + payara-micro-jar + as-is-on-disk + system + ${project.basedir}/../../extras/payara-micro/payara-micro-distribution/target/payara-micro.jar + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*.class + + fish.payara.test.util.IntegrationTest + + + + org.apache.maven.plugins + maven-failsafe-plugin + + fish.payara.test.util.IntegrationTest + + + + + integration-test + verify + + + + **/*.class + + + + + + + + diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/AsAdminIntegrationTest.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/AsAdminIntegrationTest.java new file mode 100644 index 00000000000..972401e98fc --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/AsAdminIntegrationTest.java @@ -0,0 +1,201 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.admin.cli; + +import static fish.payara.micro.ClusterCommandResult.ExitStatus.FAILURE; +import static fish.payara.micro.ClusterCommandResult.ExitStatus.SUCCESS; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; +import org.junit.experimental.categories.Category; + +import fish.payara.micro.ClusterCommandResult; +import fish.payara.micro.ClusterCommandResult.ExitStatus; +import fish.payara.test.util.IntegrationTest; +import fish.payara.test.util.PayaraMicroServer; + +@Category(IntegrationTest.class) +public abstract class AsAdminIntegrationTest { + + private static final String UNSATISFIED_DEPENDENCY_EXCEPTION_CLASS_NAME = + "org.jvnet.hk2.config.UnsatisfiedDependencyException"; + private static final String UNACCEPTABLE_VALUE_EXCEPTION_CLASS_NAME = + "org.glassfish.common.util.admin.UnacceptableValueException"; + + protected final PayaraMicroServer server = PayaraMicroServer.DEFAULT; + + @Before + public void serverSetUp() throws Exception { + server.start(); + } + + @After + public void serverTearDown() { + server.stop(); + } + + protected static void assertUnchanged(boolean expected, boolean actual) { + assertEquals(Boolean.valueOf(expected), Boolean.valueOf(actual)); + } + + protected static void assertContains(String expected, String actual) { + assertThat(actual, CoreMatchers.containsString(expected)); + } + + protected static void assertSuccess(ClusterCommandResult result) { + ExitStatus actual = result.getExitStatus(); + if (SUCCESS != actual) { + String msg = result.getOutput(); + if (actual == FAILURE && result.getFailureCause() != null) { + StringWriter writer = new StringWriter(); + result.getFailureCause().printStackTrace(new PrintWriter(writer)); + msg = writer.toString(); + } + if (msg != null) { + assertEquals(msg, SUCCESS, actual); + } else { + assertEquals(SUCCESS, actual); + } + } + } + + protected static void assertFailure(ClusterCommandResult result) { + assertEquals(FAILURE, result.getExitStatus()); + } + + private static void assertStatesUsage(ClusterCommandResult result) { + assertTrue("No usage was given.", result.getOutput().contains("Usage: ")); + } + + protected final void assertMissingParameter(String name, ClusterCommandResult result) { + assertFailure(result); + Class expectedExceptionType = server.getClass(UNSATISFIED_DEPENDENCY_EXCEPTION_CLASS_NAME); + Throwable cause = result.getFailureCause(); + assertNotNull(cause); + assertTrue("Error is not caused by a missing parameter but " + cause.getClass().getName(), + expectedExceptionType.isAssignableFrom(cause.getClass())); + String text = result.getOutput(); + int afterName = text.indexOf(" with class "); + int beforeName = text.substring(0, afterName).lastIndexOf('.'); + String actualName = text.substring(beforeName + 1, afterName); + assertEquals("Error was about another parameter", name, actualName); + assertStatesUsage(result); + } + + protected final void assertUnacceptableParameter(String name, ClusterCommandResult result) { + assertFailure(result); + Class expectedExceptionType = server.getClass(UNACCEPTABLE_VALUE_EXCEPTION_CLASS_NAME); + Throwable cause = result.getFailureCause(); + assertNotNull(cause); + assertTrue("Error is not caused by a unacceptable parameter but " + cause.getClass().getName(), + expectedExceptionType.isAssignableFrom(cause.getClass())); + String text = result.getOutput(); + try { + assertContains("Invalid parameter: " + name, text); + } catch (AssertionError e) { + assertContains("on parameter [ "+name+" ]", text); + } + assertStatesUsage(result); + } + + /** + * Runs an as-admin command on the {@link #server} + */ + protected final ClusterCommandResult asadmin(String command, String...args) { + return new PlainClusterCommandResult(server.getInstance().executeLocalAsAdmin(command, args)); + } + + protected final Class getClass(String name) { + return server.getClass(name); + } + + protected final T getExtensionByType(String target, Class type) { + return server.getExtensionByType(target, type); + } + + private static final class PlainClusterCommandResult implements ClusterCommandResult { + + final ClusterCommandResult wrapped; + + public PlainClusterCommandResult(ClusterCommandResult wrapped) { + this.wrapped = wrapped; + } + + @Override + public ExitStatus getExitStatus() { + return wrapped.getExitStatus(); + } + + @Override + public Throwable getFailureCause() { + return wrapped.getFailureCause(); + } + + @Override + public String getOutput() { + String output = wrapped.getOutput(); + if (!output.startsWith("PlainTextActionReporter")) { + return output; + } + int index = output.indexOf("SUCCESS"); + if (index < 0) { + index = output.indexOf("FAILURE"); + } + if (index > 0) { + return output.substring(index + 7); + } + return output; + } + + @Override + public String toString() { + return getExitStatus() + ": " + getOutput(); + } + } + +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/ListHealthCheckServicesTest.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/ListHealthCheckServicesTest.java new file mode 100644 index 00000000000..c15b0465fc6 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/ListHealthCheckServicesTest.java @@ -0,0 +1,67 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.admin.cli.healthcheck; + +import org.junit.Test; + +import fish.payara.admin.cli.AsAdminIntegrationTest; +import fish.payara.micro.ClusterCommandResult; + +/** + * Verifies the correctness of the {@code ListHealthCheckServices} command. + */ +public class ListHealthCheckServicesTest extends AsAdminIntegrationTest { + + @Test + public void listHealthCheckServices() { + ClusterCommandResult result = asadmin("list-healthcheck-services"); + assertSuccess(result); + String description = result.getOutput(); + assertContains("Available Health Check Services:", description); + assertContains("healthcheck-mp", description); + assertContains("healthcheck-cpu", description); + assertContains("healthcheck-gc", description); + assertContains("healthcheck-heap", description); + assertContains("healthcheck-threads", description); + assertContains("healthcheck-machinemem", description); + assertContains("healthcheck-cpool", description); + assertContains("healthcheck-stuck", description); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/SetHealthCheckConfigurationTest.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/SetHealthCheckConfigurationTest.java new file mode 100644 index 00000000000..adb3bc3cedd --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/SetHealthCheckConfigurationTest.java @@ -0,0 +1,233 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.admin.cli.healthcheck; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +import fish.payara.admin.cli.AsAdminIntegrationTest; +import fish.payara.micro.ClusterCommandResult; +import fish.payara.test.domain.healthcheck.HealthCheckService; +import fish.payara.test.domain.healthcheck.HealthCheckServiceConfiguration; +import fish.payara.test.domain.notification.Notifier; +import fish.payara.test.domain.notification.NotifierExecutionOptions; + +/** + * Verifies the correctness of the {@code SetHealthCheckConfiguration} command. + */ +public class SetHealthCheckConfigurationTest extends AsAdminIntegrationTest { + + private HealthCheckServiceConfiguration config; + private HealthCheckService service; + private Class logNotifierType; + + @Before + public void setUp() { + config = HealthCheckServiceConfiguration.from(server); + service = HealthCheckService.from(server); + logNotifierType = server.getClass(Notifier.LOG_NOTIFIER_CLASS_NAME); + } + + @Test + public void setHealthcheckConfiguration_EnabledIsMandatory() { + assertMissingParameter("enabled", asadmin("set-healthcheck-configuration")); + } + + @Test + public void setHealthcheckConfiguration_Enabled() { + boolean enabled = service.isEnabled(); + asadmin("set-healthcheck-configuration", + "--enabled", "false"); + assertFalse(config.getEnabled()); + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "true"); + assertSuccess(result); + assertEquals("log.enabled was false set to true\n", result.getOutput()); + assertTrue(config.getEnabled()); + assertUnchanged(enabled, service.isEnabled()); + result = asadmin("set-healthcheck-configuration", + "--enabled", "false"); + assertSuccess(result); + assertEquals("log.enabled was true set to false\n", result.getOutput()); + assertFalse(config.getEnabled()); + assertUnchanged(enabled, service.isEnabled()); + } + + @Test + public void setHealthcheckConfiguration_EnabledDynamic() { + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--dynamic", "true"); + assertSuccess(result); + assertTrue(service.isEnabled()); + result = asadmin("set-healthcheck-configuration", + "--enabled", "false", + "--dynamic", "true"); + assertSuccess(result); + assertFalse(service.isEnabled()); + } + + @Test + public void setHealthcheckConfiguration_EnabledAppliesToLogNotifier() { + boolean logEnabled = getLogNotifierOptions().isEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "false"); + assertSuccess(result); + Notifier logNotifier = config.getNotifierByType(logNotifierType); + assertFalse(logNotifier.getEnabled()); + assertUnchanged(logEnabled, getLogNotifierOptions().isEnabled()); + result = asadmin("set-healthcheck-configuration", + "--enabled", "true"); + assertSuccess(result); + assertTrue(logNotifier.getEnabled()); + assertUnchanged(logEnabled, getLogNotifierOptions().isEnabled()); + } + + @Test + public void setHealthcheckConfiguration_EnabledDynamicAppliesToLogNotifier() { + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "false", + "--dynamic", "true"); + assertSuccess(result); + Notifier logNotifier = config.getNotifierByType(logNotifierType); + assertFalse(logNotifier.getEnabled()); + // can't verify the active options since disabled service will not update these + result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--dynamic", "true"); + assertSuccess(result); + assertTrue(logNotifier.getEnabled()); + assertTrue(getLogNotifierOptions().isEnabled()); + } + + @Test + public void setHealthcheckConfiguration_HistoricalTraceEnabled() { + boolean historicalTraceEnabled = service.isHistoricalTraceEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--historical-trace-enabled", "false"); + assertSuccess(result); + assertUnchanged(historicalTraceEnabled, service.isHistoricalTraceEnabled()); + assertFalse(config.getHistoricalTraceEnabled()); + result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--historical-trace-enabled", "true"); + assertSuccess(result); + assertTrue(config.getHistoricalTraceEnabled()); + assertUnchanged(historicalTraceEnabled, service.isHistoricalTraceEnabled()); + } + + @Test + public void setHealthcheckConfiguration_HistoricalTraceEnabledDynamic() { + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--historical-trace-enabled", "true", + "--dynamic", "true"); + assertSuccess(result); + assertTrue(service.isHistoricalTraceEnabled()); + result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--historical-trace-enabled", "false", + "--dynamic", "true"); + assertSuccess(result); + assertFalse(service.isHistoricalTraceEnabled()); + } + + @Test + public void setHealthcheckConfiguration_HistoricalTraceStoreSize() { + Integer historicalTraceStoreSize = service.getHistoricalTraceStoreSize(); + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--historical-trace-store-size", "13"); + assertSuccess(result); + assertEquals(13, config.getHistoricalTraceStoreSize()); + assertEquals(historicalTraceStoreSize, service.getHistoricalTraceStoreSize()); + } + + @Test + public void setHealthcheckConfiguration_HistoricalTraceStoreSizeDynamic() { + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--historical-trace-store-size", "13", + "--dynamic", "true"); + assertSuccess(result); + assertEquals(13, config.getHistoricalTraceStoreSize()); + assertEquals(13, service.getHistoricalTraceStoreSize().intValue()); + } + + @Test + public void setHealthcheckConfiguration_HistoricalTraceStoreTimeout() { + Long historicalTraceStoreTimeout = service.getHistoricalTraceStoreTimeout(); + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--historical-trace-store-timeout", "42"); + assertSuccess(result); + assertEquals(42, config.getHistoricalTraceStoreTimeout()); + assertEquals(historicalTraceStoreTimeout, service.getHistoricalTraceStoreTimeout()); + } + + @Test + public void setHealthcheckConfiguration_HistoricalTraceStoreTimeoutDynamic() { + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--historical-trace-store-timeout", "42", + "--dynamic", "true"); + assertSuccess(result); + assertEquals(42, config.getHistoricalTraceStoreTimeout()); + assertEquals(42, service.getHistoricalTraceStoreTimeout().longValue()); + } + + @Test + public void setHealthcheckConfiguration_HistoricalTraceStoreSizeBelowMinimum() { + ClusterCommandResult result = asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--historical-trace-store-size", "0"); + assertUnacceptableParameter("historicalTraceStoreSize", result); + assertTrue(result.getOutput().contains("Store size must be greater than 0")); + } + + private NotifierExecutionOptions getLogNotifierOptions() { + return service.getNotifierExecutionOptions("LOG"); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/SetHealthCheckServiceConfigurationTest.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/SetHealthCheckServiceConfigurationTest.java new file mode 100644 index 00000000000..233669b68c0 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/SetHealthCheckServiceConfigurationTest.java @@ -0,0 +1,518 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.admin.cli.healthcheck; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.TimeUnit; + +import org.junit.Before; +import org.junit.Test; + +import fish.payara.admin.cli.AsAdminIntegrationTest; +import fish.payara.micro.ClusterCommandResult; +import fish.payara.test.domain.healthcheck.BaseHealthCheck; +import fish.payara.test.domain.healthcheck.Checker; +import fish.payara.test.domain.healthcheck.HealthCheckService; +import fish.payara.test.domain.healthcheck.HealthCheckServiceConfiguration; + +/** + * Verifies the correctness of the {@code SetHealthCheckServiceConfiguration} command. + */ +public class SetHealthCheckServiceConfigurationTest extends AsAdminIntegrationTest { + + private HealthCheckServiceConfiguration config; + private HealthCheckService service; + private BaseHealthCheck garbageCollection; + private BaseHealthCheck hoggingThreads; + private BaseHealthCheck stuckThreads; + + @Before + public void setUp() { + config = HealthCheckServiceConfiguration.from(server); + service = HealthCheckService.from(server); + garbageCollection = BaseHealthCheck.from(server, "GARBAGE_COLLECTOR"); + hoggingThreads = BaseHealthCheck.from(server, "HOGGING_THREADS"); + stuckThreads = BaseHealthCheck.from(server, "STUCK_THREAD"); + } + + @Test + public void setHealthCheckServiceConfiguration_EnabledIsMandatory() { + assertMissingParameter("enabled", asadmin("set-healthcheck-service-configuration", + "--service", "gc")); + } + + @Test + public void setHealthCheckServiceConfiguration_ServiceIsMandatory() { + assertMissingParameter("serviceName", asadmin("set-healthcheck-service-configuration", + "--enabled", "true")); + } + + @Test + public void setHealthCheckServiceConfiguration_ShortNames() { + String[] shortNames = { "cp", "cu", "gc", "hmu", "ht", "mmu", "st", "mh" }; + setHealthCheckServiceConfigurationNames(shortNames); + } + + @Test + public void setHealthCheckServiceConfiguration_FullNames() { + String[] fullNames = { "CONNECTION_POOL", "CPU_USAGE", "GARBAGE_COLLECTOR", "HEAP_MEMORY_USAGE", + "HOGGING_THREADS", "MACHINE_MEMORY_USAGE", "STUCK_THREAD", "MP_HEALTH" }; + setHealthCheckServiceConfigurationNames(fullNames); + } + + private void setHealthCheckServiceConfigurationNames(String[] serviceNames) { + for (String serviceName : serviceNames) { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", serviceName, + "--enabled", "true"); + assertSuccess(result); // just check the name got accepted + } + } + + @Test + public void setHealthCheckServiceConfiguration_Enabled() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true"); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertTrue(gcConfig.getEnabled()); + result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "false"); + assertFalse(gcConfig.getEnabled()); + } + + @Test + public void setHealthCheckServiceConfiguration_EnabledDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--dynamic", "true"); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + BaseHealthCheck check = service.getCheck(gcConfig.getName()); + assertNotNull(check); + assertTrue(check.isEnabled()); + result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "false", + "--dynamic", "true"); + assertFalse(check.isEnabled()); + } + + @Test + public void setHealthCheckServiceConfiguration_Time() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--time", "42"); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertEquals(42L, gcConfig.getTime().longValue()); + assertNotEquals(42L, service.getCheck(gcConfig.getName()).getTime()); + } + + @Test + public void setHealthCheckServiceConfiguration_TimeDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--time", "42", + "--dynamic", "true"); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertEquals(42L, gcConfig.getTime().longValue()); + assertEquals(42L, service.getCheck(gcConfig.getName()).getTime()); + } + + @Test + public void setHealthCheckServiceConfiguration_TimeUnitUnknownName() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--time-unit", "YEARS"); + assertUnacceptableParameter("time-unit", result); + assertContains("DAYS,HOURS,MICROSECONDS,MILLISECONDS,MINUTES,NANOSECONDS,SECONDS", result.getOutput()); + } + + @Test + public void setHealthCheckServiceConfiguration_TimeUnit() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--time-unit", TimeUnit.DAYS.name()); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertEquals(TimeUnit.DAYS, gcConfig.getUnit()); + assertNotEquals(TimeUnit.DAYS, service.getCheck(gcConfig.getName()).getUnit()); + } + + @Test + public void setHealthCheckServiceConfiguration_TimeUnitDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--time-unit", TimeUnit.HOURS.name(), + "--dynamic", "true" + ); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertEquals(TimeUnit.HOURS, gcConfig.getUnit()); + assertEquals(TimeUnit.HOURS, service.getCheck(gcConfig.getName()).getUnit()); + } + + @Test + public void setHealthCheckServiceConfiguration_HogginThreadsThresholdBelowMinumum() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "ht", + "--enabled", "true", + "--hogging-threads-threshold", "-1"); + assertUnacceptableParameter("hogginThreadsThreshold", result); + assertContains("Hogging threads threshold is a percentage so must be greater than zero", result.getOutput()); + } + + @Test + public void setHealthCheckServiceConfiguration_HogginThreadsThresholdAboveMaximum() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "ht", + "--enabled", "true", + "--hogging-threads-threshold", "101"); + assertUnacceptableParameter("hogginThreadsThreshold", result); + assertContains("Hogging threads threshold is a percentage so must be less than 100", result.getOutput()); + } + + @Test + public void setHealthCheckServiceConfiguration_HogginThreadsThreshold() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "ht", + "--enabled", "true", + "--hogging-threads-threshold", "33"); + assertSuccess(result); + Checker htConfig = config.getCheckerByType(hoggingThreads.getCheckerType()); + assertEquals(33, htConfig.getThresholdPercentage().intValue()); + assertNotEquals(Long.valueOf(33), service.getCheck(htConfig.getName()).getThresholdPercentage()); + } + + @Test + public void setHealthCheckServiceConfiguration_HogginThreadsThresholdDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "ht", + "--enabled", "true", + "--hogging-threads-threshold", "42", + "--dynamic", "true"); + assertSuccess(result); + Checker htConfig = config.getCheckerByType(hoggingThreads.getCheckerType()); + assertEquals(42, htConfig.getThresholdPercentage().intValue()); + assertEquals(Long.valueOf(42), service.getCheck(htConfig.getName()).getThresholdPercentage()); + } + + @Test + public void setHealthCheckServiceConfiguration_HogginThreadsRetryCountBelowMinimum() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "ht", + "--enabled", "true", + "--hogging-threads-retry-count", "0"); + assertUnacceptableParameter("hogginThreadsRetryCount", result); + assertContains("Hogging threads retry count must be 1 or more", result.getOutput()); + } + + @Test + public void setHealthCheckServiceConfiguration_HogginThreadsRetryCount() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "ht", + "--enabled", "true", + "--hogging-threads-retry-count", "13"); + assertSuccess(result); + Checker htConfig = config.getCheckerByType(hoggingThreads.getCheckerType()); + assertEquals(13, htConfig.getRetryCount().intValue()); + assertNotEquals(Integer.valueOf(13), service.getCheck(htConfig.getName()).getRetryCount()); + } + + @Test + public void setHealthCheckServiceConfiguration_HogginThreadsRetryCountDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "ht", + "--enabled", "true", + "--hogging-threads-retry-count", "24", + "--dynamic", "true"); + assertSuccess(result); + Checker htConfig = config.getCheckerByType(hoggingThreads.getCheckerType()); + assertEquals(24, htConfig.getRetryCount().intValue()); + assertEquals(Integer.valueOf(24), service.getCheck(htConfig.getName()).getRetryCount()); + } + + @Test + public void setHealthCheckServiceConfiguration_StuckThreadsThresholdBelowMinumum() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "st", + "--enabled", "true", + "--stuck-threads-threshold", "0"); + assertUnacceptableParameter("stuckThreadsThreshold", result); + } + + @Test + public void setHealthCheckServiceConfiguration_StuckThreadsThreshold() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "st", + "--enabled", "true", + "--stuck-threads-threshold", "13"); + assertSuccess(result); + Checker stConfig = config.getCheckerByType(stuckThreads.getCheckerType()); + assertEquals(13, stConfig.getThreshold().intValue()); + BaseHealthCheck activeService = service.getCheck(stConfig.getName()); + if (activeService != null) { + assertNotEquals(Long.valueOf(13), activeService.getTimeStuck()); + } + } + + @Test + public void setHealthCheckServiceConfiguration_StuckThreadsThresholdDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "st", + "--enabled", "true", + "--stuck-threads-threshold", "17", + "--dynamic", "true"); + assertSuccess(result); + Checker stConfig = config.getCheckerByType(stuckThreads.getCheckerType()); + assertEquals(17, stConfig.getThreshold().intValue()); + assertEquals(Long.valueOf(17), service.getCheck(stConfig.getName()).getTimeStuck()); + } + + @Test + public void setHealthCheckServiceConfiguration_StuckThreadsThresholdUnitUnknownValue() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "st", + "--enabled", "true", + "--stuck-threads-threshold-unit", "YEARS"); + assertUnacceptableParameter("stuck-threads-threshold-unit", result); + } + + @Test + public void setHealthCheckServiceConfiguration_StuckThreadsThresholdUnit() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "st", + "--enabled", "true", + "--stuck-threads-threshold-unit", TimeUnit.DAYS.name()); + assertSuccess(result); + Checker stConfig = config.getCheckerByType(stuckThreads.getCheckerType()); + assertEquals(TimeUnit.DAYS, stConfig.getThresholdTimeUnit()); + BaseHealthCheck activeService = service.getCheck(stConfig.getName()); + if (activeService != null) { + assertNotEquals(TimeUnit.DAYS, activeService.getUnitStuck()); + } + } + + @Test + public void setHealthCheckServiceConfiguration_StuckThreadsThresholdUnitDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "st", + "--enabled", "true", + "--stuck-threads-threshold-unit", TimeUnit.HOURS.name(), + "--dynamic", "true"); + assertSuccess(result); + Checker stConfig = config.getCheckerByType(stuckThreads.getCheckerType()); + assertEquals(TimeUnit.HOURS, stConfig.getThresholdTimeUnit()); + assertEquals(TimeUnit.HOURS, service.getCheck(stConfig.getName()).getUnitStuck()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdCriticalBelowMinimum() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-critical", "-1"); + assertUnacceptableParameter("thresholdCritical", result); + assertContains("Critical threshold is a percentage so must be greater than zero", result.getOutput()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdCriticalAboveMaximum() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-critical", "101"); + assertUnacceptableParameter("thresholdCritical", result); + assertContains("Critical threshold is a percentage so must be less than 100", result.getOutput()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdCritical() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-critical", "99"); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertEquals(99, gcConfig.getThresholdCritical().intValue()); + assertNotEquals(99, service.getCheck(gcConfig.getName()).getThresholdCritical()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdCriticalDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-critical", "88", + "--dynamic", "true"); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertEquals(88, gcConfig.getThresholdCritical().intValue()); + assertEquals(88, service.getCheck(gcConfig.getName()).getThresholdCritical()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdWarningBelowMinimum() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-warning", "-1"); + assertUnacceptableParameter("thresholdWarning", result); + assertContains("Warning threshold is a percentage so must be greater than zero", result.getOutput()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdWarningAboveMaximum() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-warning", "101"); + assertUnacceptableParameter("thresholdWarning", result); + assertContains("Wanring threshold is a percentage so must be less than 100", result.getOutput()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdWarning() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-warning", "99"); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertEquals(99, gcConfig.getThresholdWarning().intValue()); + assertNotEquals(99, service.getCheck(gcConfig.getName()).getThresholdWarning()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdWarningDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-warning", "88", + "--dynamic", "true"); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertEquals(88, gcConfig.getThresholdWarning().intValue()); + assertEquals(88, service.getCheck(gcConfig.getName()).getThresholdWarning()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdGoodBelowMinimum() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-good", "-1"); + assertUnacceptableParameter("thresholdGood", result); + assertContains("Good threshold is a percentage so must be greater than zero", result.getOutput()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdGoodAboveMaximum() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-good", "101"); + assertUnacceptableParameter("thresholdGood", result); + assertContains("Good threshold is a percentage so must be less than 100", result.getOutput()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdGood() { + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-good", "33"); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertEquals(33, gcConfig.getThresholdGood().intValue()); + assertNotEquals(33, service.getCheck(gcConfig.getName()).getThresholdGood()); + } + + @Test + public void setHealthCheckServiceConfiguration_ThresholdGoodDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-configuration", + "--service", "gc", + "--enabled", "true", + "--threshold-good", "22", + "--dynamic", "true"); + assertSuccess(result); + Checker gcConfig = config.getCheckerByType(garbageCollection.getCheckerType()); + assertEquals(22, gcConfig.getThresholdGood().intValue()); + assertEquals(22, service.getCheck(gcConfig.getName()).getThresholdGood()); + } + + /** + * Dynamic changes only take effect when the health check service is enabled so we make sure it is. + */ + private void ensureHealthChecksAreEnabled() { + if (service.isEnabled()) { + return; // already enabled, fine + } + assertSuccess(asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--dynamic", "true")); + } + +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/SetHealthCheckServiceNotifierConfigurationTest.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/SetHealthCheckServiceNotifierConfigurationTest.java new file mode 100644 index 00000000000..b22a0407a49 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/healthcheck/SetHealthCheckServiceNotifierConfigurationTest.java @@ -0,0 +1,186 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.admin.cli.healthcheck; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +import fish.payara.admin.cli.AsAdminIntegrationTest; +import fish.payara.micro.ClusterCommandResult; +import fish.payara.test.domain.healthcheck.HealthCheckService; +import fish.payara.test.domain.healthcheck.HealthCheckServiceConfiguration; +import fish.payara.test.domain.notification.Notifier; +import fish.payara.test.domain.notification.NotifierExecutionOptions; + +/** + * Verifies the correctness of the {@code SetHealthCheckServiceNotifierConfiguration} command. + */ +public class SetHealthCheckServiceNotifierConfigurationTest extends AsAdminIntegrationTest { + + private HealthCheckServiceConfiguration config; + private HealthCheckService service; + private Class logNotifierType; + + @Before + public void setUp() { + config = HealthCheckServiceConfiguration.from(server); + service = HealthCheckService.from(server); + logNotifierType = server.getClass(Notifier.LOG_NOTIFIER_CLASS_NAME); + } + + @Test + public void setHealthCheckServiceConfiguration_EnabledIsMandatory() { + assertMissingParameter("enabled", asadmin("set-healthcheck-service-notifier-configuration", + "--notifier", "LOG")); + } + + @Test + public void setHealthCheckServiceConfiguration_NotifierIsMandatory() { + assertMissingParameter("notifierName", asadmin("set-healthcheck-service-notifier-configuration", + "--enabled", "true")); + } + + @Test + public void setHealthCheckServiceConfiguration_NotifierNames() { + String[] names = { "LOG", "HIPCHAT", "SLACK", "JMS", "EMAIL", "XMPP", "SNMP", "EVENTBUS", "NEWRELIC", + "DATADOG", "CDIEVENTBUS" }; + for (String notiferName : names) { + ClusterCommandResult result = asadmin("set-healthcheck-service-notifier-configuration", + "--notifier", notiferName, + "--enabled", "true"); + assertSuccess(result); // just check the name got accepted + } + } + + @Test + public void setHealthCheckServiceConfiguration_Enabled() { + boolean logEnabled = getLogNotifierOptions().isEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-notifier-configuration", + "--notifier", "LOG", + "--enabled", "true"); + assertSuccess(result); + Notifier logNotifier = config.getNotifierByType(logNotifierType); + assertTrue(logNotifier.getEnabled()); + assertUnchanged(logEnabled, getLogNotifierOptions().isEnabled()); + result = asadmin("set-healthcheck-service-notifier-configuration", + "--notifier", "LOG", + "--enabled", "false"); + assertFalse(logNotifier.getEnabled()); + assertUnchanged(logEnabled, getLogNotifierOptions().isEnabled()); + } + + @Test + public void setHealthCheckServiceConfiguration_EnabledDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-notifier-configuration", + "--notifier", "LOG", + "--enabled", "true", + "--dynamic", "true"); + assertSuccess(result); + Notifier logNotifier = config.getNotifierByType(logNotifierType); + assertTrue(logNotifier.getEnabled()); + assertTrue(getLogNotifierOptions().isEnabled()); + result = asadmin("set-healthcheck-service-notifier-configuration", + "--notifier", "LOG", + "--enabled", "false", + "--dynamic", "true"); + assertFalse(logNotifier.getEnabled()); + assertFalse(getLogNotifierOptions().isEnabled()); + } + + @Test + public void setHealthCheckServiceConfiguration_Noisy() { + boolean logNoisy = getLogNotifierOptions().isNoisy(); + ClusterCommandResult result = asadmin("set-healthcheck-service-notifier-configuration", + "--notifier", "LOG", + "--enabled", "true", + "--noisy", "true"); + assertSuccess(result); + Notifier logNotifier = config.getNotifierByType(logNotifierType); + assertTrue(logNotifier.getNoisy()); + assertUnchanged(logNoisy, getLogNotifierOptions().isNoisy()); + result = asadmin("set-healthcheck-service-notifier-configuration", + "--notifier", "LOG", + "--enabled", "false", + "--noisy", "false"); + assertFalse(logNotifier.getNoisy()); + assertUnchanged(logNoisy, getLogNotifierOptions().isNoisy()); + } + + @Test + public void setHealthCheckServiceConfiguration_NoisyDynamic() { + ensureHealthChecksAreEnabled(); + ClusterCommandResult result = asadmin("set-healthcheck-service-notifier-configuration", + "--notifier", "LOG", + "--enabled", "true", + "--noisy", "true", + "--dynamic", "true"); + assertSuccess(result); + Notifier logNotifier = config.getNotifierByType(logNotifierType); + assertTrue(logNotifier.getNoisy()); + assertTrue(getLogNotifierOptions().isNoisy()); + result = asadmin("set-healthcheck-service-notifier-configuration", + "--notifier", "LOG", + "--enabled", "true", + "--noisy", "false", + "--dynamic", "true"); + assertFalse(logNotifier.getNoisy()); + assertFalse(getLogNotifierOptions().isNoisy()); + } + + private NotifierExecutionOptions getLogNotifierOptions() { + return service.getNotifierExecutionOptions("LOG"); + } + + /** + * Dynamic changes only take effect when the health check service is enabled so we make sure it is. + */ + private void ensureHealthChecksAreEnabled() { + if (service.isEnabled()) { + return; // already enabled, fine + } + assertSuccess(asadmin("set-healthcheck-configuration", + "--enabled", "true", + "--dynamic", "true")); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/network/SetHazelcastConfigurationTest.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/network/SetHazelcastConfigurationTest.java new file mode 100644 index 00000000000..47583f56771 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/admin/cli/network/SetHazelcastConfigurationTest.java @@ -0,0 +1,75 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.admin.cli.network; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +import fish.payara.admin.cli.AsAdminIntegrationTest; +import fish.payara.micro.ClusterCommandResult; +import fish.payara.test.domain.network.HazelcastRuntimeConfiguration; + +/** + * Verifies the correctness of the {@code SetHazelcastConfiguration} command. + */ +public class SetHazelcastConfigurationTest extends AsAdminIntegrationTest { + + private HazelcastRuntimeConfiguration config; + + @Before + public void setUp() { + config = HazelcastRuntimeConfiguration.from(server); + } + + @Test + public void setHazelcastConfiguration_AutoIncrementPort() { + ClusterCommandResult result = asadmin("set-hazelcast-configuration", + "--autoIncrementPort", "true"); + assertSuccess(result); + assertTrue(config.getAutoIncrementPort()); + result = asadmin("set-hazelcast-configuration", + "--autoIncrementPort", "false"); + assertSuccess(result); + assertFalse(config.getAutoIncrementPort()); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/server/properties/ShutdownGraceSystemPropertyTest.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/server/properties/ShutdownGraceSystemPropertyTest.java new file mode 100644 index 00000000000..5e0a15307c5 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/server/properties/ShutdownGraceSystemPropertyTest.java @@ -0,0 +1,75 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.server.properties; + +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import fish.payara.test.util.IntegrationTest; +import fish.payara.test.util.PayaraMicroServer; + +@Category(IntegrationTest.class) +public class ShutdownGraceSystemPropertyTest { + + /** + * The tests sets the grace period to 3 seconds. This should be long enough to notably delay shutdown but not too + * long to make test execution unnecessarily slow. + */ + @Test + public void shutdownGraceSystemPropertyHasDelayEffect() { + System.setProperty("fish.payara.shutdowngrace", "3000"); //ms + PayaraMicroServer server = PayaraMicroServer.newInstance(); + server.start(); + long beforeShutdown = System.currentTimeMillis(); + server.stop(); + long afterShutdown = System.currentTimeMillis(); + long delay = afterShutdown - beforeShutdown; + assertTrue("a grace period of at least 3 sec was expected", delay > 3000); + assertTrue("grace period should not hold shutdown much longer", delay < 5000); + } + + @After + public void clearSystemProperty() { + System.clearProperty("fish.payara.shutdowngrace"); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/BaseHealthCheck.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/BaseHealthCheck.java new file mode 100644 index 00000000000..490970b4c78 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/BaseHealthCheck.java @@ -0,0 +1,136 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.test.domain.healthcheck; + +import java.lang.annotation.Annotation; +import java.util.concurrent.TimeUnit; + +import fish.payara.test.util.BeanProxy; +import fish.payara.test.util.PayaraMicroServer; + +public class BaseHealthCheck extends BeanProxy { + + private static final String CLASS_NAME = "fish.payara.nucleus.healthcheck.preliminary.BaseHealthCheck"; + + private static final String CHECKER_CONFIGURATION_TYPE_CLASS_NAME = + "fish.payara.nucleus.healthcheck.configuration.CheckerConfigurationType"; + + public static BaseHealthCheck from(PayaraMicroServer server, String name) { + try { + @SuppressWarnings("unchecked") + Class annotationType = (Class) server.getClass(CHECKER_CONFIGURATION_TYPE_CLASS_NAME); + for (Object healthCheckService : server.getAllServices(server.getClass(CLASS_NAME))) { + BaseHealthCheck service = new BaseHealthCheck(healthCheckService); + Class checkerType = (Class) service.propertyValue("getCheckerType"); + Enum checkerTypeName = (Enum) new BeanProxy(checkerType.getAnnotation(annotationType)).propertyValue("type"); + if (checkerTypeName.name().equals(name)) { + service.checkerType = checkerType; + service.checkerTypeName = checkerTypeName; + return service; + } + } + } catch (Exception e) { + asAssertionError("Failed to resolve BaseHealthCheck", e); + } + return null; + } + + private Class checkerType; + private Enum checkerTypeName; + + BaseHealthCheck(Object bean) { + super(bean); + } + + public Class getCheckerType() { + return checkerType; + } + + public Enum getCheckerTypeName() { + return checkerTypeName; + } + + public boolean isEnabled() { + return getOptions().booleanValue("isEnabled"); + } + + public long getTime() { + return getOptions().longValue("getTime").longValue(); + } + + public TimeUnit getUnit() { + return getOptions().enumValue("getUnit", TimeUnit.class); + } + + /** + * @return hogging threads threshold + */ + public Long getThresholdPercentage() { + return getOptions().longValue("getThresholdPercentage"); + } + + public Integer getRetryCount() { + return getOptions().integerValue("getRetryCount"); + } + + public Long getTimeStuck() { + return getOptions().longValue("getTimeStuck"); + } + + public TimeUnit getUnitStuck() { + return getOptions().enumValue("getUnitStuck", TimeUnit.class); + } + + public int getThresholdCritical() { + return getOptions().intValue("getThresholdCritical"); + } + + public int getThresholdWarning() { + return getOptions().intValue("getThresholdWarning"); + } + + public int getThresholdGood() { + return getOptions().intValue("getThresholdGood"); + } + + private BeanProxy getOptions() { + return new BeanProxy(propertyValue("getOptions")); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/Checker.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/Checker.java new file mode 100644 index 00000000000..6e07268697f --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/Checker.java @@ -0,0 +1,110 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.test.domain.healthcheck; + +import java.util.concurrent.TimeUnit; + +import fish.payara.test.util.BeanProxy; + +public final class Checker extends BeanProxy { + + public static Checker from(HealthCheckServiceConfiguration config, Class checkerType) { + return new Checker(config.callMethod("getCheckerByType", "Failed to resolve Checker", Class.class, checkerType)); + } + + private Checker(Object bean) { + super(bean); + } + + public String getName() { + return stringValue("getName"); + } + + public boolean getEnabled() { + return booleanValue("getEnabled"); + } + + public Long getTime() { + return longValue("getTime"); + } + + public TimeUnit getUnit() { + return enumValue("getUnit", TimeUnit.class); + } + + /** + * @return hogging threads threshold + */ + public Integer getThresholdPercentage() { + return integerValue("getThresholdPercentage"); + } + + public Integer getRetryCount() { + return integerValue("getRetryCount"); + } + + /** + * @return stuck threads threshold + */ + public Long getThreshold() { + return longValue("getThreshold"); + } + + public TimeUnit getThresholdTimeUnit() { + return enumValue("getThresholdTimeUnit", TimeUnit.class); + } + + public Integer getThresholdCritical() { + return integerProperty("threshold-critical"); + } + + public Integer getThresholdWarning() { + return integerProperty("threshold-warning"); + } + + public Integer getThresholdGood() { + return integerProperty("threshold-good"); + } + + private Integer integerProperty(String name) { + Object propery = callMethod("getProperty", "Failed to get Property "+name, String.class, name); + return propery == null ? null : new BeanProxy(propery).integerValue("getValue"); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/HealthCheckService.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/HealthCheckService.java new file mode 100644 index 00000000000..99f2f1b345f --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/HealthCheckService.java @@ -0,0 +1,83 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.test.domain.healthcheck; + +import fish.payara.test.domain.notification.NotifierExecutionOptions; +import fish.payara.test.util.BeanProxy; +import fish.payara.test.util.PayaraMicroServer; + +public final class HealthCheckService extends BeanProxy { + + private static final String SERVICE_CLASS_NAME = + "fish.payara.nucleus.healthcheck.HealthCheckService"; + + public static HealthCheckService from(PayaraMicroServer server) { + return new HealthCheckService(server.getService(server.getClass(SERVICE_CLASS_NAME))); + } + + private HealthCheckService(Object bean) { + super(bean); + } + + public boolean isEnabled() { + return booleanValue("isEnabled"); + } + + public boolean isHistoricalTraceEnabled() { + return booleanValue("isHistoricalTraceEnabled"); + } + + public Integer getHistoricalTraceStoreSize() { + return integerValue("getHistoricalTraceStoreSize"); + } + + public Long getHistoricalTraceStoreTimeout() { + return longValue("historicalTraceStoreTimeout"); + } + + public BaseHealthCheck getCheck(String name) { + Object res = callMethod("getCheck", "Failed to getCheck", String.class, name); + return res == null ? null : new BaseHealthCheck(res); + } + + public NotifierExecutionOptions getNotifierExecutionOptions(String notifierName) { + return NotifierExecutionOptions.from(this, notifierName); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/HealthCheckServiceConfiguration.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/HealthCheckServiceConfiguration.java new file mode 100644 index 00000000000..1595b4643fe --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/healthcheck/HealthCheckServiceConfiguration.java @@ -0,0 +1,87 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.test.domain.healthcheck; + +import fish.payara.test.domain.notification.Notifier; +import fish.payara.test.util.BeanProxy; +import fish.payara.test.util.PayaraMicroServer; + +public final class HealthCheckServiceConfiguration extends BeanProxy { + + private static final String CONFIG_CLASS_NAME = + "fish.payara.nucleus.healthcheck.configuration.HealthCheckServiceConfiguration"; + + public static HealthCheckServiceConfiguration from(PayaraMicroServer server) { + return from(server, "server-config"); + } + + private static HealthCheckServiceConfiguration from(PayaraMicroServer server, String target) { + return new HealthCheckServiceConfiguration( + server.getExtensionByType(target, server.getClass(CONFIG_CLASS_NAME))); + } + + private HealthCheckServiceConfiguration(Object config) { + super(config); + } + + public boolean getEnabled() { + return booleanValue("getEnabled"); + } + + public boolean getHistoricalTraceEnabled() { + return booleanValue("getHistoricalTraceEnabled"); + } + + public int getHistoricalTraceStoreSize() { + return intValue("getHistoricalTraceStoreSize"); + } + + public int getHistoricalTraceStoreTimeout() { + return intValue("getHistoricalTraceStoreTimeout"); + } + + public Checker getCheckerByType(Class checkerType) { + return Checker.from(this, checkerType); + } + + public Notifier getNotifierByType(Class notifierType) { + return Notifier.from(this, notifierType); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/network/HazelcastRuntimeConfiguration.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/network/HazelcastRuntimeConfiguration.java new file mode 100644 index 00000000000..30a33aa6d3b --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/network/HazelcastRuntimeConfiguration.java @@ -0,0 +1,60 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.test.domain.network; + +import fish.payara.test.util.BeanProxy; +import fish.payara.test.util.PayaraMicroServer; + +public final class HazelcastRuntimeConfiguration extends BeanProxy { + + private static final String CLASS_NAME = "fish.payara.nucleus.hazelcast.HazelcastRuntimeConfiguration"; + + public static HazelcastRuntimeConfiguration from(PayaraMicroServer server) { + return new HazelcastRuntimeConfiguration(server.getDomainExtensionByType(server.getClass(CLASS_NAME))); + } + + private HazelcastRuntimeConfiguration(Object bean) { + super(bean); + } + + public boolean getAutoIncrementPort() { + return booleanValue("getAutoIncrementPort"); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/notification/Notifier.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/notification/Notifier.java new file mode 100644 index 00000000000..bf0f45cf502 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/notification/Notifier.java @@ -0,0 +1,64 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.test.domain.notification; + +import fish.payara.test.domain.healthcheck.HealthCheckServiceConfiguration; +import fish.payara.test.util.BeanProxy; + +public final class Notifier extends BeanProxy { + + public static final String LOG_NOTIFIER_CLASS_NAME = "fish.payara.nucleus.notification.log.LogNotifier"; + + public static Notifier from(HealthCheckServiceConfiguration config, Class notifierType) { + return new Notifier(config.callMethod("getNotifierByType", "Failed to resolve Notifier", Class.class, notifierType)); + } + + private Notifier(Object bean) { + super(bean); + } + + public boolean getEnabled() { + return booleanValue("getEnabled"); + } + + public boolean getNoisy() { + return booleanValue("getNoisy"); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/notification/NotifierExecutionOptions.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/notification/NotifierExecutionOptions.java new file mode 100644 index 00000000000..10875bf0693 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/domain/notification/NotifierExecutionOptions.java @@ -0,0 +1,76 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.test.domain.notification; + +import java.util.List; + +import fish.payara.test.domain.healthcheck.HealthCheckService; +import fish.payara.test.util.BeanProxy; + +public final class NotifierExecutionOptions extends BeanProxy { + + public static NotifierExecutionOptions from(HealthCheckService service, String notifierName) { + List options = (List) service.callMethod("getNotifierExecutionOptionsList", "Failed to resolve notifier options"); + for (Object option : options) { + NotifierExecutionOptions res = new NotifierExecutionOptions(option); + if (res.getNotifierType().name().equals(notifierName)) { + return res; + } + } + return null; + } + + private NotifierExecutionOptions(Object bean) { + super(bean); + } + + public Enum getNotifierType() { + return enumValue("getNotifierType"); + } + + public boolean isEnabled() { + return booleanValue("isEnabled"); + } + + public boolean isNoisy() { + return booleanValue("isNoisy"); + } + +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/util/BeanProxy.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/util/BeanProxy.java new file mode 100644 index 00000000000..26da55bd590 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/util/BeanProxy.java @@ -0,0 +1,157 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.test.util; + +import static org.junit.Assert.fail; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * Base class for test wrappers on beans of classes only available at runtime. + */ +public class BeanProxy { + + private final Object bean; + + public BeanProxy(Object bean) { + this.bean = bean; + } + + @Override + public final boolean equals(Object obj) { + return obj != null && obj.getClass() == getClass() && bean.equals(((BeanProxy)obj).bean); + } + + @Override + public final int hashCode() { + return bean.hashCode(); + } + + @Override + public String toString() { + return bean.getClass().getSimpleName(); + } + + public final boolean booleanValue(String name) { + Object res = propertyValue(name, Boolean.class); + return res instanceof Boolean ? ((Boolean)res).booleanValue() : Boolean.parseBoolean((String)res); + } + + public final int intValue(String name) { + Integer res = integerValue(name); + return res == null ? 0 : res.intValue(); + } + + public final Integer integerValue(String name) { + Object res = propertyValue(name, Integer.class); + return res instanceof Integer || res == null ? ((Integer)res) : Integer.valueOf((String)res); + } + + public final Long longValue(String name) { + Object res = propertyValue(name, Long.class); + return res instanceof Long || res == null ? ((Long)res) : Long.valueOf((String)res); + } + + public final String stringValue(String name) { + Object res = propertyValue(name, String.class); + return res instanceof String || res == null ? (String) res : String.valueOf(res); + } + + public final Enum enumValue(String name) { + return (Enum) propertyValue(name, Enum.class); + } + @SuppressWarnings("unchecked") + public final > E enumValue(String name, Class type) { + Object val = propertyValue(name, type); + if (val == null || type.isAssignableFrom(val.getClass())) { + return (E) val; + } + if (val instanceof String) { + return Enum.valueOf(type, (String)val); + } + fail("Unexpected value type for enum: " + name); + return null; + } + + public final Object propertyValue(String name) { + return propertyValue(name, Object.class); + } + + public final Object propertyValue(String name, Class type) { + String errorText = "Failed to get " + type.getSimpleName() + " value for property " + name; + return name.startsWith("get") || name.startsWith("is") || bean instanceof Annotation + ? callMethod(name, errorText) + : accessField(name, errorText); + } + + public final Object callMethod(String name, String errorText) { + try { + Method getter = bean.getClass().getMethod(name, new Class[0]); + return getter.invoke(bean); + } catch (Throwable e) { + throw asAssertionError(errorText + " for method " + name, e); + } + } + + public final

Object callMethod(String name, String errorText, Class

parameter, P argument) { + try { + Method getter = bean.getClass().getMethod(name, new Class[] { parameter }); + return getter.invoke(bean, argument); + } catch (Throwable e) { + throw asAssertionError(errorText + " for method " + name, e); + } + } + + public final Object accessField(String name, String errorText) { + try { + Field field = bean.getClass().getDeclaredField(name); + field.setAccessible(true); + return field.get(bean); + } catch (Throwable e) { + throw asAssertionError(errorText + " for field " + name, e); + } + } + + public static AssertionError asAssertionError(String msg, Throwable e) { + return e.getClass() == AssertionError.class ? (AssertionError)e : new AssertionError(msg, e); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/util/IntegrationTest.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/util/IntegrationTest.java new file mode 100644 index 00000000000..43f14c57791 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/util/IntegrationTest.java @@ -0,0 +1,48 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.test.util; + +/** + * Marker interface to be used together with junit's {@link org.junit.experimental.categories.Category} to mark + * integration tests. + */ +public interface IntegrationTest { + // marker +} diff --git a/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/util/PayaraMicroServer.java b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/util/PayaraMicroServer.java new file mode 100644 index 00000000000..f901829a449 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/java/fish/payara/test/util/PayaraMicroServer.java @@ -0,0 +1,241 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.test.util; + +import static fish.payara.test.util.BeanProxy.asAssertionError; + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import fish.payara.micro.PayaraInstance; +import fish.payara.micro.PayaraMicro; +import fish.payara.micro.PayaraMicroRuntime; + +/** + * A wrapper on the {@link PayaraMicroRuntime} and {@link PayaraInstance} to ease test setup and verification. + * + * This test setup works directly with the {@code payara-micro.jar} as its only dependency. While this has the benefit + * of testing the actual artefact this comes as the downside that there are only a few API classes available at compile + * time as the server itself is packaged within micro and only accessible at runtime using the right + * {@link ClassLoader}. + * + * Tests using the {@link PayaraMicroServer} should call {@link #start()} before the test(s) and {@link #stop()} after + * even when using the {@link #DEFAULT} instance. + */ +public final class PayaraMicroServer { + + static { + System.setProperty("java.util.logging.config.file", "src/test/resources/logging.properties"); + } + + /** + * A instance to reuse during tests running in the same VM that do not have a problem with unknown start condition. + * + * Tests using this instance may change it but should not perform operations that make further usage hard or + * impossible, like for instance shutting down the server would. + */ + public final static PayaraMicroServer DEFAULT = new PayaraMicroServer(true); + + public static PayaraMicroServer newInstance() { + return new PayaraMicroServer(false); + } + + private static final String GALSSFISH_CLASS_NAME = "org.glassfish.embeddable.GlassFish"; + private static final String SERVICE_LOCATOR_CLASS_NAME = "org.glassfish.hk2.api.ServiceLocator"; + private static final String TARGET_CLASS_NAME = "org.glassfish.internal.api.Target"; + private static final String DOMAIN_CLASS_NAME = "com.sun.enterprise.config.serverbeans.Domain"; + + private final static String DEPLOYMENT_DIR = System.getProperty("user.dir") + File.separator + "target/deployments"; + + /** + * The port number to use next if a {@link PayaraMicroServer} instance is started. + */ + private static AtomicInteger nextPort = new AtomicInteger(28989); + + private final boolean defaultInstance; + private final AtomicBoolean started = new AtomicBoolean(false); + private final AtomicBoolean startedSuccessfully = new AtomicBoolean(false); + private PayaraMicro boot; + private PayaraMicroRuntime runtime; + private PayaraInstance instance; + + private ClassLoader serverClassLoader; + private Object glassfish; + private Object serviceLocator; + private Object targetUtil; + private BeanProxy domain; + + private PayaraMicroServer(boolean defaultInstance) { + this.defaultInstance = defaultInstance; + } + + public PayaraInstance getInstance() { + return instance; + } + + public PayaraMicroRuntime getRuntime() { + return runtime; + } + + public void start() { + if (!started.compareAndSet(false, true)) { + return; // only start it once + } + try { + boot = PayaraMicro.getInstance(); + File dir = new File(DEPLOYMENT_DIR); + createDummyFile(dir); + int port = nextPort.getAndIncrement(); + runtime = boot.setInstanceName("micro-test") + .setDeploymentDir(dir) + .setHttpPort(port) + .setHttpAutoBind(true) + .bootStrap(); + startedSuccessfully.compareAndSet(false, true); + instance = getField(PayaraInstance.class, runtime); + // classes are on the CP of the server but not of the test + serverClassLoader = instance.getClass().getClassLoader(); + glassfish = getField(getClass(GALSSFISH_CLASS_NAME), runtime); + serviceLocator = getField(getClass(SERVICE_LOCATOR_CLASS_NAME), glassfish); + targetUtil = getService(getClass(TARGET_CLASS_NAME)); + domain = new BeanProxy(getService(getClass(DOMAIN_CLASS_NAME))); + if (defaultInstance) { + Runtime.getRuntime().addShutdownHook(new Thread(() -> doStop())); + } + } catch (Exception e) { + e.printStackTrace(); + asAssertionError("Failed to start micro server", e); + } + } + + public void stop() { + if (defaultInstance) { + return; // is stopped by JVM shutdown hook as it is shared amoung many tests + } + doStop(); + } + + private void doStop() { + if (!isStarted()) { + return; // don't try to stop if not started successfully + } + try { + boot.shutdown(); + } catch (Exception e) { + // ignore... + } + } + + private boolean isStarted() { + return started.get() && startedSuccessfully.get(); + } + + public T getDomainExtensionByType(Class type) { + return type.cast(domain.callMethod("getExtensionByType", + "Failed to get Domain extension of type " + type.getName(), Class.class, type)); + } + + public T getExtensionByType(String target, Class type) { + try { + Method getConfig = targetUtil.getClass().getMethod("getConfig", String.class); + Object config = getConfig.invoke(targetUtil, target); + Method getExtensionByType = config.getClass().getMethod("getExtensionByType", Class.class); + return type.cast(getExtensionByType.invoke(config, type)); + } catch (Throwable e) { + throw asAssertionError("Failed to get extension", e); + } + } + + public Class getClass(String name) { + try { + return serverClassLoader.loadClass(name); + } catch (Throwable e) { + throw asAssertionError("Failed to load class for name: " + name, e); + } + } + + public T getService(Class type) { + try { + Method getService = serviceLocator.getClass().getMethod("getService", Class.class, Annotation[].class); + return type.cast(getService.invoke(serviceLocator, type, new Annotation[0])); + } catch (Throwable e) { + throw asAssertionError("Failed to resolve service", e); + } + } + + @SuppressWarnings("unchecked") + public List getAllServices(Class type) { + try { + Method getAllServices = serviceLocator.getClass().getMethod("getAllServices", Class.class, Annotation[].class); + return (List) getAllServices.invoke(serviceLocator, type, new Annotation[0]); + } catch (Throwable e) { + throw asAssertionError("Failed to resolve services", e); + } + } + + private static T getField(Class fieldType, Object obj) { + for (Field f : obj.getClass().getDeclaredFields()) { + if (fieldType.isAssignableFrom(f.getType())) { + try { + f.setAccessible(true); + return fieldType.cast(f.get(obj)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + throw new IllegalStateException("Could not find instance field in runtime"); + } + + /** + * Currently the deployment dir is not allowed to be empty + */ + private static void createDummyFile(File dir) throws IOException { + File dummy = new File(dir, "dummy.txt"); + dummy.getParentFile().mkdirs(); + dummy.createNewFile(); + } +} diff --git a/appserver/tests/test-micro-jar/src/test/resources/logging.properties b/appserver/tests/test-micro-jar/src/test/resources/logging.properties new file mode 100644 index 00000000000..d8642566f72 --- /dev/null +++ b/appserver/tests/test-micro-jar/src/test/resources/logging.properties @@ -0,0 +1,5 @@ +# Logging setup for testing that makes the output a lot less verbose +handlers=java.util.logging.ConsoleHandler +java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter +com.sun.enterprise.server.logging.ODLLogFormatter.ansiColor=false +java.util.logging.ConsoleHandler.level=INFO \ No newline at end of file diff --git a/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/HealthCheckService.java b/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/HealthCheckService.java index b0f81bd7e50..48e3b066609 100644 --- a/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/HealthCheckService.java +++ b/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/HealthCheckService.java @@ -46,6 +46,7 @@ import fish.payara.nucleus.notification.configuration.Notifier; import fish.payara.nucleus.notification.configuration.NotifierConfigurationType; import fish.payara.nucleus.notification.domain.NotifierExecutionOptions; +import fish.payara.nucleus.notification.domain.NotifierExecutionOptionsFactory; import fish.payara.nucleus.notification.domain.NotifierExecutionOptionsFactoryStore; import fish.payara.nucleus.notification.log.LogNotifier; import fish.payara.nucleus.notification.log.LogNotifierExecutionOptions; @@ -208,13 +209,16 @@ public void bootstrapHealthCheck() { /** * Starts all notifiers that have been enable with the healthcheck service. */ - public void bootstrapNotifierList() { + public synchronized void bootstrapNotifierList() { notifierExecutionOptionsList = new ArrayList<>(); if (configuration.getNotifierList() != null) { for (Notifier notifier : configuration.getNotifierList()) { ConfigView view = ConfigSupport.getImpl(notifier); NotifierConfigurationType annotation = view.getProxyType().getAnnotation(NotifierConfigurationType.class); - notifierExecutionOptionsList.add(executionOptionsFactoryStore.get(annotation.type()).build(notifier)); + NotifierExecutionOptionsFactory factory = executionOptionsFactoryStore.get(annotation.type()); + if (factory != null) { + notifierExecutionOptionsList.add(factory.build(notifier)); + } } } if (notifierExecutionOptionsList.isEmpty()) { @@ -300,7 +304,8 @@ public void shutdownHealthCheck() { } public BaseHealthCheck getCheck(String serviceName) { - return registeredTasks.get(serviceName).getCheck(); + HealthCheckTask task = registeredTasks.get(serviceName); + return task == null ? null : task.getCheck(); } /** diff --git a/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckConfiguration.java b/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckConfiguration.java index afd4ec8a800..a64bf8be0db 100644 --- a/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckConfiguration.java +++ b/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckConfiguration.java @@ -120,7 +120,7 @@ public class SetHealthCheckConfiguration implements AdminCommand { private String target; @Param(name = "enabled") - private boolean enabled; + private Boolean enabled; @Param(name = "historical-trace-enabled", optional = true) private Boolean historicalTraceEnabled; @@ -157,7 +157,7 @@ private void updateConfig(HealthCheckServiceConfiguration config, AdminCommandCo final ActionReport report = initActionReport(context); try { ConfigSupport.apply(configProxy -> { - configProxy.enabled(String.valueOf(enabled)); + configProxy.enabled(enabled.toString()); configProxy.setHistoricalTraceStoreSize(String.valueOf(historicalTraceStoreSize)); if (historicalTraceEnabled != null) { configProxy.setHistoricalTraceEnabled(historicalTraceEnabled.toString()); @@ -183,7 +183,7 @@ private void updateLogNotifier(AdminCommandContext context) { ParameterMap params = new ParameterMap(); params.add("target", target); params.add("dynamic", String.valueOf(dynamic)); - params.add("enabled", String.valueOf(enabled)); + params.add("enabled", enabled.toString()); params.add("notifier", NotifierType.LOG.name().toLowerCase()); // noisy will default to the notifier's config when not set so we do not set it as this is what we want inv.parameters(params); diff --git a/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckServiceConfiguration.java b/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckServiceConfiguration.java index d9d116e81f9..43b1535279a 100644 --- a/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckServiceConfiguration.java +++ b/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckServiceConfiguration.java @@ -143,7 +143,7 @@ public class SetHealthCheckServiceConfiguration implements AdminCommand { // general properties params: @Param(name = "enabled", optional = false) - private boolean enabled; + private Boolean enabled; @Param(name = "time", optional = true) @Min(value = 1, message = "Time period must be 1 or more") @@ -293,9 +293,7 @@ private void updateSe private void configureDynamically( BaseHealthCheck service, C config) { - if (service.getOptions() == null) { - service.setOptions(service.constructOptions(config)); - } + service.setOptions(service.constructOptions(config)); healthCheckService.registerCheck(config.getName(), service); healthCheckService.reboot(); if (service instanceof BaseThresholdHealthCheck) { @@ -326,7 +324,7 @@ private void configureDynamically(BaseThresholdHealthCheck service) { } private Checker updateProperties(Checker config, Class type) throws PropertyVetoException { - updateProperty(config, "enabled", config.getEnabled(), String.valueOf(enabled), Checker::setEnabled); + updateProperty(config, "enabled", config.getEnabled(), enabled.toString(), Checker::setEnabled); updateProperty(config, "time", config.getTime(), time, Checker::setTime); updateProperty(config, "time-unit", config.getUnit(), timeUnit, Checker::setUnit); if (HoggingThreadsChecker.class.isAssignableFrom(type)) { diff --git a/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckServiceNotifierConfiguration.java b/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckServiceNotifierConfiguration.java index 6645321f0cd..ee70a23babb 100644 --- a/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckServiceNotifierConfiguration.java +++ b/nucleus/payara-modules/healthcheck-core/src/main/java/fish/payara/nucleus/healthcheck/admin/SetHealthCheckServiceNotifierConfiguration.java @@ -127,7 +127,7 @@ public class SetHealthCheckServiceNotifierConfiguration implements AdminCommand private Config targetConfig; @Param(name = "enabled") - private boolean enabled; + private Boolean enabled; @Param(name = "noisy", optional = true) private Boolean noisy; @@ -186,7 +186,7 @@ public void execute(AdminCommandContext context) { } private void applyValues(Notifier notifier) throws PropertyVetoException { - if (Boolean.parseBoolean(notifier.getEnabled()) != enabled) { + if (Boolean.parseBoolean(notifier.getEnabled()) != enabled.booleanValue()) { report.appendMessage(notifierName + ".enabled was " + notifier.getEnabled() + " set to " + enabled + "\n"); notifier.enabled(enabled); } diff --git a/nucleus/payara-modules/notification-core/src/main/java/fish/payara/nucleus/notification/domain/NotifierExecutionOptionsFactoryStore.java b/nucleus/payara-modules/notification-core/src/main/java/fish/payara/nucleus/notification/domain/NotifierExecutionOptionsFactoryStore.java index f7248a553dc..95ba16bef1f 100644 --- a/nucleus/payara-modules/notification-core/src/main/java/fish/payara/nucleus/notification/domain/NotifierExecutionOptionsFactoryStore.java +++ b/nucleus/payara-modules/notification-core/src/main/java/fish/payara/nucleus/notification/domain/NotifierExecutionOptionsFactoryStore.java @@ -47,6 +47,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * @author mertcaliskan @@ -56,7 +57,7 @@ public class NotifierExecutionOptionsFactoryStore { private Map execOptionsFactoryStore = - new HashMap(); + new ConcurrentHashMap(); public NotifierExecutionOptionsFactory get(NotifierType type) { return execOptionsFactoryStore.get(type);