/**
* Copyright (c) Codice Foundation
* <p/>
* 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 3 of the
* License, or any later version.
* <p/>
* This program 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. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package ddf.platform.scheduler;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.concurrent.Callable;
import org.apache.karaf.shell.api.console.Session;
import org.apache.karaf.shell.api.console.SessionFactory;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.stubbing.Answer;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.security.Subject;
/**
* Tests the {@link CommandJob} class.
*
* @author Ashraf Barakat
* @author ddf.isgs@lmco.com
*/
public class CommandJobTest {
private static final Logger LOGGER = LoggerFactory.getLogger(CommandJobTest.class);
private SessionFactory sessionFactory;
@Before
public void setup() {
sessionFactory = mock(SessionFactory.class);
}
/**
* Do no execution when no command processor available
*
* @throws Exception
*/
@Test
public void testNoCommandProcessor() throws Exception {
// given
String command = "info";
CommandJob job = getCommandJob();
// when
job.execute(getJobExecutionContext(command));
// then
/* we should not have a problem */
}
/**
* Do not execute command on null input
*
* @throws Exception
*/
@SuppressWarnings("ConstantConditions")
@Test
public void testNullCommand() throws Exception {
// given
String command = null;
FirstArgumentAnswer captureInput = new FirstArgumentAnswer();
Session session = getSession(captureInput);
when(sessionFactory.create(any(), any(), any())).thenReturn(session);
CommandJob job = getCommandJob();
// when
job.execute(getJobExecutionContext(command));
// then
verifySessionCalls(command, session, 0, 1);
}
/**
* An empty command will be executed
*
* @throws Exception
*/
@Test
public void testEmptyCommand() throws Exception {
// given
String command = "";
FirstArgumentAnswer captureInput = new FirstArgumentAnswer();
Session session = getSession(captureInput);
when(sessionFactory.create(any(), any(), any())).thenReturn(session);
CommandJob job = getCommandJob();
// when
job.execute(getJobExecutionContext(command));
// then
assertThat(captureInput.getInputArg(), is(command));
verifySessionCalls(command, session, 1, 1);
}
/**
* Tests the simplest command will be executed.
*
* @throws Exception
*/
@Test
public void testSimpleCommand() throws Exception {
// given
String command = "info";
FirstArgumentAnswer captureInput = new FirstArgumentAnswer();
Session session = getSession(captureInput);
when(sessionFactory.create(any(), any(), any())).thenReturn(session);
CommandJob job = getCommandJob();
// when
job.execute(getJobExecutionContext(command));
// then
assertThat(captureInput.getInputArg(), is(command));
verifySessionCalls(command, session, 1, 1);
}
@Test
public void testNullContext() throws JobExecutionException {
CommandJob job = getCommandJob();
job.doExecute(null);
}
@Test
public void testNullMergedJobDataMap() throws JobExecutionException {
CommandJob job = getCommandJob();
JobExecutionContext jobExecutionContext = mock(JobExecutionContext.class);
when(jobExecutionContext.getMergedJobDataMap()).thenReturn(null);
job.doExecute(jobExecutionContext);
}
private CommandJob getCommandJob() {
return new CommandJob() {
@SuppressWarnings("unchecked")
@Override
public Subject getSystemSubject() {
Subject subject = mock(Subject.class);
when(subject.execute(Matchers.<Callable<Object>>any())).thenAnswer(invocation -> {
Callable<Object> callable = (Callable<Object>) invocation.getArguments()[0];
return callable.call();
});
return subject;
}
@Override
protected SessionFactory getSessionFactory() {
return sessionFactory;
}
};
}
void verifySessionCalls(String command, Session session, int expectedAmountOfCalls,
int expectedTimesToClose) throws Exception {
verify(session, times(expectedAmountOfCalls)).execute(command);
verify(session, times(expectedTimesToClose)).close();
}
private Session getSession(Answer<String> captureInput) {
Session session = mock(Session.class);
try {
when(session.execute(isA(CharSequence.class))).then(captureInput);
} catch (Exception e) {
LOGGER.error("Exception occurred during command session", e);
}
return session;
}
private JobExecutionContext getJobExecutionContext(String command) {
JobExecutionContext context = mock(JobExecutionContext.class);
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put(CommandJob.COMMAND_KEY, command);
when(context.getMergedJobDataMap()).thenReturn(jobDataMap);
return context;
}
}