ed39efb1bf4472582fe3fea5832f2c3685836254
[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  * =============================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.onap.appc.adapter.chef.chefclient.impl;
21
22 import static junit.framework.TestCase.assertEquals;
23 import static org.mockito.BDDMockito.given;
24 import static org.mockito.Matchers.argThat;
25 import static org.mockito.Mockito.mock;
26
27 import com.google.common.collect.ImmutableMap;
28 import java.io.IOException;
29 import java.net.URI;
30 import java.net.URISyntaxException;
31 import java.util.function.Supplier;
32 import org.apache.http.Header;
33 import org.apache.http.HttpResponse;
34 import org.apache.http.HttpStatus;
35 import org.apache.http.StatusLine;
36 import org.apache.http.client.HttpClient;
37 import org.apache.http.client.methods.HttpRequestBase;
38 import org.apache.http.entity.StringEntity;
39 import org.junit.Before;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 import org.mockito.ArgumentMatcher;
43 import org.mockito.InjectMocks;
44 import org.mockito.Mock;
45 import org.mockito.runners.MockitoJUnitRunner;
46 import org.onap.appc.adapter.chef.chefclient.ChefApiClientFactory;
47 import org.onap.appc.adapter.chef.chefclient.api.ChefApiClient;
48 import org.onap.appc.adapter.chef.chefclient.api.ChefResponse;
49
50 @RunWith(MockitoJUnitRunner.class)
51 public class ChefApiClientImplTest {
52
53     private static final String END_POINT = "https://chefServer";
54     private static final String ORGANIZATIONS_PATH = "onap";
55     private static final String USER_ID = "testUser";
56     private static final String REQUEST_PATH = "/test/path";
57     private static final String BODY = "SOME BODY STRING";
58     private static final String PEM_FILEPATH = "path/to/pemFile";
59     private static final ImmutableMap<String, String> HEADERS = ImmutableMap.<String, String>builder()
60         .put("Content-type", "application/json")
61         .put("Accept", "application/json")
62         .put("X-Ops-Timestamp", "1970-01-15T06:56:07Z")
63         .put("X-Ops-UserId", USER_ID)
64         .put("X-Chef-Version", "12.4.1")
65         .put("X-Ops-Content-Hash", BODY)
66         .put("X-Ops-Sign", "version=1.0").build();
67
68     @Mock
69     private HttpClient httpClient;
70     @Mock
71     private ChefApiHeaderFactory chefHttpHeaderFactory;
72
73     @InjectMocks
74     private ChefApiClientFactory chefApiClientFactory;
75     private ChefApiClient chefApiClient;
76
77     @Before
78     public void setUp() {
79         chefApiClient = chefApiClientFactory.create(
80             END_POINT,
81             ORGANIZATIONS_PATH,
82             USER_ID,
83             PEM_FILEPATH);
84     }
85
86     @Test
87     public void execute_HttpGet_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
88         // GIVEN
89         String methodName = "GET";
90         String body = "";
91         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.get(REQUEST_PATH);
92
93         // WHEN //THEN
94         assertChefApiClientCall(methodName, body, chefClientApiCall);
95     }
96
97     @Test
98     public void execute_HttpDelete_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
99         // GIVEN
100         String methodName = "DELETE";
101         String body = "";
102         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.delete(REQUEST_PATH);
103
104         // WHEN //THEN
105         assertChefApiClientCall(methodName, body, chefClientApiCall);
106     }
107
108     @Test
109     public void execute_HttpPost_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
110         // GIVEN
111         String methodName = "POST";
112         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.post(REQUEST_PATH, BODY);
113
114         // WHEN //THEN
115         assertChefApiClientCall(methodName, BODY, chefClientApiCall);
116     }
117
118     @Test
119     public void execute_HttpPut_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
120         // GIVEN
121         String methodName = "PUT";
122         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.put(REQUEST_PATH, BODY);
123
124         // WHEN //THEN
125         assertChefApiClientCall(methodName, BODY, chefClientApiCall);
126     }
127
128     private void assertChefApiClientCall(String methodName, String body, Supplier<ChefResponse> httpMethod)
129         throws IOException {
130         // GIVEN
131         given(chefHttpHeaderFactory.create(methodName, REQUEST_PATH, body, USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH))
132             .willReturn(HEADERS);
133
134         StatusLine statusLine = mock(StatusLine.class);
135         given(statusLine.getStatusCode()).willReturn(HttpStatus.SC_OK);
136         HttpResponse httpResponse = mock(HttpResponse.class);
137         given(httpResponse.getStatusLine()).willReturn(statusLine);
138         given(httpResponse.getEntity()).willReturn(new StringEntity("Successful Response String"));
139         given(httpClient.execute(argThat(new HttpRequestBaseMatcher(methodName))))
140             .willReturn(httpResponse);
141
142         // WHEN
143         ChefResponse chefResponse = httpMethod.get();
144
145         // THEN
146         assertEquals("Successful Response String", chefResponse.getBody());
147         assertEquals(HttpStatus.SC_OK, chefResponse.getStatusCode());
148     }
149
150     @Test
151     public void execute_shouldHandleException_whenHttpClientExecutionFails() throws IOException {
152
153         // GIVEN
154         given(chefHttpHeaderFactory.create("GET", REQUEST_PATH, "", USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH))
155             .willReturn(HEADERS);
156
157         String expectedErrorMsg = "HttpClient call failed";
158         given(httpClient.execute(argThat(new HttpRequestBaseMatcher("GET"))))
159             .willThrow(new IOException(expectedErrorMsg));
160
161         // WHEN
162         ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH);
163
164         // THEN
165         assertEquals(expectedErrorMsg, chefResponse.getBody());
166         assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode());
167     }
168
169     @Test
170     public void execute_shouldHandleException_whenEndpointURIisMalformed() {
171         // GIVEN
172         String expectedErrorMsg = "Malformed escape pair at index 1: /%#@/";
173
174         // WHEN
175         ChefApiClient chefApiClient = chefApiClientFactory.create(
176             "/%#@/",
177             ORGANIZATIONS_PATH,
178             USER_ID,
179             PEM_FILEPATH);
180         ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH);
181
182         // THEN
183         assertEquals(expectedErrorMsg, chefResponse.getBody());
184         assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode());
185     }
186
187     private class HttpRequestBaseMatcher extends ArgumentMatcher<HttpRequestBase> {
188
189         private final String methodName;
190
191         public HttpRequestBaseMatcher(String methodName) {
192             this.methodName = methodName;
193         }
194
195         @Override
196         public boolean matches(Object argument) {
197             HttpRequestBase httpRequestBase = (HttpRequestBase) argument;
198
199             boolean headersMatch = checkIfHeadersMatch(httpRequestBase);
200             try {
201                 return methodName.equals(httpRequestBase.getMethod())
202                     && new URI(END_POINT + REQUEST_PATH).equals(httpRequestBase.getURI())
203                     && headersMatch;
204             } catch (URISyntaxException e) {
205                 e.printStackTrace();
206                 return false;
207             }
208         }
209
210         private boolean checkIfHeadersMatch(HttpRequestBase httpRequestBase) {
211             Header[] generatedHeaders = httpRequestBase.getAllHeaders();
212             return generatedHeaders.length > 0
213                 && generatedHeaders.length == HEADERS.size()
214                 && HEADERS.entrySet().stream()
215                 .allMatch(p -> httpRequestBase.getFirstHeader(p.getKey()).getValue().equals(p.getValue()));
216         }
217     }
218 }