blob: 5e5aa169412b0f516d0489e02c779de7bc7459d2 [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 SF 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.felix.hc.core.impl.servlet;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.contains;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.MockitoAnnotations.initMocks;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.hc.api.Result;
import org.apache.felix.hc.api.Result.Status;
import org.apache.felix.hc.api.execution.HealthCheckExecutionOptions;
import org.apache.felix.hc.api.execution.HealthCheckExecutionResult;
import org.apache.felix.hc.api.execution.HealthCheckExecutor;
import org.apache.felix.hc.api.execution.HealthCheckMetadata;
import org.apache.felix.hc.api.execution.HealthCheckSelector;
import org.apache.felix.hc.core.impl.executor.ExecutionResult;
import org.hamcrest.Description;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
public class HealthCheckExecutorServletTest {
@InjectMocks
private HealthCheckExecutorServlet healthCheckExecutorServlet = new HealthCheckExecutorServlet();
@Mock
private HttpServletRequest request;
@Mock
private HttpServletResponse response;
@Mock
private HealthCheckExecutor healthCheckExecutor;
@Mock
private ResultHtmlSerializer htmlSerializer;
@Mock
private ResultJsonSerializer jsonSerializer;
@Mock
private ResultTxtSerializer txtSerializer;
@Mock
private ResultTxtVerboseSerializer verboseTxtSerializer;
@Mock
private ServiceReference hcServiceRef;
@Mock
private PrintWriter writer;
@Mock
private HealthCheckExecutorServletConfiguration healthCheckExecutorServletConfig;
@Before
public void setup() throws IOException {
initMocks(this);
doReturn(500L).when(hcServiceRef).getProperty(Constants.SERVICE_ID);
doReturn(writer).when(response).getWriter();
doReturn(true).when(healthCheckExecutorServletConfig).disabled();
doReturn("OK:200").when(healthCheckExecutorServletConfig).httpStatusMapping();
doReturn(new String[0]).when(healthCheckExecutorServletConfig).tags();
doReturn(HealthCheckExecutorServlet.FORMAT_HTML).when(healthCheckExecutorServletConfig).format();
healthCheckExecutorServlet.activate(healthCheckExecutorServletConfig);
}
@Test
public void testDoGetHtml() throws ServletException, IOException {
final String testTag = "testTag";
doReturn(testTag).when(request).getParameter(HealthCheckExecutorServlet.PARAM_TAGS.name);
doReturn("false").when(request).getParameter(HealthCheckExecutorServlet.PARAM_COMBINE_TAGS_WITH_OR.name);
final List<HealthCheckExecutionResult> executionResults = getExecutionResults(Result.Status.CRITICAL);
doReturn(executionResults).when(healthCheckExecutor).execute(selector(new String[] { testTag }, new String[0]),
eq(new HealthCheckExecutionOptions()));
healthCheckExecutorServlet.doGet(request, response);
verifyZeroInteractions(jsonSerializer);
verifyZeroInteractions(txtSerializer);
verifyZeroInteractions(verboseTxtSerializer);
verify(htmlSerializer)
.serialize(resultEquals(new Result(Result.Status.CRITICAL, "Overall Status CRITICAL")), eq(executionResults),
contains("Supported URL parameters"), eq(false));
}
@Test
public void testDoGetNameAndTagInPath() throws ServletException, IOException {
final String testTag = "testTag";
final String testName = "test name";
doReturn(testTag + "," + testName).when(request).getPathInfo();
doReturn("false").when(request).getParameter(HealthCheckExecutorServlet.PARAM_COMBINE_TAGS_WITH_OR.name);
final List<HealthCheckExecutionResult> executionResults = getExecutionResults(Result.Status.CRITICAL);
doReturn(executionResults).when(healthCheckExecutor).execute(selector(new String[] { testTag }, new String[] { testName }),
eq(new HealthCheckExecutionOptions()));
healthCheckExecutorServlet.doGet(request, response);
verify(request, never()).getParameter(HealthCheckExecutorServlet.PARAM_TAGS.name);
verify(request, never()).getParameter(HealthCheckExecutorServlet.PARAM_NAMES.name);
verifyZeroInteractions(jsonSerializer);
verifyZeroInteractions(txtSerializer);
verifyZeroInteractions(verboseTxtSerializer);
verify(htmlSerializer)
.serialize(resultEquals(new Result(Result.Status.CRITICAL, "Overall Status CRITICAL")), eq(executionResults),
contains("Supported URL parameters"), eq(false));
}
@Test
public void testDoGetJson() throws ServletException, IOException {
final String testTag = "testTag";
doReturn("true").when(request).getParameter(HealthCheckExecutorServlet.PARAM_COMBINE_TAGS_WITH_OR.name);
int timeout = 5000;
doReturn(timeout + "").when(request).getParameter(HealthCheckExecutorServlet.PARAM_OVERRIDE_GLOBAL_TIMEOUT.name);
doReturn("/" + testTag + ".json").when(request).getPathInfo();
final List<HealthCheckExecutionResult> executionResults = getExecutionResults(Result.Status.WARN);
HealthCheckExecutionOptions options = new HealthCheckExecutionOptions();
options.setCombineTagsWithOr(true);
options.setOverrideGlobalTimeout(timeout);
doReturn(executionResults).when(healthCheckExecutor).execute(selector(new String[] { testTag }, new String[0]), eq(options));
healthCheckExecutorServlet.doGet(request, response);
verifyZeroInteractions(htmlSerializer);
verifyZeroInteractions(txtSerializer);
verifyZeroInteractions(verboseTxtSerializer);
verify(jsonSerializer).serialize(resultEquals(new Result(Result.Status.WARN, "Overall Status WARN")), eq(executionResults),
anyString(),
eq(false));
}
@Test
public void testDoGetTxt() throws ServletException, IOException {
final String testTag = "testTag";
doReturn(testTag).when(request).getParameter(HealthCheckExecutorServlet.PARAM_TAGS.name);
doReturn(HealthCheckExecutorServlet.FORMAT_TXT).when(request).getParameter(HealthCheckExecutorServlet.PARAM_FORMAT.name);
doReturn("true").when(request).getParameter(HealthCheckExecutorServlet.PARAM_COMBINE_TAGS_WITH_OR.name);
int timeout = 5000;
doReturn(timeout + "").when(request).getParameter(HealthCheckExecutorServlet.PARAM_OVERRIDE_GLOBAL_TIMEOUT.name);
final List<HealthCheckExecutionResult> executionResults = getExecutionResults(Result.Status.WARN);
HealthCheckExecutionOptions options = new HealthCheckExecutionOptions();
options.setCombineTagsWithOr(true);
options.setOverrideGlobalTimeout(timeout);
doReturn(executionResults).when(healthCheckExecutor).execute(selector(new String[] { testTag }, new String[0]), eq(options));
healthCheckExecutorServlet.doGet(request, response);
verifyZeroInteractions(htmlSerializer);
verifyZeroInteractions(jsonSerializer);
verifyZeroInteractions(verboseTxtSerializer);
verify(txtSerializer).serialize(resultEquals(new Result(Result.Status.WARN, "Overall Status WARN")));
}
@Test
public void testDoGetVerboseTxt() throws ServletException, IOException {
String testTag = "testTag";
doReturn(testTag).when(request).getParameter(HealthCheckExecutorServlet.PARAM_TAGS.name);
doReturn(HealthCheckExecutorServlet.FORMAT_VERBOSE_TXT).when(request).getParameter(HealthCheckExecutorServlet.PARAM_FORMAT.name);
List<HealthCheckExecutionResult> executionResults = getExecutionResults(Result.Status.WARN);
doReturn(executionResults).when(healthCheckExecutor).execute(selector(new String[] { testTag }, new String[0]),
any(HealthCheckExecutionOptions.class));
healthCheckExecutorServlet.doGet(request, response);
verifyZeroInteractions(htmlSerializer);
verifyZeroInteractions(jsonSerializer);
verifyZeroInteractions(txtSerializer);
verify(verboseTxtSerializer).serialize(resultEquals(new Result(Result.Status.WARN, "Overall Status WARN")), eq(executionResults),
eq(false));
}
private List<HealthCheckExecutionResult> getExecutionResults(Result.Status worstStatus) {
List<HealthCheckExecutionResult> results = new ArrayList<HealthCheckExecutionResult>();
results.add(new ExecutionResult(new HealthCheckMetadata(hcServiceRef), new Result(worstStatus, worstStatus.name()), 100));
results.add(new ExecutionResult(new HealthCheckMetadata(hcServiceRef), new Result(Result.Status.OK, "OK"), 100));
return results;
}
@Test
public void testGetStatusMapping() throws ServletException {
Map<Status, Integer> statusMapping = healthCheckExecutorServlet.getStatusMapping("CRITICAL:500");
assertEquals(statusMapping.get(Result.Status.OK), (Integer) 200);
assertEquals(statusMapping.get(Result.Status.WARN), (Integer) 200);
assertEquals(statusMapping.get(Result.Status.TEMPORARILY_UNAVAILABLE), (Integer) 503);
assertEquals(statusMapping.get(Result.Status.CRITICAL), (Integer) 500);
assertEquals(statusMapping.get(Result.Status.HEALTH_CHECK_ERROR), (Integer) 500);
statusMapping = healthCheckExecutorServlet.getStatusMapping("OK:333");
assertEquals(statusMapping.get(Result.Status.OK), (Integer) 333);
assertEquals(statusMapping.get(Result.Status.WARN), (Integer) 333);
assertEquals(statusMapping.get(Result.Status.TEMPORARILY_UNAVAILABLE), (Integer) 503);
assertEquals(statusMapping.get(Result.Status.CRITICAL), (Integer) 503);
assertEquals(statusMapping.get(Result.Status.HEALTH_CHECK_ERROR), (Integer) 500);
statusMapping = healthCheckExecutorServlet.getStatusMapping("OK:200,WARN:418,CRITICAL:503,TEMPORARILY_UNAVAILABLE:503,HEALTH_CHECK_ERROR:500");
assertEquals(statusMapping.get(Result.Status.OK), (Integer) 200);
assertEquals(statusMapping.get(Result.Status.WARN), (Integer) 418);
assertEquals(statusMapping.get(Result.Status.TEMPORARILY_UNAVAILABLE), (Integer) 503);
assertEquals(statusMapping.get(Result.Status.CRITICAL), (Integer) 503);
assertEquals(statusMapping.get(Result.Status.HEALTH_CHECK_ERROR), (Integer) 500);
statusMapping = healthCheckExecutorServlet.getStatusMapping("WARN:418,HEALTH_CHECK_ERROR:503");
assertEquals(statusMapping.get(Result.Status.OK), (Integer) 200);
assertEquals(statusMapping.get(Result.Status.WARN), (Integer) 418);
assertEquals(statusMapping.get(Result.Status.TEMPORARILY_UNAVAILABLE), (Integer) 503);
assertEquals(statusMapping.get(Result.Status.CRITICAL), (Integer) 503);
assertEquals(statusMapping.get(Result.Status.HEALTH_CHECK_ERROR), (Integer) 503);
}
@Test(expected = IllegalArgumentException.class)
public void testGetStatusMappingInvalidToken() throws ServletException {
healthCheckExecutorServlet.getStatusMapping("CRITICAL");
}
@Test(expected = IllegalArgumentException.class)
public void testGetStatusMappingInvalidStatus() throws ServletException {
healthCheckExecutorServlet.getStatusMapping("INVALID:200");
}
@Test(expected = IllegalArgumentException.class)
public void testGetStatusMappingInvalidStatusCode() throws ServletException {
healthCheckExecutorServlet.getStatusMapping("CRITICAL:xxx");
}
static Result resultEquals(Result expected) {
return argThat(new ResultMatcher(expected));
}
static class ResultMatcher extends ArgumentMatcher<Result> {
private final Result expectedResult;
public ResultMatcher(Result expected) {
this.expectedResult = expected;
}
@Override
public boolean matches(Object actual) {
Result actualResult = (Result) actual;
return actualResult.getStatus().equals(expectedResult.getStatus()); // simple status matching only sufficient for this test case
}
@Override
public void describeTo(Description description) {
description.appendText(expectedResult == null ? null : expectedResult.toString());
}
}
HealthCheckSelector selector(final String[] tags, final String[] names) {
return argThat(new ArgumentMatcher<HealthCheckSelector>() {
@Override
public boolean matches(Object actual) {
if (actual instanceof HealthCheckSelector) {
HealthCheckSelector actualSelector = (HealthCheckSelector) actual;
return Arrays.equals(actualSelector.tags(), tags.length == 0 ? new String[] { "" } : tags) &&
Arrays.equals(actualSelector.names(), names.length == 0 ? new String[] { "" } : names);
} else {
return false;
}
}
});
}
}