Return-Path: X-Original-To: apmail-incubator-cloudstack-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-cloudstack-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 88326EBAB for ; Fri, 7 Dec 2012 14:55:45 +0000 (UTC) Received: (qmail 117 invoked by uid 500); 7 Dec 2012 14:55:45 -0000 Delivered-To: apmail-incubator-cloudstack-commits-archive@incubator.apache.org Received: (qmail 99994 invoked by uid 500); 7 Dec 2012 14:55:45 -0000 Mailing-List: contact cloudstack-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: cloudstack-dev@incubator.apache.org Delivered-To: mailing list cloudstack-commits@incubator.apache.org Received: (qmail 99986 invoked by uid 99); 7 Dec 2012 14:55:45 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 07 Dec 2012 14:55:45 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id DA82731D0BC; Fri, 7 Dec 2012 14:55:44 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: hugo@apache.org To: cloudstack-commits@incubator.apache.org X-Mailer: ASF-Git Admin Mailer Subject: git commit: Add unittests for NiciraNvpApi Message-Id: <20121207145544.DA82731D0BC@tyr.zones.apache.org> Date: Fri, 7 Dec 2012 14:55:44 +0000 (UTC) Updated Branches: refs/heads/master 3ab8a65a3 -> fa207d2b4 Add unittests for NiciraNvpApi Added some unittests for the NiciraNvpApi. These tests mainly validate the logic of the execute methods, which are the main thing in this class. Other methods are basically wrappers around these functions. Changed NiciraNvpApi to have a factory method for obtaining the HttpMethod. This makes it easier to mock it. Changed the executeMethods in NiciraNvpApi to protected so the unittests have access. Fixed a bug in NiciraNvpApi where releaseconnection was not called in some cases. Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/fa207d2b Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/fa207d2b Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/fa207d2b Branch: refs/heads/master Commit: fa207d2b4de41a0799ccdb3d3a70f48184b31979 Parents: 3ab8a65 Author: Hugo Trippaers Authored: Fri Dec 7 15:54:59 2012 +0100 Committer: Hugo Trippaers Committed: Fri Dec 7 15:55:26 2012 +0100 ---------------------------------------------------------------------- .../src/com/cloud/network/nicira/NiciraNvpApi.java | 107 ++++-- .../com/cloud/network/nicira/NiciraNvpApiTest.java | 302 +++++++++++++++ 2 files changed, 373 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/fa207d2b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java index 351ff7c..3e8e028 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java @@ -41,7 +41,9 @@ import javax.net.ssl.X509TrustManager; import org.apache.commons.httpclient.ConnectTimeoutException; import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpConnectionManager; import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpMethodBase; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; @@ -71,9 +73,42 @@ public class NiciraNvpApi { private String _adminpass; private HttpClient _client; + + /* This factory method is protected so we can extend this + * in the unittests. + */ + protected HttpClient createHttpClient() { + return new HttpClient(s_httpClientManager); + } + + protected HttpMethod createMethod(String type, String uri) throws NiciraNvpApiException { + String url; + try { + url = new URL(_protocol, _host, "/ws.v1/login").toString(); + } catch (MalformedURLException e) { + s_logger.error("Unable to build Nicira API URL", e); + throw new NiciraNvpApiException("Unable to build Nicira API URL", e); + } + + if ("post".equalsIgnoreCase(type)) { + return new PostMethod(url); + } + else if ("get".equalsIgnoreCase(type)) { + return new GetMethod(url); + } + else if ("delete".equalsIgnoreCase(type)) { + return new DeleteMethod(url); + } + else if ("put".equalsIgnoreCase(type)) { + return new PutMethod(url); + } + else { + throw new NiciraNvpApiException("Requesting unknown method type"); + } + } public NiciraNvpApi() { - _client = new HttpClient(s_httpClientManager); + _client = createHttpClient(); _client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); try { @@ -100,9 +135,15 @@ public class NiciraNvpApi { * The method returns false if the login failed or the connection could not be made. * */ - private void login() throws NiciraNvpApiException { + protected void login() throws NiciraNvpApiException { String url; + if (_host == null || _host.isEmpty() || + _adminuser == null || _adminuser.isEmpty() || + _adminpass == null || _adminpass.isEmpty()) { + throw new NiciraNvpApiException("Hostname/credentials are null or empty"); + } + try { url = new URL(_protocol, _host, "/ws.v1/login").toString(); } catch (MalformedURLException e) { @@ -294,18 +335,16 @@ public class NiciraNvpApi { return executeRetrieveObject(new TypeToken>(){}.getType(), uri, params); } - private void executeUpdateObject(T newObject, String uri, Map parameters) throws NiciraNvpApiException { - String url; - try { - url = new URL(_protocol, _host, uri).toString(); - } catch (MalformedURLException e) { - s_logger.error("Unable to build Nicira API URL", e); - throw new NiciraNvpApiException("Connection to NVP Failed"); + protected void executeUpdateObject(T newObject, String uri, Map parameters) throws NiciraNvpApiException { + if (_host == null || _host.isEmpty() || + _adminuser == null || _adminuser.isEmpty() || + _adminpass == null || _adminpass.isEmpty()) { + throw new NiciraNvpApiException("Hostname/credentials are null or empty"); } Gson gson = new Gson(); - PutMethod pm = new PutMethod(url); + PutMethod pm = (PutMethod) createMethod("put", uri); pm.setRequestHeader("Content-Type", "application/json"); try { pm.setRequestEntity(new StringRequestEntity( @@ -325,18 +364,16 @@ public class NiciraNvpApi { pm.releaseConnection(); } - private T executeCreateObject(T newObject, Type returnObjectType, String uri, Map parameters) throws NiciraNvpApiException { - String url; - try { - url = new URL(_protocol, _host, uri).toString(); - } catch (MalformedURLException e) { - s_logger.error("Unable to build Nicira API URL", e); - throw new NiciraNvpApiException("Unable to build Nicira API URL", e); + protected T executeCreateObject(T newObject, Type returnObjectType, String uri, Map parameters) throws NiciraNvpApiException { + if (_host == null || _host.isEmpty() || + _adminuser == null || _adminuser.isEmpty() || + _adminpass == null || _adminpass.isEmpty()) { + throw new NiciraNvpApiException("Hostname/credentials are null or empty"); } Gson gson = new Gson(); - PostMethod pm = new PostMethod(url); + PostMethod pm = (PostMethod) createMethod("post", uri); pm.setRequestHeader("Content-Type", "application/json"); try { pm.setRequestEntity(new StringRequestEntity( @@ -366,16 +403,14 @@ public class NiciraNvpApi { return result; } - private void executeDeleteObject(String uri) throws NiciraNvpApiException { - String url; - try { - url = new URL(_protocol, _host, uri).toString(); - } catch (MalformedURLException e) { - s_logger.error("Unable to build Nicira API URL", e); - throw new NiciraNvpApiException("Unable to build Nicira API URL", e); + protected void executeDeleteObject(String uri) throws NiciraNvpApiException { + if (_host == null || _host.isEmpty() || + _adminuser == null || _adminuser.isEmpty() || + _adminpass == null || _adminpass.isEmpty()) { + throw new NiciraNvpApiException("Hostname/credentials are null or empty"); } - - DeleteMethod dm = new DeleteMethod(url); + + DeleteMethod dm = (DeleteMethod) createMethod("delete", uri); dm.setRequestHeader("Content-Type", "application/json"); executeMethod(dm); @@ -389,16 +424,14 @@ public class NiciraNvpApi { dm.releaseConnection(); } - private T executeRetrieveObject(Type returnObjectType, String uri, Map parameters) throws NiciraNvpApiException { - String url; - try { - url = new URL(_protocol, _host, uri).toString(); - } catch (MalformedURLException e) { - s_logger.error("Unable to build Nicira API URL", e); - throw new NiciraNvpApiException("Unable to build Nicira API URL", e); + protected T executeRetrieveObject(Type returnObjectType, String uri, Map parameters) throws NiciraNvpApiException { + if (_host == null || _host.isEmpty() || + _adminuser == null || _adminuser.isEmpty() || + _adminpass == null || _adminpass.isEmpty()) { + throw new NiciraNvpApiException("Hostname/credentials are null or empty"); } - GetMethod gm = new GetMethod(url); + GetMethod gm = (GetMethod) createMethod("get", uri); gm.setRequestHeader("Content-Type", "application/json"); if (parameters != null && !parameters.isEmpty()) { List nameValuePairs = new ArrayList(parameters.size()); @@ -430,7 +463,7 @@ public class NiciraNvpApi { return returnValue; } - private void executeMethod(HttpMethodBase method) throws NiciraNvpApiException { + protected void executeMethod(HttpMethodBase method) throws NiciraNvpApiException { try { _client.executeMethod(method); if (method.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { @@ -441,9 +474,11 @@ public class NiciraNvpApi { } } catch (HttpException e) { s_logger.error("HttpException caught while trying to connect to the Nicira NVP Controller", e); + method.releaseConnection(); throw new NiciraNvpApiException("API call to Nicira NVP Controller Failed", e); } catch (IOException e) { s_logger.error("IOException caught while trying to connect to the Nicira NVP Controller", e); + method.releaseConnection(); throw new NiciraNvpApiException("API call to Nicira NVP Controller Failed", e); } } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/fa207d2b/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NiciraNvpApiTest.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NiciraNvpApiTest.java b/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NiciraNvpApiTest.java new file mode 100644 index 0000000..51d9618 --- /dev/null +++ b/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NiciraNvpApiTest.java @@ -0,0 +1,302 @@ +// 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.network.nicira; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.io.IOException; +import java.util.Collections; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.DeleteMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.apache.http.HttpStatus; +import org.junit.Before; +import org.junit.Test; + +public class NiciraNvpApiTest { + NiciraNvpApi _api; + HttpClient _client = mock(HttpClient.class); + HttpMethod _method; + + @Before + public void setUp() { + HttpClientParams hmp = mock(HttpClientParams.class); + when (_client.getParams()).thenReturn(hmp); + _api = new NiciraNvpApi() { + @Override + protected HttpClient createHttpClient() { + return _client; + } + + @Override + protected HttpMethod createMethod(String type, String uri) { + return _method; + } + }; + _api.setAdminCredentials("admin", "adminpass"); + _api.setControllerAddress("localhost"); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteLoginWithoutHostname() throws NiciraNvpApiException { + _api.setControllerAddress(null); + _api.login(); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteLoginWithoutCredentials() throws NiciraNvpApiException { + _api.setAdminCredentials(null, null); + _api.login(); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteUpdateObjectWithoutHostname() throws NiciraNvpApiException { + _api.setControllerAddress(null); + _api.executeUpdateObject(new String(), "/", Collections. emptyMap()); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteUpdateObjectWithoutCredentials() throws NiciraNvpApiException { + _api.setAdminCredentials(null, null); + _api.executeUpdateObject(new String(), "/", Collections. emptyMap()); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteCreateObjectWithoutHostname() throws NiciraNvpApiException { + _api.setControllerAddress(null); + _api.executeCreateObject(new String(), String.class, "/", Collections. emptyMap()); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteCreateObjectWithoutCredentials() throws NiciraNvpApiException { + _api.setAdminCredentials(null, null); + _api.executeCreateObject(new String(), String.class, "/", Collections. emptyMap()); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteDeleteObjectWithoutHostname() throws NiciraNvpApiException { + _api.setControllerAddress(null); + _api.executeDeleteObject("/"); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteDeleteObjectWithoutCredentials() throws NiciraNvpApiException { + _api.setAdminCredentials(null, null); + _api.executeDeleteObject("/"); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteRetrieveObjectWithoutHostname() throws NiciraNvpApiException { + _api.setControllerAddress(null); + _api.executeRetrieveObject(String.class, "/", Collections. emptyMap()); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteRetrieveObjectWithoutCredentials() throws NiciraNvpApiException { + _api.setAdminCredentials(null, null); + _api.executeDeleteObject("/"); + } + + @Test + public void executeMethodTest() throws NiciraNvpApiException { + GetMethod gm = mock(GetMethod.class); + + when(gm.getStatusCode()).thenReturn(HttpStatus.SC_OK); + _api.executeMethod(gm); + verify(gm, times(1)).getStatusCode(); + } + + /* Bit of a roundabout way to ensure that login is called after an un authorized result + * It not possible to properly mock login() + */ + @Test (expected=NiciraNvpApiException.class) + public void executeMethodTestWithLogin() throws NiciraNvpApiException, HttpException, IOException { + GetMethod gm = mock(GetMethod.class); + when(_client.executeMethod((HttpMethod)any())).thenThrow(new HttpException()); + when(gm.getStatusCode()).thenReturn(HttpStatus.SC_UNAUTHORIZED).thenReturn(HttpStatus.SC_UNAUTHORIZED); + _api.executeMethod(gm); + verify(gm, times(1)).getStatusCode(); + } + + @Test + public void testExecuteCreateObject() throws NiciraNvpApiException, IOException { + LogicalSwitch ls = new LogicalSwitch(); + _method = mock(PostMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_CREATED); + when(_method.getResponseBodyAsString()).thenReturn("{ \"uuid\" : \"aaaa\" }"); + ls = _api.executeCreateObject(ls, LogicalSwitch.class, "/", Collections. emptyMap()); + assertTrue("aaaa".equals(ls.getUuid())); + verify(_method, times(1)).releaseConnection(); + + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteCreateObjectFailure() throws NiciraNvpApiException, IOException { + LogicalSwitch ls = new LogicalSwitch(); + _method = mock(PostMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR); + Header header = mock(Header.class); + when(header.getValue()).thenReturn("text/html"); + when(_method.getResponseHeader("Content-Type")).thenReturn(header); + when(_method.getResponseBodyAsString()).thenReturn("Off to timbuktu, won't be back later."); + try { + ls = _api.executeCreateObject(ls, LogicalSwitch.class, "/", Collections. emptyMap()); + } finally { + verify(_method, times(1)).releaseConnection(); + } + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteCreateObjectException() throws NiciraNvpApiException, IOException { + LogicalSwitch ls = new LogicalSwitch(); + when(_client.executeMethod((HttpMethod) any())).thenThrow(new HttpException()); + _method = mock(PostMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR); + Header header = mock(Header.class); + when(header.getValue()).thenReturn("text/html"); + when(_method.getResponseHeader("Content-Type")).thenReturn(header); + when(_method.getResponseBodyAsString()).thenReturn("Off to timbuktu, won't be back later."); + try { + ls = _api.executeCreateObject(ls, LogicalSwitch.class, "/", Collections. emptyMap()); + } finally { + verify(_method, times(1)).releaseConnection(); + } + } + + @Test + public void testExecuteUpdateObject() throws NiciraNvpApiException, IOException { + LogicalSwitch ls = new LogicalSwitch(); + _method = mock(PutMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_OK); + _api.executeUpdateObject(ls, "/", Collections. emptyMap()); + verify(_method, times(1)).releaseConnection(); + verify(_client, times(1)).executeMethod(_method); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteUpdateObjectFailure() throws NiciraNvpApiException, IOException { + LogicalSwitch ls = new LogicalSwitch(); + _method = mock(PutMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR); + Header header = mock(Header.class); + when(header.getValue()).thenReturn("text/html"); + when(_method.getResponseHeader("Content-Type")).thenReturn(header); + when(_method.getResponseBodyAsString()).thenReturn("Off to timbuktu, won't be back later."); + try { + _api.executeUpdateObject(ls, "/", Collections. emptyMap()); + } finally { + verify(_method, times(1)).releaseConnection(); + } + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteUpdateObjectException() throws NiciraNvpApiException, IOException { + LogicalSwitch ls = new LogicalSwitch(); + _method = mock(PutMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_OK); + when(_client.executeMethod((HttpMethod) any())).thenThrow(new IOException()); + try { + _api.executeUpdateObject(ls, "/", Collections. emptyMap()); + } finally { + verify(_method, times(1)).releaseConnection(); + } + } + + @Test + public void testExecuteDeleteObject() throws NiciraNvpApiException, IOException { + _method = mock(DeleteMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_NO_CONTENT); + _api.executeDeleteObject("/"); + verify(_method, times(1)).releaseConnection(); + verify(_client, times(1)).executeMethod(_method); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteDeleteObjectFailure() throws NiciraNvpApiException, IOException { + _method = mock(DeleteMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR); + Header header = mock(Header.class); + when(header.getValue()).thenReturn("text/html"); + when(_method.getResponseHeader("Content-Type")).thenReturn(header); + when(_method.getResponseBodyAsString()).thenReturn("Off to timbuktu, won't be back later."); + try { + _api.executeDeleteObject("/"); + } finally { + verify(_method, times(1)).releaseConnection(); + } + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteDeleteObjectException() throws NiciraNvpApiException, IOException { + _method = mock(DeleteMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_NO_CONTENT); + when(_client.executeMethod((HttpMethod) any())).thenThrow(new HttpException()); + try { + _api.executeDeleteObject("/"); + } finally { + verify(_method, times(1)).releaseConnection(); + } + } + + @Test + public void testExecuteRetrieveObject() throws NiciraNvpApiException, IOException { + _method = mock(GetMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_OK); + when(_method.getResponseBodyAsString()).thenReturn("{ \"uuid\" : \"aaaa\" }"); + _api.executeRetrieveObject(LogicalSwitch.class, "/", Collections. emptyMap()); + verify(_method, times(1)).releaseConnection(); + verify(_client, times(1)).executeMethod(_method); + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteRetrieveObjectFailure() throws NiciraNvpApiException, IOException { + _method = mock(GetMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR); + when(_method.getResponseBodyAsString()).thenReturn("{ \"uuid\" : \"aaaa\" }"); + Header header = mock(Header.class); + when(header.getValue()).thenReturn("text/html"); + when(_method.getResponseHeader("Content-Type")).thenReturn(header); + when(_method.getResponseBodyAsString()).thenReturn("Off to timbuktu, won't be back later."); + try { + _api.executeRetrieveObject(LogicalSwitch.class, "/", Collections. emptyMap()); + } finally { + verify(_method, times(1)).releaseConnection(); + } + } + + @Test (expected=NiciraNvpApiException.class) + public void testExecuteRetrieveObjectException() throws NiciraNvpApiException, IOException { + _method = mock(GetMethod.class); + when(_method.getStatusCode()).thenReturn(HttpStatus.SC_OK); + when(_method.getResponseBodyAsString()).thenReturn("{ \"uuid\" : \"aaaa\" }"); + when(_client.executeMethod((HttpMethod) any())).thenThrow(new HttpException()); + try { + _api.executeRetrieveObject(LogicalSwitch.class, "/", Collections. emptyMap()); + } finally { + verify(_method, times(1)).releaseConnection(); + } + } + +}