blob: a533aeb2991f4d1356d789a9d87c9f2946ea852d [file] [log] [blame]
/*
* 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.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
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.contrib.java.lang.system.RestoreSystemProperties;
import org.junit.rules.TemporaryFolder;
import org.apache.geode.management.internal.cli.LogWrapper;
/**
* 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.
*/
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 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();
@Rule
public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
/*
* 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);
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();
}
Gfsh.getCurrentInstance().stop();
}
@Before
public void setUp() 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(null);
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 {}
}
}