2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018 Nokia. All rights reserved.
6 * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
7 * =============================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 package org.onap.appc.adapter.chef.chefclient.impl;
23 import static junit.framework.TestCase.assertEquals;
24 import static org.mockito.BDDMockito.given;
25 import static org.mockito.Matchers.argThat;
26 import static org.mockito.Mockito.mock;
28 import com.google.common.collect.ImmutableMap;
29 import java.io.IOException;
31 import java.net.URISyntaxException;
32 import java.util.function.Supplier;
33 import org.apache.http.Header;
34 import org.apache.http.HttpResponse;
35 import org.apache.http.HttpStatus;
36 import org.apache.http.StatusLine;
37 import org.apache.http.client.HttpClient;
38 import org.apache.http.client.methods.HttpRequestBase;
39 import org.apache.http.entity.StringEntity;
40 import org.junit.Before;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.mockito.ArgumentMatcher;
44 import org.mockito.InjectMocks;
45 import org.mockito.Mock;
46 import org.mockito.runners.MockitoJUnitRunner;
47 import org.onap.appc.adapter.chef.chefclient.ChefApiClientFactory;
48 import org.onap.appc.adapter.chef.chefclient.api.ChefApiClient;
49 import org.onap.appc.adapter.chef.chefclient.api.ChefResponse;
51 @RunWith(MockitoJUnitRunner.class)
52 public class ChefApiClientImplTest {
54 private static final String END_POINT = "https://chefServer";
55 private static final String ORGANIZATIONS_PATH = "onap";
56 private static final String USER_ID = "testUser";
57 private static final String REQUEST_PATH = "/test/path";
58 private static final String BODY = "SOME BODY STRING";
59 private static final String PEM_FILEPATH = "path/to/pemFile";
60 private static final ImmutableMap<String, String> HEADERS = ImmutableMap.<String, String>builder()
61 .put("Content-type", "application/json")
62 .put("Accept", "application/json")
63 .put("X-Ops-Timestamp", "1970-01-15T06:56:07Z")
64 .put("X-Ops-UserId", USER_ID)
65 .put("X-Chef-Version", "12.4.1")
66 .put("X-Ops-Content-Hash", BODY)
67 .put("X-Ops-Sign", "version=1.0").build();
70 private HttpClient httpClient;
72 private ChefApiHeaderFactory chefHttpHeaderFactory;
75 private ChefApiClientFactory chefApiClientFactory;
76 private ChefApiClient chefApiClient;
80 chefApiClient = chefApiClientFactory.create(
88 public void execute_HttpGet_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
90 String methodName = "GET";
92 Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.get(REQUEST_PATH);
95 assertChefApiClientCall(methodName, body, chefClientApiCall);
99 public void execute_HttpDelete_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
101 String methodName = "DELETE";
103 Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.delete(REQUEST_PATH);
106 assertChefApiClientCall(methodName, body, chefClientApiCall);
110 public void execute_HttpPost_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
112 String methodName = "POST";
113 Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.post(REQUEST_PATH, BODY);
116 assertChefApiClientCall(methodName, BODY, chefClientApiCall);
120 public void execute_HttpPut_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
122 String methodName = "PUT";
123 Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.put(REQUEST_PATH, BODY);
126 assertChefApiClientCall(methodName, BODY, chefClientApiCall);
129 private void assertChefApiClientCall(String methodName, String body, Supplier<ChefResponse> httpMethod)
132 given(chefHttpHeaderFactory.create(methodName, REQUEST_PATH, body, USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH))
133 .willReturn(HEADERS);
135 StatusLine statusLine = mock(StatusLine.class);
136 given(statusLine.getStatusCode()).willReturn(HttpStatus.SC_OK);
137 HttpResponse httpResponse = mock(HttpResponse.class);
138 given(httpResponse.getStatusLine()).willReturn(statusLine);
139 given(httpResponse.getEntity()).willReturn(new StringEntity("Successful Response String"));
140 given(httpClient.execute(argThat(new HttpRequestBaseMatcher(methodName))))
141 .willReturn(httpResponse);
144 ChefResponse chefResponse = httpMethod.get();
147 assertEquals("Successful Response String", chefResponse.getBody());
148 assertEquals(HttpStatus.SC_OK, chefResponse.getStatusCode());
152 public void execute_shouldHandleException_whenHttpClientExecutionFails() throws IOException {
155 given(chefHttpHeaderFactory.create("GET", REQUEST_PATH, "", USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH))
156 .willReturn(HEADERS);
158 String expectedErrorMsg = "HttpClient call failed";
159 given(httpClient.execute(argThat(new HttpRequestBaseMatcher("GET"))))
160 .willThrow(new IOException(expectedErrorMsg));
163 ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH);
166 assertEquals(expectedErrorMsg, chefResponse.getBody());
167 assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode());
171 public void execute_shouldHandleException_whenEndpointURIisMalformed() {
173 String expectedErrorMsg = "Malformed escape pair at index 1: /%#@/";
176 ChefApiClient chefApiClient = chefApiClientFactory.create(
181 ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH);
184 assertEquals(expectedErrorMsg, chefResponse.getBody());
185 assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode());
188 private class HttpRequestBaseMatcher extends ArgumentMatcher<HttpRequestBase> {
190 private final String methodName;
192 public HttpRequestBaseMatcher(String methodName) {
193 this.methodName = methodName;
197 public boolean matches(Object argument) {
198 HttpRequestBase httpRequestBase = (HttpRequestBase) argument;
200 boolean headersMatch = checkIfHeadersMatch(httpRequestBase);
202 return methodName.equals(httpRequestBase.getMethod())
203 && new URI(END_POINT + "/organizations/" + ORGANIZATIONS_PATH + REQUEST_PATH).equals(httpRequestBase.getURI())
205 } catch (URISyntaxException e) {
211 private boolean checkIfHeadersMatch(HttpRequestBase httpRequestBase) {
212 Header[] generatedHeaders = httpRequestBase.getAllHeaders();
213 return generatedHeaders.length > 0
214 && generatedHeaders.length == HEADERS.size()
215 && HEADERS.entrySet().stream()
216 .allMatch(p -> httpRequestBase.getFirstHeader(p.getKey()).getValue().equals(p.getValue()));