AAI Query optimization for VID
[vid.git] / vid-app-common / src / test / java / org / onap / vid / aai / AaiClientTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2019 AT&T Intellectual Property. 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
21 package org.onap.vid.aai;
22
23 import static java.util.stream.Collectors.toList;
24 import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase;
25 import static org.hamcrest.MatcherAssert.assertThat;
26 import static org.hamcrest.Matchers.contains;
27 import static org.hamcrest.Matchers.containsInAnyOrder;
28 import static org.hamcrest.Matchers.containsString;
29 import static org.hamcrest.Matchers.either;
30 import static org.hamcrest.Matchers.hasProperty;
31 import static org.hamcrest.Matchers.instanceOf;
32 import static org.hamcrest.Matchers.is;
33 import static org.hamcrest.Matchers.sameInstance;
34 import static org.mockito.ArgumentMatchers.any;
35 import static org.mockito.ArgumentMatchers.anyBoolean;
36 import static org.mockito.ArgumentMatchers.anyString;
37 import static org.mockito.ArgumentMatchers.argThat;
38 import static org.mockito.ArgumentMatchers.eq;
39 import static org.mockito.ArgumentMatchers.isNull;
40 import static org.mockito.ArgumentMatchers.nullable;
41 import static org.mockito.Mockito.mock;
42 import static org.mockito.Mockito.verify;
43 import static org.mockito.Mockito.when;
44 import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
45 import static org.onap.vid.utils.Unchecked.toURI;
46 import static org.testng.Assert.assertEquals;
47 import static org.testng.Assert.assertFalse;
48 import static org.testng.Assert.assertNull;
49 import static org.testng.Assert.fail;
50
51 import com.fasterxml.jackson.core.JsonProcessingException;
52 import com.fasterxml.jackson.databind.ObjectMapper;
53 import com.google.common.collect.ImmutableList;
54 import java.io.FileNotFoundException;
55 import java.io.IOException;
56 import java.net.URI;
57 import java.security.cert.CertificateException;
58 import java.util.ArrayList;
59 import java.util.Map;
60 import java.util.function.BiConsumer;
61 import java.util.function.Function;
62 import java.util.stream.Stream;
63 import javax.crypto.BadPaddingException;
64 import javax.net.ssl.SSLHandshakeException;
65 import javax.servlet.ServletContext;
66 import javax.ws.rs.ProcessingException;
67 import javax.ws.rs.client.Client;
68 import javax.ws.rs.core.Response;
69 import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
70 import org.apache.commons.lang3.builder.ToStringStyle;
71 import org.apache.commons.lang3.exception.ExceptionUtils;
72 import org.apache.commons.lang3.reflect.FieldUtils;
73 import org.apache.commons.lang3.tuple.Pair;
74 import org.apache.http.HttpStatus;
75 import org.hamcrest.Matcher;
76 import org.mockito.Mockito;
77 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
78 import org.onap.portalsdk.core.util.SystemProperties;
79 import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse;
80 import org.onap.vid.aai.model.CustomQuerySimpleResult;
81 import org.onap.vid.aai.model.ModelVer;
82 import org.onap.vid.aai.model.ModelVersions;
83 import org.onap.vid.aai.model.PortDetailsTranslator;
84 import org.onap.vid.aai.model.Properties;
85 import org.onap.vid.aai.model.RelatedToProperty;
86 import org.onap.vid.aai.model.ResourceType;
87 import org.onap.vid.aai.model.SimpleResult;
88 import org.onap.vid.aai.util.AAIRestInterface;
89 import org.onap.vid.aai.util.CacheProvider;
90 import org.onap.vid.aai.util.HttpsAuthClient;
91 import org.onap.vid.aai.util.ServletRequestHelper;
92 import org.onap.vid.aai.util.SystemPropertyHelper;
93 import org.onap.vid.controller.LocalWebConfig;
94 import org.onap.vid.exceptions.GenericUncheckedException;
95 import org.onap.vid.model.Subscriber;
96 import org.onap.vid.model.SubscriberList;
97 import org.onap.vid.model.probes.ExternalComponentStatus;
98 import org.onap.vid.model.probes.HttpRequestMetadata;
99 import org.onap.vid.model.probes.StatusMetadata;
100 import org.onap.vid.testUtils.TestUtils;
101 import org.onap.vid.utils.Logging;
102 import org.onap.vid.utils.Unchecked;
103 import org.springframework.http.HttpMethod;
104 import org.springframework.test.context.ContextConfiguration;
105 import org.springframework.test.context.web.WebAppConfiguration;
106 import org.testng.Assert;
107 import org.testng.annotations.BeforeMethod;
108 import org.testng.annotations.DataProvider;
109 import org.testng.annotations.Test;
110 import sun.security.provider.certpath.SunCertPathBuilderException;
111 import sun.security.validator.ValidatorException;
112
113 @ContextConfiguration(classes = {LocalWebConfig.class, SystemProperties.class})
114 @WebAppConfiguration
115 public class AaiClientTest {
116
117     private final String NO_LCP_REGION_AND_TENANTS_MSG = "A&AI has no LCP Region & Tenants associated to subscriber 'subscriberId' and service type 'serviceType'";
118     private AaiClient aaiClientMock;
119     private ServletContext servletContext;
120
121     @BeforeMethod
122     public void initMocks(){
123         aaiClientMock = mock(AaiClient.class);
124         aaiClientMock.logger = mock(EELFLoggerDelegate.class);
125         aaiClientMock.objectMapper = new ObjectMapper();
126         servletContext = mock(ServletContext.class);
127
128         when(servletContext.getRealPath(any(String.class))).thenReturn("");
129
130         when(aaiClientMock.doAaiGet(any(String.class),any(Boolean.class))).thenReturn(null);
131         when(aaiClientMock.doAaiGet(any(URI.class), anyBoolean(), anyBoolean())).thenReturn(null);
132     }
133
134     @DataProvider
135     public static Object[][] logicalLinkData() {
136         return new Object[][] {
137                 {"", "network/logical-links/logical-link/"},
138                 {"link", "network/logical-links/logical-link/link"}
139         };
140     }
141
142       private static String nfRoleOnly = "{\"start\":[\"/business/customers/customer/globalCustomerId1-360-as988q/service-subscriptions/service-subscription/TEST1-360/service-instances\"],\"query\":\"query/vnfs-fromServiceInstance-filter?nfRole=test360\"}";
143     private static String nfRoleAndCloudRegion = "{\"start\":[\"/business/customers/customer/globalCustomerId1-360-as988q/service-subscriptions/service-subscription/TEST1-360/service-instances\"],\"query\":\"query/vnfs-fromServiceInstance-filterByCloudRegion?nfRole=test360&cloudRegionID=cloudRegion-1\"}";
144     private static String cloudRegionOnly = "{\"start\":[\"/business/customers/customer/globalCustomerId1-360-as988q/service-subscriptions/service-subscription/TEST1-360/service-instances\"],\"query\":\"query/vnfs-fromServiceInstance-filterByCloudRegion?cloudRegionID=cloudRegion-1\"}";
145     private static String withoutNfroleAndCloudRegion = "{\"start\":[\"/business/customers/customer/globalCustomerId1-360-as988q/service-subscriptions/service-subscription/TEST1-360/service-instances\"],\"query\":\"query/vnfs-fromServiceInstance-filter\"}";
146     private static String withoutNfroleAndCloudRegionWithSpace = "{\"start\":[\"/business/customers/customer/globalCustomerId1with%20space%20360-as988q/service-subscriptions/service-subscription/TEST1%20360/service-instances\"],\"query\":\"query/vnfs-fromServiceInstance-filter\"}";
147
148     private static String responseJsonNfRole = "/payload_jsons/changeManagement/vnfs-fromServiceInstance-filterNfRole.json";
149     private static String responseJsonCloudRegion ="/payload_jsons/changeManagement/vnfs-fromServiceInstance-filterByCloudRegion.json";
150
151     private static String responseJsonDSLServiceInstance ="/payload_jsons/service-instance-by-subscriberid.json";
152     private static String dslQueryPayloadByServiceInstanceId = "{\"dsl\":\"customer*('global-customer-id','SOME_GLOBAL_CUST_ID')>service-subscription>service-instance*('service-instance-id','SOME_SERVICE_INSTANCE_ID')\"}";
153     private static String dslQueryPayloadByServiceInstanceName = "{\"dsl\":\"customer*('global-customer-id','SOME_GLOBAL_CUST_ID')>service-subscription>service-instance*('service-instance-name','SOME_SERVICE_INSTANCE_NAME')\"}";
154
155     @DataProvider
156     public static Object[][] aaiPutCustomQueryData() {
157         return new Object[][] {
158             {"globalCustomerId1-360-as988q", "TEST1-360", "test360", null, nfRoleOnly, responseJsonNfRole, "908419144", 200},
159             {"globalCustomerId1-360-as988q", "TEST1-360", null, "cloudRegion-1", cloudRegionOnly, responseJsonCloudRegion, "1165906024", 200},
160             {"globalCustomerId1-360-as988q", "TEST1-360", "test360", "cloudRegion-1", nfRoleAndCloudRegion,
161                 responseJsonCloudRegion, "1165906024", 200},
162             {"globalCustomerId1with space 360-as988q", "TEST1 360", null, null, withoutNfroleAndCloudRegionWithSpace, responseJsonNfRole, "908419144", 200},
163                 {"globalCustomerId1-360-as988q", "TEST1-360", null, null, withoutNfroleAndCloudRegion, responseJsonNfRole, "908419144", 200},
164         };
165     }
166
167     @Test(dataProvider = "aaiPutCustomQueryData")
168     public void testAaiPutCustomQueryByParams(String globalCustomerId, String serviceType, String nfRole, String cloudRegion, String expectedPayload, String responseBody, String expectedId, int responseHttpCode) {
169         String queryFormat = "query?format=simple";
170         final ResponseWithRequestInfo mockedResponseWithRequestInfo = mockedResponseWithRequestInfo(Response.Status.OK,
171             TestUtils.readFileAsString(responseBody),
172             "query?format=simple&Mock=True",
173             HttpMethod.PUT);
174         when(aaiClientMock.doAaiPut(eq(queryFormat), anyString(), anyBoolean(), anyBoolean())).thenReturn(mockedResponseWithRequestInfo);
175         when(aaiClientMock.getVnfsByParamsForChangeManagement(anyString(), anyString(), nullable(String.class), nullable(String.class))).thenCallRealMethod();
176         AaiResponse<AaiGetVnfResponse> response = aaiClientMock.getVnfsByParamsForChangeManagement(globalCustomerId, serviceType, nfRole, cloudRegion);
177         verify(aaiClientMock).doAaiPut(eq(queryFormat), eq(expectedPayload), eq(false), eq(false));
178         assertEquals(response.getHttpCode(), responseHttpCode);
179         assertEquals(response.getT().getResults().get(0).id, expectedId);
180     }
181
182     @Test(dataProvider = "logicalLinkData")
183     public void getLogicalLink_Link_Is_Empty(String link, String expectedUrl) {
184
185         when(aaiClientMock.getLogicalLink(any(String.class))).thenCallRealMethod();
186         aaiClientMock.getLogicalLink(link);
187         verify(aaiClientMock).doAaiGet(argThat(s -> equalsIgnoreCase(s, expectedUrl)),any(Boolean.class));
188     }
189
190     @DataProvider
191     public static Object[][] subscribersResults() {
192         return new Object[][] {
193                 {new SubscriberList(new ArrayList<Subscriber>() {{ add(new Subscriber());  add(new Subscriber()); }}), true},
194                 {new SubscriberList(new ArrayList<Subscriber>() {{ add(new Subscriber()); }}), true},
195                 {new SubscriberList(new ArrayList<Subscriber>()), false}
196         };
197     }
198
199     @Test(dataProvider = "subscribersResults")
200     public void testProbeAaiGetAllSubscribers_returnsTwoToZeroSubscribers_ResultsAsExpected(SubscriberList subscribers, boolean isAvailable){
201         ExternalComponentStatus expectedStatus = new ExternalComponentStatus(ExternalComponentStatus.Component.AAI,isAvailable, new HttpRequestMetadata(
202                 HttpMethod.GET,
203                 200,
204                 "url",
205                 "rawData",
206                 isAvailable ? "OK" : "No subscriber received",
207                 0
208         ));
209         Mockito.when(aaiClientMock.getAllSubscribers(true)).thenReturn(
210                 new AaiResponseWithRequestInfo<>(
211                         HttpMethod.GET, "url", new AaiResponse<>(subscribers, null, 200),
212                         "rawData"));
213         Mockito.when(aaiClientMock.probeComponent()).thenCallRealMethod();
214         ExternalComponentStatus result  = aaiClientMock.probeComponent();
215         assertThat(statusDataReflected(result),is(statusDataReflected(expectedStatus)));
216         assertThat(requestMetadataReflected(result.getMetadata()),is(requestMetadataReflected(expectedStatus.getMetadata())));
217     }
218
219     @Test(expectedExceptions = Exception.class)
220     public void typedAaiGet_aaiRestInterfaceRestGetReturnsError_exceptionIsThrown() {
221         AAIRestInterface aaiRestInterface = mock(AAIRestInterface.class);
222         final ResponseWithRequestInfo responseWithRequestInfo = mockedResponseWithRequestInfo(Response.Status.INTERNAL_SERVER_ERROR, "entity");
223         mockForGetRequest(aaiRestInterface, responseWithRequestInfo);
224         final AaiClient aaiClient = new AaiClient(aaiRestInterface, null, null);
225
226         try {
227
228             aaiClient.typedAaiGet(toURI("/irrelevant/url"), RelatedToProperty.class);
229
230         } catch (Exception e) {
231             assertThat(ExceptionUtils.getStackTrace(e), e, instanceOf(ExceptionWithRequestInfo.class));
232             ExceptionWithRequestInfo e2 = ((ExceptionWithRequestInfo) e);
233             assertThat(e2.getHttpCode(), is(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()));
234             assertThat(e2.getRawData(), is("entity"));
235             assertThat(e2.getHttpMethod(), is(HttpMethod.GET));
236             assertThat(e2.getRequestedUrl(), is("/my/mocked/url"));
237
238             throw e;
239         }
240     }
241
242     @Test(expectedExceptions = Exception.class)
243     public void typedAaiGet_aaiRestInterfaceRestGetReturnsInparsableResponse_exceptionIsThrown() {
244         AAIRestInterface aaiRestInterface = mock(AAIRestInterface.class);
245         final ResponseWithRequestInfo responseWithRequestInfo = mockedResponseWithRequestInfo(Response.Status.OK, "entity");
246         mockForGetRequest(aaiRestInterface, responseWithRequestInfo);
247         final AaiClient aaiClient = new AaiClient(aaiRestInterface, null, null);
248
249         try {
250
251             aaiClient.typedAaiGet(toURI("/irrelevant/url"), RelatedToProperty.class);
252
253         } catch (Exception e) {
254             assertThat(ExceptionUtils.getStackTrace(e), e, instanceOf(ExceptionWithRequestInfo.class));
255             assertThat(e.getCause(),
256                     hasProperty("cause", is(instanceOf(com.fasterxml.jackson.core.JsonParseException.class)))
257             );
258             throw e;
259         }
260     }
261
262     @Test
263     public void typedAaiGet_aaiRestInterfaceRestGetReturns_objectIsFine() {
264         AAIRestInterface aaiRestInterface = mock(AAIRestInterface.class);
265         final ResponseWithRequestInfo responseWithRequestInfo = mockedResponseWithRequestInfo(Response.Status.OK,
266                 "{ \"property-key\": \"foo\", \"property-value\": \"bar\" }");
267         mockForGetRequest(aaiRestInterface, responseWithRequestInfo);
268
269         final AaiClient aaiClient = new AaiClient(aaiRestInterface, null, null);
270
271         final RelatedToProperty relatedToPropertyAaiResponse = aaiClient.typedAaiGet(toURI("/irrelevant/url"), RelatedToProperty.class);
272
273         assertThat(relatedToPropertyAaiResponse.getPropertyKey(), is("foo"));
274         assertThat(relatedToPropertyAaiResponse.getPropertyValue(), is("bar"));
275     }
276
277     private ResponseWithRequestInfo mockedResponseWithRequestInfo(Response.Status status, String entity) {
278         return mockedResponseWithRequestInfo(status, entity, "/my/mocked/url", HttpMethod.GET);
279     }
280
281     private ResponseWithRequestInfo mockedResponseWithRequestInfo(Response.Status status, String entity, String requestUrl, HttpMethod method) {
282         final Response mockResponse = mock(Response.class);
283         when(mockResponse.getStatus()).thenReturn(status.getStatusCode());
284         when(mockResponse.getStatusInfo()).thenReturn(status);
285         when(mockResponse.readEntity(String.class)).thenReturn(entity);
286         return new ResponseWithRequestInfo(mockResponse, requestUrl, method);
287     }
288
289     //serialize fields except of fields we cannot know ahead of time
290     private static String requestMetadataReflected(StatusMetadata metadata) {
291         return new ReflectionToStringBuilder(metadata, ToStringStyle.SHORT_PREFIX_STYLE)
292                 .setExcludeFieldNames("duration")
293                 .toString();
294     }
295
296     private static String statusDataReflected(ExternalComponentStatus status) {
297         return new ReflectionToStringBuilder(status, ToStringStyle.SHORT_PREFIX_STYLE)
298                 .setExcludeFieldNames("metadata")
299                 .toString();
300     }
301
302     @DataProvider
303     public static Object[][] rawData() {
304         return new Object[][]{
305                 {"errorMessage", }, {""}, {null}
306         };
307     }
308
309     @Test(dataProvider = "rawData")
310     public void testProbeAaiGetFullSubscribersWithNullResponse_returnsNotAvailableWithErrorRawData(String rawData){
311         Mockito.when(aaiClientMock.getAllSubscribers(true)).thenReturn(
312                 new AaiResponseWithRequestInfo<>(HttpMethod.GET, "url", null,
313                         rawData));
314         ExternalComponentStatus result = callProbeAaiGetAllSubscribersAndAssertNotAvailable();
315         assertThat(result.getMetadata(), instanceOf(HttpRequestMetadata.class));
316         assertEquals(((HttpRequestMetadata) result.getMetadata()).getRawData(), rawData);
317     }
318
319     @DataProvider
320     public static Object[][] exceptions() {
321         return new Object[][] {
322                 {"NullPointerException", "errorMessage",
323                         new ExceptionWithRequestInfo(HttpMethod.GET, "url",
324                                 "errorMessage", null, new NullPointerException())},
325                 {"RuntimeException", null,
326                         new ExceptionWithRequestInfo(HttpMethod.GET, "url",
327                                 null, null, new RuntimeException())},
328                 {"RuntimeException", null,
329                         new RuntimeException()},
330         };
331     }
332
333     @Test(dataProvider = "exceptions")
334     public void testProbeAaiGetFullSubscribersWithNullResponse_returnsNotAvailableWithErrorRawData(String description, String expectedRawData, Exception exception){
335         Mockito.when(aaiClientMock.getAllSubscribers(true)).thenThrow(exception);
336         ExternalComponentStatus result = callProbeAaiGetAllSubscribersAndAssertNotAvailable();
337         if (exception instanceof ExceptionWithRequestInfo) {
338             assertThat(result.getMetadata(), instanceOf(HttpRequestMetadata.class));
339             assertEquals(((HttpRequestMetadata) result.getMetadata()).getRawData(), expectedRawData);
340         }
341         assertThat(result.getMetadata().getDescription(), containsString(description));
342     }
343
344     private ExternalComponentStatus callProbeAaiGetAllSubscribersAndAssertNotAvailable() {
345         Mockito.when(aaiClientMock.probeComponent()).thenCallRealMethod();
346         ExternalComponentStatus result  = aaiClientMock.probeComponent();
347         assertFalse(result.isAvailable());
348         return result;
349     }
350
351
352     @Test
353     public void getTenants_Arguments_Are_Null_Or_Empty() {
354
355         when(aaiClientMock.getTenants(any(), any())).thenCallRealMethod();
356
357         AaiResponse response = aaiClientMock.getTenants("", "");
358
359         assertEquals(response.getErrorMessage(), "{\"statusText\":\" Failed to retrieve LCP Region & Tenants from A&AI, Subscriber ID or Service Type is missing.\"}");
360
361
362         response = aaiClientMock.getTenants(null, null);
363
364         assertEquals(response.getErrorMessage(), "{\"statusText\":\" Failed to retrieve LCP Region & Tenants from A&AI, Subscriber ID or Service Type is missing.\"}");
365     }
366
367     @Test(expectedExceptions = AaiClient.ParsingGetTenantsResponseFailure.class, expectedExceptionsMessageRegExp = NO_LCP_REGION_AND_TENANTS_MSG)
368     public void getTenants_Arguments_Are_Valid_But_Tenants_Not_Exist() {
369
370         when(aaiClientMock.getTenantsNonCached(any(String.class),any(String.class))).thenCallRealMethod();
371
372         Response generalEmptyResponse = mock(Response.class);
373         when(aaiClientMock.doAaiGet(any(String.class),any(Boolean.class))).thenReturn(generalEmptyResponse);
374
375         aaiClientMock.getTenantsNonCached("subscriberId", "serviceType");
376     }
377
378     @Test
379     public void whenCacheThrowException_thenGetTenantReturnAaiResponse() {
380         CacheProvider mockCacheProvider = mock(CacheProvider.class);
381         CacheProvider.Cache mockCache = mock(CacheProvider.Cache.class);
382         AaiClient aaiClientUnderTest = new AaiClient(null, null, mockCacheProvider);
383
384         when(mockCacheProvider.aaiClientCacheFor(any(), any())).thenReturn(mockCache);
385         when(mockCache.get(any())).thenThrow(new AaiClient.ParsingGetTenantsResponseFailure(NO_LCP_REGION_AND_TENANTS_MSG));
386         AaiResponse aaiResponse = aaiClientUnderTest.getTenants("subscriberId", "serviceType");
387         assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, aaiResponse.getHttpCode());
388         assertEquals("{\"statusText\":\""+NO_LCP_REGION_AND_TENANTS_MSG+"\"}", aaiResponse.getErrorMessage());
389     }
390
391     @Test
392     public void getTenants_Arguments_Are_Valid_Get_The_Tenanats() {
393
394         when(aaiClientMock.getTenantsNonCached(any(String.class),any(String.class))).thenCallRealMethod();
395
396
397         Response generalEmptyResponse = mock(Response.class);
398
399         when(generalEmptyResponse.readEntity(String.class)).thenReturn(tenantResponseRaw);
400         when(generalEmptyResponse.getStatus()).thenReturn(200);
401         when(generalEmptyResponse.getStatusInfo()).thenReturn(Response.Status.OK);
402
403
404         when(aaiClientMock.doAaiGet(any(String.class),any(Boolean.class))).thenReturn(generalEmptyResponse);
405
406         AaiResponse<GetTenantsResponse[]> response = aaiClientMock.getTenantsNonCached("subscriberId", "serviceType");
407
408         GetTenantsResponse[] tenants = response.getT();
409
410         Assert.assertTrue(response.t.length> 0);
411
412         Assert.assertEquals(tenants[0].cloudOwner,"irma-aic-cloud-owner");
413     }
414
415     final String tenantResponseRaw ="" +
416             "{" +
417             "\"service-type\": \"VIRTUAL USP\"," +
418             "\"resource-version\": \"1494001841964\"," +
419             "\"relationship-list\": {" +
420             "\"relationship\": [{" +
421             "\"related-to\": \"tenant\"," +
422             "\"related-link\": \"/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/AAIAIC25/tenants/tenant/092eb9e8e4b7412e8787dd091bc58e86\"," +
423             "\"relationship-data\": [{" +
424             "\"relationship-key\": \"cloud-region.cloud-owner\"," +
425             "\"relationship-value\": \"irma-aic-cloud-owner\"" +
426             "}," +
427             "{" +
428             "\"relationship-key\": \"cloud-region.cloud-region-id\"," +
429             "\"relationship-value\": \"AAIAIC25\"" +
430             "}," +
431             "{" +
432             "\"relationship-key\": \"tenant.tenant-id\"," +
433             "\"relationship-value\": \"092eb9e8e4b7412e8787dd091bc58e86\"" +
434             "}" +
435             "]," +
436             "\"related-to-property\": [{" +
437             "\"property-key\": \"tenant.tenant-name\"," +
438             "\"property-value\": \"USP-SIP-IC-24335-T-01\"" +
439             "}]" +
440             "}]" +
441             "}" +
442             "}";
443
444     final String vfModuleHomingResponseRaw ="{" +
445             "    \"vf-module-id\": \"ed02354a-3217-45ce-a1cd-e0b69b7a8cea\"," +
446             "    \"vf-module-name\": \"apndns_az_02_module_1\"," +
447             "    \"heat-stack-id\": \"apndns_az_02_module_1/97a319f3-b095-4fff-befa-c657508ecaf8\"," +
448             "    \"orchestration-status\": \"active\"," +
449             "    \"is-base-vf-module\": false," +
450             "    \"resource-version\": \"1530559380383\"," +
451             "    \"model-invariant-id\": \"74450b48-0aa0-4743-8314-9163e92b7862\"," +
452             "    \"model-version-id\": \"6bc01a2b-bc48-4991-b9fe-e22c2215d801\"," +
453             "    \"model-customization-id\": \"74f638c2-0368-4212-8f73-e961005af17c\"," +
454             "    \"module-index\": 0," +
455             "    \"relationship-list\": {" +
456             "        \"relationship\": [" +
457             "            {" +
458             "                \"related-to\": \"l3-network\"," +
459             "                \"relationship-label\": \"org.onap.relationships.inventory.DependsOn\"," +
460             "                \"related-link\": \"/aai/v12/network/l3-networks/l3-network/335e62be-73a3-41e8-930b-1a677bcafea5\"," +
461             "                \"relationship-data\": [" +
462             "                    {" +
463             "                        \"relationship-key\": \"l3-network.network-id\"," +
464             "                        \"relationship-value\": \"335e62be-73a3-41e8-930b-1a677bcafea5\"" +
465             "                    }" +
466             "                ]," +
467             "                \"related-to-property\": [" +
468             "                    {" +
469             "                        \"property-key\": \"l3-network.network-name\"," +
470             "                        \"property-value\": \"MNS-FN-25180-T-02Shared_oam_protected_net_1\"" +
471             "                    }" +
472             "                ]" +
473             "            }," +
474             "            {" +
475             "                \"related-to\": \"l3-network\"," +
476             "                \"relationship-label\": \"org.onap.relationships.inventory.DependsOn\"," +
477             "                \"related-link\": \"/aai/v12/network/l3-networks/l3-network/2db4ee3e-2ac7-4fc3-8739-ecf53416459e\"," +
478             "                \"relationship-data\": [" +
479             "                    {" +
480             "                        \"relationship-key\": \"l3-network.network-id\"," +
481             "                        \"relationship-value\": \"2db4ee3e-2ac7-4fc3-8739-ecf53416459e\"" +
482             "                    }" +
483             "                ]," +
484             "                \"related-to-property\": [" +
485             "                    {" +
486             "                        \"property-key\": \"l3-network.network-name\"," +
487             "                        \"property-value\": \"Mobisupport-FN-27099-T-02_int_apn_dns_net_1\"" +
488             "                    }" +
489             "                ]" +
490             "            }," +
491             "            {" +
492             "                \"related-to\": \"volume-group\"," +
493             "                \"relationship-label\": \"org.onap.relationships.inventory.Uses\"," +
494             "                \"related-link\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/volume-groups/volume-group/66013ebe-0c81-44b9-a24f-7c6acba73a39\"," +
495             "                \"relationship-data\": [" +
496             "                    {" +
497             "                        \"relationship-key\": \"cloud-region.cloud-owner\"," +
498             "                        \"relationship-value\": \"irma-aic\"" +
499             "                    }," +
500             "                    {" +
501             "                        \"relationship-key\": \"cloud-region.cloud-region-id\"," +
502             "                        \"relationship-value\": \"rdm5b\"" +
503             "                    }," +
504             "                    {" +
505             "                        \"relationship-key\": \"volume-group.volume-group-id\"," +
506             "                        \"relationship-value\": \"66013ebe-0c81-44b9-a24f-7c6acba73a39\"" +
507             "                    }" +
508             "                ]" +
509             "            }," +
510             "            {" +
511             "                \"related-to\": \"vserver\"," +
512             "                \"relationship-label\": \"org.onap.relationships.inventory.Uses\"," +
513             "                \"related-link\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/tenants/tenant/db1818f7f2e34862b378bfb2cc520f91/vservers/vserver/5eef9f6d-9933-4bc6-9a1a-862d61309437\"," +
514             "                \"relationship-data\": [" +
515             "                    {" +
516             "                        \"relationship-key\": \"cloud-region.cloud-owner\"," +
517             "                        \"relationship-value\": \"irma-aic\"" +
518             "                    }," +
519             "                    {" +
520             "                        \"relationship-key\": \"cloud-region.cloud-region-id\"," +
521             "                        \"relationship-value\": \"rdm5b\"" +
522             "                    }," +
523             "                    {" +
524             "                        \"relationship-key\": \"tenant.tenant-id\"," +
525             "                        \"relationship-value\": \"db1818f7f2e34862b378bfb2cc520f91\"" +
526             "                    }," +
527             "                    {" +
528             "                        \"relationship-key\": \"vserver.vserver-id\"," +
529             "                        \"relationship-value\": \"5eef9f6d-9933-4bc6-9a1a-862d61309437\"" +
530             "                    }" +
531             "                ]," +
532             "                \"related-to-property\": [" +
533             "                    {" +
534             "                        \"property-key\": \"vserver.vserver-name\"," +
535             "                        \"property-value\": \"zrdm5bfapn01dns002\"" +
536             "                    }" +
537             "                ]" +
538             "            }" +
539             "        ]" +
540             "    }" +
541             "}";
542     @Test
543     public void get_homingDataForVfModule() {
544         when(aaiClientMock.getHomingDataByVfModule(any(String.class), any(String.class))).thenCallRealMethod();
545
546         Response homingResponse = mock(Response.class);
547
548         when(homingResponse.readEntity(String.class)).thenReturn(vfModuleHomingResponseRaw);
549         when(homingResponse.getStatus()).thenReturn(200);
550         when(homingResponse.getStatusInfo()).thenReturn(Response.Status.OK);
551
552
553         when(aaiClientMock.doAaiGet(any(String.class), any(Boolean.class))).thenReturn(homingResponse);
554
555         GetTenantsResponse tenant = aaiClientMock.getHomingDataByVfModule("vnfInstanceId", "vfModuleId");
556
557         Assert.assertEquals(tenant.cloudOwner,"irma-aic" );
558         Assert.assertEquals(tenant.cloudRegionID,"rdm5b");
559         Assert.assertEquals(tenant.tenantID,"db1818f7f2e34862b378bfb2cc520f91");
560
561     }
562     @Test(expectedExceptions = GenericUncheckedException.class, expectedExceptionsMessageRegExp = "A&AI has no homing data associated to vfModule 'vfModuleId' of vnf 'vnfInstanceId'")
563     public void getVfModule_Homing_Arguments_Are_Valid_But_Not_Exists() {
564         when(aaiClientMock.getHomingDataByVfModule(any(String.class), any(String.class))).thenCallRealMethod();
565
566         Response generalEmptyResponse = mock(Response.class);
567         when(aaiClientMock.doAaiGet(any(String.class),any(Boolean.class))).thenReturn(generalEmptyResponse);
568
569         aaiClientMock.getHomingDataByVfModule("vnfInstanceId", "vfModuleId");
570     }
571
572     @DataProvider
573     public static Object[][] invalidDataId() {
574         return new String[][] {
575                 {""},
576                 {null}
577         };
578     }
579
580     @Test(dataProvider = "invalidDataId", expectedExceptions = GenericUncheckedException.class, expectedExceptionsMessageRegExp = "Failed to retrieve homing data associated to vfModule from A&AI, VNF InstanceId or VF Module Id is missing.")
581     public void getVfModule_Homing_Arguments_Are_Empty_Or_Null(String data) {
582         when(aaiClientMock.getHomingDataByVfModule(any(), any())).thenCallRealMethod();
583              aaiClientMock.getHomingDataByVfModule(data, data);
584     }
585
586     @DataProvider
587     public static Object[][] resourceTypesProvider() {
588         return new Object[][] {
589                 {"service-instance", ResourceType.SERVICE_INSTANCE},
590                 {"generic-vnf", ResourceType.GENERIC_VNF},
591                 {"vf-module", ResourceType.VF_MODULE}
592         };
593     }
594
595     @DataProvider
596     public static Object[][] nameAndResourceTypeProvider() {
597         return new Object[][] {
598                 {"SRIOV_SVC", ResourceType.SERVICE_INSTANCE, "nodes/service-instances?service-instance-name=SRIOV_SVC"},
599                 {"b1707vidnf", ResourceType.GENERIC_VNF, "nodes/generic-vnfs?vnf-name=b1707vidnf"},
600                 {"connectivity_test", ResourceType.VF_MODULE, "nodes/vf-modules?vf-module-name=connectivity_test"},
601                 {"ByronPace", ResourceType.INSTANCE_GROUP, "nodes/instance-groups?instance-group-name=ByronPace"},
602                 {"MjVg1234", ResourceType.VOLUME_GROUP, "nodes/volume-groups?volume-group-name=MjVg1234"}
603         };
604     }
605
606     @Test(dataProvider = "nameAndResourceTypeProvider")
607     public void whenSearchNodeTypeByName_callRightAaiPath(String name, ResourceType type, String expectedUrl) {
608         AAIRestInterface aaiRestInterface = mock(AAIRestInterface.class);
609         ResponseWithRequestInfo responseWithRequestInfo = mockedResponseWithRequestInfo(Response.Status.OK, "{}");
610
611         when(aaiRestInterface.RestGet(anyString(), anyString(), eq(toURI(expectedUrl)), anyBoolean(), anyBoolean()))
612                 .thenReturn(responseWithRequestInfo);
613
614         AaiClient aaiClient = new AaiClient(aaiRestInterface, null, null);
615
616         aaiClient.isNodeTypeExistsByName(name, type);
617     }
618
619     @DataProvider
620     public static Object[][] aaiClientInternalExceptions() {
621         return Stream.<Pair<Class<? extends Throwable>, UncheckedBiConsumer<HttpsAuthClient, Client>>>of(
622
623                 // Exception out of httpsAuthClientMock
624                 Pair.of(CertificateException.class, (httpsAuthClientMock, javaxClientMock) -> {
625                     final CertificateException e0 = new CertificateException("No X509TrustManager implementation available");
626                     SSLHandshakeException e = new SSLHandshakeException(e0.toString());
627                     e.initCause(e0);
628
629                     when(httpsAuthClientMock.getClient(any())).thenThrow(e);
630                 }),
631
632                 Pair.of(StringIndexOutOfBoundsException.class, mockExceptionOnClientProvider(new StringIndexOutOfBoundsException(4))),
633
634                 Pair.of(NullPointerException.class, mockExceptionOnClientProvider(new NullPointerException("null"))),
635
636                 Pair.of(FileNotFoundException.class, mockExceptionOnClientProvider(new FileNotFoundException("vid/WEB-INF/cert/aai-client-cert.p12"))),
637
638                 Pair.of(BadPaddingException.class, mockExceptionOnClientProvider(
639                         new IOException("keystore password was incorrect", new BadPaddingException("Given final block not properly padded")))
640                 ),
641                 Pair.of(GenericUncheckedException.class, mockExceptionOnClientProvider(new GenericUncheckedException("basa"))),
642
643                 Pair.of(NullPointerException.class, (httpsAuthClientMock, javaxClientMock) ->
644                         when(httpsAuthClientMock.getClient(any())).thenReturn(null)),
645
646
647                 // Exception out of javax's Client
648                 Pair.of(SSLHandshakeException.class, (httpsAuthClientMock, javaxClientMock) -> {
649                     when(javaxClientMock.target(nullable(String.class))).thenThrow(
650                             new ProcessingException(new SSLHandshakeException("Received fatal alert: certificate_expired"))
651                     );
652                 }),
653
654                 Pair.of(SunCertPathBuilderException.class, (httpsAuthClientMock, javaxClientMock) -> {
655                     SunCertPathBuilderException e0 = new SunCertPathBuilderException("unable to find valid certification path to requested target");
656                     when(javaxClientMock.target(nullable(String.class))).thenThrow(
657                             new ProcessingException(new ValidatorException("PKIX path building failed: " + e0.toString(), e0))
658                     );
659                 }),
660
661                 Pair.of(GenericUncheckedException.class, (httpsAuthClientMock, javaxClientMock) ->
662                         when(javaxClientMock.target(nullable(String.class))).thenThrow(new GenericUncheckedException("basa")))
663
664         ).flatMap(l -> Stream.of(
665                 // double each case to propagateExceptions = true/false, to verify that "don't propagate" really still work
666                 ImmutableList.of(l.getLeft(), l.getRight(), true).toArray(),
667                 ImmutableList.of(l.getLeft(), l.getRight(), false).toArray()
668         )).collect(toList()).toArray(new Object[][]{});
669     }
670
671     private static UncheckedBiConsumer<HttpsAuthClient, Client> mockExceptionOnClientProvider(Exception e) {
672         return (httpsAuthClientMock, javaxClientMock) ->
673                 when(httpsAuthClientMock.getClient(any())).thenThrow(e);
674     }
675
676     @Test(dataProvider = "aaiClientInternalExceptions")
677     public void propagateExceptions_internalsThrowException_ExceptionRethrown(Class<? extends Throwable> expectedType, BiConsumer<HttpsAuthClient, Client> setupMocks, boolean propagateExceptions) throws Exception {
678         /*
679         Call chain is like:
680             this test -> AaiClient -> AAIRestInterface -> HttpsAuthClient -> javax's Client
681
682         In this test, *AaiClient* and *AAIRestInterface* are under test (actual
683         implementation is used), while HttpsAuthClient and the javax's Client are
684         mocked to return pseudo-responses or - better- throw exceptions.
685          */
686
687         // prepare mocks
688         HttpsAuthClient httpsAuthClientMock = mock(HttpsAuthClient.class);
689         TestUtils.JavaxRsClientMocks mocks = new TestUtils.JavaxRsClientMocks();
690         Client javaxClientMock = mocks.getFakeClient();
691         Response responseMock = mocks.getFakeResponse();
692
693         // prepare real AAIRestInterface and AaiClient, and wire mocks
694         AAIRestInterface aaiRestInterface = new AAIRestInterface(httpsAuthClientMock,
695             mock(ServletRequestHelper.class),
696             mock(SystemPropertyHelper.class),
697             mock(Logging.class));
698         final AaiClient aaiClient = new AaiClient(aaiRestInterface, null, null);
699         when(httpsAuthClientMock.getClient(any())).thenReturn(javaxClientMock);
700
701         // define atomic method under test, including reset of "aaiRestInterface.client"
702         final Function<Boolean, Response> doAaiGet = (propagateExceptions1) -> {
703             try {
704                 FieldUtils.writeField(aaiRestInterface, "client", null, true);
705                 return aaiClient.doAaiGet("uri", false, propagateExceptions1).getResponse();
706             } catch (IllegalAccessException e) {
707                 throw new RuntimeException(e);
708             }
709         };
710
711         // verify setup again
712         assertThat("mocks setup should make doAaiGet return our responseMock", doAaiGet.apply(true), is(sameInstance(responseMock)));
713
714
715         /// TEST:
716         setupMocks.accept(httpsAuthClientMock, javaxClientMock);
717
718         try {
719             final Response response = doAaiGet.apply(propagateExceptions);
720         } catch (Exception e) {
721             if (propagateExceptions) {
722                 assertThat("root cause incorrect for " + ExceptionUtils.getStackTrace(e), ExceptionUtils.getRootCause(e), instanceOf(expectedType));
723                 return; // ok, done
724             } else {
725                 // Verify that "don't propagate" really still work
726                 Assert.fail("calling doAaiGet when propagateExceptions is false must result with no exception", e);
727             }
728         }
729
730         // If no exception caught
731         // We're asserting that the legacy behaviour is still in place. Hopefully
732         // one day we will remove the non-propagateExceptions case
733         assertFalse(propagateExceptions, "calling doAaiGet when propagateExceptions is 'true' must result with an exception (in this test)");
734     }
735
736     @DataProvider
737     public static Object[][] aaiClientGetCloudOwnerByCloudRegionId() {
738
739         final String cloudRegion = "{" +
740                 "      \"cloud-owner\": \"mure-royo-ru22\"," +
741                 "      \"cloud-region-id\": \"ravitu\"," +
742                 "      \"cloud-type\": \"openstack\"," +
743                 "      \"resource-version\": \"1523631256125\"," +
744                 "      \"relationship-list\": {" +
745                 "        \"relationship\": [{" +
746                 "            \"related-to\": \"pserver\"" +
747                 "          }" +
748                 "        ]" +
749                 "      }" +
750                 "    }";
751
752         String bodyWith0 = "{  \"cloud-region\": [" + "  ]}";
753         String bodyWith1 = "{  \"cloud-region\": [" + cloudRegion + "  ]}";
754         String bodyWith2 = "{  \"cloud-region\": [" + cloudRegion + ", " + cloudRegion + "  ]}";
755         String bodyWithDifferent2 = "{  \"cloud-region\": [" + cloudRegion + ", " +
756                 cloudRegion.replace("mure-royo-ru22", "nolay-umaxo") +
757                 "]}";
758
759         return new Object[][] {
760                 { "regular single result", bodyWith1, false },
761                 { "exceptional empty result", bodyWith0, true },
762                 { "two same results", bodyWith2, false },
763                 { "two incoherent results", bodyWithDifferent2, true },
764         };
765     }
766
767     @Test(dataProvider = "aaiClientGetCloudOwnerByCloudRegionId")
768     public void getCloudOwnerByCloudRegionIdNonCached(String desc, String body, boolean expectingException) {
769         final String cloudRegion = "ravitu";
770         AAIRestInterface aaiRestInterface = mock(AAIRestInterface.class);
771         final ResponseWithRequestInfo responseWithRequestInfo = mockedResponseWithRequestInfo(Response.Status.OK, body);
772         when(aaiRestInterface.doRest(anyString(), anyString(), eq(Unchecked.toURI("cloud-infrastructure/cloud-regions?cloud-region-id=" + cloudRegion)),
773                 isNull(), eq(HttpMethod.GET), anyBoolean(), anyBoolean()))
774                 .thenReturn(responseWithRequestInfo);
775
776         final AaiClient aaiClient = new AaiClient(aaiRestInterface, null, null);
777
778         try {
779             final String result = aaiClient.getCloudOwnerByCloudRegionIdNonCached(cloudRegion);
780             if (expectingException) fail("expected failure on " + desc + ", got " + result);
781             else {
782                 assertThat(result, is("mure-royo-ru22"));
783             }
784         } catch (Exception e) {
785             if (!expectingException) throw e;
786             else {
787                 assertThat(e.toString(), either(
788                         containsString("No cloud-owner found for " + cloudRegion))
789                         .or(containsString("Conflicting cloud-owner found for " + cloudRegion)));
790             }
791         }
792     }
793
794     @DataProvider
795     public static Object[][]  cloudRegionAndTenantDataProvider() {
796         return new Object[][] {
797                 { "APPC-24595-T-IST-02C", "mtn23b" },
798                 { "APPC-24595-T-IST-02C", null },
799                 { null, "mtn23b" },
800                 { null, null },
801         };
802     }
803
804     @DataProvider
805     public static Object[][]  versionsDataProvider() {
806         return new Object[][] {
807                 { Stream.of("20","10","30"), Stream.of("30","20","10"), "30" },
808                 { Stream.of("10","20","20"), Stream.of("20","20","10"), "20" },
809                 { Stream.of("c","b","a"), Stream.of("c","b","a"), "c" },
810                 { Stream.of("1.0","2.0","1.8"), Stream.of("2.0","1.8","1.0"), "2.0" },
811                 { Stream.of("1.0.7","2.0.9","2.0.2"), Stream.of("2.0.9","2.0.2","1.0.7"), "2.0.9" },
812                 { Stream.of("0","0","0"), Stream.of("0","0","0"), "0" },
813                 { Stream.of("","10"), Stream.of("10",""), "10" },
814         };
815     }
816
817     @Test(dataProvider = "versionsDataProvider")
818     public void sortedModelVer(Stream<String> input, Stream<String> expectedSorted, String expectedMax) {
819         Stream<ModelVer> modelVerStream = input.map(version -> {
820             ModelVer mv = new ModelVer();
821             mv.setModelVersion(version);
822             return mv;
823         });
824
825         final AaiClient aaiClient = new AaiClient(null, null, null);
826
827         assertThat(aaiClient.sortedModelVer(modelVerStream),
828             contains(
829                 expectedSorted.map(it -> hasProperty("modelVersion", is(it))).toArray(Matcher[]::new)
830             ));
831     }
832
833     @Test(dataProvider = "versionsDataProvider")
834     public void maxModelVer(Stream<String> input, Stream<String> expectedSorted, String expectedMax) {
835         Stream<ModelVer> modelVerStream = input.map(version -> {
836             ModelVer mv = new ModelVer();
837             mv.setModelVersion(version);
838             return mv;
839         });
840
841         final AaiClient aaiClient = new AaiClient(null, null, null);
842
843         assertThat(aaiClient.maxModelVer(modelVerStream), hasProperty("modelVersion", is(expectedMax)));
844     }
845
846     @Test(expectedExceptions = GenericUncheckedException.class)
847     public void maxModelVerException() {
848         final AaiClient aaiClient = new AaiClient(null, null, null);
849         aaiClient.maxModelVer(Stream.of(new ModelVer()));
850     }
851     @Test(dataProvider = "cloudRegionAndTenantDataProvider")
852     public void getCloudRegionAndTenantByVnfId(String tenantName, String cloudRegionId) throws JsonProcessingException {
853         SimpleResult tenant = new SimpleResult();
854         if (tenantName != null) {
855             tenant.setJsonNodeType("tenant");
856             Properties tenantProps = new Properties();
857             tenantProps.setTenantName(tenantName);
858             tenant.setJsonProperties(tenantProps);
859         }
860
861         SimpleResult cloudRegion = new SimpleResult();
862         if (cloudRegionId != null) {
863             cloudRegion.setJsonNodeType("cloud-region");
864             Properties cloudRegionProps = new Properties();
865             cloudRegionProps.setCloudRegionId(cloudRegionId);
866             cloudRegion.setJsonProperties(cloudRegionProps);
867         }
868
869         CustomQuerySimpleResult customQuerySimpleResult = new CustomQuerySimpleResult(ImmutableList.of(tenant, cloudRegion));
870         String mockedBody = new ObjectMapper().writeValueAsString(customQuerySimpleResult);
871
872         AAIRestInterface aaiRestInterface = mock(AAIRestInterface.class);
873         final ResponseWithRequestInfo responseWithRequestInfo = mockedResponseWithRequestInfo(Response.Status.OK, mockedBody, "query?format=simple", HttpMethod.PUT);
874         when(aaiRestInterface.doRest(anyString(), anyString(), eq(Unchecked.toURI("query?format=simple")),
875                 any(), eq(HttpMethod.PUT), anyBoolean(), anyBoolean()))
876                 .thenReturn(responseWithRequestInfo);
877
878         final AaiClient aaiClient = new AaiClient(aaiRestInterface, null, null);
879         Map<String, Properties> result = aaiClient.getCloudRegionAndTenantByVnfId("anyVnfId");
880         if (tenantName != null) {
881             assertEquals(result.get("tenant").getTenantName(), tenantName);
882         } else {
883             assertNull(result.get("tenant"));
884         }
885
886         if (cloudRegionId != null) {
887             assertEquals(result.get("cloud-region").getCloudRegionId(), cloudRegionId);
888         } else {
889             assertNull(result.get("cloud-region"));
890         }
891     }
892
893     protected void mockForGetRequest(AAIRestInterface aaiRestInterface, ResponseWithRequestInfo responseWithRequestInfo) {
894         when(aaiRestInterface.doRest(anyString(), anyString(), any(URI.class), isNull(), eq(HttpMethod.GET) ,anyBoolean(), anyBoolean()))
895                 .thenReturn(responseWithRequestInfo);
896     }
897
898     @Test
899     public void shouldProperlyReadResponseOnceWhenSubscribersAreNotPresent() {
900         AAIRestInterface restInterface = mock(AAIRestInterface.class);
901         PortDetailsTranslator portDetailsTranslator = mock(PortDetailsTranslator.class);
902         Response response = mock(Response.class);
903         when(response.getStatus()).thenReturn(404);
904         when(response.readEntity(String.class)).thenReturn("sampleEntity");
905         when(response.getStatusInfo()).thenReturn(Response.Status.NOT_FOUND);
906         ResponseWithRequestInfo responseWithRequestInfo = new ResponseWithRequestInfo(response, "test", HttpMethod.GET);
907         when(restInterface.RestGet(eq("VidAaiController"), any(String.class),
908                 eq(Unchecked.toURI("business/customers?subscriber-type=INFRA&depth=0")), eq(false), eq(true))).thenReturn(responseWithRequestInfo);
909         AaiClient aaiClient = new AaiClient(restInterface, portDetailsTranslator, null);
910
911
912         aaiClient.getAllSubscribers(true);
913
914         verify(response).readEntity(String.class);
915     }
916
917     @FunctionalInterface
918     public interface UncheckedBiConsumer<T, U> extends BiConsumer<T, U> {
919         @Override
920         default void accept(T t, U u) {
921             try {
922                 acceptThrows(t, u);
923             } catch (Exception e) {
924                 throw new RuntimeException(e);
925             }
926         }
927
928         void acceptThrows(T t, U u) throws Exception;
929     }
930
931     @Test
932     public void getLatestVersionByInvariantId_verifyCallingExpectedApi(){
933
934         when(aaiClientMock.getLatestVersionByInvariantId(anyString())).thenCallRealMethod();
935
936         aaiClientMock.getLatestVersionByInvariantId("model-invariant-id");
937
938         Mockito.verify(aaiClientMock).doAaiPut(argThat(url -> url.endsWith("query?format=resource&depth=0")),argThat(payload -> payload.contains("service-design-and-creation/models/model/model-invariant-id")),anyBoolean());
939
940     }
941
942     @DataProvider
943     public static Object[][]  getSubscriberDataDataProvider() {
944         return new Object[][] {
945             { "Some-ID", true },
946             { "another id 123", false },
947         };
948     }
949
950     @Test(dataProvider = "getSubscriberDataDataProvider")
951     public void getSubscriberDataParams(String subscriberId, boolean omitServiceInstances) {
952         String depth = omitServiceInstances ? "1" : "2";
953         when(aaiClientMock.getSubscriberData(anyString(),anyBoolean())).thenCallRealMethod();
954         aaiClientMock.getSubscriberData(subscriberId, omitServiceInstances);
955         Mockito.verify(aaiClientMock).doAaiGet(argThat(s -> s.contains("customer/" + subscriberId + "?") && s.contains("depth=" + depth)),any(Boolean.class));
956     }
957
958
959     @DataProvider
960     public static Object[][] aaiDSLPutServiceInstanceQueryData() {
961         return new Object[][] {
962             {"SOME_GLOBAL_CUST_ID", "Service Instance Id", "SOME_SERVICE_INSTANCE_ID",
963                 dslQueryPayloadByServiceInstanceId, responseJsonDSLServiceInstance, "SOME_SERVICE_INSTANCE_ID", 200},
964             {"SOME_GLOBAL_CUST_ID", "Service Instance Name", "SOME_SERVICE_INSTANCE_NAME",
965                 dslQueryPayloadByServiceInstanceName, responseJsonDSLServiceInstance, "SOME_SERVICE_INSTANCE_ID", 200},
966             {"SOME_GLOBAL_CUST_ID", "Service Instance Name", "SOME_SERVICE_INSTANCE_NAME",
967                 dslQueryPayloadByServiceInstanceName, responseJsonDSLServiceInstance, "SOME_SERVICE_INSTANCE_ID",200},
968
969         };
970     }
971
972     @Test(dataProvider = "aaiDSLPutServiceInstanceQueryData")
973     public void testAaiDSLPutServiceInstanceQueryByParams(          String globalCustomerId,
974                                                                     String identifierType,
975                                                                     String identifier,
976                                                                     String expectedPayload,
977                                                                     String responseBody,
978                                                                     String expectedSiId,
979                                                                     int responseHttpCode) {
980
981         String queryFormat = "dsl?format=resource&nodesOnly=true&depth=0&as-tree=true";
982
983         final ResponseWithRequestInfo mockedResponseWithRequestInfo = mockedResponseWithRequestInfo(Response.Status.OK,
984             TestUtils.readFileAsString(responseBody),
985             "dsl?format=resource&nodesOnly=true&depth=0&as-tree=true&Mock=True",
986             HttpMethod.PUT);
987
988         when(aaiClientMock.doAaiPut(eq(queryFormat), anyString(), anyBoolean(), anyBoolean())).thenReturn(mockedResponseWithRequestInfo);
989         when(aaiClientMock.getServiceInstanceBySubscriberIdAndInstanceIdentifier(anyString(), anyString(), anyString())).thenCallRealMethod();
990
991         AaiResponse<DSLQuerySimpleResponse> response = aaiClientMock.getServiceInstanceBySubscriberIdAndInstanceIdentifier(globalCustomerId, identifierType, identifier);
992
993         verify(aaiClientMock).doAaiPut(eq(queryFormat), eq(expectedPayload), eq(false), eq(false));
994
995         assertEquals(response.getHttpCode(), responseHttpCode);
996         assertEquals(response.getT().getResults().get(0).getCustomer().getCustomerRelatedNodes().get(0).getCustomerServiceSubscription().
997             getServiceSubscriptionRelatedNodes().get(0).getServiceInstance().serviceInstanceId, expectedSiId);
998
999         assertEquals(response.getT().getResults().get(0).getCustomer().getSubscriberName(), "Mobility");
1000
1001         assertEquals(response.getT().getResults().get(0).getCustomer().getCustomerRelatedNodes().get(0).getCustomerServiceSubscription().
1002             getServiceSubscriptionRelatedNodes().get(0).getServiceInstance().orchestrationStatus, "SOME_ORCH_STATUS");
1003
1004     }
1005
1006     @Test
1007     public void testToModelVerStream() throws IOException {
1008
1009         ModelVersions modelVersions = JACKSON_OBJECT_MAPPER.readValue("" +
1010             "{\n" +
1011             "    \"results\": [\n" +
1012             "        {\n" +
1013             "            \"model\": {\n" +
1014             "                \"model-invariant-id\": \"f6342be5-d66b-4d03-a1aa-c82c3094c4ea\",\n" +
1015             "                \"model-type\": \"service\",\n" +
1016             "                \"resource-version\": \"1534274421300\"\n" +
1017             "            }\n" +
1018             "        },\n" +
1019             "        {\n" +
1020             "            \"model-ver\": {\n" +
1021             "                \"model-version-id\": \"a92f899d-a3ec-465b-baed-1663b0a5aee1\",\n" +
1022             "                \"model-name\": \"NCM_VLAN_SVC_ym161f\",\n" +
1023             "                \"model-version\": \"bbb\",\n" +
1024             "                \"distribution-status\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
1025             "                \"model-description\": \"Network Collection service for vLAN tagging\",\n" +
1026             "                \"resource-version\": \"1534788756086\"\n" +
1027             "            }\n" +
1028             "        },\n" +
1029             "        {\n" +
1030             "            \"model-ver\": {\n" +
1031             "                \"model-version-id\": \"d2fda667-e92e-4cfa-9620-5da5de01a319\",\n" +
1032             "                \"model-name\": \"NCM_VLAN_SVC_ym161f\",\n" +
1033             "                \"model-version\": \"aaa\",\n" +
1034             "                \"distribution-status\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
1035             "                \"model-description\": \"Network Collection service for vLAN tagging\",\n" +
1036             "                \"resource-version\": \"1534444087221\"\n" +
1037             "            }\n" +
1038             "        }]}", ModelVersions.class);
1039
1040
1041         final AaiClient aaiClient = new AaiClient(null, null, null);
1042
1043         assertThat(aaiClient.toModelVerStream(modelVersions).collect(toList()),
1044             containsInAnyOrder(
1045                 hasProperty("modelVersionId", is("a92f899d-a3ec-465b-baed-1663b0a5aee1")),
1046                 hasProperty("modelVersionId", is("d2fda667-e92e-4cfa-9620-5da5de01a319"))
1047             ));
1048
1049     }
1050 }