/*
* Sakuli - Testing and Monitoring-Tool for Websites and common UIs.
*
* Copyright 2013 - 2015 the original author or authors.
*
* Licensed 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.sakuli.services.forwarder.gearman;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.time.DateUtils;
import org.gearman.client.*;
import org.gearman.common.GearmanJobServerConnection;
import org.mockito.*;
import org.sakuli.BaseTest;
import org.sakuli.builder.TestCaseExampleBuilder;
import org.sakuli.builder.TestCaseStepExampleBuilder;
import org.sakuli.builder.TestSuiteExampleBuilder;
import org.sakuli.datamodel.TestSuite;
import org.sakuli.exceptions.SakuliActionException;
import org.sakuli.exceptions.SakuliExceptionHandler;
import org.sakuli.exceptions.SakuliForwarderException;
import org.sakuli.exceptions.SakuliRuntimeException;
import org.sakuli.services.forwarder.gearman.crypt.Aes;
import org.sakuli.services.forwarder.gearman.model.NagiosCachedCheckResult;
import org.sakuli.services.forwarder.gearman.model.NagiosCheckResult;
import org.sakuli.services.forwarder.gearman.model.builder.NagiosCheckResultBuilder;
import org.springframework.test.util.ReflectionTestUtils;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.nio.channels.UnresolvedAddressException;
import java.util.*;
import java.util.concurrent.Future;
import static org.mockito.Mockito.*;
import static org.testng.Assert.assertEquals;
public class GearmanResultServiceImplTest extends BaseTest {
@Spy
@InjectMocks
private GearmanResultServiceImpl testling;
@Mock
private GearmanCacheService gearmanCacheService;
@Mock
private GearmanProperties properties;
@Mock
private SakuliExceptionHandler exceptionHandler;
@Mock
private NagiosCheckResultBuilder checkResultBuilder;
private String testResult = "type=passive\n" +
"host_name=win7sakuli\n" +
"start_time=1425729540.000\n" +
"finish_time=1425729600.000\n" +
"return_code=2\n" +
"service_description=sakuli_demo22\n" +
"output=CRITICAL - CRITICAL - [CRIT] Sakuli suite \"sakuli_demo22\" ran in 60.00 seconds - EXCEPTION: \" - CASE 'error_case': exception test message\". (Last suite run: 07.03 13:00:00)" +
"\\\\n<table style=\"border-collapse: collapse;\">" +
"<tr valign=\"top\"><td class=\"serviceCRITICAL\">[CRIT] Sakuli suite \"sakuli_demo22\" ran in 60.00 seconds - EXCEPTION: \" - CASE 'error_case': exception test message\". (Last suite run: 07.03 13:00:00)</td></tr>" +
"<tr valign=\"top\"><td class=\"serviceOK\">[OK] case \"ok_case\" ran in 12.00s - ok</td></tr>" +
"<tr valign=\"top\"><td class=\"serviceWARNING\">[WARN] case \"warn_case\" over runtime (30.00s /warning at 20s) </td></tr>" +
"<tr valign=\"top\"><td class=\"serviceWARNING\">[WARN] case \"warn_in_step\" over runtime (30.00s /warning in step at 40s) step \"warn_step_1\" (9.00s /warn at 5s), step \"warn_step_2\" (9.00s /warn at 5s)</td></tr>" +
"<tr valign=\"top\"><td class=\"serviceCRITICAL\">[CRIT] case \"crit_case\" over runtime (14.00s /critical at 13s) </td></tr>" +
"<tr valign=\"top\"><td class=\"serviceCRITICAL\">[CRIT] case \"error_case\" EXCEPTION: exception test message</td></tr></table>" +
"|" +
"suite__state=2;;;; " +
"suite_sakuli_demo22=60.00s;;;; " +
"c_1__state_ok_case=0;;;; " +
"c_1_ok_case=12.00s;13;20;; " +
"s_1_1_step_for_unit_test=1.00s;2;;; " +
"c_2__state_warn_case=1;;;; " +
"c_2_warn_case=30.00s;20;40;; " +
"s_2_1_step_for_unit_test=1.00s;2;;; " +
"c_3__state_warn_in_step=1;;;; " +
"c_3_warn_in_step=30.00s;40;50;; " +
"s_3_1_warn_step_1=9.00s;5;;; " +
"s_3_2_warn_step_2=9.00s;5;;; " +
"c_4__state_crit_case=2;;;; " +
"c_4_crit_case=14.00s;10;13;; " +
"s_4_1_step_for_unit_test=1.00s;2;;; " +
"c_5__state_error_case=2;;;; " +
"c_5_error_case=-1.00s;4;5;; " +
"s_5_1_step_for_unit_test=1.00s;2;;; " +
"[check_sakuli]";
@BeforeMethod
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@BeforeClass
public void setKeyLength() {
//set key length to 16 byte in unit tests, so default Java JRE security policy applies
Aes.keyLength = 16;
}
@AfterClass(alwaysRun = true)
public void restoreKeyLength() {
//restore default key length
Aes.keyLength = Aes.DEFAULT_KEY_LENGTH;
}
@Test
public void testSaveAllResults() throws Exception {
when(properties.getServiceType()).thenReturn("passive");
final String queueName = "check_results";
when(properties.getServerQueue()).thenReturn(queueName);
final String host = "99.99.99.20";
when(properties.getServerHost()).thenReturn(host);
final int port = 4730;
when(properties.getServerPort()).thenReturn(port);
when(properties.getNagiosHost()).thenReturn("win7sakuli");
when(checkResultBuilder.build()).thenReturn(new NagiosCachedCheckResult(queueName, "sakuli_demo22__2015_03_07_12_59_00_00", testResult));
GearmanClient gearmanClient = mock(GearmanClientImpl.class);
doReturn(gearmanClient).when(testling).getGearmanClient();
GearmanJobServerConnection connection = mock(GearmanJobServerConnection.class);
doReturn(connection).when(testling).getGearmanConnection(host, port);
GearmanJob job = mock(GearmanJob.class);
doReturn(job).when(testling).creatJob(any(NagiosCheckResult.class));
Future future = mock(Future.class);
when(gearmanClient.addJobServer(connection)).thenReturn(true);
when(gearmanClient.submit(job)).thenReturn(future);
GearmanJobResult jobResult = mock(GearmanJobResult.class);
when(future.get()).thenReturn(jobResult);
when(jobResult.jobSucceeded()).thenReturn(true);
GearmanJobStatus jobStatus = mock(GearmanJobStatus.class);
when(jobStatus.isRunning()).thenReturn(false);
when(gearmanClient.getJobStatus(job)).thenReturn(jobStatus);
Date stopDate = new GregorianCalendar(2014, 14, 7, 13, 0).getTime();
TestSuite testSuite = new TestSuiteExampleBuilder()
.withHost("win7sakuli")
.withId("sakuli_demo22")
.withStopDate(stopDate)
.withStartDate(DateUtils.addSeconds(stopDate, -60))
.withTestCases(Collections.singletonList(
new TestCaseExampleBuilder()
.withId("ok_case")
.withStartDate(DateUtils.addSeconds(stopDate, -12))
.withStopDate(stopDate)
.withWarningTime(13)
.withCriticalTime(20)
.buildExample()))
.buildExample();
stopDate = DateUtils.addSeconds(stopDate, 300);
testSuite.addTestCase(new TestCaseExampleBuilder()
.withId("warn_case")
.withStartDate(DateUtils.addSeconds(stopDate, -30))
.withStopDate(stopDate)
.withWarningTime(20)
.withCriticalTime(40)
.buildExample());
stopDate = DateUtils.addSeconds(stopDate, 300);
testSuite.addTestCase(new TestCaseExampleBuilder()
.withId("warn_in_step")
.withStartDate(DateUtils.addSeconds(stopDate, -30))
.withStopDate(stopDate)
.withWarningTime(40)
.withCriticalTime(50)
.withTestCaseSteps(Arrays.asList(new TestCaseStepExampleBuilder()
.withName("warn_step_1")
.withStartDate(DateUtils.addSeconds(stopDate, -29))
.withStopDate(DateUtils.addSeconds(stopDate, -20))
.withWarningTime(5)
.buildExample(),
new TestCaseStepExampleBuilder()
.withName("warn_step_2")
.withStartDate(DateUtils.addSeconds(stopDate, -19))
.withStopDate(DateUtils.addSeconds(stopDate, -10))
.withWarningTime(5)
.buildExample()))
.buildExample());
stopDate = DateUtils.addSeconds(stopDate, 300);
testSuite.addTestCase(new TestCaseExampleBuilder()
.withId("crit_case")
.withStartDate(DateUtils.addSeconds(stopDate, -14))
.withStopDate(stopDate)
.withWarningTime(10)
.withCriticalTime(13)
.buildExample());
stopDate = DateUtils.addSeconds(stopDate, 300);
testSuite.addTestCase(new TestCaseExampleBuilder()
.withId("error_case")
.withStartDate(DateUtils.addSeconds(stopDate, -14))
.withException(new SakuliActionException("exception test message"))
.buildExample());
ReflectionTestUtils.setField(testling, "testSuite", testSuite);
testling.saveAllResults();
//checks
verify(gearmanCacheService, never()).cacheResults(anyList());
verify(gearmanCacheService, never()).getCachedResults();
verify(exceptionHandler, never()).handleException(any(Throwable.class));
verify(exceptionHandler, never()).handleException(any(Throwable.class), anyBoolean());
verify(testling).getGearmanClient();
verify(testling).getGearmanConnection(host, port);
verify(gearmanClient).addJobServer(connection);
verify(gearmanClient).submit(job);
verify(future).get();
verify(gearmanClient).shutdown();
ArgumentCaptor<NagiosCheckResult> checkresult = ArgumentCaptor.forClass(NagiosCheckResult.class);
verify(testling).creatJob(checkresult.capture());
assertEquals(checkresult.getValue().getQueueName(), queueName);
assertEquals(checkresult.getValue().getUuid(), testSuite.getGuid());
assertEquals(checkresult.getValue().getPayloadString(), testResult);
}
@Test
public void testCreateJobEncryptionDisabled() throws Exception {
when(properties.getServiceType()).thenReturn("passive");
final String queueName = "check_results";
when(properties.getServerQueue()).thenReturn(queueName);
final String host = "99.99.99.20";
when(properties.getServerHost()).thenReturn(host);
final int port = 4730;
when(properties.getServerPort()).thenReturn(port);
when(properties.getNagiosHost()).thenReturn("win7sakuli");
when(properties.isEncryption()).thenReturn(false);
GearmanJob gearmanJob = testling.creatJob(new NagiosCachedCheckResult(queueName, "sakuli_demo22__2015_03_07_12_59_00_00", testResult));
assertEquals(new String(Base64.decodeBase64(gearmanJob.getData())), testResult);
}
@Test
public void testCreateJobEncryptionEnabled() throws Exception {
when(properties.getServiceType()).thenReturn("passive");
final String queueName = "check_results";
when(properties.getServerQueue()).thenReturn(queueName);
final String host = "99.99.99.20";
when(properties.getServerHost()).thenReturn(host);
final int port = 4730;
when(properties.getServerPort()).thenReturn(port);
when(properties.getNagiosHost()).thenReturn("win7sakuli");
when(properties.isEncryption()).thenReturn(true);
final String secretKey = "abcdefghijklmnopqrstuvwxyz";
when(properties.getSecretKey()).thenReturn(secretKey);
GearmanJob gearmanJob = testling.creatJob(new NagiosCachedCheckResult(queueName, "sakuli_demo22__2015_03_07_12_59_00_00", testResult));
assertEquals(Aes.decrypt(gearmanJob.getData(), secretKey), testResult);
}
@Test
public void testSaveAllResultsConnectionFailed() throws Exception {
when(properties.getServiceType()).thenReturn("passive");
final String queueName = "check_results";
when(properties.getServerQueue()).thenReturn(queueName);
final String host = "99.99.99.20";
when(properties.getServerHost()).thenReturn(host);
final int port = 4730;
when(properties.getServerPort()).thenReturn(port);
when(properties.getNagiosHost()).thenReturn("win7sakuli");
when(checkResultBuilder.build()).thenReturn(new NagiosCachedCheckResult(queueName, "sakuli_demo22__2015_03_07_12_59_00_00", testResult));
GearmanClient gearmanClient = mock(GearmanClientImpl.class);
doReturn(gearmanClient).when(testling).getGearmanClient();
GearmanJobServerConnection connection = mock(GearmanJobServerConnection.class);
doReturn(connection).when(testling).getGearmanConnection(host, port);
when(gearmanClient.addJobServer(connection)).thenReturn(false);
testling.saveAllResults();
//checks
verify(gearmanCacheService, never()).cacheResults(anyList());
verify(gearmanCacheService, never()).getCachedResults();
verify(exceptionHandler).handleException(any(Throwable.class), eq(true));
verify(testling).getGearmanClient();
verify(testling).getGearmanConnection(host, port);
verify(gearmanClient).addJobServer(connection);
verify(gearmanClient).shutdown();
}
@Test
public void testSaveAllResultsConnectionFailedCacheResults() throws Exception {
when(properties.getServiceType()).thenReturn("passive");
final String queueName = "check_results";
when(properties.getServerQueue()).thenReturn(queueName);
final String host = "99.99.99.20";
when(properties.getServerHost()).thenReturn(host);
final int port = 4730;
when(properties.getServerPort()).thenReturn(port);
when(properties.getNagiosHost()).thenReturn("win7sakuli");
when(properties.isCacheEnabled()).thenReturn(true);
when(checkResultBuilder.build()).thenReturn(new NagiosCachedCheckResult(queueName, "sakuli_demo22__2015_03_07_12_59_00_00", testResult));
GearmanClient gearmanClient = mock(GearmanClientImpl.class);
doReturn(gearmanClient).when(testling).getGearmanClient();
GearmanJobServerConnection connection = mock(GearmanJobServerConnection.class);
doReturn(connection).when(testling).getGearmanConnection(host, port);
when(gearmanClient.addJobServer(connection)).thenReturn(false);
when(gearmanCacheService.getCachedResults()).thenReturn(Collections.emptyList());
doAnswer(invocationOnMock -> {
assertEquals(((List) invocationOnMock.getArguments()[0]).size(), 1L);
return null;
}).when(gearmanCacheService).cacheResults(anyList());
testling.saveAllResults();
//checks
verify(gearmanCacheService).cacheResults(anyList());
verify(gearmanCacheService).getCachedResults();
verify(exceptionHandler).handleException(any(Throwable.class), eq(true));
verify(testling).getGearmanClient();
verify(testling).getGearmanConnection(host, port);
verify(gearmanClient).addJobServer(connection);
verify(gearmanClient).shutdown();
}
@Test
public void testSaveAllResultsJobSubmitFailedAddCacheResults() throws Exception {
when(properties.getServiceType()).thenReturn("passive");
final String queueName = "check_results";
when(properties.getServerQueue()).thenReturn(queueName);
final String host = "99.99.99.20";
when(properties.getServerHost()).thenReturn(host);
final int port = 4730;
when(properties.getServerPort()).thenReturn(port);
when(properties.getNagiosHost()).thenReturn("win7sakuli");
when(properties.isCacheEnabled()).thenReturn(true);
GearmanClient gearmanClient = mock(GearmanClientImpl.class);
doReturn(gearmanClient).when(testling).getGearmanClient();
GearmanJobServerConnection connection = mock(GearmanJobServerConnection.class);
doReturn(connection).when(testling).getGearmanConnection(host, port);
GearmanJob job = mock(GearmanJob.class);
doReturn(job).when(testling).creatJob(any(NagiosCheckResult.class));
when(gearmanClient.addJobServer(connection)).thenReturn(true);
when(gearmanClient.submit(job)).thenThrow(new SakuliRuntimeException("Something went wrong!"));
NagiosCheckResult mockedResult1 = Mockito.mock(NagiosCheckResult.class);
NagiosCheckResult mockedResult2 = Mockito.mock(NagiosCheckResult.class);
when(gearmanCacheService.getCachedResults()).thenReturn(Arrays.asList(mockedResult1, mockedResult2));
NagiosCheckResult newResult = new NagiosCachedCheckResult(queueName, "sakuli_demo22__2015_03_07_12_59_00_00", testResult);
when(checkResultBuilder.build()).thenReturn(newResult);
doAnswer(invocationOnMock -> {
List<NagiosCheckResult> results = ((List) invocationOnMock.getArguments()[0]);
assertEquals(results.size(), 3L);
assertEquals(results.get(0), newResult);
assertEquals(results.get(1), mockedResult1);
assertEquals(results.get(2), mockedResult2);
return null;
}).when(gearmanCacheService).cacheResults(anyList());
StringBuilder sendOrder = new StringBuilder();
doAnswer(invocationOnMock -> {
Object result = invocationOnMock.getArguments()[1];
Assert.assertTrue(result instanceof NagiosCheckResult);
sendOrder.append(result.hashCode());
return invocationOnMock.callRealMethod();
}).when(testling).sendResult(any(), any());
testling.saveAllResults();
//checks
assertEquals(sendOrder.toString(), "" + mockedResult2.hashCode() + mockedResult1.hashCode() + newResult.hashCode());
verify(gearmanCacheService).cacheResults(anyList());
verify(gearmanCacheService).getCachedResults();
verify(exceptionHandler, times(3)).handleException(any(Throwable.class), eq(true));
verify(testling).getGearmanClient();
verify(testling).getGearmanConnection(host, port);
verify(gearmanClient).addJobServer(connection);
verify(gearmanClient).shutdown();
}
@Test
public void testSaveAllResultsConnectionFailedAddCacheResults() throws Exception {
when(properties.getServiceType()).thenReturn("passive");
final String queueName = "check_results";
when(properties.getServerQueue()).thenReturn(queueName);
final String host = "99.99.99.20";
when(properties.getServerHost()).thenReturn(host);
final int port = 4730;
when(properties.getServerPort()).thenReturn(port);
when(properties.getNagiosHost()).thenReturn("win7sakuli");
when(properties.isCacheEnabled()).thenReturn(true);
GearmanClient gearmanClient = mock(GearmanClientImpl.class);
doReturn(gearmanClient).when(testling).getGearmanClient();
GearmanJobServerConnection connection = mock(GearmanJobServerConnection.class);
doReturn(connection).when(testling).getGearmanConnection(host, port);
GearmanJob job = mock(GearmanJob.class);
doReturn(job).when(testling).creatJob(any(NagiosCheckResult.class));
when(gearmanClient.addJobServer(connection)).thenReturn(false);
NagiosCheckResult mockedResult1 = Mockito.mock(NagiosCheckResult.class);
when(gearmanCacheService.getCachedResults()).thenReturn(Collections.singletonList(mockedResult1));
NagiosCheckResult newResult = new NagiosCachedCheckResult(queueName, "sakuli_demo22__2015_03_07_12_59_00_00", testResult);
when(checkResultBuilder.build()).thenReturn(newResult);
doAnswer(invocationOnMock -> {
List<NagiosCheckResult> results = ((List) invocationOnMock.getArguments()[0]);
assertEquals(results.size(), 2L);
assertEquals(results.get(0), newResult);
assertEquals(results.get(1), mockedResult1);
return null;
}).when(gearmanCacheService).cacheResults(anyList());
testling.saveAllResults();
//checks
verify(gearmanCacheService).cacheResults(anyList());
verify(gearmanCacheService).getCachedResults();
verify(exceptionHandler).handleException(any(Throwable.class), eq(true));
verify(testling).getGearmanClient();
verify(testling).getGearmanConnection(host, port);
verify(gearmanClient).addJobServer(connection);
verify(gearmanClient).shutdown();
}
@Test
public void testSaveAllResultsWrongConnectionCacheResults() throws Exception {
when(properties.getServiceType()).thenReturn("passive");
final String queueName = "check_results";
when(properties.getServerQueue()).thenReturn(queueName);
final String host = "not-resolveable-host.de";
when(properties.getServerHost()).thenReturn(host);
final int port = 4730;
when(properties.getServerPort()).thenReturn(port);
when(properties.getNagiosHost()).thenReturn("win7sakuli");
when(properties.isCacheEnabled()).thenReturn(true);
when(checkResultBuilder.build()).thenReturn(new NagiosCachedCheckResult(queueName, "sakuli_demo22__2015_03_07_12_59_00_00", testResult));
GearmanClient gearmanClient = mock(GearmanClientImpl.class);
doReturn(gearmanClient).when(testling).getGearmanClient();
GearmanJobServerConnection connection = mock(GearmanJobServerConnection.class);
doReturn(connection).when(testling).getGearmanConnection(host, port);
when(gearmanClient.addJobServer(connection)).thenThrow(new UnresolvedAddressException());
when(gearmanCacheService.getCachedResults()).thenReturn(Collections.emptyList());
doAnswer(invocationOnMock -> {
assertEquals(((List) invocationOnMock.getArguments()[0]).size(), 1L);
return null;
}).when(gearmanCacheService).cacheResults(anyList());
doAnswer(invocationOnMock -> {
Exception exception = (Exception) invocationOnMock.getArguments()[0];
assertRegExMatch(exception.getMessage(),
"Could not transfer Sakuli results to the Gearman server.*");
assertEquals(exception.getSuppressed()[0].getClass(), UnresolvedAddressException.class);
return null;
}).when(exceptionHandler).handleException(any(Throwable.class), anyBoolean());
testling.saveAllResults();
//checks
verify(gearmanCacheService).cacheResults(anyList());
verify(gearmanCacheService).getCachedResults();
verify(exceptionHandler).handleException(any(SakuliForwarderException.class), anyBoolean());
verify(testling).getGearmanClient();
verify(testling).getGearmanConnection(host, port);
verify(gearmanClient).addJobServer(connection);
verify(gearmanClient).shutdown();
}
}