xref: /OpenGrok/opengrok-web/src/test/java/org/opengrok/web/api/v1/controller/SuggesterControllerTest.java (revision d6df19e1b22784c78f567cf74c42f18e3901b900)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * See LICENSE.txt included in this distribution for the specific
9  * language governing permissions and limitations under the License.
10  *
11  * When distributing Covered Code, include this CDDL HEADER in each
12  * file and include the License file at LICENSE.txt.
13  * If applicable, add the following below this CDDL HEADER, with the
14  * fields enclosed by brackets "[]" replaced with your own identifying
15  * information: Portions Copyright [yyyy] [name of copyright owner]
16  *
17  * CDDL HEADER END
18  */
19 
20 /*
21  * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
22  * Portions Copyright (c) 2019, 2020, Chris Fraire <cfraire@me.com>.
23  */
24 package org.opengrok.web.api.v1.controller;
25 
26 import jakarta.ws.rs.client.Entity;
27 import jakarta.ws.rs.core.Application;
28 import jakarta.ws.rs.core.GenericType;
29 import jakarta.ws.rs.core.Response;
30 import org.apache.lucene.index.Term;
31 import org.junit.jupiter.api.AfterAll;
32 import org.junit.jupiter.api.BeforeAll;
33 import org.junit.jupiter.api.BeforeEach;
34 import org.junit.jupiter.api.MethodOrderer;
35 import org.junit.jupiter.api.Test;
36 import org.junit.jupiter.api.TestMethodOrder;
37 import org.opengrok.indexer.configuration.RuntimeEnvironment;
38 import org.opengrok.indexer.configuration.SuggesterConfig;
39 import org.opengrok.indexer.index.Indexer;
40 import org.opengrok.indexer.search.QueryBuilder;
41 import org.opengrok.indexer.util.TestRepository;
42 import org.opengrok.web.api.v1.RestApp;
43 import org.opengrok.web.api.v1.suggester.provider.filter.AuthorizationFilter;
44 import org.opengrok.web.api.v1.suggester.provider.service.impl.SuggesterServiceImpl;
45 
46 import java.util.AbstractMap.SimpleEntry;
47 import java.util.Arrays;
48 import java.util.Collections;
49 import java.util.List;
50 import java.util.Map.Entry;
51 import java.util.Set;
52 import java.util.concurrent.TimeUnit;
53 import java.util.stream.Collectors;
54 
55 import static org.hamcrest.MatcherAssert.assertThat;
56 import static org.hamcrest.Matchers.containsInAnyOrder;
57 import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
58 import static org.junit.jupiter.api.Assertions.assertEquals;
59 import static org.junit.jupiter.api.Assertions.assertTrue;
60 import static org.opengrok.web.api.v1.filter.CorsFilter.ALLOW_CORS_HEADER;
61 import static org.opengrok.web.api.v1.filter.CorsFilter.CORS_REQUEST_HEADER;
62 
63 @TestMethodOrder(MethodOrderer.MethodName.class)
64 public class SuggesterControllerTest extends OGKJerseyTest {
65 
66     public static class Result {
67         public long time;
68         public List<ResultItem> suggestions;
69         public String identifier;
70         public String queryText;
71         public boolean partialResult;
72     }
73 
74     public static class ResultItem {
75         public String phrase;
76         public Set<String> projects;
77         public long score;
78     }
79 
80     private static class TermIncrementData {
81         public String project;
82         public String field;
83         public String token;
84         public int increment;
85     }
86 
87     private static final RuntimeEnvironment env = RuntimeEnvironment.getInstance();
88 
89     private static final GenericType<List<Entry<String, Integer>>> popularityDataType = new GenericType<>() {
90     };
91 
92 
93     private static TestRepository repository;
94 
95     @Override
configure()96     protected Application configure() {
97         return new RestApp();
98     }
99 
100     @BeforeAll
setUpClass()101     public static void setUpClass() throws Exception {
102         System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); // necessary to test CORS from controllers
103         repository = new TestRepository();
104 
105         repository.create(SuggesterControllerTest.class.getClassLoader().getResource("sources"));
106 
107         env.setHistoryEnabled(false);
108         env.setProjectsEnabled(true);
109         Indexer.getInstance().prepareIndexer(env, true, true,
110                 false, null, null);
111         env.setDefaultProjectsFromNames(Collections.singleton("__all__"));
112         Indexer.getInstance().doIndexerExecution(true, null, null);
113 
114         env.getSuggesterConfig().setRebuildCronConfig(null);
115     }
116 
117     @AfterAll
tearDownClass()118     public static void tearDownClass() {
119         repository.destroy();
120     }
121 
122     @BeforeEach
before()123     public void before() throws InterruptedException {
124         SuggesterServiceImpl.getInstance().waitForInit(15, TimeUnit.SECONDS);
125 
126         env.setSuggesterConfig(new SuggesterConfig());
127     }
128 
129     @Test
testGetSuggesterConfig()130     void testGetSuggesterConfig() {
131         SuggesterConfig config = target(SuggesterController.PATH)
132                 .path("config")
133                 .request()
134                 .get(SuggesterConfig.class);
135 
136         assertEquals(env.getSuggesterConfig(), config);
137     }
138 
139     @Test
testGetSuggesterConfigCors()140     void testGetSuggesterConfigCors() {
141         Response response = target(SuggesterController.PATH)
142                 .path("config")
143                 .request()
144                 .header(CORS_REQUEST_HEADER, "http://example.com")
145                 .get();
146         assertEquals("*", response.getHeaderString(ALLOW_CORS_HEADER));
147     }
148 
149     @Test
testGetSuggestionsSimpleFull()150     void testGetSuggestionsSimpleFull() {
151         Result res = target(SuggesterController.PATH)
152                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
153                 .queryParam("field", QueryBuilder.FULL)
154                 .queryParam(QueryBuilder.FULL, "inner")
155                 .request()
156                 .get(Result.class);
157 
158         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
159                 containsInAnyOrder("innermethod", "innerclass"));
160     }
161 
162     @Test
testGetSuggestionsCors()163     void testGetSuggestionsCors() {
164         Response response = target(SuggesterController.PATH)
165                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
166                 .queryParam("field", QueryBuilder.FULL)
167                 .queryParam(QueryBuilder.FULL, "inner")
168                 .request()
169                 .header(CORS_REQUEST_HEADER, "http://example.com")
170                 .get();
171 
172         assertEquals("*", response.getHeaderString(ALLOW_CORS_HEADER));
173     }
174 
175     @Test
testGetSuggestionsSimpleDefs()176     void testGetSuggestionsSimpleDefs() {
177         Result res = target(SuggesterController.PATH)
178                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
179                 .queryParam("field", QueryBuilder.DEFS)
180                 .queryParam(QueryBuilder.DEFS, "Inner")
181                 .request()
182                 .get(Result.class);
183 
184         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
185                 containsInAnyOrder("InnerMethod", "InnerClass"));
186     }
187 
188     @Test
testGetSuggestionsSimpleRefs()189     void testGetSuggestionsSimpleRefs() {
190         Result res = target(SuggesterController.PATH)
191                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
192                 .queryParam("field", QueryBuilder.REFS)
193                 .queryParam(QueryBuilder.REFS, "Inner")
194                 .request()
195                 .get(Result.class);
196 
197         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
198                 containsInAnyOrder("InnerMethod", "InnerClass"));
199     }
200 
201     @Test
testGetSuggestionsSimplePath()202     void testGetSuggestionsSimplePath() {
203         Result res = target(SuggesterController.PATH)
204                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "c")
205                 .queryParam("field", QueryBuilder.PATH)
206                 .queryParam(QueryBuilder.PATH, "he")
207                 .request()
208                 .get(Result.class);
209 
210         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
211                 contains("header"));
212     }
213 
214     @Test
testGetSuggestionsBadRequest()215     void testGetSuggestionsBadRequest() {
216         Response r = target(SuggesterController.PATH)
217                 .queryParam("field", "")
218                 .request()
219                 .get();
220 
221         assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), r.getStatus());
222     }
223 
224     @Test
testGetSuggestionsBadRequest2()225     void testGetSuggestionsBadRequest2() {
226         Response r = target(SuggesterController.PATH)
227                 .queryParam("field", QueryBuilder.FULL)
228                 .queryParam("caret", -2)
229                 .request()
230                 .get();
231 
232         assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), r.getStatus());
233     }
234 
235     @Test
testGetSuggestionUnknownField()236     void testGetSuggestionUnknownField() {
237         Response r = target(SuggesterController.PATH)
238                 .queryParam("field", "unknown")
239                 .request()
240                 .get();
241 
242         assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), r.getStatus());
243     }
244 
245     @Test
testGetSuggestionsMultipleProjects()246     void testGetSuggestionsMultipleProjects() {
247         Result res = target(SuggesterController.PATH)
248                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java", "kotlin")
249                 .queryParam("field", QueryBuilder.FULL)
250                 .queryParam(QueryBuilder.FULL, "me")
251                 .request()
252                 .get(Result.class);
253 
254         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
255                 containsInAnyOrder("me", "method", "message", "meta"));
256     }
257 
258     @Test
testGetSuggestionsMultipleProjects2()259     void testGetSuggestionsMultipleProjects2() {
260         Result res = target(SuggesterController.PATH)
261                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java", "kotlin")
262                 .queryParam("field", QueryBuilder.FULL)
263                 .queryParam(QueryBuilder.FULL, "mai")
264                 .request()
265                 .get(Result.class);
266 
267         assertEquals(1, res.suggestions.size());
268         assertThat(res.suggestions.get(0).projects, containsInAnyOrder("java", "kotlin"));
269     }
270 
271     @Test
testComplexSuggestions()272     void testComplexSuggestions() {
273         Result res = target(SuggesterController.PATH)
274                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
275                 .queryParam("field", QueryBuilder.FULL)
276                 .queryParam(QueryBuilder.FULL, "s")
277                 .queryParam(QueryBuilder.PATH, "bug15890")
278                 .request()
279                 .get(Result.class);
280 
281         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
282                 containsInAnyOrder("since"));
283     }
284 
285     @Test
testWildcard()286     void testWildcard() {
287         Result res = target(SuggesterController.PATH)
288                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
289                 .queryParam("field", QueryBuilder.FULL)
290                 .queryParam(QueryBuilder.FULL, "b?")
291                 .queryParam(QueryBuilder.PATH, "sample")
292                 .request()
293                 .get(Result.class);
294 
295         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
296                 contains("by"));
297     }
298 
299     @Test
testRegex()300     void testRegex() {
301         Result res = target(SuggesterController.PATH)
302                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
303                 .queryParam("field", QueryBuilder.FULL)
304                 .queryParam(QueryBuilder.FULL, "/b./")
305                 .queryParam(QueryBuilder.PATH, "sample")
306                 .queryParam("caret", 1)
307                 .request()
308                 .get(Result.class);
309 
310         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
311                 contains("by"));
312     }
313 
314     @Test
testPhraseAfter()315     void testPhraseAfter() {
316         Result res = target(SuggesterController.PATH)
317                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
318                 .queryParam("field", QueryBuilder.FULL)
319                 .queryParam(QueryBuilder.FULL, "\"contents of this \"")
320                 .queryParam(QueryBuilder.PATH, "sample")
321                 .queryParam("caret", 18)
322                 .request()
323                 .get(Result.class);
324 
325         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
326                 contains("file"));
327     }
328 
329     @Test
testPhraseBefore()330     void testPhraseBefore() {
331         Result res = target(SuggesterController.PATH)
332                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
333                 .queryParam("field", QueryBuilder.FULL)
334                 .queryParam(QueryBuilder.FULL, "\" contents of this\"")
335                 .queryParam(QueryBuilder.PATH, "sample")
336                 .queryParam("caret", 1)
337                 .request()
338                 .get(Result.class);
339 
340         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
341                 contains("the"));
342     }
343 
344     @Test
testPhraseMiddle()345     void testPhraseMiddle() {
346         Result res = target(SuggesterController.PATH)
347                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
348                 .queryParam("field", QueryBuilder.FULL)
349                 .queryParam(QueryBuilder.FULL, "\"contents  this\"")
350                 .queryParam(QueryBuilder.PATH, "sample")
351                 .queryParam("caret", 10)
352                 .request()
353                 .get(Result.class);
354 
355         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
356                 contains("of"));
357     }
358 
359     @Test
testSloppyPhrase()360     void testSloppyPhrase() {
361         Result res = target(SuggesterController.PATH)
362                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
363                 .queryParam("field", QueryBuilder.FULL)
364                 .queryParam(QueryBuilder.FULL, "\"contents of this \"~1")
365                 .queryParam(QueryBuilder.PATH, "sample")
366                 .queryParam("caret", 18)
367                 .request()
368                 .get(Result.class);
369 
370         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
371                 containsInAnyOrder("file", "are"));
372     }
373 
374     @Test
testRangeQueryUpper()375     void testRangeQueryUpper() {
376         Result res = target(SuggesterController.PATH)
377                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "kotlin")
378                 .queryParam("field", QueryBuilder.FULL)
379                 .queryParam(QueryBuilder.FULL, "{templ}").resolveTemplate("templ", "{main TO m}")
380                 .queryParam("caret", 10)
381                 .request()
382                 .get(Result.class);
383 
384         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
385                 containsInAnyOrder("me", "mutablelistof"));
386     }
387 
388     @Test
testRangeQueryLower()389     void testRangeQueryLower() {
390         Result res = target(SuggesterController.PATH)
391                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "kotlin")
392                 .queryParam("field", QueryBuilder.FULL)
393                 .queryParam(QueryBuilder.FULL, "{templ}").resolveTemplate("templ", "{m TO mutablelistof}")
394                 .queryParam("caret", 1)
395                 .request()
396                 .get(Result.class);
397 
398         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
399                 containsInAnyOrder("main", "me"));
400     }
401 
402     @Test
testComplexSuggestions2()403     void testComplexSuggestions2() {
404         Result res = target(SuggesterController.PATH)
405                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "kotlin")
406                 .queryParam("field", QueryBuilder.FULL)
407                 .queryParam(QueryBuilder.FULL, "me m")
408                 .queryParam("caret", 4)
409                 .request()
410                 .get(Result.class);
411 
412         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
413                 containsInAnyOrder("main", "mutablelistof"));
414     }
415 
416     @Test
testInitPopularTermsFromQueries()417     void testInitPopularTermsFromQueries() {
418         // terms for prefix t: "text", "texttrim", "tell", "teach", "trimmargin"
419 
420         List<String> queries = Arrays.asList(
421                 "http://localhost:8080/source/search?project=kotlin&full=text",
422                 "http://localhost:8080/source/search?project=kotlin&full=text",
423                 "http://localhost:8080/source/search?project=kotlin&full=teach"
424         );
425 
426         target(SuggesterController.PATH)
427                 .path("init")
428                 .path("queries")
429                 .request()
430                 .post(Entity.json(queries));
431 
432         Result res = target(SuggesterController.PATH)
433                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "kotlin")
434                 .queryParam("field", QueryBuilder.FULL)
435                 .queryParam(QueryBuilder.FULL, "t")
436                 .queryParam("caret", 1)
437                 .queryParam(QueryBuilder.PATH, "kt")
438                 .request()
439                 .get(Result.class);
440 
441         List<String> suggestions = res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList());
442 
443         assertEquals("text", suggestions.get(0));
444         assertEquals("teach", suggestions.get(1));
445     }
446 
447     @Test
testInitPopularTermsFromRawData()448     void testInitPopularTermsFromRawData() {
449         // terms for prefix a: "args", "array", "and"
450 
451         TermIncrementData data1 = new TermIncrementData();
452         data1.project = "kotlin";
453         data1.field = QueryBuilder.FULL;
454         data1.token = "args";
455         data1.increment = 100;
456 
457         TermIncrementData data2 = new TermIncrementData();
458         data2.project = "kotlin";
459         data2.field = QueryBuilder.FULL;
460         data2.token = "array";
461         data2.increment = 50;
462 
463         target(SuggesterController.PATH)
464                 .path("init")
465                 .path("raw")
466                 .request()
467                 .post(Entity.json(Arrays.asList(data1, data2)));
468 
469         Result res = target(SuggesterController.PATH)
470                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "kotlin")
471                 .queryParam("field", QueryBuilder.FULL)
472                 .queryParam(QueryBuilder.FULL, "a")
473                 .queryParam("caret", 1)
474                 .queryParam(QueryBuilder.PATH, "kt")
475                 .request()
476                 .get(Result.class);
477 
478         List<String> suggestions = res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList());
479 
480         assertEquals("args", suggestions.get(0));
481         assertEquals("array", suggestions.get(1));
482     }
483 
484     @Test
testInitPopularTermsFromRawDataInvalidRequest()485     void testInitPopularTermsFromRawDataInvalidRequest() {
486         TermIncrementData data = new TermIncrementData();
487         data.project = "kotlin";
488         data.field = QueryBuilder.FULL;
489         data.token = "array";
490         data.increment = -10;
491 
492         Response r = target(SuggesterController.PATH)
493                 .path("init")
494                 .path("raw")
495                 .request()
496                 .post(Entity.json(Collections.singleton(data)));
497 
498         assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), r.getStatus());
499     }
500 
501     @Test
testDisabledSuggestions()502     void testDisabledSuggestions() {
503         env.getSuggesterConfig().setEnabled(false);
504 
505         Response r = target(SuggesterController.PATH)
506                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
507                 .queryParam("field", QueryBuilder.FULL)
508                 .queryParam(QueryBuilder.FULL, "inner")
509                 .request()
510                 .get();
511 
512         assertEquals(Response.Status.NOT_FOUND.getStatusCode(), r.getStatus());
513     }
514 
515     @Test
testMinChars()516     void testMinChars() {
517         env.getSuggesterConfig().setMinChars(2);
518 
519         Response r = target(SuggesterController.PATH)
520                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java")
521                 .queryParam("field", QueryBuilder.FULL)
522                 .queryParam(QueryBuilder.FULL, "i")
523                 .request()
524                 .get();
525 
526         assertEquals(Response.Status.NOT_FOUND.getStatusCode(), r.getStatus());
527     }
528 
529     @Test
testAllowedProjects()530     void testAllowedProjects() {
531         env.getSuggesterConfig().setAllowedProjects(Collections.singleton("kotlin"));
532 
533         Result res = target(SuggesterController.PATH)
534                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java", "kotlin")
535                 .queryParam("field", QueryBuilder.FULL)
536                 .queryParam(QueryBuilder.FULL, "me")
537                 .request()
538                 .get(Result.class);
539 
540         // only terms from kotlin project are expected
541         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
542                 containsInAnyOrder("me"));
543     }
544 
545     @Test
testMaxProjects()546     void testMaxProjects() {
547         env.getSuggesterConfig().setMaxProjects(1);
548 
549         Response r = target(SuggesterController.PATH)
550                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java", "kotlin")
551                 .queryParam("field", QueryBuilder.FULL)
552                 .queryParam(QueryBuilder.FULL, "me")
553                 .request()
554                 .get();
555 
556         assertEquals(Response.Status.NOT_FOUND.getStatusCode(), r.getStatus());
557     }
558 
559     @Test
testAllowedFields()560     void testAllowedFields() {
561         env.getSuggesterConfig().setAllowedFields(Collections.singleton(QueryBuilder.DEFS));
562 
563         Response r = target(SuggesterController.PATH)
564                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java", "kotlin")
565                 .queryParam("field", QueryBuilder.FULL)
566                 .queryParam(QueryBuilder.FULL, "me")
567                 .request()
568                 .get();
569 
570         assertEquals(Response.Status.NOT_FOUND.getStatusCode(), r.getStatus());
571     }
572 
573     @Test
testAllowComplexQueries()574     void testAllowComplexQueries() {
575         env.getSuggesterConfig().setAllowComplexQueries(false);
576 
577         Response r = target(SuggesterController.PATH)
578                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "java", "kotlin")
579                 .queryParam("field", QueryBuilder.FULL)
580                 .queryParam(QueryBuilder.FULL, "me")
581                 .queryParam(QueryBuilder.PATH, "kt")
582                 .request()
583                 .get();
584 
585         assertEquals(Response.Status.NOT_FOUND.getStatusCode(), r.getStatus());
586     }
587 
588     @Test
589     @SuppressWarnings("unchecked") // for contains
testGetPopularityDataSimple()590     void testGetPopularityDataSimple() {
591         assertTrue(SuggesterServiceImpl.getInstance().increaseSearchCount("rust",
592                 new Term(QueryBuilder.FULL, "main"), 10, true));
593 
594         List<Entry<String, Integer>> res = target(SuggesterController.PATH)
595                 .path("popularity")
596                 .path("rust")
597                 .request()
598                 .get(popularityDataType);
599 
600         assertThat(res, contains(new SimpleEntry<>("main", 10)));
601     }
602 
603     @Test
604     @SuppressWarnings("unchecked") // for contains
testGetPopularityDataAll()605     void testGetPopularityDataAll() {
606         assertTrue(SuggesterServiceImpl.getInstance().increaseSearchCount("csharp",
607                 new Term(QueryBuilder.FULL, "mynamespace"), 10, true));
608         assertTrue(SuggesterServiceImpl.getInstance().increaseSearchCount("csharp",
609                 new Term(QueryBuilder.FULL, "topclass"), 15, true));
610 
611         List<Entry<String, Integer>> res = target(SuggesterController.PATH)
612                 .path("popularity")
613                 .path("csharp")
614                 .queryParam("pageSize", 1)
615                 .queryParam("all", true)
616                 .request()
617                 .get(popularityDataType);
618 
619         assertThat(res, contains(new SimpleEntry<>("topclass", 15), new SimpleEntry<>("mynamespace", 10)));
620     }
621 
622     @Test
623     @SuppressWarnings("unchecked") // for contains
testGetPopularityDataDifferentField()624     void testGetPopularityDataDifferentField() {
625         assertTrue(SuggesterServiceImpl.getInstance().increaseSearchCount("swift",
626                 new Term(QueryBuilder.FULL, "print"), 10, true));
627         assertTrue(SuggesterServiceImpl.getInstance().increaseSearchCount("swift",
628                 new Term(QueryBuilder.DEFS, "greet"), 4, true));
629 
630         List<Entry<String, Integer>> res = target(SuggesterController.PATH)
631                 .path("popularity")
632                 .path("swift")
633                 .queryParam("field", QueryBuilder.DEFS)
634                 .request()
635                 .get(popularityDataType);
636 
637         assertThat(res, contains(new SimpleEntry<>("greet", 4)));
638     }
639 
640     @Test
testWildcardQueryEndingWithAsterisk()641     void testWildcardQueryEndingWithAsterisk() {
642         Result res = target(SuggesterController.PATH)
643                 .queryParam(AuthorizationFilter.PROJECTS_PARAM, "c")
644                 .queryParam("field", QueryBuilder.FULL)
645                 .queryParam(QueryBuilder.FULL, "pr?nt*")
646                 .request()
647                 .get(Result.class);
648 
649         assertThat(res.suggestions.stream().map(r -> r.phrase).collect(Collectors.toList()),
650                 containsInAnyOrder("print", "printf"));
651     }
652 
653     @Test
zTestRebuild()654     void zTestRebuild() throws InterruptedException {
655         Response res = target(SuggesterController.PATH)
656                 .path("rebuild")
657                 .request()
658                 .put(Entity.text(""));
659 
660         assertEquals(Response.Status.NO_CONTENT.getStatusCode(), res.getStatus());
661         SuggesterServiceImpl.getInstance().waitForRebuild(15, TimeUnit.SECONDS);
662     }
663 
664     @Test
zTestRebuildProject()665     void zTestRebuildProject() throws InterruptedException {
666         Response res = target(SuggesterController.PATH)
667                 .path("rebuild")
668                 .path("c")
669                 .request()
670                 .put(Entity.text(""));
671 
672         assertEquals(Response.Status.NO_CONTENT.getStatusCode(), res.getStatus());
673         SuggesterServiceImpl.getInstance().waitForRebuild(15, TimeUnit.SECONDS);
674     }
675 }
676