2 * ============LICENSE_START===================================================
3 * SPARKY (AAI UI service)
4 * ============================================================================
5 * Copyright © 2017 AT&T Intellectual Property.
6 * Copyright © 2017 Amdocs
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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=====================================================
22 * ECOMP and OpenECOMP are trademarks
23 * and service marks of AT&T Intellectual Property.
26 package org.onap.aai.sparky.search;
28 import static org.junit.Assert.assertEquals;
29 import static org.junit.Assert.assertNotNull;
30 import static org.junit.Assert.assertNull;
32 import java.io.IOException;
33 import java.util.ArrayList;
34 import java.util.List;
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;
57 import com.fasterxml.jackson.core.JsonProcessingException;
58 import com.fasterxml.jackson.databind.ObjectMapper;
61 public class UnifiedSearchProcessorTest {
63 public interface Suggester {
64 public void addSuggestion( SearchSuggestion suggestion );
67 private abstract class AbstractDummySearchProvider implements SearchProvider, Suggester {
69 protected List<SearchSuggestion> suggestions;
71 protected AbstractDummySearchProvider() {
72 suggestions = new ArrayList<SearchSuggestion>();
75 public List<SearchSuggestion> getSuggestions() {
80 public List<SearchSuggestion> search(QuerySearchEntity queryRequest) {
81 return getSuggestions();
85 private class AlphaSearchProvider extends AbstractDummySearchProvider {
86 public AlphaSearchProvider() {
91 public void addSuggestion(SearchSuggestion suggestion) {
92 if (suggestion != null) {
93 suggestions.add(suggestion);
98 private class BravoSearchProvider extends AbstractDummySearchProvider {
99 public BravoSearchProvider() {
104 public void addSuggestion(SearchSuggestion suggestion) {
105 if (suggestion != null) {
106 suggestions.add(suggestion);
111 private class GammaSearchProvider extends AbstractDummySearchProvider {
112 public GammaSearchProvider() {
117 public void addSuggestion(SearchSuggestion suggestion) {
118 if (suggestion != null) {
119 suggestions.add(suggestion);
124 private SearchServiceAdapter mockSearchAdapter;
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;
138 requestClientInfo = new ClientInfo();
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);
146 unifiedSearchProcessor = new UnifiedSearchProcessor();
147 unifiedSearchProcessor.setUseOrderedSearchProviderKeys(true);
149 mapper = new ObjectMapper();
151 mockSearchAdapter = Mockito.mock(SearchServiceAdapter.class);
156 public void validateDefaultConstructor() {
158 // initially it should be null until the bean wiring initializes it
159 assertNull(unifiedSearchProcessor.getSearchProviderRegistry());
165 public void validateAccessors() {
167 SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
168 unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
170 // initially it should be null until the bean wiring initializes it
171 assertNotNull(unifiedSearchProcessor.getSearchProviderRegistry());
172 assertEquals(0, searchProviderRegistry.getSearchProviders().size());
176 private void initializeSearchMocks(String requestPayload) {
178 Mockito.when(mockRestletRequest.getClientInfo()).thenReturn(requestClientInfo);
180 Mockito.when(mockRequestMessage.getBody(String.class)).thenReturn(requestPayload);
181 Mockito.when(mockRequestMessage.getHeader(RestletConstants.RESTLET_REQUEST, Request.class))
182 .thenReturn(mockRestletRequest);
184 Mockito.when(mockRequestMessage.getHeader(RestletConstants.RESTLET_RESPONSE, Response.class))
185 .thenReturn(mockRestletResponse);
187 Mockito.when(mockExchange.getIn()).thenReturn(mockRequestMessage);
188 Mockito.when(mockExchange.getOut()).thenReturn(mockResponseMessage);
192 private String getSearchRequestJson(String queryString, int maxResults) {
194 JSONObject root = new JSONObject();
195 root.put("queryStr", queryString);
196 root.put("maxResults", maxResults);
198 return root.toString();
202 private String getExternalSearchRequestJson() {
203 JSONObject root = new JSONObject();
205 root.put("view", "testView");
206 root.put("entityId", "thisIsAnId");
207 root.put("entityType", "pserver");
209 return root.toString();
214 public void testSearch_search_when_noSearchProviders() throws IOException {
218 initializeSearchMocks(getSearchRequestJson("vnfs",10));
220 SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
221 unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
224 unifiedSearchProcessor.search(mockExchange);
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());
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());
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());
240 SearchResponse searchResponse = mapper.readValue(entityPayload.getValue(), SearchResponse.class);
242 assertEquals(0, searchResponse.getTotalFound());
243 assertEquals(0, searchResponse.getSuggestions().size());
248 public void testSearch_search_when_ThreeSearchProviders_no_suggestions() throws IOException {
252 initializeSearchMocks(getSearchRequestJson("vnfs",10));
254 SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
256 AlphaSearchProvider alpha = new AlphaSearchProvider();
257 BravoSearchProvider bravo = new BravoSearchProvider();
258 GammaSearchProvider gamma = new GammaSearchProvider();
260 searchProviderRegistry.addSearchProvider(alpha);
261 searchProviderRegistry.addSearchProvider(bravo);
262 searchProviderRegistry.addSearchProvider(gamma);
264 unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
268 unifiedSearchProcessor.search(mockExchange);
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());
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());
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());
285 * With a null view name, an empty filter set should be returned - there should be 0 filters
288 SearchResponse searchResponse = mapper.readValue(entityPayload.getValue(), SearchResponse.class);
290 assertEquals(0, searchResponse.getTotalFound());
291 assertEquals(0, searchResponse.getSuggestions().size());
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);
303 private int countSuggestions(String suggestionPrefix, MockSearchResponse response) {
307 for ( SearchSuggestion suggestion : response.getSuggestions()) {
309 if ( suggestion.getText() != null && suggestion.getText().startsWith(suggestionPrefix)) {
319 public void testSearch_search_when_ThreeSearchProviders_5suggestions_each() throws IOException {
323 initializeSearchMocks(getSearchRequestJson("vnfs",10));
325 SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
327 AlphaSearchProvider alpha = new AlphaSearchProvider();
328 BravoSearchProvider bravo = new BravoSearchProvider();
329 GammaSearchProvider gamma = new GammaSearchProvider();
331 addSuggestions(5, "alpha", alpha);
332 addSuggestions(5, "bravo", bravo);
333 addSuggestions(5, "gamma", gamma);
335 searchProviderRegistry.addSearchProvider(alpha);
336 searchProviderRegistry.addSearchProvider(bravo);
337 searchProviderRegistry.addSearchProvider(gamma);
339 unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
342 unifiedSearchProcessor.search(mockExchange);
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());
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());
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());
358 MockSearchResponse searchResponse = mapper.readValue(entityPayload.getValue(), MockSearchResponse.class);
360 assertEquals(10, searchResponse.getTotalFound());
361 assertEquals(10, searchResponse.getSuggestions().size());
363 assertEquals( 4, countSuggestions("alpha", searchResponse));
364 assertEquals( 3, countSuggestions("bravo", searchResponse));
365 assertEquals( 3, countSuggestions("gamma", searchResponse));
370 public void testSearch_search_when_ThreeSearchProviders_mixedNumSuggestions() throws IOException {
374 initializeSearchMocks(getSearchRequestJson("vnfs",13));
376 SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
378 AlphaSearchProvider alpha = new AlphaSearchProvider();
379 BravoSearchProvider bravo = new BravoSearchProvider();
380 GammaSearchProvider gamma = new GammaSearchProvider();
382 searchProviderRegistry.addSearchProvider(alpha);
383 searchProviderRegistry.addSearchProvider(bravo);
384 searchProviderRegistry.addSearchProvider(gamma);
386 unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
388 addSuggestions(45,"alpha",alpha);
389 addSuggestions(1,"bravo",bravo);
390 addSuggestions(99,"gamma",gamma);
393 unifiedSearchProcessor.search(mockExchange);
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());
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());
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());
409 MockSearchResponse searchResponse = mapper.readValue(entityPayload.getValue(), MockSearchResponse.class);
411 assertEquals(13, searchResponse.getTotalFound());
412 assertEquals(13, searchResponse.getSuggestions().size());
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
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:
430 assertEquals( 6, countSuggestions("alpha", searchResponse));
431 assertEquals( 1, countSuggestions("bravo", searchResponse));
432 assertEquals( 6, countSuggestions("gamma", searchResponse));
437 public void testSearch_search_when_ThreeSearchProviders_wantedMoreSuggestionsThanAvailable() throws IOException {
441 initializeSearchMocks(getSearchRequestJson("vnfs",13));
443 SearchProviderRegistry searchProviderRegistry = new SearchProviderRegistry();
445 AlphaSearchProvider alpha = new AlphaSearchProvider();
446 BravoSearchProvider bravo = new BravoSearchProvider();
447 GammaSearchProvider gamma = new GammaSearchProvider();
449 searchProviderRegistry.addSearchProvider(alpha);
450 searchProviderRegistry.addSearchProvider(bravo);
451 searchProviderRegistry.addSearchProvider(gamma);
453 unifiedSearchProcessor.setSearchProviderRegistry(searchProviderRegistry);
455 addSuggestions(1,"alpha",alpha);
456 addSuggestions(4,"bravo",bravo);
457 addSuggestions(0,"gamma",gamma);
460 unifiedSearchProcessor.search(mockExchange);
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());
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());
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());
476 MockSearchResponse searchResponse = mapper.readValue(entityPayload.getValue(), MockSearchResponse.class);
478 assertEquals(5, searchResponse.getTotalFound());
479 assertEquals(5, searchResponse.getSuggestions().size());
481 assertEquals( 1, countSuggestions("alpha", searchResponse));
482 assertEquals( 4, countSuggestions("bravo", searchResponse));
483 assertEquals( 0, countSuggestions("gamma", searchResponse));