/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.management.internal.cli.commands; import static org.apache.geode.distributed.ConfigurationProperties.*; import static org.apache.geode.test.dunit.Assert.*; import static org.apache.geode.test.dunit.LogWriterUtils.*; import java.io.File; import java.io.IOException; import java.util.Properties; import org.apache.geode.management.cli.Result.Status; import org.apache.geode.management.internal.cli.i18n.CliStrings; import org.apache.geode.management.internal.cli.json.GfJsonException; import org.apache.geode.management.internal.cli.result.CommandResult; import org.apache.geode.management.internal.cli.util.CommandStringBuilder; import org.apache.geode.test.dunit.Host; import org.apache.geode.test.dunit.SerializableRunnable; import org.apache.geode.test.dunit.VM; import org.apache.geode.test.junit.categories.DistributedTest; import org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.rules.TemporaryFolder; /*** * DUnit test for 'show stack-trace' command */ @Category(DistributedTest.class) public class ShowStackTraceDUnitTest extends CliCommandTestBase { private static final long serialVersionUID = 1L; @Rule public TemporaryFolder workDirectory = new SerializableTemporaryFolder(); private void createCache(Properties props) { getSystem(props); getCache(); } private Properties createProperties(Host host, String name, String groups) { Properties props = new Properties(); props.setProperty(MCAST_PORT, "0"); props.setProperty(LOG_LEVEL, "info"); props.setProperty(STATISTIC_SAMPLING_ENABLED, "true"); props.setProperty(ENABLE_TIME_STATISTICS, "true"); props.setProperty(NAME, name); props.setProperty(GROUPS, groups); return props; } /*** * Sets up a system of 3 peers */ private void setupSystem() { disconnectAllFromDS(); final Host host = Host.getHost(0); final VM[] servers = {host.getVM(0), host.getVM(1)}; final Properties propsManager = createProperties(host, "Manager", "G1"); final Properties propsServer2 = createProperties(host, "Server", "G2"); setUpJmxManagerOnVm0ThenConnect(propsManager); servers[1].invoke(new SerializableRunnable("Create cache for server1") { public void run() { createCache(propsServer2); } }); } /*** * Tests the default behavior of the show stack-trace command * * @throws ClassNotFoundException * @throws IOException */ @Test public void testExportStacktrace() throws ClassNotFoundException, IOException { setupSystem(); File allStacktracesFile = workDirectory.newFile("allStackTraces.txt"); CommandStringBuilder csb = new CommandStringBuilder(CliStrings.EXPORT_STACKTRACE); csb.addOption(CliStrings.EXPORT_STACKTRACE__FILE, allStacktracesFile.getCanonicalPath()); String commandString = csb.toString(); getLogWriter().info("CommandString : " + commandString); CommandResult commandResult = executeCommand(commandString); getLogWriter().info("Output : \n" + commandResultToString(commandResult)); assertTrue(commandResult.getStatus().equals(Status.OK)); File mgrStacktraceFile = workDirectory.newFile("managerStacktrace.txt"); csb = new CommandStringBuilder(CliStrings.EXPORT_STACKTRACE); csb.addOption(CliStrings.EXPORT_STACKTRACE__FILE, mgrStacktraceFile.getCanonicalPath()); csb.addOption(CliStrings.EXPORT_STACKTRACE__MEMBER, "Manager"); commandString = csb.toString(); getLogWriter().info("CommandString : " + commandString); commandResult = executeCommand(commandString); getLogWriter().info("Output : \n" + commandResultToString(commandResult)); assertTrue(commandResult.getStatus().equals(Status.OK)); File serverStacktraceFile = workDirectory.newFile("serverStacktrace.txt"); csb = new CommandStringBuilder(CliStrings.EXPORT_STACKTRACE); csb.addOption(CliStrings.EXPORT_STACKTRACE__FILE, serverStacktraceFile.getCanonicalPath()); csb.addOption(CliStrings.EXPORT_STACKTRACE__MEMBER, "Server"); commandString = csb.toString(); getLogWriter().info("CommandString : " + commandString); commandResult = executeCommand(commandString); getLogWriter().info("Output : \n" + commandResultToString(commandResult)); assertTrue(commandResult.getStatus().equals(Status.OK)); File groupStacktraceFile = workDirectory.newFile("groupstacktrace.txt"); csb = new CommandStringBuilder(CliStrings.EXPORT_STACKTRACE); csb.addOption(CliStrings.EXPORT_STACKTRACE__FILE, groupStacktraceFile.getCanonicalPath()); csb.addOption(CliStrings.EXPORT_STACKTRACE__GROUP, "G2"); commandString = csb.toString(); getLogWriter().info("CommandString : " + commandString); commandResult = executeCommand(commandString); getLogWriter().info("Output : \n" + commandResultToString(commandResult)); assertTrue(commandResult.getStatus().equals(Status.OK)); File wrongStackTraceFile = workDirectory.newFile("wrongStackTrace.txt"); csb = new CommandStringBuilder(CliStrings.EXPORT_STACKTRACE); csb.addOption(CliStrings.EXPORT_STACKTRACE__FILE, wrongStackTraceFile.getCanonicalPath()); csb.addOption(CliStrings.EXPORT_STACKTRACE__MEMBER, "WrongMember"); commandString = csb.toString(); getLogWriter().info("CommandString : " + commandString); commandResult = executeCommand(commandString); getLogWriter().info("Output : \n" + commandResultToString(commandResult)); assertFalse(commandResult.getStatus().equals(Status.OK)); } /*** * Tests the behavior of the show stack-trace command to verify that files with any extension are * allowed Refer: GEODE-734 * * @throws ClassNotFoundException * @throws IOException */ @Test public void testExportStacktraceWithNonTXTFile() throws ClassNotFoundException, IOException { setupSystem(); // Test non txt extension file is allowed File stacktracesFile = workDirectory.newFile("allStackTraces.log"); CommandStringBuilder commandStringBuilder = new CommandStringBuilder(CliStrings.EXPORT_STACKTRACE); commandStringBuilder.addOption(CliStrings.EXPORT_STACKTRACE__FILE, stacktracesFile.getCanonicalPath()); String exportCommandString = commandStringBuilder.toString(); getLogWriter().info("CommandString : " + exportCommandString); CommandResult exportCommandResult = executeCommand(exportCommandString); getLogWriter().info("Output : \n" + commandResultToString(exportCommandResult)); assertTrue(exportCommandResult.getStatus().equals(Status.OK)); // test file with-out any extension File allStacktracesFile = workDirectory.newFile("allStackTraces"); commandStringBuilder = new CommandStringBuilder(CliStrings.EXPORT_STACKTRACE); commandStringBuilder.addOption(CliStrings.EXPORT_STACKTRACE__FILE, allStacktracesFile.getCanonicalPath()); exportCommandString = commandStringBuilder.toString(); getLogWriter().info("CommandString : " + exportCommandString); exportCommandResult = executeCommand(exportCommandString); getLogWriter().info("Output : \n" + commandResultToString(exportCommandResult)); assertTrue(exportCommandResult.getStatus().equals(Status.OK)); } /*** * Tests the behavior of the show stack-trace command when file is already present and * abort-if-file-exists option is set to false(which is default). As a result it should overwrite * the file and return OK status * * @throws ClassNotFoundException * @throws IOException */ @Test public void testExportStacktraceWhenFilePresent() throws ClassNotFoundException, IOException { setupSystem(); // test pass although file present File stacktracesFile = workDirectory.newFile("allStackTraces.log"); CommandStringBuilder commandStringBuilder = new CommandStringBuilder(CliStrings.EXPORT_STACKTRACE); commandStringBuilder.addOption(CliStrings.EXPORT_STACKTRACE__FILE, stacktracesFile.getCanonicalPath()); String exportCommandString = commandStringBuilder.toString(); getLogWriter().info("CommandString : " + exportCommandString); CommandResult exportCommandResult = executeCommand(exportCommandString); getLogWriter().info("Output : \n" + commandResultToString(exportCommandResult)); assertTrue(exportCommandResult.getStatus().equals(Status.OK)); } /*** * Tests the behavior of the show stack-trace command when file is already present and when * abort-if-file-exists option is set to true. As a result it should fail with ERROR status * * @throws ClassNotFoundException * @throws IOException */ @Test public void testExportStacktraceFilePresentWithAbort() throws ClassNotFoundException, IOException, GfJsonException { setupSystem(); File stacktracesFile = workDirectory.newFile("allStackTraces.log"); CommandStringBuilder commandStringBuilder = new CommandStringBuilder(CliStrings.EXPORT_STACKTRACE); commandStringBuilder.addOption(CliStrings.EXPORT_STACKTRACE__FILE, stacktracesFile.getCanonicalPath()); commandStringBuilder.addOption(CliStrings.EXPORT_STACKTRACE__FAIL__IF__FILE__PRESENT, Boolean.TRUE.toString()); String exportCommandString = commandStringBuilder.toString(); getLogWriter().info("CommandString : " + exportCommandString); CommandResult exportCommandResult = executeCommand(exportCommandString); getLogWriter().info("Output : \n" + commandResultToString(exportCommandResult)); assertTrue(exportCommandResult.getStatus().equals(Status.ERROR)); assertTrue(((String) exportCommandResult.getResultData().getGfJsonObject() .getJSONObject("content").getJSONArray("message").get(0)) .contains("file " + stacktracesFile.getCanonicalPath() + " already present")); } /*** * Tests the behavior of the show stack-trace command when file option is not provided File should * get auto-generated * * @throws ClassNotFoundException * @throws IOException */ @Test public void testExportStacktraceAutoGenerateFile() throws ClassNotFoundException, IOException, GfJsonException { setupSystem(); // test auto generated file when file name is not provided CommandStringBuilder commandStringBuilder = new CommandStringBuilder(CliStrings.EXPORT_STACKTRACE); String exportCommandString = commandStringBuilder.toString(); getLogWriter().info("CommandString : " + exportCommandString); CommandResult exportCommandResult = executeCommand(exportCommandString); getLogWriter().info("Output : \n" + commandResultToString(exportCommandResult)); assertTrue(exportCommandResult.getStatus().equals(Status.OK)); assertTrue( ((String) exportCommandResult.getResultData().getGfJsonObject().getJSONObject("content") .getJSONArray("message").get(0)).contains("stack-trace(s) exported to file:")); } }