Unit test for ChefApiClientImplTest
[appc.git] / appc-adapters / appc-chef-adapter / appc-chef-adapter-bundle / src / test / java / org / onap / appc / adapter / chef / chefclient / impl / ChefApiClientImplTest.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
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
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
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=========================================================
20  */
21 package org.onap.appc.adapter.chef.chefclient.impl;
22
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;
27
28 import com.google.common.collect.ImmutableMap;
29 import java.io.IOException;
30 import java.net.URI;
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.HttpEntityEnclosingRequestBase;
39 import org.apache.http.client.methods.HttpRequestBase;
40 import org.apache.http.entity.StringEntity;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.mockito.ArgumentMatcher;
45 import org.mockito.InjectMocks;
46 import org.mockito.Mock;
47 import org.mockito.runners.MockitoJUnitRunner;
48 import org.onap.appc.adapter.chef.chefclient.ChefApiClientFactory;
49 import org.onap.appc.adapter.chef.chefclient.api.ChefApiClient;
50 import org.onap.appc.adapter.chef.chefclient.api.ChefResponse;
51
52 @RunWith(MockitoJUnitRunner.class)
53 public class ChefApiClientImplTest {
54
55     private static final String END_POINT = "https://chefServer";
56     private static final String ORGANIZATIONS_PATH = "onap";
57     private static final String USER_ID = "testUser";
58     private static final String REQUEST_PATH = "/test/path";
59     private static final String BODY = "SOME BODY STRING";
60     private static final String PEM_FILEPATH = "path/to/pemFile";
61     private static final ImmutableMap<String, String> HEADERS = ImmutableMap.<String, String>builder()
62         .put("Content-type", "application/json")
63         .put("Accept", "application/json")
64         .put("X-Ops-Timestamp", "1970-01-15T06:56:07Z")
65         .put("X-Ops-UserId", USER_ID)
66         .put("X-Chef-Version", "12.4.1")
67         .put("X-Ops-Content-Hash", BODY)
68         .put("X-Ops-Sign", "version=1.0").build();
69
70     @Mock
71     private HttpClient httpClient;
72     @Mock
73     private ChefApiHeaderFactory chefHttpHeaderFactory;
74
75     @InjectMocks
76     private ChefApiClientFactory chefApiClientFactory;
77     private ChefApiClient chefApiClient;
78
79     @Before
80     public void setUp() {
81         chefApiClient = chefApiClientFactory.create(
82             END_POINT,
83             ORGANIZATIONS_PATH,
84             USER_ID,
85             PEM_FILEPATH);
86     }
87
88     @Test
89     public void execute_HttpGet_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
90         // GIVEN
91         String methodName = "GET";
92         String body = "";
93         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.get(REQUEST_PATH);
94
95         // WHEN //THEN
96         assertChefApiClientCall(methodName, body, chefClientApiCall);
97     }
98
99     @Test
100     public void execute_HttpDelete_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
101         // GIVEN
102         String methodName = "DELETE";
103         String body = "";
104         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.delete(REQUEST_PATH);
105
106         // WHEN //THEN
107         assertChefApiClientCall(methodName, body, chefClientApiCall);
108     }
109
110     @Test
111     public void execute_HttpPost_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
112         // GIVEN
113         String methodName = "POST";
114         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.post(REQUEST_PATH, BODY);
115
116         // WHEN //THEN
117         assertChefApiClientCall(methodName, BODY, chefClientApiCall);
118     }
119
120     @Test
121     public void execute_HttpPut_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
122         // GIVEN
123         String methodName = "PUT";
124         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.put(REQUEST_PATH, BODY);
125
126         // WHEN //THEN
127         assertChefApiClientCall(methodName, BODY, chefClientApiCall);
128     }
129
130     private void assertChefApiClientCall(String methodName, String body, Supplier<ChefResponse> httpMethod)
131         throws IOException {
132         // GIVEN
133         given(chefHttpHeaderFactory.create(methodName, REQUEST_PATH, body, USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH))
134             .willReturn(HEADERS);
135
136         StatusLine statusLine = mock(StatusLine.class);
137         given(statusLine.getStatusCode()).willReturn(HttpStatus.SC_OK);
138         HttpResponse httpResponse = mock(HttpResponse.class);
139         given(httpResponse.getStatusLine()).willReturn(statusLine);
140         given(httpResponse.getEntity()).willReturn(new StringEntity("Successful Response String"));
141         given(httpClient.execute(argThat(new HttpRequestBaseMatcher(methodName))))
142             .willReturn(httpResponse);
143
144         // WHEN
145         ChefResponse chefResponse = httpMethod.get();
146
147         // THEN
148         assertEquals("Successful Response String", chefResponse.getBody());
149         assertEquals(HttpStatus.SC_OK, chefResponse.getStatusCode());
150     }
151
152     @Test
153     public void execute_shouldHandleException_whenHttpClientExecutionFails() throws IOException {
154
155         // GIVEN
156         given(chefHttpHeaderFactory.create("GET", REQUEST_PATH, "", USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH))
157             .willReturn(HEADERS);
158
159         String expectedErrorMsg = "HttpClient call failed";
160         given(httpClient.execute(argThat(new HttpRequestBaseMatcher("GET"))))
161             .willThrow(new IOException(expectedErrorMsg));
162
163         // WHEN
164         ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH);
165
166         // THEN
167         assertEquals(expectedErrorMsg, chefResponse.getBody());
168         assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode());
169     }
170
171     @Test
172     public void execute_shouldHandleException_whenEndpointURIisMalformed() {
173         // GIVEN
174         String expectedErrorMsg = "Malformed escape pair at index 1: /%#@/";
175
176         // WHEN
177         ChefApiClient chefApiClient = chefApiClientFactory.create(
178             "/%#@/",
179             ORGANIZATIONS_PATH,
180             USER_ID,
181             PEM_FILEPATH);
182         ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH);
183
184         // THEN
185         assertEquals(expectedErrorMsg, chefResponse.getBody());
186         assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode());
187     }
188
189     private class HttpRequestBaseMatcher extends ArgumentMatcher<HttpRequestBase> {
190
191         private final String methodName;
192
193         public HttpRequestBaseMatcher(String methodName) {
194             this.methodName = methodName;
195         }
196
197         @Override
198         public boolean matches(Object argument) {
199             HttpRequestBase httpRequestBase = (HttpRequestBase) argument;
200
201             try {
202                 return methodName.equals(httpRequestBase.getMethod())
203                     && new URI(END_POINT + "/organizations/" + ORGANIZATIONS_PATH + REQUEST_PATH)
204                     .equals(httpRequestBase.getURI())
205                     && checkIfBodyMatches(httpRequestBase)
206                     && checkIfHeadersMatch(httpRequestBase);
207             } catch (URISyntaxException e) {
208                 e.printStackTrace();
209                 return false;
210             }
211         }
212
213         public boolean checkIfBodyMatches(HttpRequestBase httpRequestBase) {
214             if (httpRequestBase instanceof HttpEntityEnclosingRequestBase) {
215                 HttpEntityEnclosingRequestBase requestBaseWithBody = (HttpEntityEnclosingRequestBase) httpRequestBase;
216                 StringEntity stringEntity = new StringEntity(BODY, "UTF-8");
217                 stringEntity.setContentType("application/json");
218                 return stringEntity.toString().equals(requestBaseWithBody.getEntity().toString());
219             }
220             return true;
221         }
222
223         private boolean checkIfHeadersMatch(HttpRequestBase httpRequestBase) {
224             Header[] generatedHeaders = httpRequestBase.getAllHeaders();
225             return generatedHeaders.length > 0
226                 && generatedHeaders.length == HEADERS.size()
227                 && HEADERS.entrySet().stream()
228                 .allMatch(p -> httpRequestBase.getFirstHeader(p.getKey()).getValue().equals(p.getValue()));
229         }
230     }
231 }