/* * JBoss, Home of Professional Open Source. * Copyright 2015, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.test.manualmode.management.cli; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ENABLED; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILURE_DESCRIPTION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INPUT_STREAM_INDEX; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_RESOURCE_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Collections; import java.util.List; import org.codehaus.plexus.util.FileUtils; import org.jboss.as.controller.client.ModelControllerClient; import org.jboss.as.controller.client.Operation; import org.jboss.as.protocol.StreamUtils; import org.jboss.as.test.deployment.trivial.ServiceActivatorDeploymentUtil; import org.jboss.as.test.integration.management.base.AbstractCliTestBase; import org.jboss.as.test.integration.management.extension.EmptySubsystemParser; import org.jboss.as.test.integration.management.extension.ExtensionUtils; import org.jboss.as.test.integration.management.extension.blocker.BlockerExtension; import org.jboss.as.test.integration.management.util.CLIOpResult; import org.jboss.as.test.shared.TestSuiteEnvironment; import org.jboss.as.test.shared.TimeoutUtil; import org.jboss.dmr.ModelNode; import org.jboss.logging.Logger; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.jboss.stdio.SimpleStdioContextSelector; import org.jboss.stdio.StdioContext; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.wildfly.security.manager.WildFlySecurityManager; /** * Tests embedding a server in the CLI. * * @author Brian Stansberry (c) 2015 Red Hat Inc. */ public class CLIEmbedServerTestCase extends AbstractCliTestBase { /** * Use this if you are debugging and want to look at the original System.out output, * as the tests play tricks with it later. */ private static final PrintStream out = System.out; private static final File ROOT = new File(System.getProperty("jboss.home")); private static final String JBOSS_HOME = " --jboss-home=" + ROOT.getAbsolutePath(); private static final String STOP = "stop-embedded-server"; private static final String SERVICE_ACTIVATOR_DEPLOYMENT_NAME = "service-activated.jar"; private static JavaArchive serviceActivatorDeployment; private static File serviceActivatorDeploymentFile; private static boolean uninstallStdio; public static final String JBOSS_SERVER_BASE_DIR = "jboss.server.base.dir"; public static final String JBOSS_SERVER_CONFIG_DIR = "jboss.server.config.dir"; public static final String JBOSS_SERVER_CONTENT_DIR = "jboss.server.content.dir"; public static final String JBOSS_SERVER_DEPLOY_DIR = "jboss.server.deploy.dir"; public static final String JBOSS_SERVER_TEMP_DIR = "jboss.server.temp.dir"; public static final String JBOSS_SERVER_LOG_DIR = "jboss.server.log.dir"; public static final String JBOSS_SERVER_DATA_DIR = "jboss.server.data.dir"; public static final String JBOSS_CONTROLLER_TEMP_DIR = "jboss.controller.temp.dir"; public static final String[] SERVER_PROPS = { JBOSS_SERVER_BASE_DIR, JBOSS_SERVER_CONFIG_DIR, JBOSS_SERVER_DEPLOY_DIR, JBOSS_SERVER_TEMP_DIR, JBOSS_SERVER_LOG_DIR, JBOSS_SERVER_DATA_DIR }; // Sink for embedding app (i.e. this class and the CLI) and embedded server writes to stdout private ByteArrayOutputStream logOut; private static StdioContext initialStdioContext; @BeforeClass public static void beforeClass() throws Exception { CLIEmbedUtil.copyConfig(ROOT, "standalone", "logging.properties", "logging.properties.backup", false); // Set up ability to manipulate stdout initialStdioContext = StdioContext.getStdioContext(); try { StdioContext.install(); uninstallStdio = true; } catch (IllegalStateException ignore) { // } serviceActivatorDeployment = ServiceActivatorDeploymentUtil.createServiceActivatorDeploymentArchive(SERVICE_ACTIVATOR_DEPLOYMENT_NAME, Collections.emptyMap()); File tmpDir = new File(System.getProperty("java.io.tmpdir")); serviceActivatorDeploymentFile = new File(tmpDir, SERVICE_ACTIVATOR_DEPLOYMENT_NAME); serviceActivatorDeployment.as(ZipExporter.class).exportTo(serviceActivatorDeploymentFile, true); ExtensionUtils.createExtensionModule(BlockerExtension.MODULE_NAME, BlockerExtension.class, EmptySubsystemParser.class.getPackage()); // Set jboss.bind.address so the embedded server uses the expected IP address System.setProperty("jboss.bind.address.management", TestSuiteEnvironment.getServerAddress()); // Silly assertion just to stop IDEs complaining about field 'out' not being used. assertNotNull(out); } @AfterClass public static void afterClass() throws IOException { CLIEmbedUtil.copyConfig(ROOT, "standalone", "logging.properties.backup", "logging.properties", false); try { StdioContext.setStdioContextSelector(new SimpleStdioContextSelector(initialStdioContext)); } finally { if (uninstallStdio) { StdioContext.uninstall(); } } if (serviceActivatorDeploymentFile != null) { Files.deleteIfExists(serviceActivatorDeploymentFile.toPath()); } ExtensionUtils.deleteExtensionModule(BlockerExtension.MODULE_NAME); } @Before public void setup() throws Exception { CLIEmbedUtil.copyConfig(ROOT, "standalone", "logging.properties.backup", "logging.properties", false); CLIEmbedUtil.copyConfig(ROOT, "standalone", "standalone.xml", "standalone-cli.xml", true); // Capture stdout logOut = new ByteArrayOutputStream(); final StdioContext replacement = StdioContext.create(initialStdioContext.getIn(), logOut, initialStdioContext.getErr()); StdioContext.setStdioContextSelector(new SimpleStdioContextSelector(replacement)); initCLI(false); } @After public void cleanup() throws Exception { try { closeCLI(); } finally { StdioContext.setStdioContextSelector(new SimpleStdioContextSelector(initialStdioContext)); } } /** Tests logging behavior with no --std-out param */ @Test public void testStdOutDefault() throws Exception { stdoutTest(null); } /** Tests logging behavior with --std-out=discard */ @Test public void testStdOutDiscard() throws Exception { stdoutTest("discard"); } /** Tests logging behavior with --std-out=echo */ @Test public void testStdOutEcho() throws Exception { stdoutTest("echo"); } /** * This test is about confirming the CLI side and embedded server side logging to stdout * works as expected. CLI logging should always be captured in the 'logOut' sink, while * embedded server logging should only be captured if paramVal is 'echo'. * * @param paramVal value to assign to the --std-out param, or null if the param should be omitted * @throws Exception just because */ private void stdoutTest(String paramVal) throws Exception { String stdoutParam = paramVal == null ? "" : ("--std-out=" + paramVal); boolean expectServerLogging = "echo".equals(paramVal); // The app embedding the server should be able to log checkClientSideLogging(); // Use --admin-only=false or the logging subsystem won't log anyway String line = "embed-server --admin-only=false --server-config=standalone-cli.xml " + stdoutParam + JBOSS_HOME; cli.sendLine(line); if (expectServerLogging) { checkLogging("WFLYSRV0025"); } else { checkNoLogging("WFLYSRV0025"); } assertState("running", TimeoutUtil.adjust(30000)); // The app embedding the server should still be able to log checkClientSideLogging(); // Do something that certainly creates a server-side logger after boot, // as part of executing a management op. Confirm its logging gets the // appropriate server-side behavior. cli.sendLine("/extension=" + BlockerExtension.MODULE_NAME + ":add"); if (expectServerLogging) { checkLogging(BlockerExtension.REGISTERED_MESSAGE); } else { checkNoLogging(BlockerExtension.REGISTERED_MESSAGE); } // The app embedding the server should still be able to log checkClientSideLogging(); cli.sendLine(STOP); if (expectServerLogging) { checkLogging("WFLYSRV0050"); } else { checkNoLogging("WFLYSRV0050"); } // The app embedding the server should still be able to log checkClientSideLogging(); } private void checkClientSideLogging() throws IOException { String text = "test." + System.nanoTime(); Logger.getLogger(text).error(text); checkLogging(text); } /** Confirms that low level and high level reloads work */ @Test public void testReload() throws Exception { // Don't use admin-only or reload-required won't be triggered String line = "embed-server --admin-only=false --server-config=standalone-cli.xml " + JBOSS_HOME; cli.sendLine(line); cli.sendLine("/subsystem=request-controller:remove"); assertState("reload-required", 0); // Low level cli.sendLine(":reload"); assertState("running", TimeoutUtil.adjust(30000)); cli.sendLine("/subsystem=request-controller:add"); assertState("reload-required", 0); // High level cli.sendLine("reload"); assertState("running", TimeoutUtil.adjust(30000)); } /** Confirms that the low and high level shutdown commands are not available */ @Test public void testShutdownNotAvailable() throws Exception { String line = "embed-server --server-config=standalone-cli.xml " + JBOSS_HOME; cli.sendLine(line); assertTrue(cli.isConnected()); assertState("running", 0); cli.sendLine(":shutdown", true); assertState("running", 0); cli.sendLine("shutdown", true); assertState("running", 0); } @Test @Ignore public void testTimeout() throws Exception { cli.sendLine("command-timeout set 60"); String line = "embed-server --server-config=standalone-cli.xml " + JBOSS_HOME; cli.sendLine(line); cli.sendLine("stop-embedded-server"); } /** Tests the standard cli 'deploy' command */ @Test public void testFileDeploy() throws Exception { validateServerConnectivity(); cli.sendLine("deploy " + serviceActivatorDeploymentFile.getAbsolutePath()); // We could use the CLI to do this, but since the code using MCC already exists, re-use it ModelControllerClient mcc = cli.getCommandContext().getModelControllerClient(); ServiceActivatorDeploymentUtil.validateProperties(mcc); } /** * Tests accessing a ModelControllerClient from the cli, and using it to deploy with the de * deployment content attached as a stream. */ @Test public void testModelControllerDeploy() throws Exception { validateServerConnectivity(); ModelNode opNode = new ModelNode(); opNode.get(OP).set(ADD); opNode.get(OP_ADDR).add(DEPLOYMENT, SERVICE_ACTIVATOR_DEPLOYMENT_NAME); opNode.get(ENABLED).set(true); ModelNode content = opNode.get(CONTENT).add(); content.get(INPUT_STREAM_INDEX).set(0); InputStream is = serviceActivatorDeployment.as(ZipExporter.class).exportAsInputStream(); Operation op = Operation.Factory.create(opNode, Collections.singletonList(is), true); ModelControllerClient mcc = cli.getCommandContext().getModelControllerClient(); ModelNode response = mcc.execute(op); assertEquals(response.toString(), SUCCESS, response.get(OUTCOME).asString()); // We could use the CLI to do this, but since we have the MCC and the code already exists, re-use it ServiceActivatorDeploymentUtil.validateProperties(mcc); } /** Tests building an entire server config from scratch */ @Test public void testBuildServerConfig() throws Exception { String line = "embed-server --server-config=standalone-cli.xml --empty-config --remove-existing " + JBOSS_HOME; cli.sendLine(line); // One batch for extensions so their API is available for the ops in the 2nd batch cli.sendLine("batch"); cli.sendLine("/extension=org.jboss.as.deployment-scanner:add"); cli.sendLine("/extension=org.jboss.as.jmx:add"); cli.sendLine("/extension=org.jboss.as.logging:add"); cli.sendLine("/extension=org.jboss.as.remoting:add"); cli.sendLine("/extension=org.wildfly.extension.io:add"); cli.sendLine("/extension=org.wildfly.extension.request-controller:add"); cli.sendLine("run-batch"); // Another batch for everything else cli.sendLine("batch"); cli.sendLine("/core-service=management/security-realm=ManagementRealm:add(map-groups-to-roles=false)"); cli.sendLine("/core-service=management/security-realm=ManagementRealm/authentication=local:add(default-user=\"$local\",skip-group-loading=true)"); cli.sendLine("/core-service=management/security-realm=ManagementRealm/authentication=properties:add(path=mgmt-users.properties,relative-to=jboss.server.config.dir)"); cli.sendLine("/core-service=management/security-realm=ManagementRealm/authorization=properties:add(path=mgmt-groups.properties,relative-to=jboss.server.config.dir)"); cli.sendLine("/core-service=management/security-realm=ApplicationRealm:add"); cli.sendLine("/core-service=management/security-realm=ApplicationRealm/authentication=local:add(default-user=\"$local\",allowed-users=*,skip-group-loading=true)"); cli.sendLine("/core-service=management/security-realm=ApplicationRealm/authentication=properties:add(path=application-users.properties,relative-to=jboss.server.config.dir)"); cli.sendLine("/core-service=management/security-realm=ApplicationRealm/authorization=properties:add(path=application-roles.properties,relative-to=jboss.server.config.dir)"); cli.sendLine("/core-service=management/access=audit:add"); cli.sendLine("/core-service=management/access=audit/json-formatter=json-formatter:add"); cli.sendLine("/core-service=management/access=audit/file-handler=file:add(formatter=json-formatter,relative-to=jboss.server.data.dir,path=audit-log.log)"); cli.sendLine("/core-service=management/access=audit/logger=audit-log:add(log-boot=true,log-read-only=false,enabled=true)"); cli.sendLine("/core-service=management/access=audit/logger=audit-log/handler=file:add"); cli.sendLine("/core-service=management/management-interface=http-interface:add(security-realm=ManagementRealm,http-upgrade-enabled=true,socket-binding=management-http)"); cli.sendLine("/core-service=management/access=authorization:write-attribute(name=provider,value=simple)"); cli.sendLine("/core-service=management/access=authorization/role-mapping=SuperUser:add"); cli.sendLine("/core-service=management/access=authorization/role-mapping=SuperUser/include=\"user-$local\":add(type=user,name=\"$local\")"); cli.sendLine("/interface=management:add(inet-address=${jboss.bind.address.management:127.0.0.1})"); cli.sendLine("/interface=public:add(inet-address=${jboss.bind.address:127.0.0.1})"); cli.sendLine("/interface=unsecure:add(inet-address=${jboss.bind.address.unsecure:127.0.0.1})"); cli.sendLine("/socket-binding-group=standard-sockets:add(default-interface=public,port-offset=${jboss.socket.binding.port-offset:0})"); cli.sendLine("/socket-binding-group=standard-sockets/socket-binding=management-http:add(interface=management,port=${jboss.management.http.port:9990})"); cli.sendLine("/socket-binding-group=standard-sockets/socket-binding=management-https:add(interface=management,port=${jboss.management.https.port:9993})"); cli.sendLine("/socket-binding-group=standard-sockets/socket-binding=http:add(port=${jboss.http.port:8080})"); cli.sendLine("/socket-binding-group=standard-sockets/socket-binding=https:add(port=${jboss.https.port:8443})"); cli.sendLine("/subsystem=logging:add"); cli.sendLine("/subsystem=logging/pattern-formatter=PATTERN:add(pattern=\"%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n\")"); cli.sendLine("/subsystem=logging/pattern-formatter=COLOR-PATTERN:add(pattern=\"%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n\")"); cli.sendLine("/subsystem=logging/console-handler=CONSOLE:add(level=INFO,named-formatter=COLOR-PATTERN)"); cli.sendLine("/subsystem=logging/periodic-rotating-file-handler=FILE:add(autoflush=true,named-formatter=PATTERN,file={relative-to=jboss.server.log.dir,path=server.log},suffix=.yyyy-MM-dd,append=true)"); cli.sendLine("/subsystem=logging/logger=com.arjuna:add(level=WARN)"); cli.sendLine("/subsystem=logging/logger=org.jboss.as.config:add(level=DEBUG)"); cli.sendLine("/subsystem=logging/logger=sun.rmi:add(level=WARN)"); cli.sendLine("/subsystem=logging/logger=jacorb:add(level=WARN)"); cli.sendLine("/subsystem=logging/logger=jacorb.config:add(level=ERROR)"); cli.sendLine("/subsystem=logging/root-logger=ROOT:add(level=INFO,handlers=[CONSOLE,FILE])"); cli.sendLine("/subsystem=deployment-scanner:add"); cli.sendLine("/subsystem=deployment-scanner/scanner=default:add(path=deployments,relative-to=jboss.server.base.dir,scan-interval=5000,runtime-failure-causes-rollback=\"${jboss.deployment.scanner.rollback.on.failure:false}\")"); cli.sendLine("/subsystem=io:add"); cli.sendLine("/subsystem=io/worker=default:add"); cli.sendLine("/subsystem=io/buffer-pool=default:add"); cli.sendLine("/subsystem=jmx:add"); cli.sendLine("/subsystem=jmx/expose-model=resolved:add"); cli.sendLine("/subsystem=jmx/expose-model=expression:add"); cli.sendLine("/subsystem=jmx/remoting-connector=jmx:add"); cli.sendLine("/subsystem=remoting:add"); cli.sendLine("/subsystem=remoting/configuration=endpoint:add(worker=default)"); cli.sendLine("/subsystem=remoting/http-connector=http-remoting-connector:add(connector-ref=default,security-realm=ApplicationRealm)"); cli.sendLine("deploy " + serviceActivatorDeploymentFile.getAbsolutePath()); cli.sendLine("run-batch"); assertState("reload-required", 0); cli.sendLine("reload --admin-only=false"); assertState("running", TimeoutUtil.adjust(30000)); // We could use the CLI to do this, but since the code using MCC already exists, re-use it ModelControllerClient mcc = cli.getCommandContext().getModelControllerClient(); ServiceActivatorDeploymentUtil.validateProperties(mcc); } /** * Test not specifying a server config works. * @throws IOException */ @Test public void testDefaultServerConfig() throws IOException { validateServerConnectivity(""); } /** * Test the -c shorthand for specifying a server config works. * @throws IOException */ @Test public void testDashC() throws IOException { validateServerConnectivity("-c=standalone-cli.xml"); } /** Confirms that the --empty-config param will trigger failure if the specified config exists */ @Test public void testRejectEmptyExistingConfig() throws Exception { assertFalse(cli.isConnected()); String line = "embed-server --server-config=standalone-cli.xml --empty-config " + JBOSS_HOME; cli.sendLine(line, true); assertFalse(cli.isConnected()); } /** * Tests using and empty config and also that the --remove-existing param will allow use of the * --empty-config param regardless of whether the specified config exists. */ @Test public void testAllowEmptyExistingConfig() throws Exception { assertFalse(cli.isConnected()); // Confirm starting with --empty-config and --remove-config succeeds even if the file doesn't exist File f = new File(ROOT, "standalone" + File.separatorChar + "configuration" + File.separatorChar + "standalone-cli.xml"); if (f.exists()) { Files.delete(f.toPath()); } String line = "embed-server --server-config=standalone-cli.xml --empty-config --remove-existing " + JBOSS_HOME; cli.sendLine(line); assertTrue(cli.isConnected()); assertTrue(f.exists()); assertEquals(0, countExtensions()); // Config file is still empty. Confirm we can reload w/ an empty config cli.sendLine("reload"); assertEquals(0, countExtensions()); cli.sendLine("stop-embedded-server"); assertFalse(cli.isConnected()); // Validate file was created and that we can boot from it even though it is empty line = "embed-server --server-config=standalone-cli.xml " + JBOSS_HOME; cli.sendLine(line); assertEquals(0, countExtensions()); // Config file is still empty. Confirm we can reload w/ an empty config cli.sendLine("reload"); assertEquals(0, countExtensions()); cli.sendLine("stop-embedded-server"); assertFalse(cli.isConnected()); // Confirm starting with --empty-config and --remove-existing succeeds even if the file exists CLIEmbedUtil.copyConfig(ROOT, "standalone", "standalone.xml", "standalone-cli.xml", true); line = "embed-server --server-config=standalone-cli.xml --empty-config --remove-existing " + JBOSS_HOME; cli.sendLine(line); assertTrue(cli.isConnected()); assertEquals(0, countExtensions()); cli.sendLine("stop-embedded-server"); assertFalse(cli.isConnected()); // Validate file was created and that we can boot from it even though it is empty line = "embed-server --server-config=standalone-cli.xml " + JBOSS_HOME; cli.sendLine(line); assertEquals(0, countExtensions()); } /** Tests the stop-embedded-server command */ @Test public void testStopEmbeddedServer() throws IOException { validateServerConnectivity(); cli.sendLine("stop-embedded-server"); assertFalse(cli.isConnected()); validateRemoteConnection(false); } /** Tests that the quit command stops any embedded server */ @Test @Ignore public void testStopServerOnQuit() throws IOException { validateServerConnectivity(); cli.sendLine("quit"); assertFalse(cli.isConnected()); validateRemoteConnection(false); } /** Tests the the CommandContext terminateSession method stops any embedded server */ @Test public void testStopServerOnTerminateSession() throws IOException { validateServerConnectivity(); cli.getCommandContext().terminateSession(); assertFalse(cli.isConnected()); validateRemoteConnection(false); } /** * Tests the --help param works. * @throws IOException */ @Test public void testHelp() throws IOException { cli.sendLine("embed-server --help"); checkLogging("embed-server"); String line = "embed-server --server-config=standalone-cli.xml " + JBOSS_HOME; cli.sendLine(line); assertTrue(cli.isConnected()); cli.sendLine("stop-embedded-server --help"); checkLogging("stop-embedded-server"); } @Test public void testBaseDir() throws IOException, InterruptedException { String currBaseDir = null; final String newStandalone = "CLIEmbedServerTestCaseStandaloneTmp"; assertFalse(cli.isConnected()); try { // save the current value currBaseDir = WildFlySecurityManager.getPropertyPrivileged(JBOSS_SERVER_BASE_DIR, null); CLIEmbedUtil.copyServerBaseDir(ROOT, "standalone", newStandalone, true); //CLIEmbedUtil.copyConfig(ROOT, newStandalone, "logging.properties.backup", "logging.properties", false); String newBaseDir = ROOT + File.separator + newStandalone; setProperties(newBaseDir); String line = "embed-server --std-out=echo " + JBOSS_HOME; cli.sendLine(line); assertTrue(cli.isConnected()); assertPath(JBOSS_SERVER_BASE_DIR, ROOT + File.separator + newStandalone); assertPath(JBOSS_SERVER_CONFIG_DIR, ROOT + File.separator + newStandalone + File.separator + "configuration"); assertPath(JBOSS_SERVER_DATA_DIR, ROOT + File.separator + newStandalone + File.separator + "data"); assertPath(JBOSS_SERVER_LOG_DIR, ROOT + File.separator + newStandalone + File.separator + "log"); assertPath(JBOSS_SERVER_TEMP_DIR, ROOT + File.separator + newStandalone + File.separator + "tmp"); assertPath(JBOSS_CONTROLLER_TEMP_DIR, ROOT + File.separator + newStandalone + File.separator + "tmp"); cli.sendLine("/system-property=" + newStandalone + ":add(value=" + newStandalone +")"); assertProperty(newStandalone, newStandalone, false); // WFCORE-1187, when this overrides logging.properties correctly, we can check this // for now it will refer to the previously persisted log file in standalone/configuration/logging.properties //File f = new File(ROOT + File.separator + newStandalone + File.separator + "log" + File.separator + "server.log"); //assertTrue(f.exists()); //assertTrue(f.length() > 0); // stop the hc, and restart it with default properties cli.sendLine("stop-embedded-server"); setProperties(null); cli.sendLine(line); assertTrue(cli.isConnected()); // shouldn't be set assertProperty(newStandalone, null, true); cli.sendLine("stop-embedded-server"); setProperties(newBaseDir); cli.sendLine(line); assertTrue(cli.isConnected()); assertProperty(newStandalone, newStandalone, false); } finally { cli.sendLine("stop-embedded-server"); // restore the original setProperties(currBaseDir); FileUtils.deleteDirectory(new File(ROOT + File.separator + newStandalone)); } } @Test public void testLogDir() throws IOException, InterruptedException { testPathDir(JBOSS_SERVER_LOG_DIR, "log"); } @Test public void testTempDir() throws IOException, InterruptedException { testPathDir(JBOSS_SERVER_TEMP_DIR, "temp"); } @Test public void testDataDir() throws IOException, InterruptedException { testPathDir(JBOSS_SERVER_DATA_DIR, "data"); } @Test public void testConfigDir() throws IOException, InterruptedException { testPathDir(JBOSS_SERVER_CONFIG_DIR, "configuration"); } @Test public void testLogDirProperty() throws IOException, InterruptedException { String currBaseDir = null; final String newStandalone = "CLIEmbedServerTestCaseStandaloneTmp"; assertFalse(cli.isConnected()); try { // save the current value currBaseDir = WildFlySecurityManager.getPropertyPrivileged(JBOSS_SERVER_BASE_DIR, null); CLIEmbedUtil.copyServerBaseDir(ROOT, "standalone", newStandalone, true); String newBaseDir = ROOT + File.separator + newStandalone; setProperties(newBaseDir); String line = "embed-server --std-out=echo " + JBOSS_HOME; cli.sendLine(line); assertTrue(cli.isConnected()); assertPath(JBOSS_SERVER_BASE_DIR, ROOT + File.separator + newStandalone); assertPath(JBOSS_SERVER_CONFIG_DIR, ROOT + File.separator + newStandalone + File.separator + "configuration"); assertPath(JBOSS_SERVER_DATA_DIR, ROOT + File.separator + newStandalone + File.separator + "data"); assertPath(JBOSS_SERVER_LOG_DIR, ROOT + File.separator + newStandalone + File.separator + "log"); assertPath(JBOSS_SERVER_TEMP_DIR, ROOT + File.separator + newStandalone + File.separator + "tmp"); assertPath(JBOSS_CONTROLLER_TEMP_DIR, ROOT + File.separator + newStandalone + File.separator + "tmp"); } finally { cli.sendLine("stop-embedded-server"); // restore the original setProperties(currBaseDir); FileUtils.deleteDirectory(new File(ROOT + File.separator + newStandalone)); } } private void assertPath(final String path, final String expected) throws IOException, InterruptedException { cli.sendLine("/path=" + path + " :read-attribute(name=path)", true); CLIOpResult result = cli.readAllAsOpResult(); ModelNode resp = result.getResponseNode(); ModelNode stateNode = result.isIsOutcomeSuccess() ? resp.get(RESULT) : resp.get(FAILURE_DESCRIPTION); assertEquals(expected, stateNode.asString()); } private void assertProperty(final String propertyName, final String expected, final boolean notPresent) throws IOException, InterruptedException { cli.sendLine("/system-property=" + propertyName + " :read-attribute(name=value)", true); CLIOpResult result = cli.readAllAsOpResult(); ModelNode resp = result.getResponseNode(); ModelNode stateNode = result.isIsOutcomeSuccess() ? resp.get(RESULT) : resp.get(FAILURE_DESCRIPTION); if (notPresent) { assertTrue(stateNode.asString().indexOf("WFLYCTL0216") != -1); } else { assertEquals(expected, stateNode.asString()); } } private void assertState(String expected, int timeout) throws IOException, InterruptedException { long done = timeout < 1 ? 0 : System.currentTimeMillis() + timeout; String history = ""; String state = null; do { try { cli.sendLine(":read-attribute(name=server-state)", true); CLIOpResult result = cli.readAllAsOpResult(); ModelNode resp = result.getResponseNode(); ModelNode stateNode = result.isIsOutcomeSuccess() ? resp.get(RESULT) : resp.get(FAILURE_DESCRIPTION); state = stateNode.asString(); history += state+"\n"; } catch (Exception ignored) { // history += ignored.toString()+ "--" + cli.readOutput() + "\n"; } if (expected.equals(state)) { return; } else { Thread.sleep(20); } } while (timeout > 0 && System.currentTimeMillis() < done); assertEquals(history, expected, state); } private void checkNoLogging(String line) throws IOException { String output = readLogOut(); assertFalse(output, checkLogging(output, line)); } private String readLogOut() { if (logOut.size() > 0) { String output = new String(logOut.toByteArray(), StandardCharsets.UTF_8).trim(); logOut.reset(); return output; } return null; } private void checkLogging(String line) throws IOException { String logOutput = readLogOut(); assertTrue(logOutput, checkLogging(logOutput, line)); } private boolean checkLogging(String logOutput, String line) throws IOException { List<String> output = CLIEmbedUtil.getOutputLines(logOutput); for (String s : output) { if (s.contains(line)) { return true; } } return false; } private int countExtensions() throws IOException { cli.sendLine(":read-children-names(child-type=extension"); CLIOpResult result = cli.readAllAsOpResult(); return ((List) result.getFromResponse(RESULT)).size(); } private void validateRemoteConnection(boolean expectSuccess) { ModelControllerClient mcc = null; try { mcc = TestSuiteEnvironment.getModelControllerClient(); ModelNode op = new ModelNode(); op.get(OP).set(READ_RESOURCE_OPERATION); ModelNode response = mcc.execute(op); assertEquals(response.toString(), SUCCESS, response.get(OUTCOME).asString()); } catch (Exception e) { if (expectSuccess) { e.printStackTrace(); fail("Cannot connect remotely: " + e.toString()); } } finally { StreamUtils.safeClose(mcc); } } private void validateServerConnectivity() throws IOException { validateServerConnectivity("--server-config=standalone-cli.xml"); } private void validateServerConnectivity(String serverConfigParam) throws IOException { assertFalse(cli.isConnected()); validateRemoteConnection(false); // Don't use admin-only or reload-required won't be triggered String line = "embed-server --admin-only=false " + serverConfigParam + " " + JBOSS_HOME; cli.sendLine(line); assertTrue(cli.isConnected()); validateRemoteConnection(true); } private void testPathDir(final String propName, final String value) throws IOException, InterruptedException { String currBaseDir = null; final String newStandalone = "CLIEmbedServerTestCaseStandaloneTmp"; assertFalse(cli.isConnected()); try { // save the current value currBaseDir = WildFlySecurityManager.getPropertyPrivileged(JBOSS_SERVER_BASE_DIR, null); //if (currBaseDir == null) { // currBaseDir = ROOT + File.separator + "standalone"; //} CLIEmbedUtil.copyServerBaseDir(ROOT, "standalone", newStandalone, true); String newBaseDir = ROOT + File.separator + newStandalone; WildFlySecurityManager.setPropertyPrivileged(propName, newBaseDir + File.separator + value); String line = "embed-server --std-out=echo " + JBOSS_HOME; cli.sendLine(line); assertTrue(cli.isConnected()); for(String prop : SERVER_PROPS) { if (prop.equals(propName)) { assertPath(propName, ROOT + File.separator + newStandalone + File.separator + value); } else { // just make sure the unchanged property has the default basedir //assertTrue(WildFlySecurityManager.getPropertyPrivileged(prop, "").indexOf(currBaseDir) != -1); } } } finally { // stop the server cli.sendLine("stop-embedded-server"); // restore the original setProperties(currBaseDir); FileUtils.deleteDirectory(new File(ROOT + File.separator + newStandalone)); } } private void setProperties(final String newBaseDir) { if (newBaseDir == null) { for (String prop : SERVER_PROPS) { WildFlySecurityManager.clearPropertyPrivileged(prop); } return; } WildFlySecurityManager.setPropertyPrivileged(JBOSS_SERVER_BASE_DIR, newBaseDir); WildFlySecurityManager.setPropertyPrivileged(JBOSS_SERVER_CONFIG_DIR, newBaseDir + File.separator + "configuration"); WildFlySecurityManager.setPropertyPrivileged(JBOSS_SERVER_DATA_DIR, newBaseDir + File.separator + "data"); WildFlySecurityManager.setPropertyPrivileged(JBOSS_SERVER_LOG_DIR, newBaseDir + File.separator + "log"); WildFlySecurityManager.setPropertyPrivileged(JBOSS_SERVER_TEMP_DIR, newBaseDir + File.separator + "tmp"); } }