]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18856 Refactor subportfolios and fix build and tests
authorLukasz Jarocki <lukasz.jarocki@sonarsource.com>
Tue, 23 May 2023 08:27:06 +0000 (10:27 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 1 Jun 2023 20:02:59 +0000 (20:02 +0000)
21 files changed:
server/sonar-db-dao/src/main/java/org/sonar/db/entity/EntityDto.java
server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/project/ProjectMapper.xml
server/sonar-server-common/src/it/java/org/sonar/server/component/index/ComponentIndexerIT.java
server/sonar-server-common/src/main/java/org/sonar/server/component/index/ComponentDoc.java
server/sonar-server-common/src/main/java/org/sonar/server/component/index/ComponentIndexDefinition.java
server/sonar-server-common/src/main/java/org/sonar/server/component/index/ComponentIndexer.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexCombinationTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexFeatureExactTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexFeatureFavoriteTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexFeatureKeyTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexFeaturePartialTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexFeaturePrefixTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexFeatureRecentlyBrowsedTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexHighlightTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexLoginTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexMultipleWordsTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexScoreTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexSearchWindowExceededTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/component/index/ComponentIndexTest.java
server/sonar-webserver-es/src/testFixtures/java/org/sonar/server/permission/index/PermissionIndexerTester.java

index 11aa6ef3d3713bdae0283a857c84a323828115e1..03e0b564dc3d3bd18a592c291624d429244fd739 100644 (file)
@@ -32,6 +32,16 @@ public class EntityDto {
   protected String qualifier;
   protected boolean isPrivate;
 
+  // This field should be null for anything that is not subportfolio
+  protected String authUuid;
+
+  public String getAuthUuid() {
+    if (qualifier.equals("SVW")) {
+      return authUuid;
+    }
+    return uuid;
+  }
+
   public String getKey() {
     return kee;
   }
index 0264a211032d1ab4dfbae3c596d0ead540878683..d48462256c2dd2abba8cd239591afa2257c01fd3 100644 (file)
@@ -14,7 +14,9 @@
     p.selection_mode as selectionMode,
     p.selection_expression as selectionExpression,
     p.created_at as createdAt,
-    p.updated_at as updatedAt
+    p.updated_at as updatedAt,
+    case when p.parent_uuid is null then 'VW' else 'SVW' end as qualifier,
+    case when p.root_uuid != p.uuid then p.root_uuid else null end as authUuid
   </sql>
 
   <sql id="projectColumns">
index 11332464dcd96b8c4a8b1684dbaeed93a61daa96..e623ae82be765e09f63c69a83167a11019700d06 100644 (file)
   </select>
 
   <sql id="entityProjectColumns">
-    p.uuid as uuid, p.kee as kee, p.name as name, p.private as isPrivate, p.qualifier as qualifier
+    p.uuid as uuid, p.kee as kee, p.name as name, p.private as isPrivate, p.qualifier as qualifier, null as authUuid
   </sql>
 
   <sql id="entityPortfolioColumns">
     p.uuid as uuid, p.kee as kee, p.name as name, p.private as isPrivate,
-    case when p.parent_uuid is null then 'VW' else 'SVW' end as qualifier
+    case when p.parent_uuid is null then 'VW' else 'SVW' end as qualifier,
+    case when p.root_uuid != p.uuid then p.root_uuid else null end as authUuid
   </sql>
 
   <select id="selectEntityByUuid" parameterType="string" resultType="Entity">
index 4835bc85c94aea204b1d757226d6abd3919ed244..28bc6d98112a1c8f951c09299e9999179b324c52 100644 (file)
@@ -32,6 +32,7 @@ import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentUpdateDto;
 import org.sonar.db.es.EsQueueDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.es.EsClient;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.es.IndexingResult;
@@ -135,22 +136,6 @@ public class ComponentIndexerIT {
     assertThatIndexContainsOnly(project);
   }
 
-  @Test
-  public void indexOnAnalysis_updates_index_on_changes() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    underTest.indexOnAnalysis(project.uuid());
-    assertThatComponentHasName(project, project.name());
-
-    // modify
-    project.setName("NewName");
-    updateDb(project);
-
-    // verify that index is updated
-    underTest.indexOnAnalysis(project.uuid());
-    assertThatIndexContainsOnly(project);
-    assertThatComponentHasName(project, "NewName");
-  }
-
   @Test
   public void indexOnAnalysis_does_not_index_non_main_branches() {
     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
@@ -264,7 +249,11 @@ public class ComponentIndexerIT {
       Arrays.stream(expectedComponents).map(ComponentDto::uuid).toArray(String[]::new));
   }
 
-  private void assertThatComponentHasName(ComponentDto component, String expectedName) {
+  private void assertThatIndexContainsOnly(String uuid) {
+    assertThat(es.getIds(TYPE_COMPONENT)).containsExactlyInAnyOrder(uuid);
+  }
+
+  private void assertThatComponentHasName(String uuid, String expectedName) {
     SearchHit[] hits = es.client()
       .search(EsClient.prepareSearch(TYPE_COMPONENT.getMainType())
         .source(new SearchSourceBuilder()
@@ -273,6 +262,6 @@ public class ComponentIndexerIT {
       .getHits();
     assertThat(hits)
       .extracting(SearchHit::getId)
-      .contains(component.uuid());
+      .contains(uuid);
   }
 }
index d2fff419631a277289ab88126ada6df1f938aec0..a05706d4f3edef8d4e69a66dafaab149827435bd 100644 (file)
@@ -20,7 +20,9 @@
 package org.sonar.server.component.index;
 
 import java.util.HashMap;
+import java.util.Map;
 import org.sonar.server.es.BaseDoc;
+import org.sonar.server.permission.index.AuthorizationDoc;
 
 import static org.sonar.server.component.index.ComponentIndexDefinition.FIELD_KEY;
 import static org.sonar.server.component.index.ComponentIndexDefinition.FIELD_NAME;
@@ -34,6 +36,13 @@ public class ComponentDoc extends BaseDoc {
     super(TYPE_COMPONENT, new HashMap<>(6));
   }
 
+  /**
+   * Needed for reflection. Do not remove.
+   */
+  public ComponentDoc(Map<String, Object> fields) {
+    super(TYPE_COMPONENT, fields);
+  }
+
   @Override
   public String getId() {
     return getField(FIELD_UUID);
@@ -41,6 +50,7 @@ public class ComponentDoc extends BaseDoc {
 
   public ComponentDoc setId(String s) {
     setField(FIELD_UUID, s);
+    setParent(AuthorizationDoc.idOf(s));
     return this;
   }
 
@@ -70,4 +80,9 @@ public class ComponentDoc extends BaseDoc {
     setField(FIELD_QUALIFIER, s);
     return this;
   }
+
+  public ComponentDoc setAuthUuid(String s) {
+    setParent(AuthorizationDoc.idOf(s));
+    return this;
+  }
 }
index 8c8d295d0a0b001e1f96be2ff9b06b2e11f8b70a..3c0802f194f81de2fe4b0c00e0c0d6fae2dbaa43 100644 (file)
@@ -56,7 +56,7 @@ public class ComponentIndexDefinition implements IndexDefinition {
 
   private ComponentIndexDefinition(Configuration config, boolean enableSource) {
     this.config = config;
-    this.enableSource = enableSource;
+    this.enableSource = true;
   }
 
   @Inject
index c328728925758aedca5ac4e38d7754bb3076f953..5051ed8284c49a4b118100b1ff3d7290981066ce 100644 (file)
@@ -25,7 +25,9 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Collectors;
 import javax.annotation.Nullable;
 import org.elasticsearch.action.search.SearchRequest;
 import org.elasticsearch.index.query.QueryBuilders;
@@ -35,6 +37,7 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.entity.EntityDto;
 import org.sonar.db.es.EsQueueDto;
+import org.sonar.db.portfolio.PortfolioDto;
 import org.sonar.server.es.BaseDoc;
 import org.sonar.server.es.BulkIndexer;
 import org.sonar.server.es.BulkIndexer.Size;
@@ -70,11 +73,11 @@ public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexe
 
   @Override
   public void indexOnStartup(Set<IndexType> uninitializedIndexTypes) {
-    doIndexByProjectUuid(null, Size.LARGE);
+    doIndexByProjectUuid(Size.LARGE);
   }
 
   public void indexAll() {
-    doIndexByProjectUuid(null, Size.REGULAR);
+    doIndexByProjectUuid(Size.REGULAR);
   }
 
   @Override
@@ -83,8 +86,8 @@ public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexe
   }
 
   @Override
-  public void indexOnAnalysis(String branchUuid, Set<String> unchangedComponentUuids) {
-    doIndexByProjectUuid(branchUuid, Size.REGULAR);
+  public void indexOnAnalysis(String entityUuid, Set<String> unchangedComponentUuids) {
+    doIndexByProjectUuid(entityUuid);
   }
 
   @Override
@@ -124,8 +127,8 @@ public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexe
     for (String entityUuid : entityUuids) {
       dbClient.projectDao().scrollEntitiesForIndexing(dbSession, entityUuid, context -> {
         EntityDto dto = context.getResultObject();
-        bulkIndexer.add(toDocument(dto).toIndexRequest());
         remaining.remove(dto.getUuid());
+        bulkIndexer.add(toDocument(dto).toIndexRequest());
       });
     }
 
@@ -137,20 +140,42 @@ public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexe
   }
 
   /**
-   * @param projectUuid the uuid of the project to analyze, or {@code null} if all content should be indexed.<br/>
-   *                    <b>Warning:</b> only use {@code null} during startup.
+   * @param entityUuid the uuid of the project to analyze, or {@code null} if all content should be indexed.<br/>
+   *                   <b>Warning:</b> only use {@code null} during startup.
    */
-  private void doIndexByProjectUuid(@Nullable String projectUuid, Size bulkSize) {
-    BulkIndexer bulk = new BulkIndexer(esClient, TYPE_COMPONENT, bulkSize);
+  private void doIndexByProjectUuid(String entityUuid) {
+    BulkIndexer bulk = new BulkIndexer(esClient, TYPE_COMPONENT, Size.REGULAR);
+    bulk.start();
+
+    try (DbSession dbSession = dbClient.openSession(false)) {
+      Optional<EntityDto> entityDto = dbClient.projectDao().selectEntityByUuid(dbSession, entityUuid);
+
+      if (entityDto.isEmpty()) {
+        return;
+      }
+      EntityDto entity = entityDto.get();
+
+      bulk.add(toDocument(entity).toIndexRequest());
 
+      if (entity.getQualifier().equals("VW")) {
+        dbClient.portfolioDao().selectTree(dbSession, entityUuid).forEach(sub ->
+          bulk.add(toDocument(sub).toIndexRequest()));
+      }
+    }
+
+    bulk.stop();
+  }
+
+  private void doIndexByProjectUuid(Size bulkSize) {
+    BulkIndexer bulk = new BulkIndexer(esClient, TYPE_COMPONENT, bulkSize);
     bulk.start();
     try (DbSession dbSession = dbClient.openSession(false)) {
-      dbClient.projectDao()
-        .scrollEntitiesForIndexing(dbSession, projectUuid, context -> {
-          EntityDto dto = context.getResultObject();
-          bulk.add(toDocument(dto).toIndexRequest());
-        });
+      dbClient.projectDao().scrollEntitiesForIndexing(dbSession, null, context -> {
+        EntityDto dto = context.getResultObject();
+        bulk.add(toDocument(dto).toIndexRequest());
+      });
     }
+
     bulk.stop();
   }
 
@@ -182,6 +207,7 @@ public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexe
   public static ComponentDoc toDocument(EntityDto component) {
     return new ComponentDoc()
       .setId(component.getUuid())
+      .setAuthUuid(component.getAuthUuid())
       .setName(component.getName())
       .setKey(component.getKey())
       .setQualifier(component.getQualifier());
index 313d905018455ffc50ff3a2de04d1e90f12673bd..f1b08fb1340ff43a468b7d26aa5e434dd897cc6b 100644 (file)
@@ -23,6 +23,7 @@ import java.util.stream.IntStream;
 import org.junit.Test;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.project.ProjectDto;
 
 import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -44,13 +45,21 @@ public class ComponentIndexCombinationTest extends ComponentIndexTest {
   }
 
   @Test
-  public void filter_results_by_qualifier() {
-    ComponentDto project = indexProject("struts", "Apache Struts");
-    indexFile(project, "src/main/java/StrutsManager.java", "StrutsManager.java");
+  public void index_whenQualifierMatchesWhatIsTheIndex_shouldReturnTheProject() {
+    ProjectDto project = indexProject("struts", "Apache Struts");
 
     assertSearchResults(SuggestionQuery.builder().setQuery("struts").setQualifiers(singletonList(Qualifiers.PROJECT)).build(), project);
   }
 
+  @Test
+  public void index_whenQualifierDoesNotMatchWhatIsTheIndex_shouldReturnTheProject() {
+    ProjectDto project = indexProject("struts", "Apache Struts");
+
+    SuggestionQuery query = SuggestionQuery.builder().setQuery("struts").setQualifiers(singletonList(Qualifiers.VIEW)).build();
+
+    assertNoSearchResults(query.getQuery(), Qualifiers.VIEW);
+  }
+
   @Test
   public void should_limit_the_number_of_results() {
     IntStream.rangeClosed(0, 10).forEach(i -> indexProject("sonarqube" + i, "SonarQube" + i));
index cb48c9e79c9d23c790eb69067b881b19a02d7d90..7ed802952030acc97ef9bfabbefe6b80854a4114 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Collections;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.es.textsearch.ComponentTextSearchFeatureRepertoire;
 
 import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
@@ -37,8 +38,8 @@ public class ComponentIndexFeatureExactTest extends ComponentIndexTest {
 
   @Test
   public void scoring_cares_about_exact_matches() {
-    ComponentDto project1 = indexProject("project1", "LongNameLongNameLongNameLongNameSonarQube");
-    ComponentDto project2 = indexProject("project2", "LongNameLongNameLongNameLongNameSonarQubeX");
+    ProjectDto project1 = indexProject("project1", "LongNameLongNameLongNameLongNameSonarQube");
+    ProjectDto project2 = indexProject("project2", "LongNameLongNameLongNameLongNameSonarQubeX");
 
     SuggestionQuery query1 = SuggestionQuery.builder()
       .setQuery("LongNameLongNameLongNameLongNameSonarQube")
index 8fc4a10d6bca91e61d25a518a18309a902a67bdd..c992bc553e8baede743d2713c86cb4dd6ee39745 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.component.index;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.es.textsearch.ComponentTextSearchFeatureRepertoire;
 
 import static com.google.common.collect.ImmutableSet.of;
@@ -40,8 +41,8 @@ public class ComponentIndexFeatureFavoriteTest extends ComponentIndexTest {
 
   @Test
   public void scoring_cares_about_favorites() {
-    ComponentDto project1 = indexProject("sonarqube", "SonarQube");
-    ComponentDto project2 = indexProject("recent", "SonarQube Recently");
+    ProjectDto project1 = indexProject("sonarqube", "SonarQube");
+    ProjectDto project2 = indexProject("recent", "SonarQube Recently");
 
     SuggestionQuery query1 = SuggestionQuery.builder()
       .setQuery("SonarQube")
@@ -61,7 +62,7 @@ public class ComponentIndexFeatureFavoriteTest extends ComponentIndexTest {
   @Test
   public void irrelevant_favorites_are_not_returned() {
     features.set(q -> termQuery(FIELD_KEY, "non-existing-value"), ComponentTextSearchFeatureRepertoire.FAVORITE);
-    ComponentDto project1 = indexProject("foo", "foo");
+    ProjectDto project1 = indexProject("foo", "foo");
 
     SuggestionQuery query1 = SuggestionQuery.builder()
       .setQuery("bar")
index 0a00196cbe4b4f9665fdcdb52052d3a02e4f89ec..3ab5ac210853762f410a2c33e7f4e9b78aa852f1 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.component.index;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.es.textsearch.ComponentTextSearchFeatureRepertoire;
 
 public class ComponentIndexFeatureKeyTest extends ComponentIndexTest {
@@ -33,7 +34,7 @@ public class ComponentIndexFeatureKeyTest extends ComponentIndexTest {
 
   @Test
   public void should_search_projects_by_exact_case_insensitive_key() {
-    ComponentDto project1 = indexProject("keyOne", "Project One");
+    ProjectDto project1 = indexProject("keyOne", "Project One");
     indexProject("keyTwo", "Project Two");
 
     assertSearchResults("keyOne", project1);
@@ -43,7 +44,7 @@ public class ComponentIndexFeatureKeyTest extends ComponentIndexTest {
 
   @Test
   public void should_search_project_with_dot_in_key() {
-    ComponentDto project = indexProject("org.sonarqube", "SonarQube");
+    ProjectDto project = indexProject("org.sonarqube", "SonarQube");
 
     assertSearchResults("org.sonarqube", project);
     assertNoSearchResults("orgsonarqube");
@@ -51,7 +52,7 @@ public class ComponentIndexFeatureKeyTest extends ComponentIndexTest {
 
   @Test
   public void should_search_project_with_dash_in_key() {
-    ComponentDto project = indexProject("org-sonarqube", "SonarQube");
+    ProjectDto project = indexProject("org-sonarqube", "SonarQube");
 
     assertSearchResults("org-sonarqube", project);
     assertNoSearchResults("orgsonarqube");
@@ -59,7 +60,7 @@ public class ComponentIndexFeatureKeyTest extends ComponentIndexTest {
 
   @Test
   public void should_search_project_with_colon_in_key() {
-    ComponentDto project = indexProject("org:sonarqube", "Quality Product");
+    ProjectDto project = indexProject("org:sonarqube", "Quality Product");
 
     assertSearchResults("org:sonarqube", project);
     assertNoSearchResults("orgsonarqube");
@@ -69,7 +70,7 @@ public class ComponentIndexFeatureKeyTest extends ComponentIndexTest {
 
   @Test
   public void should_search_project_with_all_special_characters_in_key() {
-    ComponentDto project = indexProject("org.sonarqube:sonar-sérvèr_ç", "SonarQube");
+    ProjectDto project = indexProject("org.sonarqube:sonar-sérvèr_ç", "SonarQube");
 
     assertSearchResults("org.sonarqube:sonar-sérvèr_ç", project);
   }
index 033dfa48f5aaf6edbb92c14b473b9b1cb572d2ec..9bd6485da6ebc6c81f61b2106fad54fe51fe79e9 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.component.index;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.es.textsearch.ComponentTextSearchFeatureRepertoire;
 
 public class ComponentIndexFeaturePartialTest extends ComponentIndexTest {
@@ -33,7 +34,7 @@ public class ComponentIndexFeaturePartialTest extends ComponentIndexTest {
 
   @Test
   public void search_projects_by_exact_name() {
-    ComponentDto struts = indexProject("struts", "Apache Struts");
+    ProjectDto struts = indexProject("struts", "Apache Struts");
     indexProject("sonarqube", "SonarQube");
 
     assertSearchResults("Apache Struts", struts);
@@ -41,20 +42,9 @@ public class ComponentIndexFeaturePartialTest extends ComponentIndexTest {
     assertSearchResults("APACHE struTS", struts);
   }
 
-  @Test
-  public void search_file_with_long_name() {
-    ComponentDto project = indexProject("struts", "Apache Struts");
-    ComponentDto file1 = indexFile(project, "src/main/java/DefaultRubyComponentServiceTestManagerFactory.java", "DefaultRubyComponentServiceTestManagerFactory.java");
-
-    assertSearchResults("DefaultRubyComponentServiceTestManagerFactory", file1);
-    assertSearchResults("DefaultRubyComponentServiceTestManagerFactory.java", file1);
-    assertSearchResults("RubyComponentServiceTestManager", file1);
-    assertSearchResults("te", file1);
-  }
-
   @Test
   public void should_search_by_name_with_two_characters() {
-    ComponentDto project = indexProject("struts", "Apache Struts");
+    ProjectDto project = indexProject("struts", "Apache Struts");
 
     assertSearchResults("st", project);
     assertSearchResults("tr", project);
@@ -62,7 +52,7 @@ public class ComponentIndexFeaturePartialTest extends ComponentIndexTest {
 
   @Test
   public void search_projects_by_partial_name() {
-    ComponentDto struts = indexProject("struts", "Apache Struts");
+    ProjectDto struts = indexProject("struts", "Apache Struts");
 
     assertSearchResults("truts", struts);
     assertSearchResults("pache", struts);
@@ -72,52 +62,36 @@ public class ComponentIndexFeaturePartialTest extends ComponentIndexTest {
 
   @Test
   public void search_projects_and_files_by_partial_name() {
-    ComponentDto project = indexProject("struts", "Apache Struts");
-    ComponentDto file1 = indexFile(project, "src/main/java/StrutsManager.java", "StrutsManager.java");
-    indexFile(project, "src/main/java/Foo.java", "Foo.java");
-
-    assertSearchResults("struts", project, file1);
-    assertSearchResults("Struts", project, file1);
-    assertSearchResults("StrutsManager", file1);
-    assertSearchResults("STRUTSMAN", file1);
-    assertSearchResults("utsManag", file1);
-  }
+    ProjectDto project = indexProject("struts", "Apache Struts");
 
-  @Test
-  public void should_find_file_by_file_extension() {
-    ComponentDto project = indexProject("struts", "Apache Struts");
-    ComponentDto file1 = indexFile(project, "src/main/java/StrutsManager.java", "StrutsManager.java");
-    ComponentDto file2 = indexFile(project, "src/main/java/Foo.java", "Foo.java");
-
-    assertSearchResults(".java", file1, file2);
-    assertSearchResults("manager.java", file1);
-
-    // do not match
-    assertNoSearchResults("somethingStrutsManager.java");
+    assertSearchResults("struts", project);
+    assertSearchResults("Struts", project);
   }
 
   @Test
   public void should_search_for_word_and_suffix() {
-    assertFileMatches("plugin java", "AbstractPluginFactory.java");
+    assertResultOrder("plugin java", "AbstractPluginFactory.java");
   }
 
   @Test
   public void should_search_for_word_and_suffix_in_any_order() {
-    assertFileMatches("java plugin", "AbstractPluginFactory.java");
+    assertResultOrder("java plugin", "AbstractPluginFactory.java");
   }
 
   @Test
   public void should_search_for_two_words() {
-    assertFileMatches("abstract factory", "AbstractPluginFactory.java");
+    assertResultOrder("abstract factory", "AbstractPluginFactory.java");
   }
 
   @Test
   public void should_search_for_two_words_in_any_order() {
-    assertFileMatches("factory abstract", "AbstractPluginFactory.java");
+    assertResultOrder("factory abstract", "AbstractPluginFactory.java");
   }
 
   @Test
   public void should_require_at_least_one_matching_word() {
-    assertNoFileMatches("monitor object", "AbstractPluginFactory.java");
+    indexProject("AbstractPluginFactory");
+
+    assertNoSearchResults("monitor object");
   }
 }
index 2885f26eb81b65968d2f48e16fb2a1888bc07987..69a4f0411daa6dcf1c4dd66fe7d02870ed99f513 100644 (file)
@@ -42,7 +42,9 @@ public class ComponentIndexFeaturePrefixTest extends ComponentIndexTest {
 
   @Test
   public void should_not_find_partially() {
-    assertNoFileMatches("component.js", "my_component.js");
+    indexProject("my_component");
+
+    assertNoSearchResults("component.js");
   }
 
   @Test
index 2548f01b28ff126983eb935b95992f267ae997ac..56c2c27e1020b77a09799d2532a9766f8444a024 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Collections;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.es.textsearch.ComponentTextSearchFeatureRepertoire;
 
 import static com.google.common.collect.ImmutableSet.of;
@@ -38,8 +39,8 @@ public class ComponentIndexFeatureRecentlyBrowsedTest extends ComponentIndexTest
 
   @Test
   public void scoring_cares_about_recently_browsed() {
-    ComponentDto project1 = indexProject("sonarqube", "SonarQube");
-    ComponentDto project2 = indexProject("recent", "SonarQube Recently");
+    ProjectDto project1 = indexProject("sonarqube", "SonarQube");
+    ProjectDto project2 = indexProject("recent", "SonarQube Recently");
 
     SuggestionQuery query1 = SuggestionQuery.builder()
       .setQuery("SonarQube")
index 73cbfa4b589e89c8ea88b93fa261dc42269ad873..6d73654b38ffb291df8cfbc04acd9320a62a36c8 100644 (file)
@@ -59,12 +59,12 @@ public class ComponentIndexHighlightTest extends ComponentIndexTest {
     assertHighlighting("quickbrownfox", "fox brown", "quick<mark>brownfox</mark>");
   }
 
-  private void assertHighlighting(String fileName, String search, String expectedHighlighting) {
-    indexFile(fileName);
+  private void assertHighlighting(String projectName, String search, String expectedHighlighting) {
+    indexProject(projectName, projectName);
 
     SuggestionQuery query = SuggestionQuery.builder()
       .setQuery(search)
-      .setQualifiers(Collections.singletonList(Qualifiers.FILE))
+      .setQualifiers(Collections.singletonList(Qualifiers.PROJECT))
       .build();
     Stream<ComponentHitsPerQualifier> results = index.searchSuggestions(query, features.get()).getQualifiers();
 
index 47b513f166e00009829a85f3fb6eba5360e08352..6e2bf368fa702bbdb036febbe63baafe68e7eaa2 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.server.component.index;
 
 import org.junit.Test;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.entity.EntityDto;
 import org.sonar.db.user.GroupDto;
 import org.sonar.db.user.UserDto;
 
@@ -44,7 +45,7 @@ public class ComponentIndexLoginTest extends ComponentIndexTest {
     UserDto user = newUserDto();
     userSession.logIn(user);
 
-    ComponentDto project = newProject("sonarqube", "Quality Product");
+    EntityDto project = newProject("sonarqube", "Quality Product");
     indexer.index(project);
 
     assertNoSearchResults("sonarqube");
@@ -59,7 +60,7 @@ public class ComponentIndexLoginTest extends ComponentIndexTest {
     GroupDto group = newGroupDto();
     userSession.logIn().setGroups(group);
 
-    ComponentDto project = newProject("sonarqube", "Quality Product");
+    EntityDto project = newProject("sonarqube", "Quality Product");
     indexer.index(project);
 
     assertNoSearchResults("sonarqube");
index 7bbef7a476226aa68f6e8ac2a56610c3ef1d7c55..0ec52d288b90127e4dcd58dc2aac2055f3abe47b 100644 (file)
@@ -73,23 +73,5 @@ public class ComponentIndexMultipleWordsTest extends ComponentIndexTest {
       "Some.Struts.Class.java.old");
   }
 
-  @Test
-  public void should_require_all_words_to_match() {
-    assertNoFileMatches("struts java",
-      "Struts");
-  }
-
-  @Test
-  public void should_ignore_empty_words() {
-    assertFileMatches("            struts   \n     \n\n",
-      "Struts");
-  }
-
-  @Test
-  public void should_require_all_words_to_match_for_partial() {
-    features.set(ComponentTextSearchFeatureRepertoire.PARTIAL);
-    assertNoFileMatches("struts java",
-      "Struts");
-  }
 
 }
index 847532a171c11b00a26c2f64f79d6a115f8ba178..e911826d01f5398165c7c9edeff04bb76584eae6 100644 (file)
 package org.sonar.server.component.index;
 
 import com.google.common.collect.ImmutableSet;
+import java.util.List;
+import java.util.Set;
 import org.junit.Test;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.es.textsearch.ComponentTextSearchFeatureRepertoire;
 
 import static java.util.Arrays.asList;
@@ -49,8 +52,8 @@ public class ComponentIndexScoreTest extends ComponentIndexTest {
   @Test
   public void should_prefer_key_matching_over_name_matching() {
     es.recreateIndexes();
-    ComponentDto project1 = indexProject("quality", "SonarQube");
-    ComponentDto project2 = indexProject("sonarqube", "Quality Product");
+    ProjectDto project1 = indexProject("quality", "SonarQube");
+    ProjectDto project2 = indexProject("sonarqube", "Quality Product");
 
     assertExactResults("sonarqube", project2, project1);
   }
@@ -113,37 +116,25 @@ public class ComponentIndexScoreTest extends ComponentIndexTest {
 
   @Test
   public void should_prefer_favorite_over_recently_browsed() {
-    ComponentDto file1 = db.components().insertPrivateProject(c -> c.setName("File1")).getMainBranchComponent();
-    index(file1);
+    ProjectDto project1 = db.components().insertPrivateProject(c -> c.setName("File1")).getProjectDto();
+    index(project1);
 
-    ComponentDto file2 = db.components().insertPrivateProject(c -> c.setName("File2")).getMainBranchComponent();
-    index(file2);
+    ProjectDto project2 = db.components().insertPrivateProject(c -> c.setName("File2")).getProjectDto();
+    index(project2);
 
     assertSearch(SuggestionQuery.builder()
       .setQuery("File")
-      .setQualifiers(asList(PROJECT, DIRECTORY, FILE))
-      .setRecentlyBrowsedKeys(ImmutableSet.of(file1.getKey()))
-      .setFavoriteKeys(ImmutableSet.of(file2.getKey()))
-      .build()).containsExactly(uuids(file2, file1));
+      .setQualifiers(List.of(PROJECT))
+      .setRecentlyBrowsedKeys(Set.of(project1.getKey()))
+      .setFavoriteKeys(Set.of(project2.getKey()))
+      .build()).containsExactly(uuids(project2, project1));
 
     assertSearch(SuggestionQuery.builder()
       .setQuery("File")
-      .setQualifiers(asList(PROJECT, DIRECTORY, FILE))
-      .setRecentlyBrowsedKeys(ImmutableSet.of(file2.getKey()))
-      .setFavoriteKeys(ImmutableSet.of(file1.getKey()))
-      .build()).containsExactly(uuids(file1, file2));
-  }
-
-  @Test
-  public void do_not_match_wrong_file_extension() {
-    ComponentDto file1 = indexFile("MyClass.java");
-    ComponentDto file2 = indexFile("ClassExample.java");
-    ComponentDto file3 = indexFile("Class.java");
-    indexFile("Class.cs");
-    indexFile("Class.js");
-    indexFile("Class.rb");
-
-    assertExactResults("Class java", file3, file2, file1);
+      .setQualifiers(List.of(PROJECT))
+      .setRecentlyBrowsedKeys(Set.of(project2.getKey()))
+      .setFavoriteKeys(Set.of(project1.getKey()))
+      .build()).containsExactly(uuids(project1, project2));
   }
 
   @Test
@@ -157,23 +148,8 @@ public class ComponentIndexScoreTest extends ComponentIndexTest {
   public void scoring_test_DbTester() {
     features.set(ComponentTextSearchFeatureRepertoire.PARTIAL);
 
-    ComponentDto project = indexProject("key-1", "Quality Product");
-
-    index(ComponentTesting.newFileDto(project)
-      .setName("DbTester.java")
-      .setKey("java/org/example/DbTester.java")
-      .setUuid("UUID-DbTester"));
-
-    index(ComponentTesting.newFileDto(project)
-      .setName("WebhookDbTesting.java")
-      .setKey("java/org/example/WebhookDbTesting.java")
-      .setUuid("UUID-WebhookDbTesting"));
-
-    assertSearch("dbt").containsExactly(
-
-      "UUID-DbTester",
-      "UUID-WebhookDbTesting"
+    ProjectDto project = indexProject("key-1", "Quality Product");
 
-    );
+    assertSearch("dbt").isEmpty();
   }
 }
index c3c9ea9602d01a46e3407a0c9e919c936d8dbbf5..6efa0172d2218af47022438e76e73050d18f1630 100644 (file)
@@ -65,7 +65,6 @@ public class ComponentIndexSearchWindowExceededTest {
       .setId(componentDoc.uuid())
       .setKey(componentDoc.getKey())
       .setName(componentDoc.name())
-      .setProjectUuid(componentDoc.branchUuid())
       .setQualifier(componentDoc.qualifier());
   }
 }
index 3751a7dea191403de4c4a2c74f9d2eaa6f198a2f..5e48e0c37335f9e04c69e178200a40ac4f79158f 100644 (file)
@@ -22,12 +22,17 @@ package org.sonar.server.component.index;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
+import java.util.stream.Collectors;
 import org.assertj.core.api.ListAssert;
 import org.junit.Rule;
+import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.entity.EntityDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.es.textsearch.ComponentTextSearchFeatureRule;
 import org.sonar.server.permission.index.PermissionIndexerTester;
@@ -44,7 +49,7 @@ public abstract class ComponentIndexTest {
   @Rule
   public EsTester es = EsTester.create();
   @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
+  public DbTester db = DbTester.create(System2.INSTANCE, true);
   @Rule
   public UserSessionRule userSession = UserSessionRule.standalone();
 
@@ -55,32 +60,21 @@ public abstract class ComponentIndexTest {
   protected ComponentIndex index = new ComponentIndex(es.client(), new WebAuthorizationTypeSupport(userSession), System2.INSTANCE);
   protected PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, indexer);
 
-  protected void assertFileMatches(String query, String... fileNames) {
-    ComponentDto[] files = Arrays.stream(fileNames)
-      .map(this::indexFile)
-      .toArray(ComponentDto[]::new);
-    assertSearch(query).containsExactlyInAnyOrder(uuids(files));
-  }
-
-  protected void assertNoFileMatches(String query, String... fileNames) {
-    Arrays.stream(fileNames)
-      .forEach(this::indexFile);
-    assertSearch(query).isEmpty();
-  }
+  private final ComponentDbTester componentDbTester = new ComponentDbTester(db);
 
   protected void assertResultOrder(String query, String... resultsInOrder) {
-    ComponentDto project = indexProject("key-1", "Quality Product");
-    List<ComponentDto> files = Arrays.stream(resultsInOrder)
-      .map(r -> ComponentTesting.newFileDto(project).setName(r))
-      .peek(f -> f.setUuid(f.uuid() + "_" + f.name().replaceAll("[^a-zA-Z0-9]", "")))
+    indexProject("key-1", "Quality Product");
+    List<ProjectDto> projects = Arrays.stream(resultsInOrder)
+      .map(r -> componentDbTester.insertPublicProject(c -> c.setName(r).setKey(r)).getProjectDto())
+      .peek(p -> p.setUuid(p.getUuid() + "_" + p.getName().replaceAll("[^a-zA-Z0-9]", "")))
       .toList();
 
     // index them, but not in the expected order
-    files.stream()
-      .sorted(Comparator.comparing(ComponentDto::uuid).reversed())
+    projects.stream()
+      .sorted(Comparator.comparing(ProjectDto::getUuid).reversed())
       .forEach(this::index);
 
-    assertExactResults(query, files.toArray(new ComponentDto[0]));
+    assertExactResults(query, projects.toArray(new ProjectDto[0]));
   }
 
   protected ListAssert<String> assertSearch(String query) {
@@ -93,54 +87,45 @@ public abstract class ComponentIndexTest {
       .extracting(ComponentHit::getUuid);
   }
 
-  protected void assertSearchResults(String query, ComponentDto... expectedComponents) {
-    assertSearchResults(SuggestionQuery.builder().setQuery(query).setQualifiers(asList(PROJECT, FILE)).build(), expectedComponents);
+  protected void assertSearchResults(String query, EntityDto... expectedComponents) {
+    assertSearchResults(query, List.of(PROJECT), expectedComponents);
   }
 
-  protected void assertSearchResults(SuggestionQuery query, ComponentDto... expectedComponents) {
-    assertSearch(query).containsOnly(uuids(expectedComponents));
+  protected void assertSearchResults(String query, List<String> queryQualifiers, EntityDto... expectedComponents) {
+    assertSearchResults(SuggestionQuery.builder().setQuery(query).setQualifiers(queryQualifiers).build(), expectedComponents);
   }
 
-  protected void assertExactResults(String query, ComponentDto... expectedComponents) {
-    assertSearch(query).containsExactly(uuids(expectedComponents));
+  protected void assertSearchResults(SuggestionQuery query, EntityDto... expectedComponents) {
+    assertSearch(query).containsOnly(uuids(expectedComponents));
   }
 
-  protected void assertNoSearchResults(String query) {
-    assertSearchResults(query);
+  protected void assertExactResults(String query, ProjectDto... expectedComponents) {
+    assertSearch(query).containsExactly(uuids(expectedComponents));
   }
 
-  protected ComponentDto indexProject(String key, String name) {
-    return index(
-      ComponentTesting.newPrivateProjectDto("UUID_" + key)
-        .setKey(key)
-        .setName(name));
+  protected void assertNoSearchResults(String query, String ... qualifiers) {
+    assertSearchResults(query, List.of(qualifiers));
   }
 
-  protected ComponentDto newProject(String key, String name) {
-    return ComponentTesting.newPrivateProjectDto("UUID_" + key)
-      .setKey(key)
-      .setName(name);
+  protected ProjectDto indexProject(String name) {
+    return indexProject(name, name);
   }
 
-  protected ComponentDto indexFile(String fileName) {
-    ComponentDto project = indexProject("key-1", "SonarQube");
-    return indexFile(project, "src/main/java/" + fileName, fileName);
+  protected ProjectDto indexProject(String key, String name) {
+    return index(componentDbTester.insertPublicProject("UUID" + key, c -> c.setKey(key).setName(name)).getProjectDto());
   }
 
-  protected ComponentDto indexFile(ComponentDto project, String fileKey, String fileName) {
-    return index(
-      ComponentTesting.newFileDto(project)
-        .setKey(fileKey)
-        .setName(fileName));
+  protected EntityDto newProject(String key, String name) {
+    return componentDbTester.insertPublicProject("UUID_" + key, c -> c.setKey(key).setName(name)).getProjectDto();
   }
 
-  protected ComponentDto index(ComponentDto dto) {
+  protected ProjectDto index(ProjectDto dto) {
     indexer.index(dto);
     authorizationIndexerTester.allowOnlyAnyone(dto);
     return dto;
   }
 
-  protected static String[] uuids(ComponentDto... expectedComponents) {
-    return Arrays.stream(expectedComponents).map(ComponentDto::uuid).toArray(String[]::new);
+  protected static String[] uuids(EntityDto... expectedComponents) {
+    return Arrays.stream(expectedComponents).map(EntityDto::getUuid).toArray(String[]::new);
   }
 }
index 59d6417564fb795be29ee624e984804660cc5f8b..abc0453fa77ccb25b9d3219a856116cf551cc250 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.permission.index;
 import java.util.List;
 import java.util.stream.Stream;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.entity.EntityDto;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.db.user.GroupDto;
 import org.sonar.db.user.UserDto;
@@ -52,12 +53,24 @@ public class PermissionIndexerTester {
     return allow(dto);
   }
 
+  public PermissionIndexerTester allowOnlyUser(EntityDto entityDto, UserDto user) {
+    IndexPermissions dto = new IndexPermissions(entityDto.getUuid(), entityDto.getQualifier())
+      .addUserUuid(user.getUuid());
+    return allow(dto);
+  }
+
   public PermissionIndexerTester allowOnlyGroup(ComponentDto project, GroupDto group) {
     IndexPermissions dto = new IndexPermissions(project.uuid(), project.qualifier())
       .addGroupUuid(group.getUuid());
     return allow(dto);
   }
 
+  public PermissionIndexerTester allowOnlyGroup(EntityDto entityDto, GroupDto group) {
+    IndexPermissions dto = new IndexPermissions(entityDto.getUuid(), entityDto.getQualifier())
+      .addGroupUuid(group.getUuid());
+    return allow(dto);
+  }
+
   public PermissionIndexerTester allow(IndexPermissions... indexPermissions) {
     return allow(stream(indexPermissions).toList());
   }