Adding interfaces in documentation
[aai/sparky-be.git] / src / test / java / org / onap / aai / sparky / search / UnifiedSearchProcessorTest.java
1 /**
2  * ============LICENSE_START===================================================
3  * SPARKY (AAI UI service)
4  * ============================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
8  * ============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=====================================================
21  *
22  * ECOMP and OpenECOMP are trademarks
23  * and service marks of AT&T Intellectual Property.
24  */
25
26 package org.onap.aai.sparky.search;
27
28 import static org.junit.Assert.assertEquals;
29 import static org.junit.Assert.assertNotNull;
30 import static org.junit.Assert.assertNull;
31
32 import java.io.IOException;
33 import java.util.ArrayList;
34 import java.util.List;
35
36 import org.apache.camel.Exchange;
37 import org.apache.camel.Message;
38 import org.apache.camel.component.restlet.RestletConstants;
39 import org.json.JSONArray;
40 import org.json.JSONObject;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.mockito.ArgumentCaptor;
44 import org.mockito.Mockito;
45 import org.onap.aai.sparky.common.search.CommonSearchSuggestion;
46 import org.onap.aai.sparky.search.api.SearchProvider;
47 import org.onap.aai.sparky.search.entity.MockSearchResponse;
48 import org.onap.aai.sparky.search.entity.QuerySearchEntity;
49 import org.onap.aai.sparky.search.entity.SearchSuggestion;
50 import org.onap.aai.sparky.search.registry.SearchProviderRegistry;
51 import org.restlet.Request;
52 import org.restlet.Response;
53 import org.restlet.data.ClientInfo;
54 import org.restlet.data.MediaType;
55 import org.restlet.data.Status;
56
57 import com.fasterxml.jackson.core.JsonProcessingException;
58 import com.fasterxml.jackson.databind.ObjectMapper;
59
60
61 public class UnifiedSearchProcessorTest {
62   
63   public interface Suggester {
64     public void addSuggestion( SearchSuggestion suggestion );
65   }
66   
67   private abstract class AbstractDummySearchProvider implements SearchProvider, Suggester {
68
69     protected List<SearchSuggestion> suggestions;
70
71     protected AbstractDummySearchProvider() {
72       suggestions = new ArrayList<SearchSuggestion>();
73     }
74
75     public List<SearchSuggestion> getSuggestions() {
76       return suggestions;
77     }
78
79     @Override
80     public List<SearchSuggestion> search(QuerySearchEntity queryRequest) {
81       return getSuggestions();
82     }
83   }
84
85   private class AlphaSearchProvider extends AbstractDummySearchProvider {
86     public AlphaSearchProvider() {
87       super();
88     }
89
90     @Override
91     public void addSuggestion(SearchSuggestion suggestion) {
92       if (suggestion != null) {
93         suggestions.add(suggestion);
94       }
95     }
96   }
97
98   private class BravoSearchProvider extends AbstractDummySearchProvider {
99     public BravoSearchProvider() {
100       super();
101     }
102
103     @Override
104     public void addSuggestion(SearchSuggestion suggestion) {
105       if (suggestion != null) {
106         suggestions.add(suggestion);
107       }
108     }
109   }
110
111   private class GammaSearchProvider extends AbstractDummySearchProvider {
112     public GammaSearchProvider() {
113       super();
114     }
115
116     @Override
117     public void addSuggestion(SearchSuggestion suggestion) {
118       if (suggestion != null) {
119         suggestions.add(suggestion);
120       }
121     }
122   }
123   
124   private SearchServiceAdapter mockSearchAdapter;
125   
126   private UnifiedSearchProcessor unifiedSearchProcessor;
127   private Exchange mockExchange;
128   private Message mockRequestMessage;
129   private Message mockResponseMessage;
130   private Request mockRestletRequest;
131   private Response mockRestletResponse;
132   private ClientInfo requestClientInfo;
133   private ObjectMapper mapper;
134
135   @Before
136   public void init() {
137
138     requestClientInfo = new ClientInfo();
139     
140     mockExchange = Mockito.mock(Exchange.class);
141     mockRequestMessage = Mockito.mock(Message.class);
142     mockResponseMessage = Mockito.mock(Message.class);
143     mockRestletRequest = Mockito.mock(Request.class);
144     mockRestletResponse = Mockito.mock(Response.class);
145
146     unifiedSearchProcessor = new UnifiedSearchProcessor();
147     unifiedSearchProcessor.setUseOrderedSearchProviderKeys(true);
148
149     mapper = new ObjectMapper();
150     
151     mockSearchAdapter = Mockito.mock(SearchServiceAdapter.class);
152   }
153
154
155   @Test
156   public void validateDefaultConstructor() {
157
158     // initially it should be null until the bean wiring initializes it
159     assertNull(unifiedSearchProcessor.getSearchProviderRegistry());
160
161   }
162   
163   
164   @Test
165   public void validateAccessors() {
166
167     SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
168     unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
169     
170     // initially it should be null until the bean wiring initializes it
171     assertNotNull(unifiedSearchProcessor.getSearchProviderRegistry());
172     assertEquals(0, searchProviderRegistry.getSearchProviders().size());
173
174   }
175   
176   private void initializeSearchMocks(String requestPayload) {
177
178     Mockito.when(mockRestletRequest.getClientInfo()).thenReturn(requestClientInfo);
179
180     Mockito.when(mockRequestMessage.getBody(String.class)).thenReturn(requestPayload);
181     Mockito.when(mockRequestMessage.getHeader(RestletConstants.RESTLET_REQUEST, Request.class))
182         .thenReturn(mockRestletRequest);
183
184     Mockito.when(mockRequestMessage.getHeader(RestletConstants.RESTLET_RESPONSE, Response.class))
185         .thenReturn(mockRestletResponse);
186     
187     Mockito.when(mockExchange.getIn()).thenReturn(mockRequestMessage);
188     Mockito.when(mockExchange.getOut()).thenReturn(mockResponseMessage);
189
190   }
191   
192   private String getSearchRequestJson(String queryString, int maxResults) {
193     
194     JSONObject root = new JSONObject();
195     root.put("queryStr", queryString);
196     root.put("maxResults", maxResults);
197     
198     return root.toString();
199
200   }
201   
202   private String getExternalSearchRequestJson() {
203     JSONObject root = new JSONObject();
204     
205     root.put("view", "testView");
206     root.put("entityId", "thisIsAnId");
207     root.put("entityType", "pserver");
208     
209     return root.toString();
210   }
211   
212   
213   @Test
214   public void testSearch_search_when_noSearchProviders() throws IOException {
215
216     // mock env setup
217
218     initializeSearchMocks(getSearchRequestJson("vnfs",10));
219
220     SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
221     unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
222     
223     // method under test
224     unifiedSearchProcessor.search(mockExchange);
225
226     ArgumentCaptor<Status> responseCodeCaptor = ArgumentCaptor.forClass(Status.class);
227     Mockito.verify(mockRestletResponse, Mockito.atLeast(1)).setStatus(responseCodeCaptor.capture());
228     assertEquals(Status.SUCCESS_OK, responseCodeCaptor.getValue());
229
230     ArgumentCaptor<String> entityPayload = ArgumentCaptor.forClass(String.class);
231     ArgumentCaptor<MediaType> payloadMediaType = ArgumentCaptor.forClass(MediaType.class);
232     Mockito.verify(mockRestletResponse, Mockito.atLeast(1)).setEntity(entityPayload.capture(),
233         payloadMediaType.capture());
234     assertNotNull(entityPayload.getValue());
235
236     ArgumentCaptor<Response> responseObject = ArgumentCaptor.forClass(Response.class);
237     Mockito.verify(mockResponseMessage, Mockito.atLeast(1)).setBody(responseObject.capture());
238     assertEquals(MediaType.APPLICATION_JSON, payloadMediaType.getValue());
239
240     SearchResponse searchResponse = mapper.readValue(entityPayload.getValue(), SearchResponse.class);
241
242     assertEquals(0, searchResponse.getTotalFound());
243     assertEquals(0, searchResponse.getSuggestions().size());
244     
245   }
246   
247   @Test
248   public void testSearch_search_when_ThreeSearchProviders_no_suggestions() throws IOException {
249
250     // mock env setup
251
252     initializeSearchMocks(getSearchRequestJson("vnfs",10));
253
254     SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
255     
256     AlphaSearchProvider alpha = new AlphaSearchProvider();
257     BravoSearchProvider bravo = new BravoSearchProvider();
258     GammaSearchProvider gamma = new GammaSearchProvider();
259     
260     searchProviderRegistry.addSearchProvider(alpha);
261     searchProviderRegistry.addSearchProvider(bravo);
262     searchProviderRegistry.addSearchProvider(gamma);
263     
264     unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
265     
266     
267     // method under test
268     unifiedSearchProcessor.search(mockExchange);
269     
270     ArgumentCaptor<Status> responseCodeCaptor = ArgumentCaptor.forClass(Status.class);
271     Mockito.verify(mockRestletResponse, Mockito.atLeast(1)).setStatus(responseCodeCaptor.capture());
272     assertEquals(Status.SUCCESS_OK, responseCodeCaptor.getValue());
273
274     ArgumentCaptor<String> entityPayload = ArgumentCaptor.forClass(String.class);
275     ArgumentCaptor<MediaType> payloadMediaType = ArgumentCaptor.forClass(MediaType.class);
276     Mockito.verify(mockRestletResponse, Mockito.atLeast(1)).setEntity(entityPayload.capture(),
277         payloadMediaType.capture());
278     assertNotNull(entityPayload.getValue());
279
280     ArgumentCaptor<Response> responseObject = ArgumentCaptor.forClass(Response.class);
281     Mockito.verify(mockResponseMessage, Mockito.atLeast(1)).setBody(responseObject.capture());
282     assertEquals(MediaType.APPLICATION_JSON, payloadMediaType.getValue());
283     
284     /*
285      * With a null view name, an empty filter set should be returned - there should be 0 filters
286      */
287     
288     SearchResponse searchResponse = mapper.readValue(entityPayload.getValue(), SearchResponse.class);
289
290     assertEquals(0, searchResponse.getTotalFound());
291     assertEquals(0, searchResponse.getSuggestions().size());
292     
293   }
294   
295   private void addSuggestions(int numSuggestions, String suggestionPrefix, Suggester suggester) {
296     for ( int x = 0; x < numSuggestions; x++ ){
297       CommonSearchSuggestion suggestion = new CommonSearchSuggestion();
298       suggestion.setText(suggestionPrefix + "-" + x);
299       suggester.addSuggestion(suggestion);
300     }
301   }
302   
303   private int countSuggestions(String suggestionPrefix, MockSearchResponse response) {
304     
305     int totalFound = 0;
306     
307     for ( SearchSuggestion suggestion : response.getSuggestions()) {
308       
309       if ( suggestion.getText() != null && suggestion.getText().startsWith(suggestionPrefix)) {
310         totalFound++;
311       }
312     }
313     
314     return totalFound;
315     
316   }
317   
318   @Test
319   public void testSearch_search_when_ThreeSearchProviders_5suggestions_each() throws IOException {
320
321     // mock env setup
322
323     initializeSearchMocks(getSearchRequestJson("vnfs",10));
324
325     SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
326     
327     AlphaSearchProvider alpha = new AlphaSearchProvider();
328     BravoSearchProvider bravo = new BravoSearchProvider();
329     GammaSearchProvider gamma = new GammaSearchProvider();
330     
331     addSuggestions(5, "alpha", alpha);
332     addSuggestions(5, "bravo", bravo);
333     addSuggestions(5, "gamma", gamma);
334     
335     searchProviderRegistry.addSearchProvider(alpha);
336     searchProviderRegistry.addSearchProvider(bravo);
337     searchProviderRegistry.addSearchProvider(gamma);
338     
339     unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
340     
341     // method under test
342     unifiedSearchProcessor.search(mockExchange);
343
344     ArgumentCaptor<Status> responseCodeCaptor = ArgumentCaptor.forClass(Status.class);
345     Mockito.verify(mockRestletResponse, Mockito.atLeast(1)).setStatus(responseCodeCaptor.capture());
346     assertEquals(Status.SUCCESS_OK, responseCodeCaptor.getValue());
347
348     ArgumentCaptor<String> entityPayload = ArgumentCaptor.forClass(String.class);
349     ArgumentCaptor<MediaType> payloadMediaType = ArgumentCaptor.forClass(MediaType.class);
350     Mockito.verify(mockRestletResponse, Mockito.atLeast(1)).setEntity(entityPayload.capture(),
351         payloadMediaType.capture());
352     assertNotNull(entityPayload.getValue());
353
354     ArgumentCaptor<Response> responseObject = ArgumentCaptor.forClass(Response.class);
355     Mockito.verify(mockResponseMessage, Mockito.atLeast(1)).setBody(responseObject.capture());
356     assertEquals(MediaType.APPLICATION_JSON, payloadMediaType.getValue());
357     
358     MockSearchResponse searchResponse = mapper.readValue(entityPayload.getValue(), MockSearchResponse.class);
359
360     assertEquals(10, searchResponse.getTotalFound());
361     assertEquals(10, searchResponse.getSuggestions().size());
362     
363     assertEquals( 4, countSuggestions("alpha", searchResponse));
364     assertEquals( 3, countSuggestions("bravo", searchResponse));
365     assertEquals( 3, countSuggestions("gamma", searchResponse));
366     
367   }
368
369   @Test
370   public void testSearch_search_when_ThreeSearchProviders_mixedNumSuggestions() throws IOException {
371
372     // mock env setup
373
374     initializeSearchMocks(getSearchRequestJson("vnfs",13));
375
376     SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
377     
378     AlphaSearchProvider alpha = new AlphaSearchProvider();
379     BravoSearchProvider bravo = new BravoSearchProvider();
380     GammaSearchProvider gamma = new GammaSearchProvider();
381     
382     searchProviderRegistry.addSearchProvider(alpha);
383     searchProviderRegistry.addSearchProvider(bravo);
384     searchProviderRegistry.addSearchProvider(gamma);
385     
386     unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
387     
388     addSuggestions(45,"alpha",alpha);
389     addSuggestions(1,"bravo",bravo);
390     addSuggestions(99,"gamma",gamma);
391     
392     // method under test
393     unifiedSearchProcessor.search(mockExchange);
394
395     ArgumentCaptor<Status> responseCodeCaptor = ArgumentCaptor.forClass(Status.class);
396     Mockito.verify(mockRestletResponse, Mockito.atLeast(1)).setStatus(responseCodeCaptor.capture());
397     assertEquals(Status.SUCCESS_OK, responseCodeCaptor.getValue());
398
399     ArgumentCaptor<String> entityPayload = ArgumentCaptor.forClass(String.class);
400     ArgumentCaptor<MediaType> payloadMediaType = ArgumentCaptor.forClass(MediaType.class);
401     Mockito.verify(mockRestletResponse, Mockito.atLeast(1)).setEntity(entityPayload.capture(),
402         payloadMediaType.capture());
403     assertNotNull(entityPayload.getValue());
404
405     ArgumentCaptor<Response> responseObject = ArgumentCaptor.forClass(Response.class);
406     Mockito.verify(mockResponseMessage, Mockito.atLeast(1)).setBody(responseObject.capture());
407     assertEquals(MediaType.APPLICATION_JSON, payloadMediaType.getValue());
408     
409     MockSearchResponse searchResponse = mapper.readValue(entityPayload.getValue(), MockSearchResponse.class);
410
411     assertEquals(13, searchResponse.getTotalFound());
412     assertEquals(13, searchResponse.getSuggestions().size());
413     
414     /**
415      * There should be an even divide of suggestions per search provider relative
416      * to the suggestions available per search provider.
417      * Alpha has 45 suggestions
418      * Bravo has 1  suggestion
419      * Gamma has 99 suggestions
420      * 
421      * We only asked for 13 suggestions to be returned, so based on the suggestion
422      * distribution algorithm we will get a fair distribution of suggestions per provider
423      * relative to what each provider has available.  Resulting in:
424      * 6 from Alpha
425      * 1 from Bravo
426      * 6 from Gamma
427      * 
428      */
429     
430     assertEquals( 6, countSuggestions("alpha", searchResponse));
431     assertEquals( 1, countSuggestions("bravo", searchResponse));
432     assertEquals( 6, countSuggestions("gamma", searchResponse));
433     
434   }
435   
436   @Test
437   public void testSearch_search_when_ThreeSearchProviders_wantedMoreSuggestionsThanAvailable() throws IOException {
438
439     // mock env setup
440
441     initializeSearchMocks(getSearchRequestJson("vnfs",13));
442
443     SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
444     
445     AlphaSearchProvider alpha = new AlphaSearchProvider();
446     BravoSearchProvider bravo = new BravoSearchProvider();
447     GammaSearchProvider gamma = new GammaSearchProvider();
448     
449     searchProviderRegistry.addSearchProvider(alpha);
450     searchProviderRegistry.addSearchProvider(bravo);
451     searchProviderRegistry.addSearchProvider(gamma);
452     
453     unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
454     
455     addSuggestions(1,"alpha",alpha);
456     addSuggestions(4,"bravo",bravo);
457     addSuggestions(0,"gamma",gamma);
458     
459     // method under test
460     unifiedSearchProcessor.search(mockExchange);
461
462     ArgumentCaptor<Status> responseCodeCaptor = ArgumentCaptor.forClass(Status.class);
463     Mockito.verify(mockRestletResponse, Mockito.atLeast(1)).setStatus(responseCodeCaptor.capture());
464     assertEquals(Status.SUCCESS_OK, responseCodeCaptor.getValue());
465
466     ArgumentCaptor<String> entityPayload = ArgumentCaptor.forClass(String.class);
467     ArgumentCaptor<MediaType> payloadMediaType = ArgumentCaptor.forClass(MediaType.class);
468     Mockito.verify(mockRestletResponse, Mockito.atLeast(1)).setEntity(entityPayload.capture(),
469         payloadMediaType.capture());
470     assertNotNull(entityPayload.getValue());
471
472     ArgumentCaptor<Response> responseObject = ArgumentCaptor.forClass(Response.class);
473     Mockito.verify(mockResponseMessage, Mockito.atLeast(1)).setBody(responseObject.capture());
474     assertEquals(MediaType.APPLICATION_JSON, payloadMediaType.getValue());
475     
476     MockSearchResponse searchResponse = mapper.readValue(entityPayload.getValue(), MockSearchResponse.class);
477
478     assertEquals(5, searchResponse.getTotalFound());
479     assertEquals(5, searchResponse.getSuggestions().size());
480     
481     assertEquals( 1, countSuggestions("alpha", searchResponse));
482     assertEquals( 4, countSuggestions("bravo", searchResponse));
483     assertEquals( 0, countSuggestions("gamma", searchResponse));
484     
485   }
486 }