3 * Copyright (C) 2009-2023 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.component.index;
22 import java.util.Arrays;
23 import java.util.List;
24 import java.util.stream.IntStream;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.sonar.api.resources.Qualifiers;
28 import org.sonar.api.utils.System2;
29 import org.sonar.db.DbTester;
30 import org.sonar.db.component.ComponentDto;
31 import org.sonar.db.component.ProjectData;
32 import org.sonar.db.entity.EntityDto;
33 import org.sonar.db.project.ProjectDto;
34 import org.sonar.server.es.EsTester;
35 import org.sonar.server.es.SearchIdResult;
36 import org.sonar.server.es.SearchOptions;
37 import org.sonar.server.es.textsearch.ComponentTextSearchFeatureRule;
38 import org.sonar.server.permission.index.PermissionIndexerTester;
39 import org.sonar.server.permission.index.WebAuthorizationTypeSupport;
40 import org.sonar.server.tester.UserSessionRule;
42 import static java.util.Collections.singleton;
43 import static org.assertj.core.api.Assertions.assertThat;
45 public class ComponentIndexSearchTest {
47 public EsTester es = EsTester.create();
49 public DbTester db = DbTester.create(System2.INSTANCE, true);
51 public UserSessionRule userSession = UserSessionRule.standalone().logIn();
53 public ComponentTextSearchFeatureRule features = new ComponentTextSearchFeatureRule();
55 private final ComponentIndexer indexer = new ComponentIndexer(db.getDbClient(), es.client());
56 private final PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, indexer);
57 private final ComponentIndex underTest = new ComponentIndex(es.client(), new WebAuthorizationTypeSupport(userSession), System2.INSTANCE);
60 public void filter_by_name() {
61 ProjectData ignoredProject = db.components().insertPrivateProject(p -> p.setName("ignored project"));
62 ProjectData project = db.components().insertPrivateProject(p -> p.setName("Project Shiny name"));
63 index(ignoredProject.getProjectDto(), project.getProjectDto());
65 SearchIdResult<String> result = underTest.search(ComponentQuery.builder().setQuery("shiny").build(), new SearchOptions());
67 assertThat(result.getUuids()).containsExactlyInAnyOrder(project.projectUuid());
71 public void filter_by_key_with_exact_match() {
72 ProjectData ignoredProject = db.components().insertPrivateProject(p -> p.setKey("ignored-project"));
73 ProjectData project = db.components().insertPrivateProject(p -> p.setKey("shiny-project"));
74 db.components().insertPrivateProject(p -> p.setKey("another-shiny-project")).getMainBranchComponent();
75 index(ignoredProject.getProjectDto(), project.getProjectDto());
77 SearchIdResult<String> result = underTest.search(ComponentQuery.builder().setQuery("shiny-project").build(), new SearchOptions());
79 assertThat(result.getUuids()).containsExactlyInAnyOrder(project.projectUuid());
83 public void filter_by_qualifier() {
84 ProjectData project = db.components().insertPrivateProject();
85 ComponentDto portfolio = db.components().insertPrivatePortfolio();
86 index(project.getProjectDto());
87 index(db.components().getPortfolioDto(portfolio));
89 SearchIdResult<String> result = underTest.search(ComponentQuery.builder().setQualifiers(singleton(Qualifiers.PROJECT)).build(), new SearchOptions());
91 assertThat(result.getUuids()).containsExactlyInAnyOrder(project.projectUuid());
95 public void order_by_name_case_insensitive() {
96 ProjectData project2 = db.components().insertPrivateProject(p -> p.setName("PROJECT 2"));
97 ProjectData project3 = db.components().insertPrivateProject(p -> p.setName("project 3"));
98 ProjectData project1 = db.components().insertPrivateProject(p -> p.setName("Project 1"));
99 index(project1.getProjectDto(), project2.getProjectDto(), project3.getProjectDto());
101 SearchIdResult<String> result = underTest.search(ComponentQuery.builder().build(), new SearchOptions());
103 assertThat(result.getUuids()).containsExactly(project1.projectUuid(),
104 project2.projectUuid(),
105 project3.projectUuid());
109 public void paginate_results() {
110 List<ProjectData> projects = IntStream.range(0, 9)
111 .mapToObj(i -> db.components().insertPrivateProject(p -> p.setName("project " + i)))
113 ProjectDto[] projectDtos = projects.stream().map(p -> p.getProjectDto()).toArray(ProjectDto[]::new);
116 SearchIdResult<String> result = underTest.search(ComponentQuery.builder().build(), new SearchOptions().setPage(2, 3));
118 assertThat(result.getUuids()).containsExactlyInAnyOrder(projects.get(3).projectUuid(),
119 projects.get(4).projectUuid(),
120 projects.get(5).projectUuid());
124 public void filter_unauthorized_components() {
125 ProjectDto unauthorizedProject = db.components().insertPrivateProject().getProjectDto();
126 ProjectDto project1 = db.components().insertPrivateProject().getProjectDto();
127 ProjectDto project2 = db.components().insertPrivateProject().getProjectDto();
129 authorizationIndexerTester.allowOnlyAnyone(project1);
130 authorizationIndexerTester.allowOnlyAnyone(project2);
132 SearchIdResult<String> result = underTest.search(ComponentQuery.builder().build(), new SearchOptions());
134 assertThat(result.getUuids()).containsExactlyInAnyOrder(project1.getUuid(), project2.getUuid())
135 .doesNotContain(unauthorizedProject.getUuid());
138 private void index(EntityDto... components) {
140 Arrays.stream(components).forEach(authorizationIndexerTester::allowOnlyAnyone);