Fixes for Chef Adapter bundle
[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.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;
50
51 @RunWith(MockitoJUnitRunner.class)
52 public class ChefApiClientImplTest {
53
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();
68
69     @Mock
70     private HttpClient httpClient;
71     @Mock
72     private ChefApiHeaderFactory chefHttpHeaderFactory;
73
74     @InjectMocks
75     private ChefApiClientFactory chefApiClientFactory;
76     private ChefApiClient chefApiClient;
77
78     @Before
79     public void setUp() {
80         chefApiClient = chefApiClientFactory.create(
81             END_POINT,
82             ORGANIZATIONS_PATH,
83             USER_ID,
84             PEM_FILEPATH);
85     }
86
87     @Test
88     public void execute_HttpGet_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
89         // GIVEN
90         String methodName = "GET";
91         String body = "";
92         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.get(REQUEST_PATH);
93
94         // WHEN //THEN
95         assertChefApiClientCall(methodName, body, chefClientApiCall);
96     }
97
98     @Test
99     public void execute_HttpDelete_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
100         // GIVEN
101         String methodName = "DELETE";
102         String body = "";
103         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.delete(REQUEST_PATH);
104
105         // WHEN //THEN
106         assertChefApiClientCall(methodName, body, chefClientApiCall);
107     }
108
109     @Test
110     public void execute_HttpPost_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
111         // GIVEN
112         String methodName = "POST";
113         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.post(REQUEST_PATH, BODY);
114
115         // WHEN //THEN
116         assertChefApiClientCall(methodName, BODY, chefClientApiCall);
117     }
118
119     @Test
120     public void execute_HttpPut_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException {
121         // GIVEN
122         String methodName = "PUT";
123         Supplier<ChefResponse> chefClientApiCall = () -> chefApiClient.put(REQUEST_PATH, BODY);
124
125         // WHEN //THEN
126         assertChefApiClientCall(methodName, BODY, chefClientApiCall);
127     }
128
129     private void assertChefApiClientCall(String methodName, String body, Supplier<ChefResponse> httpMethod)
130         throws IOException {
131         // GIVEN
132         given(chefHttpHeaderFactory.create(methodName, REQUEST_PATH, body, USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH))
133             .willReturn(HEADERS);
134
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);
142
143         // WHEN
144         ChefResponse chefResponse = httpMethod.get();
145
146         // THEN
147         assertEquals("Successful Response String", chefResponse.getBody());
148         assertEquals(HttpStatus.SC_OK, chefResponse.getStatusCode());
149     }
150
151     @Test
152     public void execute_shouldHandleException_whenHttpClientExecutionFails() throws IOException {
153
154         // GIVEN
155         given(chefHttpHeaderFactory.create("GET", REQUEST_PATH, "", USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH))
156             .willReturn(HEADERS);
157
158         String expectedErrorMsg = "HttpClient call failed";
159         given(httpClient.execute(argThat(new HttpRequestBaseMatcher("GET"))))
160             .willThrow(new IOException(expectedErrorMsg));
161
162         // WHEN
163         ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH);
164
165         // THEN
166         assertEquals(expectedErrorMsg, chefResponse.getBody());
167         assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode());
168     }
169
170     @Test
171     public void execute_shouldHandleException_whenEndpointURIisMalformed() {
172         // GIVEN
173         String expectedErrorMsg = "Malformed escape pair at index 1: /%#@/";
174
175         // WHEN
176         ChefApiClient chefApiClient = chefApiClientFactory.create(
177             "/%#@/",
178             ORGANIZATIONS_PATH,
179             USER_ID,
180             PEM_FILEPATH);
181         ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH);
182
183         // THEN
184         assertEquals(expectedErrorMsg, chefResponse.getBody());
185         assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode());
186     }
187
188     private class HttpRequestBaseMatcher extends ArgumentMatcher<HttpRequestBase> {
189
190         private final String methodName;
191
192         public HttpRequestBaseMatcher(String methodName) {
193             this.methodName = methodName;
194         }
195
196         @Override
197         public boolean matches(Object argument) {
198             HttpRequestBase httpRequestBase = (HttpRequestBase) argument;
199
200             boolean headersMatch = checkIfHeadersMatch(httpRequestBase);
201             try {
202                 return methodName.equals(httpRequestBase.getMethod())
203                     && new URI(END_POINT + "/organizations/" + ORGANIZATIONS_PATH + REQUEST_PATH).equals(httpRequestBase.getURI())
204                     && headersMatch;
205             } catch (URISyntaxException e) {
206                 e.printStackTrace();
207                 return false;
208             }
209         }
210
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()));
217         }
218     }
219 }