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