blob: 037c36e3b95bd2038e20243b3671cbf8d10916c2 [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 com.cloud.api;
import org.apache.cloudstack.api.auth.APIAuthenticationManager;
import org.apache.cloudstack.api.auth.APIAuthenticationType;
import org.apache.cloudstack.api.auth.APIAuthenticator;
import com.cloud.server.ManagementServer;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.User;
import org.apache.cloudstack.api.ApiConstants;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
@RunWith(MockitoJUnitRunner.class)
public class ApiServletTest {
@Mock
ApiServer apiServer;
@Mock
HttpServletRequest request;
@Mock
HttpServletResponse response;
@Mock
AccountService accountService;
@Mock
APIAuthenticationManager authManager;
@Mock
APIAuthenticator authenticator;
@Mock
User user;
@Mock
Account account;
@Mock
HttpSession session;
@Mock
ManagementServer managementServer;
StringWriter responseWriter;
ApiServlet servlet;
@SuppressWarnings("unchecked")
@Before
public void setup() throws SecurityException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException, IOException, UnknownHostException {
servlet = new ApiServlet();
responseWriter = new StringWriter();
Mockito.when(response.getWriter()).thenReturn(
new PrintWriter(responseWriter));
Mockito.when(request.getRemoteAddr()).thenReturn("127.0.0.1");
Mockito.when(accountService.getSystemUser()).thenReturn(user);
Mockito.when(accountService.getSystemAccount()).thenReturn(account);
Field accountMgrField = ApiServlet.class.getDeclaredField("accountMgr");
accountMgrField.setAccessible(true);
accountMgrField.set(servlet, accountService);
Mockito.when(authManager.getAPIAuthenticator(Mockito.anyString())).thenReturn(authenticator);
Mockito.when(authenticator.authenticate(Mockito.anyString(), Mockito.anyMap(), Mockito.isA(HttpSession.class),
Mockito.same(InetAddress.getByName("127.0.0.1")), Mockito.anyString(), Mockito.isA(StringBuilder.class), Mockito.isA(HttpServletRequest.class), Mockito.isA(HttpServletResponse.class))).thenReturn("{\"loginresponse\":{}");
Field authManagerField = ApiServlet.class.getDeclaredField("authManager");
authManagerField.setAccessible(true);
authManagerField.set(servlet, authManager);
Field apiServerField = ApiServlet.class.getDeclaredField("apiServer");
apiServerField.setAccessible(true);
apiServerField.set(servlet, apiServer);
}
/**
* These are envinonment hacks, actually getting into the behavior of other
* classes, but there is no other way to run the test.
*/
@Before
public void hackEnvironment() throws Exception {
Field smsField = ApiDBUtils.class.getDeclaredField("s_ms");
smsField.setAccessible(true);
smsField.set(null, managementServer);
Mockito.when(managementServer.getVersion()).thenReturn(
"LATEST-AND-GREATEST");
}
@After
public void cleanupEnvironmentHacks() throws Exception {
Field smsField = ApiDBUtils.class.getDeclaredField("s_ms");
smsField.setAccessible(true);
smsField.set(null, null);
}
@Test
public void utf8Fixup() {
Mockito.when(request.getQueryString()).thenReturn(
"foo=12345&bar=blah&baz=&param=param");
HashMap<String, Object[]> params = new HashMap<String, Object[]>();
servlet.utf8Fixup(request, params);
Assert.assertEquals("12345", params.get("foo")[0]);
Assert.assertEquals("blah", params.get("bar")[0]);
}
@Test
public void utf8FixupNull() {
Mockito.when(request.getQueryString()).thenReturn("&&=a&=&&a&a=a=a=a");
servlet.utf8Fixup(request, new HashMap<String, Object[]>());
}
@Test
public void utf8FixupStrangeInputs() {
Mockito.when(request.getQueryString()).thenReturn("&&=a&=&&a&a=a=a=a");
HashMap<String, Object[]> params = new HashMap<String, Object[]>();
servlet.utf8Fixup(request, params);
Assert.assertTrue(params.containsKey(""));
}
@Test
public void utf8FixupUtf() throws UnsupportedEncodingException {
Mockito.when(request.getQueryString()).thenReturn(
URLEncoder.encode("防水镜钻孔机", "UTF-8") + "="
+ URLEncoder.encode("árvíztűrőtükörfúró", "UTF-8"));
HashMap<String, Object[]> params = new HashMap<String, Object[]>();
servlet.utf8Fixup(request, params);
Assert.assertEquals("árvíztűrőtükörfúró", params.get("防水镜钻孔机")[0]);
}
@SuppressWarnings("unchecked")
@Test
public void processRequestInContextUnauthorizedGET() {
Mockito.when(request.getMethod()).thenReturn("GET");
Mockito.when(
apiServer.verifyRequest(Mockito.anyMap(), Mockito.anyLong(), Mockito.any(InetAddress.class)))
.thenReturn(false);
servlet.processRequestInContext(request, response);
Mockito.verify(response).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
Mockito.verify(apiServer, Mockito.never()).handleRequest(
Mockito.anyMap(), Mockito.anyString(),
Mockito.any(StringBuilder.class));
}
@SuppressWarnings("unchecked")
@Test
public void processRequestInContextAuthorizedGet() {
Mockito.when(request.getMethod()).thenReturn("GET");
Mockito.when(
apiServer.verifyRequest(Mockito.anyMap(), Mockito.anyLong(), Mockito.any(InetAddress.class)))
.thenReturn(true);
servlet.processRequestInContext(request, response);
Mockito.verify(response).setStatus(HttpServletResponse.SC_OK);
Mockito.verify(apiServer, Mockito.times(1)).handleRequest(
Mockito.anyMap(), Mockito.anyString(),
Mockito.any(StringBuilder.class));
}
@SuppressWarnings("unchecked")
@Test
public void processRequestInContextLogout() throws UnknownHostException {
Mockito.when(request.getMethod()).thenReturn("GET");
Mockito.when(request.getSession(Mockito.anyBoolean())).thenReturn(
session);
Mockito.when(session.getAttribute("userid")).thenReturn(1l);
Mockito.when(session.getAttribute("accountobj")).thenReturn(account);
HashMap<String, String[]> params = new HashMap<String, String[]>();
params.put(ApiConstants.COMMAND, new String[] { "logout" });
Mockito.when(request.getParameterMap()).thenReturn(params);
Mockito.when(authenticator.getAPIType()).thenReturn(APIAuthenticationType.LOGOUT_API);
servlet.processRequestInContext(request, response);
Mockito.verify(authManager).getAPIAuthenticator("logout");
Mockito.verify(authenticator).authenticate(Mockito.anyString(), Mockito.anyMap(), Mockito.isA(HttpSession.class),
Mockito.eq(InetAddress.getByName("127.0.0.1")), Mockito.anyString(), Mockito.isA(StringBuilder.class), Mockito.isA(HttpServletRequest.class), Mockito.isA(HttpServletResponse.class));
Mockito.verify(session).invalidate();
}
@SuppressWarnings("unchecked")
@Test
public void processRequestInContextLogin() throws UnknownHostException {
Mockito.when(request.getMethod()).thenReturn("GET");
Mockito.when(request.getSession(Mockito.anyBoolean())).thenReturn(
session);
HashMap<String, String[]> params = new HashMap<String, String[]>();
params.put(ApiConstants.COMMAND, new String[] { "login" });
params.put(ApiConstants.USERNAME, new String[] { "TEST" });
params.put(ApiConstants.PASSWORD, new String[] { "TEST-PWD" });
params.put(ApiConstants.DOMAIN_ID, new String[] { "42" });
params.put(ApiConstants.DOMAIN, new String[] { "TEST-DOMAIN" });
Mockito.when(request.getParameterMap()).thenReturn(params);
servlet.processRequestInContext(request, response);
Mockito.verify(authManager).getAPIAuthenticator("login");
Mockito.verify(authenticator).authenticate(Mockito.anyString(), Mockito.anyMap(), Mockito.isA(HttpSession.class),
Mockito.eq(InetAddress.getByName("127.0.0.1")), Mockito.anyString(), Mockito.isA(StringBuilder.class), Mockito.isA(HttpServletRequest.class), Mockito.isA(HttpServletResponse.class));
}
@Test
public void getClientAddressWithXForwardedFor() throws UnknownHostException {
Mockito.when(request.getHeader(Mockito.eq("X-Forwarded-For"))).thenReturn("192.168.1.1");
Assert.assertEquals(InetAddress.getByName("192.168.1.1"), ApiServlet.getClientAddress(request));
}
@Test
public void getClientAddressWithHttpXForwardedFor() throws UnknownHostException {
Mockito.when(request.getHeader(Mockito.eq("HTTP_X_FORWARDED_FOR"))).thenReturn("192.168.1.1");
Assert.assertEquals(InetAddress.getByName("192.168.1.1"), ApiServlet.getClientAddress(request));
}
@Test
public void getClientAddressWithXRemoteAddr() throws UnknownHostException {
Mockito.when(request.getHeader(Mockito.eq("Remote_Addr"))).thenReturn("192.168.1.1");
Assert.assertEquals(InetAddress.getByName("192.168.1.1"), ApiServlet.getClientAddress(request));
}
@Test
public void getClientAddressWithHttpClientIp() throws UnknownHostException {
Mockito.when(request.getHeader(Mockito.eq("HTTP_CLIENT_IP"))).thenReturn("192.168.1.1");
Assert.assertEquals(InetAddress.getByName("192.168.1.1"), ApiServlet.getClientAddress(request));
}
@Test
public void getClientAddressDefault() throws UnknownHostException {
Mockito.when(request.getRemoteAddr()).thenReturn("127.0.0.1");
Assert.assertEquals(InetAddress.getByName("127.0.0.1"), ApiServlet.getClientAddress(request));
}
}