/* * 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.shell; import static org.junit.Assert.*; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.logging.Handler; import java.util.logging.LogRecord; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.rules.TemporaryFolder; import org.apache.geode.management.internal.cli.LogWrapper; import org.apache.geode.test.junit.categories.UnitTest; /** * Unit tests for supplying an init file to Gfsh. * </P> * Makes use of reflection to reset private static variables on some classes to replace loggers that * would otherwise clutter the console. */ @Category(UnitTest.class) public class GfshInitFileJUnitTest { private static final String INIT_FILE_NAME = GfshConfig.DEFAULT_INIT_FILE_NAME; private static final boolean APPEND = true; private static final int BANNER_LINES = 1; private static final int INIT_FILE_CITATION_LINES = 1; private static String saveLog4j2Config; private static String saveUserDir; private static String saveUserHome; private static java.util.logging.Logger julLogger; private static Handler[] saveHandlers; private ByteArrayOutputStream sysout = new ByteArrayOutputStream(); private String gfshHistoryFileName; private LogWrapper gfshFileLogger; private JUnitLoggerHandler junitLoggerHandler; @ClassRule public static TemporaryFolder temporaryFolder_Config = new TemporaryFolder(); @Rule public TemporaryFolder temporaryFolder_CurrentDirectory = new TemporaryFolder(); /* * Turn off console logging from JUL and Log4j2 for the duration of this class's tests, to reduce * noise level of output in automated build. */ @BeforeClass public static void setUpBeforeClass() throws Exception { saveLog4j2Config = System.getProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY); saveUserDir = System.getProperty("user.dir"); saveUserHome = System.getProperty("user.home"); julLogger = java.util.logging.Logger.getLogger(""); saveHandlers = julLogger.getHandlers(); for (Handler handler : saveHandlers) { julLogger.removeHandler(handler); } File log4j2XML = temporaryFolder_Config.newFile("log4j2.xml"); FileUtils.writeStringToFile(log4j2XML, "<Configuration/>", APPEND); System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, log4j2XML.toURI().toString()); } /* * Restore logging to state prior to the execution of this class */ @AfterClass public static void tearDownAfterClass() throws Exception { for (Handler handler : saveHandlers) { julLogger.addHandler(handler); } if (saveLog4j2Config == null) { System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY); } else { System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, saveLog4j2Config); ((LoggerContext) LogManager.getContext(false)).reconfigure(); } if (saveUserDir == null) { System.clearProperty("user.dir"); } else { System.setProperty("user.dir", saveUserDir); } if (saveUserHome == null) { System.clearProperty("user.home"); } else { System.setProperty("user.home", saveUserHome); } } /* * Reset $HOME and current directory for tests, and confirm this has been accepted. */ @Before public void setUp() throws Exception { // Fake running from home directory String userDir = temporaryFolder_CurrentDirectory.getRoot().getAbsolutePath(); String userHome = userDir; System.setProperty("user.dir", userDir); System.setProperty("user.home", userHome); // Abort all tests if system properties cannot be overridden assertEquals("user.dir", System.getProperty("user.dir"), userDir); assertEquals("user.home", System.getProperty("user.home"), userHome); } @Before public void setUp2() throws Exception { // Null out static instance so can reinitialise Field gfsh_instance = Gfsh.class.getDeclaredField("instance"); gfsh_instance.setAccessible(true); gfsh_instance.set(null, null); this.junitLoggerHandler = new JUnitLoggerHandler(); this.gfshFileLogger = LogWrapper.getInstance(); Field logWrapper_INSTANCE = LogWrapper.class.getDeclaredField("INSTANCE"); logWrapper_INSTANCE.setAccessible(true); logWrapper_INSTANCE.set(null, this.gfshFileLogger); Field logWrapper_logger = LogWrapper.class.getDeclaredField("logger"); logWrapper_logger.setAccessible(true); julLogger.addHandler(this.junitLoggerHandler); logWrapper_logger.set(this.gfshFileLogger, julLogger); Gfsh.gfshout = new PrintStream(sysout); this.gfshHistoryFileName = temporaryFolder_CurrentDirectory.newFile("historyFile").getAbsolutePath(); } @After public void tearDown() throws Exception { julLogger.removeHandler(this.junitLoggerHandler); } @Test public void testInitFile_NotProvided() throws Exception { /* * String historyFileName, String defaultPrompt, int historySize, String logDir, Level logLevel, * Integer logLimit, Integer logCount, String initFileName */ GfshConfig gfshConfig = new GfshConfig(this.gfshHistoryFileName, "", 0, temporaryFolder_CurrentDirectory.getRoot().getAbsolutePath(), null, null, null, null); assertNull(INIT_FILE_NAME, gfshConfig.getInitFileName()); /* * boolean launchShell, String[] args, GfshConfig gfshConfig */ Gfsh gfsh = Gfsh.getInstance(false, new String[] {}, gfshConfig); int actualStatus = gfsh.getLastExecutionStatus(); int expectedStatus = 0; assertEquals("Status 0==success", expectedStatus, actualStatus); int expectedLogCount = BANNER_LINES; assertEquals("Log records written", expectedLogCount, this.junitLoggerHandler.getLog().size()); for (LogRecord logRecord : this.junitLoggerHandler.getLog()) { assertNull("No exceptions in log", logRecord.getThrown()); } } @Test public void testInitFile_NotFound() throws Exception { // Construct the file name but not the file String initFileName = temporaryFolder_CurrentDirectory.getRoot().getAbsolutePath() + File.separator + INIT_FILE_NAME; /* * String historyFileName, String defaultPrompt, int historySize, String logDir, Level logLevel, * Integer logLimit, Integer logCount, String initFileName */ GfshConfig gfshConfig = new GfshConfig(this.gfshHistoryFileName, "", 0, temporaryFolder_CurrentDirectory.getRoot().getAbsolutePath(), null, null, null, initFileName); assertNotNull(INIT_FILE_NAME, gfshConfig.getInitFileName()); /* * boolean launchShell, String[] args, GfshConfig gfshConfig */ Gfsh gfsh = Gfsh.getInstance(false, new String[] {}, gfshConfig); int actualStatus = gfsh.getLastExecutionStatus(); int expectedStatus = 0; assertNotEquals("Status <0==failure", expectedStatus, actualStatus); int expectedLogCount = BANNER_LINES + INIT_FILE_CITATION_LINES + 1; assertEquals("Log records written", expectedLogCount, this.junitLoggerHandler.getLog().size()); Throwable exception = null; for (LogRecord logRecord : this.junitLoggerHandler.getLog()) { if (logRecord.getThrown() != null) { exception = logRecord.getThrown(); break; } } assertNotNull("Exceptions in log", exception); } @Test public void testInitFile_Empty() throws Exception { File initFile = temporaryFolder_CurrentDirectory.newFile(INIT_FILE_NAME); /* * String historyFileName, String defaultPrompt, int historySize, String logDir, Level logLevel, * Integer logLimit, Integer logCount, String initFileName */ GfshConfig gfshConfig = new GfshConfig(this.gfshHistoryFileName, "", 0, temporaryFolder_CurrentDirectory.getRoot().getAbsolutePath(), null, null, null, initFile.getAbsolutePath()); assertNotNull(INIT_FILE_NAME, gfshConfig.getInitFileName()); /* * boolean launchShell, String[] args, GfshConfig gfshConfig */ Gfsh gfsh = Gfsh.getInstance(false, new String[] {}, gfshConfig); int actualStatus = gfsh.getLastExecutionStatus(); int expectedStatus = 0; assertEquals("Status 0==success", expectedStatus, actualStatus); int expectedLogCount = BANNER_LINES + INIT_FILE_CITATION_LINES + 1; assertEquals("Log records written", expectedLogCount, this.junitLoggerHandler.getLog().size()); for (LogRecord logRecord : this.junitLoggerHandler.getLog()) { assertNull("No exceptions in log", logRecord.getThrown()); } } @Test public void testInitFile_OneGoodCommand() throws Exception { File initFile = temporaryFolder_CurrentDirectory.newFile(INIT_FILE_NAME); FileUtils.writeStringToFile(initFile, "echo --string=hello" + Gfsh.LINE_SEPARATOR, APPEND); /* * String historyFileName, String defaultPrompt, int historySize, String logDir, Level logLevel, * Integer logLimit, Integer logCount, String initFileName */ GfshConfig gfshConfig = new GfshConfig(this.gfshHistoryFileName, "", 0, temporaryFolder_CurrentDirectory.getRoot().getAbsolutePath(), null, null, null, initFile.getAbsolutePath()); assertNotNull(INIT_FILE_NAME, gfshConfig.getInitFileName()); /* * boolean launchShell, String[] args, GfshConfig gfshConfig */ Gfsh gfsh = Gfsh.getInstance(false, new String[] {}, gfshConfig); int actualStatus = gfsh.getLastExecutionStatus(); int expectedStatus = 0; assertEquals("Status 0==success", expectedStatus, actualStatus); int expectedLogCount = BANNER_LINES + INIT_FILE_CITATION_LINES + 1; assertEquals("Log records written", expectedLogCount, this.junitLoggerHandler.getLog().size()); for (LogRecord logRecord : this.junitLoggerHandler.getLog()) { assertNull("No exceptions in log", logRecord.getThrown()); } } @Test public void testInitFile_TwoGoodCommands() throws Exception { File initFile = temporaryFolder_CurrentDirectory.newFile(INIT_FILE_NAME); FileUtils.writeStringToFile(initFile, "echo --string=hello" + Gfsh.LINE_SEPARATOR, APPEND); FileUtils.writeStringToFile(initFile, "echo --string=goodbye" + Gfsh.LINE_SEPARATOR, APPEND); /* * String historyFileName, String defaultPrompt, int historySize, String logDir, Level logLevel, * Integer logLimit, Integer logCount, String initFileName */ GfshConfig gfshConfig = new GfshConfig(this.gfshHistoryFileName, "", 0, temporaryFolder_CurrentDirectory.getRoot().getAbsolutePath(), null, null, null, initFile.getAbsolutePath()); assertNotNull(INIT_FILE_NAME, gfshConfig.getInitFileName()); /* * boolean launchShell, String[] args, GfshConfig gfshConfig */ Gfsh gfsh = Gfsh.getInstance(false, new String[] {}, gfshConfig); int actualStatus = gfsh.getLastExecutionStatus(); int expectedStatus = 0; assertEquals("Status 0==success", expectedStatus, actualStatus); int expectedLogCount = BANNER_LINES + INIT_FILE_CITATION_LINES + 1; assertEquals("Log records written", expectedLogCount, this.junitLoggerHandler.getLog().size()); for (LogRecord logRecord : this.junitLoggerHandler.getLog()) { assertNull("No exceptions in log", logRecord.getThrown()); } } @Test public void testInitFile_OneBadCommand() throws Exception { File initFile = temporaryFolder_CurrentDirectory.newFile(INIT_FILE_NAME); FileUtils.writeStringToFile(initFile, "fail" + Gfsh.LINE_SEPARATOR, APPEND); /* * String historyFileName, String defaultPrompt, int historySize, String logDir, Level logLevel, * Integer logLimit, Integer logCount, String initFileName */ GfshConfig gfshConfig = new GfshConfig(this.gfshHistoryFileName, "", 0, temporaryFolder_CurrentDirectory.getRoot().getAbsolutePath(), null, null, null, initFile.getAbsolutePath()); assertNotNull(INIT_FILE_NAME, gfshConfig.getInitFileName()); /* * boolean launchShell, String[] args, GfshConfig gfshConfig */ Gfsh gfsh = Gfsh.getInstance(false, new String[] {}, gfshConfig); int actualStatus = gfsh.getLastExecutionStatus(); int expectedStatus = 0; assertNotEquals("Status <0==failure", expectedStatus, actualStatus); // after upgrading to Spring-shell 1.2, the bad command exception is logged as well int expectedLogCount = BANNER_LINES + INIT_FILE_CITATION_LINES + 2; assertEquals("Log records written", expectedLogCount, this.junitLoggerHandler.getLog().size()); } @Test public void testInitFile_TwoBadCommands() throws Exception { File initFile = temporaryFolder_CurrentDirectory.newFile(INIT_FILE_NAME); FileUtils.writeStringToFile(initFile, "fail" + Gfsh.LINE_SEPARATOR, APPEND); FileUtils.writeStringToFile(initFile, "fail" + Gfsh.LINE_SEPARATOR, APPEND); /* * String historyFileName, String defaultPrompt, int historySize, String logDir, Level logLevel, * Integer logLimit, Integer logCount, String initFileName */ GfshConfig gfshConfig = new GfshConfig(this.gfshHistoryFileName, "", 0, temporaryFolder_CurrentDirectory.getRoot().getAbsolutePath(), null, null, null, initFile.getAbsolutePath()); assertNotNull(INIT_FILE_NAME, gfshConfig.getInitFileName()); /* * boolean launchShell, String[] args, GfshConfig gfshConfig */ Gfsh gfsh = Gfsh.getInstance(false, new String[] {}, gfshConfig); int actualStatus = gfsh.getLastExecutionStatus(); int expectedStatus = 0; assertNotEquals("Status <0==failure", expectedStatus, actualStatus); // after upgrading to Spring-shell 1.2, the bad command exception is logged as well int expectedLogCount = BANNER_LINES + INIT_FILE_CITATION_LINES + 2; assertEquals("Log records written", expectedLogCount, this.junitLoggerHandler.getLog().size()); } @Test public void testInitFile_BadAndGoodCommands() throws Exception { File initFile = temporaryFolder_CurrentDirectory.newFile(INIT_FILE_NAME); FileUtils.writeStringToFile(initFile, "fail" + Gfsh.LINE_SEPARATOR, APPEND); FileUtils.writeStringToFile(initFile, "echo --string=goodbye" + Gfsh.LINE_SEPARATOR, APPEND); /* * String historyFileName, String defaultPrompt, int historySize, String logDir, Level logLevel, * Integer logLimit, Integer logCount, String initFileName */ GfshConfig gfshConfig = new GfshConfig(this.gfshHistoryFileName, "", 0, temporaryFolder_CurrentDirectory.getRoot().getAbsolutePath(), null, null, null, initFile.getAbsolutePath()); assertNotNull(INIT_FILE_NAME, gfshConfig.getInitFileName()); /* * boolean launchShell, String[] args, GfshConfig gfshConfig */ Gfsh gfsh = Gfsh.getInstance(false, new String[] {}, gfshConfig); int actualStatus = gfsh.getLastExecutionStatus(); int expectedStatus = 0; assertNotEquals("Status <0==failure", expectedStatus, actualStatus); // after upgrading to Spring-shell 1.2, the bad command exception is logged as well int expectedLogCount = BANNER_LINES + INIT_FILE_CITATION_LINES + 2; assertEquals("Log records written", expectedLogCount, this.junitLoggerHandler.getLog().size()); } /** * Log handler for testing. Capture logged messages for later inspection. * * @see java.util.logging.Handler#publish(java.util.logging.LogRecord) */ private static class JUnitLoggerHandler extends Handler { private List<LogRecord> log; public JUnitLoggerHandler() { log = new ArrayList<>(); } public List<LogRecord> getLog() { return log; } @Override public void publish(LogRecord record) { log.add(record); } @Override public void flush() {} @Override public void close() throws SecurityException {} } }