/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package com.emc.storageos.api.errorhandling; import java.net.URI; import java.util.HashSet; import java.util.Set; import javax.ws.rs.core.Response.Status; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import com.emc.storageos.api.service.impl.resource.StorageApplication; import com.emc.storageos.db.client.URIUtil; import com.emc.storageos.db.client.model.DataObject; import com.emc.storageos.db.client.model.VirtualArray; import com.emc.storageos.db.client.model.VirtualPool; import com.emc.storageos.db.client.model.Volume; import com.emc.storageos.model.errorhandling.ServiceErrorRestRep; import com.emc.storageos.svcs.errorhandling.mappers.ServiceCodeExceptionMapper; import com.emc.storageos.svcs.errorhandling.resources.ServiceCode; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.core.DefaultResourceConfig; import com.sun.jersey.api.core.ResourceConfig; import com.sun.jersey.spi.container.servlet.ServletContainer; public class ErrorHandlingTest { private static final int HTTP_BAD_REQUEST = 400; private static final int HTTP_UNAUTHORIZED = 401; private static final int HTTP_FORBIDDEN = 403; private static final int HTTP_NOT_FOUND = 404; private static final int HTTP_METHOD_NOT_ALLOWED = 405; private static final int HTTP_INTERNAL_SERVER_ERROR = 500; private static final int HTTP_SERVICE_UNAVAILABLE = 503; private static final int port = 12345; private static volatile Server _server; private Client client; private WebResource baseResource; @BeforeClass public static void setupServer() throws Exception { _server = new Server(port); // AuthN servlet filters ServletContextHandler rootHandler = new ServletContextHandler(); rootHandler.setContextPath("/"); _server.setHandler(rootHandler); final StorageApplication application = new StorageApplication(); final Set<Object> resources = new HashSet<Object>(); resources.add(new ErrorHandlingTestResource()); resources.add(new ServiceCodeExceptionMapper()); application.setResource(resources); final ResourceConfig config = new DefaultResourceConfig(); config.add(application); rootHandler.addServlet(new ServletHolder(new ServletContainer(config)), "/*"); _server.start(); } @AfterClass public static void shutdownServer() throws Exception { _server.stop(); } @Before public void setupClient() { client = Client.create(); baseResource = client.resource("http://localhost:" + port); } private void assertResponse(final ClientResponse actualResponse, final int expectedStatusCode, final int expectedServiceCode) { Assert.assertEquals(expectedStatusCode, actualResponse.getStatus()); try { final ServiceErrorRestRep error = actualResponse .getEntity(ServiceErrorRestRep.class); Assert.assertEquals(expectedServiceCode, error.getCode()); } catch (final ClientHandlerException e) { Assert.fail("Expected a ServiceError object"); } } @Test public void methodNotAllowedGet() { // methodNotAllowed method will throw a ServiceCodeException final ClientResponse response = baseResource.path("methodNotAllowed") .get(ClientResponse.class); final int statusCode = HTTP_METHOD_NOT_ALLOWED; final int serviceCode = ServiceCode.API_METHOD_NOT_SUPPORTED.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void methodNotAllowedPost() { // jersey will throw a WebApplicationException as we cannot post to the // base resource, the mapper should convert this to a // ServiceCodeException final ClientResponse response = baseResource.post(ClientResponse.class); final int statusCode = HTTP_METHOD_NOT_ALLOWED; final int serviceCode = ServiceCode.API_METHOD_NOT_SUPPORTED.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void errorStartingService() { // errorStartingService method will throw a ServiceCodeException final ClientResponse response = baseResource.path( "errorStartingService").get(ClientResponse.class); final int statusCode = HTTP_INTERNAL_SERVER_ERROR; final int serviceCode = ServiceCode.COORDINATOR_ERROR.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void unableToLocateService() { // unableToLocateService method will throw a ServiceCodeException final ClientResponse response = baseResource.path( "unableToLocateService").get(ClientResponse.class); final int statusCode = HTTP_INTERNAL_SERVER_ERROR; final int serviceCode = ServiceCode.COORDINATOR_SVC_NOT_FOUND.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void entityInactive() { // entityInactive method will throw a ServiceCodeException final URI id = URIUtil.createId(DataObject.class); final ClientResponse response = baseResource.path( "entityInactive/" + id).get(ClientResponse.class); final int statusCode = HTTP_INTERNAL_SERVER_ERROR; final int serviceCode = ServiceCode.DBSVC_ENTITY_NOT_FOUND.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void unsupportedType() { // unsupportedType method will throw a ServiceCodeException final ClientResponse response = baseResource.path("unsupportedType") .get(ClientResponse.class); final int statusCode = HTTP_INTERNAL_SERVER_ERROR; final int serviceCode = ServiceCode.DBSVC_SERIALIZATION_ERROR.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void connectionException() { // connectionException method will throw a ServiceCodeException final ClientResponse response = baseResource .path("connectionException").get(ClientResponse.class); final int statusCode = HTTP_SERVICE_UNAVAILABLE; final int serviceCode = ServiceCode.DBSVC_CONNECTION_ERROR.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void idInPath() { // idInPath method will throw a ServiceCodeException final URI id = URIUtil.createId(DataObject.class); final ClientResponse response = baseResource.path("idInPath/" + id) .get(ClientResponse.class); final int statusCode = HTTP_NOT_FOUND; final int serviceCode = ServiceCode.API_URL_ENTITY_NOT_FOUND.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void idNotInPath() { // idNotInPath method will throw a ServiceCodeException final URI id = URIUtil.createId(DataObject.class); final ClientResponse response = baseResource.path("idNotInPath") .queryParam("id", id.toString()).get(ClientResponse.class); final int statusCode = HTTP_BAD_REQUEST; final int serviceCode = ServiceCode.API_PARAMETER_NOT_FOUND.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void unableToCreateDir() { // unableToCreateDir method will throw a ServiceCodeException final String dirPath = "serverIdDir"; final ClientResponse response = baseResource.path("createDir") .path(dirPath).get(ClientResponse.class); final int statusCode = HTTP_INTERNAL_SERVER_ERROR; final int serviceCode = ServiceCode.IO_ERROR.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void missingOrInvalid() { // missingOrInvalid method will throw a ServiceCodeException final String fieldName = "fieldName"; final ClientResponse response = baseResource.path("missingOrInvalid") .path(fieldName).get(ClientResponse.class); final int statusCode = HTTP_BAD_REQUEST; final int serviceCode = ServiceCode.API_PARAMETER_MISSING.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void invalidContext() { // invalidContext method will throw a ServiceCodeException final ClientResponse response = baseResource.path("invalidContext") .get(ClientResponse.class); final int statusCode = HTTP_FORBIDDEN; final int serviceCode = ServiceCode.SECURITY_INSUFFICIENT_PERMISSIONS.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void noPoolFound() { // noPoolFound method will throw a ServiceCodeException final URI cosId = URIUtil.createId(VirtualPool.class); final URI neighborhoodId = URIUtil.createId(VirtualArray.class); final ClientResponse response = baseResource.path("noPoolFound") .queryParam("vpool", cosId.toString()) .queryParam("varray", neighborhoodId.toString()) .get(ClientResponse.class); final int statusCode = HTTP_BAD_REQUEST; final int serviceCode = ServiceCode.API_NO_PLACEMENT_FOUND.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void noDelete() { // noDelete method will throw a ServiceCodeException final URI id = URIUtil.createId(Volume.class); final ClientResponse response = baseResource.path("noDelete") .path(id.toString()).get(ClientResponse.class); final int statusCode = HTTP_INTERNAL_SERVER_ERROR; final int serviceCode = ServiceCode.API_RP_VOLUME_DELETE_ERROR.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void noTenantForUser() { // noTenantForUser method will throw a ServiceCodeException final ClientResponse response = baseResource.path("noTenantForUser") .get(ClientResponse.class); final int statusCode = HTTP_BAD_REQUEST; final int serviceCode = ServiceCode.API_PARAMETER_NOT_FOUND.getCode(); assertResponse(response, statusCode, serviceCode); } // Known non-ServiceCodeExceptions @Test public void illegalArgumentException() { // This method will throw an IllegalArgumentException, the mapper should // convert this to a ServiceCodeException final ClientResponse response = baseResource.path( "illegalArgumentException").get(ClientResponse.class); final int statusCode = HTTP_BAD_REQUEST; final int serviceCode = ServiceCode.API_PARAMETER_INVALID.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void illegalStateException() { // This method will throw an IllegalStateException, the mapper should // convert this to a ServiceCodeException final ClientResponse response = baseResource.path( "illegalStateException").get(ClientResponse.class); final int statusCode = HTTP_INTERNAL_SERVER_ERROR; final int serviceCode = ServiceCode.UNFORSEEN_ERROR.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void illegalStateExceptionWithCause() { // This method will throw an IllegalStateException, the mapper should // convert this to a ServiceCodeException final ClientResponse response = baseResource.path( "illegalStateExceptionWithCause").get(ClientResponse.class); final int statusCode = HTTP_INTERNAL_SERVER_ERROR; final int serviceCode = ServiceCode.DBSVC_SERIALIZATION_ERROR.getCode(); assertResponse(response, statusCode, serviceCode); } // WebApplication Tests @Test public void webApplicationExceptionBadRequest() { // This method will throw an WebApplicationException with the specified // status, the mapper should convert this to a ServiceCodeException final ClientResponse response = baseResource .path("webApplicationException/" + Status.BAD_REQUEST.getStatusCode()).get( ClientResponse.class); final int statusCode = HTTP_BAD_REQUEST; final int serviceCode = ServiceCode.API_BAD_REQUEST.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void webApplicationExceptionUnauthorized() { // This method will throw an WebApplicationException with the specified // status, the mapper should convert this to a ServiceCodeException final ClientResponse response = baseResource.path( "webApplicationException/" + Status.UNAUTHORIZED.getStatusCode()).get( ClientResponse.class); final int statusCode = HTTP_UNAUTHORIZED; final int serviceCode = ServiceCode.SECURITY_UNAUTHORIZED_OPERATION.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void webApplicationExceptionForbidden() { // This method will throw an WebApplicationException with the specified // status, the mapper should convert this to a ServiceCodeException final ClientResponse response = baseResource.path( "webApplicationException/" + Status.FORBIDDEN.getStatusCode()) .get(ClientResponse.class); final int statusCode = HTTP_FORBIDDEN; final int serviceCode = ServiceCode.SECURITY_INSUFFICIENT_PERMISSIONS.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void webApplicationExceptionNotFound() { // This method will throw an WebApplicationException with the specified // status, the mapper should convert this to a ServiceCodeException final ClientResponse response = baseResource.path( "webApplicationException/" + Status.NOT_FOUND.getStatusCode()) .get(ClientResponse.class); final int statusCode = HTTP_NOT_FOUND; final int serviceCode = ServiceCode.API_URL_ENTITY_NOT_FOUND.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void webApplicationExceptionMethodNotAllowed() { // This method will throw an WebApplicationException with the specified // status, the mapper should convert this to a ServiceCodeException final ClientResponse response = baseResource.path( "webApplicationException/" + ClientResponse.Status.METHOD_NOT_ALLOWED.getStatusCode()).get( ClientResponse.class); final int statusCode = HTTP_METHOD_NOT_ALLOWED; final int serviceCode = ServiceCode.API_METHOD_NOT_SUPPORTED.getCode(); assertResponse(response, statusCode, serviceCode); } @Test public void webApplicationExceptionServiceUnavaliable() { // This method will throw an WebApplicationException with the specified // status, the mapper should convert this to a ServiceCodeException final ClientResponse response = baseResource.path( "webApplicationException/" + Status.SERVICE_UNAVAILABLE.getStatusCode()).get( ClientResponse.class); final int statusCode = HTTP_SERVICE_UNAVAILABLE; final int serviceCode = ServiceCode.API_SERVICE_UNAVAILABLE.getCode(); assertResponse(response, statusCode, serviceCode); } // Other Exceptions @Test public void nullPointerException() { // This method will throw an NullPointerException, the mapper should // convert this to a ServiceCodeException final ClientResponse response = baseResource.path( "nullPointerException").get(ClientResponse.class); final int statusCode = HTTP_INTERNAL_SERVER_ERROR; final int serviceCode = ServiceCode.UNFORSEEN_ERROR.getCode(); assertResponse(response, statusCode, serviceCode); } }