| // |
| // 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.hamcrest.MatcherAssert.assertThat; |
| import static org.hamcrest.Matchers.containsString; |
| import static org.hamcrest.Matchers.isEmptyOrNullString; |
| import static org.hamcrest.Matchers.not; |
| import static org.hamcrest.Matchers.notNullValue; |
| import static org.hamcrest.Matchers.sameInstance; |
| import static org.junit.Assert.fail; |
| import static org.mockito.ArgumentMatchers.eq; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.spy; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| |
| import org.apache.http.HttpHost; |
| import org.apache.http.ProtocolVersion; |
| import org.apache.http.StatusLine; |
| import org.apache.http.client.methods.CloseableHttpResponse; |
| import org.apache.http.client.methods.HttpUriRequest; |
| import org.apache.http.client.protocol.HttpClientContext; |
| import org.apache.http.impl.client.CloseableHttpClient; |
| import org.apache.http.message.BasicStatusLine; |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.junit.MockitoJUnitRunner; |
| |
| import com.cloud.utils.rest.CloudstackRESTException; |
| import com.cloud.utils.rest.HttpMethods; |
| import com.cloud.utils.rest.HttpRequestMatcher; |
| import com.cloud.utils.rest.HttpUriRequestBuilder; |
| |
| @RunWith(MockitoJUnitRunner.class) |
| public class NiciraRestClientTest { |
| |
| private static final int HTTPS_PORT = 443; |
| |
| private static final String HTTPS = "HTTPS"; |
| private static final String LOGIN_PATH = "/login"; |
| private static final String LOCALHOST = "localhost"; |
| private static final String ADMIN = "admin"; |
| private static final String ADMIN_PASSWORD = "adminpassword"; |
| |
| private static final HttpHost HTTP_HOST = new HttpHost(LOCALHOST, HTTPS_PORT, HTTPS); |
| |
| private static final StatusLine HTTP_200_STATUSLINE = new BasicStatusLine(new ProtocolVersion(HTTPS, 1, 1), 200, "OK"); |
| private static final StatusLine HTTP_401_STATUSLINE = new BasicStatusLine(new ProtocolVersion(HTTPS, 1, 1), 401, "Unauthorized"); |
| |
| private static final Map<String, String> loginParameters = new LinkedHashMap<String, String>(); |
| private static HttpUriRequest request; |
| private static HttpUriRequest loginRequest; |
| private final CloseableHttpClient httpClient = mock(CloseableHttpClient.class); |
| private final CloseableHttpResponse mockResponse = mock(CloseableHttpResponse.class); |
| private HttpClientContext httpClientContext; |
| private NiciraRestClient client; |
| |
| @BeforeClass |
| public static void setupClass() { |
| loginParameters.put("username", ADMIN); |
| loginParameters.put("password", ADMIN_PASSWORD); |
| request = HttpUriRequestBuilder.create() |
| .method(HttpMethods.GET) |
| .path("/path") |
| .build(); |
| loginRequest = HttpUriRequestBuilder.create() |
| .method(HttpMethods.POST) |
| .methodParameters(loginParameters) |
| .path(LOGIN_PATH) |
| .build(); |
| } |
| |
| @Before |
| public void setup() { |
| httpClientContext = HttpClientContext.create(); |
| client = spy(NiciraRestClient.create() |
| .client(httpClient) |
| .clientContext(httpClientContext) |
| .hostname(LOCALHOST) |
| .username(ADMIN) |
| .password(ADMIN_PASSWORD) |
| .loginUrl(LOGIN_PATH) |
| .executionLimit(5) |
| .build()); |
| } |
| |
| @Test |
| public void testExecuteSuccessAtFirstAttempt() throws Exception { |
| when(mockResponse.getStatusLine()).thenReturn(HTTP_200_STATUSLINE); |
| when(httpClient.execute(eq(HTTP_HOST), eq(request), eq(httpClientContext))).thenReturn(mockResponse); |
| |
| final CloseableHttpResponse response = client.execute(request); |
| |
| assertThat(response, notNullValue()); |
| assertThat(response, sameInstance(mockResponse)); |
| verify(client).execute(request, 0); |
| } |
| |
| @Test |
| public void testExecuteUnauthorizedThenSuccess() throws Exception { |
| when(mockResponse.getStatusLine()) |
| .thenReturn(HTTP_401_STATUSLINE) |
| .thenReturn(HTTP_200_STATUSLINE) |
| .thenReturn(HTTP_200_STATUSLINE); |
| when(httpClient.execute(eq(HTTP_HOST), HttpRequestMatcher.eq(request), eq(httpClientContext))) |
| .thenReturn(mockResponse) |
| .thenReturn(mockResponse); |
| when(httpClient.execute(eq(HTTP_HOST), HttpRequestMatcher.eq(loginRequest), eq(httpClientContext))) |
| .thenReturn(mockResponse); |
| |
| final CloseableHttpResponse response = client.execute(request); |
| |
| assertThat(response, notNullValue()); |
| assertThat(response, sameInstance(mockResponse)); |
| verify(client).execute((HttpUriRequest)HttpRequestMatcher.eq(request), eq(0)); |
| verify(client).execute((HttpUriRequest)HttpRequestMatcher.eq(request), eq(200)); |
| verify(client).execute((HttpUriRequest)HttpRequestMatcher.eq(loginRequest), eq(401)); |
| } |
| |
| @Test |
| public void testExecuteTwoConsecutiveUnauthorizedExecutions() throws Exception { |
| when(mockResponse.getStatusLine()) |
| .thenReturn(HTTP_401_STATUSLINE) |
| .thenReturn(HTTP_401_STATUSLINE); |
| when(httpClient.execute(eq(HTTP_HOST), HttpRequestMatcher.eq(request), eq(httpClientContext))) |
| .thenReturn(mockResponse); |
| when(httpClient.execute(eq(HTTP_HOST), HttpRequestMatcher.eq(loginRequest), eq(httpClientContext))) |
| .thenReturn(mockResponse); |
| final NiciraRestClient client = spy(NiciraRestClient.create() |
| .client(httpClient) |
| .clientContext(httpClientContext) |
| .hostname(LOCALHOST) |
| .username(ADMIN) |
| .password(ADMIN_PASSWORD) |
| .loginUrl(LOGIN_PATH) |
| .executionLimit(2) |
| .build()); |
| |
| try { |
| client.execute(request); |
| fail("Expected CloudstackRESTException exception"); |
| } catch (final CloudstackRESTException e) { |
| assertThat(e.getMessage(), not(isEmptyOrNullString())); |
| verify(client).execute((HttpUriRequest)HttpRequestMatcher.eq(request), eq(0)); |
| verify(client).execute((HttpUriRequest)HttpRequestMatcher.eq(loginRequest), eq(401)); |
| } |
| } |
| |
| @Test |
| public void testExecuteLiveLockWhenControllerAllowsLoginAndFollowsWithUnauthorizedButDoesNotRediect() throws Exception { |
| when(mockResponse.getStatusLine()) |
| .thenReturn(HTTP_401_STATUSLINE) |
| .thenReturn(HTTP_200_STATUSLINE) |
| .thenReturn(HTTP_401_STATUSLINE) |
| .thenReturn(HTTP_200_STATUSLINE) |
| .thenReturn(HTTP_401_STATUSLINE) |
| .thenReturn(HTTP_200_STATUSLINE) |
| .thenReturn(HTTP_401_STATUSLINE) |
| .thenReturn(HTTP_200_STATUSLINE) |
| .thenReturn(HTTP_401_STATUSLINE); |
| when(httpClient.execute(eq(HTTP_HOST), HttpRequestMatcher.eq(request), eq(httpClientContext))) |
| .thenReturn(mockResponse) |
| .thenReturn(mockResponse) |
| .thenReturn(mockResponse) |
| .thenReturn(mockResponse) |
| .thenReturn(mockResponse); |
| when(httpClient.execute(eq(HTTP_HOST), HttpRequestMatcher.eq(loginRequest), eq(httpClientContext))) |
| .thenReturn(mockResponse) |
| .thenReturn(mockResponse) |
| .thenReturn(mockResponse) |
| .thenReturn(mockResponse); |
| final NiciraRestClient client = spy(NiciraRestClient.create() |
| .client(httpClient) |
| .clientContext(httpClientContext) |
| .hostname(LOCALHOST) |
| .username(ADMIN) |
| .password(ADMIN_PASSWORD) |
| .loginUrl(LOGIN_PATH) |
| .executionLimit(2) |
| .build()); |
| |
| try { |
| client.execute(request); |
| fail("Execution count should have been maxed out"); |
| } catch (final CloudstackRESTException e) { |
| assertThat(e.getMessage(), containsString("Reached max executions limit of ")); |
| } |
| } |
| } |