Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id EC54110B7A for ; Sat, 22 Mar 2014 19:41:57 +0000 (UTC) Received: (qmail 51681 invoked by uid 500); 22 Mar 2014 19:41:57 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 51651 invoked by uid 500); 22 Mar 2014 19:41:56 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 51369 invoked by uid 99); 22 Mar 2014 19:41:52 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 22 Mar 2014 19:41:52 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 07944948CAA; Sat, 22 Mar 2014 19:41:52 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: kocka@apache.org To: commits@cloudstack.apache.org Date: Sat, 22 Mar 2014 19:41:53 -0000 Message-Id: <8fecf7652145438996b87711851a991e@git.apache.org> In-Reply-To: <915b321fd37247629cf01440e784bc8a@git.apache.org> References: <915b321fd37247629cf01440e784bc8a@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [3/4] git commit: updated refs/heads/master to 265208a Basic tests for ApiServlet new tests for ApiServlet covering - utf8Fixup - some of processRequestInContext minor cleanup done in StringBuffer handling and utf8Fixup got a bit shorter Signed-off-by: Laszlo Hornyak Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/265208a2 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/265208a2 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/265208a2 Branch: refs/heads/master Commit: 265208a261403dc33edb6903c83b0a943ee4aafa Parents: 3dc4d2e Author: Laszlo Hornyak Authored: Sat Mar 22 17:32:16 2014 +0100 Committer: Laszlo Hornyak Committed: Sat Mar 22 18:34:46 2014 +0100 ---------------------------------------------------------------------- server/src/com/cloud/api/ApiServlet.java | 34 ++--- server/test/com/cloud/api/ApiServletTest.java | 169 +++++++++++++++++++++ 2 files changed, 186 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/265208a2/server/src/com/cloud/api/ApiServlet.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/ApiServlet.java b/server/src/com/cloud/api/ApiServlet.java index 37a2549..c24877a 100755 --- a/server/src/com/cloud/api/ApiServlet.java +++ b/server/src/com/cloud/api/ApiServlet.java @@ -82,7 +82,7 @@ public class ApiServlet extends HttpServlet { processRequest(req, resp); } - private void utf8Fixup(final HttpServletRequest req, final Map params) { + void utf8Fixup(final HttpServletRequest req, final Map params) { if (req.getQueryString() == null) { return; } @@ -91,18 +91,9 @@ public class ApiServlet extends HttpServlet { if (paramsInQueryString != null) { for (final String param : paramsInQueryString) { final String[] paramTokens = param.split("=", 2); - if (paramTokens != null && paramTokens.length == 2) { - String name = paramTokens[0]; - String value = paramTokens[1]; - - try { - name = URLDecoder.decode(name, "UTF-8"); - } catch (final UnsupportedEncodingException e) { - } - try { - value = URLDecoder.decode(value, "UTF-8"); - } catch (final UnsupportedEncodingException e) { - } + if (paramTokens.length == 2) { + String name = decodeUtf8(paramTokens[0]); + String value = decodeUtf8(paramTokens[1]); params.put(name, new String[] {value}); } else { s_logger.debug("Invalid parameter in URL found. param: " + param); @@ -111,6 +102,15 @@ public class ApiServlet extends HttpServlet { } } + private String decodeUtf8(final String value) { + try { + return URLDecoder.decode(value, "UTF-8"); + } catch (final UnsupportedEncodingException e) { + //should never happen + return null; + } + } + private void processRequest(final HttpServletRequest req, final HttpServletResponse resp) { _managedContext.runWithContext(new Runnable() { @Override @@ -120,10 +120,10 @@ public class ApiServlet extends HttpServlet { }); } - private void processRequestInContext(final HttpServletRequest req, final HttpServletResponse resp) { + void processRequestInContext(final HttpServletRequest req, final HttpServletResponse resp) { final StringBuffer auditTrailSb = new StringBuffer(); - auditTrailSb.append(" " + req.getRemoteAddr()); - auditTrailSb.append(" -- " + req.getMethod() + " "); + auditTrailSb.append(" ").append(req.getRemoteAddr()); + auditTrailSb.append(" -- ").append(req.getMethod()).append(' '); // get the response format since we'll need it in a couple of places String responseType = BaseCmd.RESPONSE_TYPE_XML; final Map params = new HashMap(); @@ -171,7 +171,7 @@ public class ApiServlet extends HttpServlet { } } auditTrailSb.append("command=logout"); - auditTrailSb.append(" " + HttpServletResponse.SC_OK); + auditTrailSb.append(" ").append(HttpServletResponse.SC_OK); writeResponse(resp, getLogoutSuccessResponse(responseType), HttpServletResponse.SC_OK, responseType); return; } else if ("login".equalsIgnoreCase(command)) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/265208a2/server/test/com/cloud/api/ApiServletTest.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/api/ApiServletTest.java b/server/test/com/cloud/api/ApiServletTest.java new file mode 100644 index 0000000..85c5723 --- /dev/null +++ b/server/test/com/cloud/api/ApiServletTest.java @@ -0,0 +1,169 @@ +// 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 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.util.HashMap; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.cloudstack.api.ApiConstants; +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 com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.User; + +@RunWith(MockitoJUnitRunner.class) +public class ApiServletTest { + + @Mock + ApiServer apiServer; + + @Mock + HttpServletRequest request; + + @Mock + HttpServletResponse response; + + @Mock + AccountService accountService; + + @Mock + User user; + + @Mock + Account account; + + @Mock + HttpSession session; + + StringWriter responseWriter; + + ApiServlet servlet; + + @Before + public void setup() throws SecurityException, NoSuchFieldException, + IllegalArgumentException, IllegalAccessException, IOException { + 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); + + Field apiServerField = ApiServlet.class.getDeclaredField("_apiServer"); + apiServerField.setAccessible(true); + apiServerField.set(servlet, apiServer); + } + + @Test + public void utf8Fixup() { + Mockito.when(request.getQueryString()).thenReturn( + "foo=12345&bar=blah&baz=¶m=param"); + HashMap params = new HashMap(); + 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()); + } + + @Test + public void utf8FixupStrangeInputs() { + Mockito.when(request.getQueryString()).thenReturn("&&=a&=&&a&a=a=a=a"); + HashMap params = new HashMap(); + 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 params = new HashMap(); + servlet.utf8Fixup(request, params); + Assert.assertEquals("árvíztűrőtükörfúró", params.get("防水镜钻孔机")[0]); + } + + @Test + public void processRequestInContextUnauthorizedGET() { + Mockito.when(request.getMethod()).thenReturn("GET"); + Mockito.when( + apiServer.verifyRequest(Mockito.anyMap(), Mockito.anyLong())) + .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(StringBuffer.class)); + } + + @Test + public void processRequestInContextAuthorizedGet() { + Mockito.when(request.getMethod()).thenReturn("GET"); + Mockito.when( + apiServer.verifyRequest(Mockito.anyMap(), Mockito.anyLong())) + .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(StringBuffer.class)); + } + + @Test + public void processRequestInContextLougout() { + 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 params = new HashMap(); + params.put(ApiConstants.COMMAND, new String[] { "logout" }); + Mockito.when(request.getParameterMap()).thenReturn(params); + + servlet.processRequestInContext(request, response); + + Mockito.verify(apiServer).logoutUser(1l); + Mockito.verify(session).invalidate(); + } + +}