Merge "Merge branch 'stable-2.15'"
diff --git a/javatests/com/google/gerrit/elasticsearch/BUILD b/javatests/com/google/gerrit/elasticsearch/BUILD
index a2f5229..3360cf4 100644
--- a/javatests/com/google/gerrit/elasticsearch/BUILD
+++ b/javatests/com/google/gerrit/elasticsearch/BUILD
@@ -15,6 +15,7 @@
         "//lib:guava",
         "//lib:junit",
         "//lib/elasticsearch",
+        "//lib/guice",
         "//lib/jgit/org.eclipse.jgit:jgit",
         "//lib/jgit/org.eclipse.jgit.junit:junit",
         "//lib/truth",
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticQueryAccountsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticQueryAccountsTest.java
index 6cfc583..3358037 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticQueryAccountsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticQueryAccountsTest.java
@@ -23,7 +23,6 @@
 import com.google.inject.Injector;
 import java.util.concurrent.ExecutionException;
 import org.eclipse.jgit.lib.Config;
-import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 
@@ -57,11 +56,10 @@
     return testName.getMethodName().toLowerCase() + "_";
   }
 
-  @After
-  public void cleanupIndex() {
-    if (nodeInfo != null) {
-      ElasticTestUtils.deleteAllIndexes(nodeInfo, testName());
-    }
+  @Override
+  protected void initAfterLifecycleStart() throws Exception {
+    super.initAfterLifecycleStart();
+    ElasticTestUtils.createAllIndexes(injector);
   }
 
   @Override
@@ -70,7 +68,6 @@
     InMemoryModule.setDefaults(elasticsearchConfig);
     String indicesPrefix = testName();
     ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
-    ElasticTestUtils.createAllIndexes(nodeInfo, indicesPrefix);
     return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
   }
 }
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticQueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticQueryChangesTest.java
index 5949c06..dbc68df 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticQueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticQueryChangesTest.java
@@ -25,7 +25,6 @@
 import java.util.concurrent.ExecutionException;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.Config;
-import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -60,11 +59,10 @@
     return testName.getMethodName().toLowerCase() + "_";
   }
 
-  @After
-  public void cleanupIndex() {
-    if (nodeInfo != null) {
-      ElasticTestUtils.deleteAllIndexes(nodeInfo, testName());
-    }
+  @Override
+  protected void initAfterLifecycleStart() throws Exception {
+    super.initAfterLifecycleStart();
+    ElasticTestUtils.createAllIndexes(injector);
   }
 
   @Override
@@ -73,7 +71,6 @@
     InMemoryModule.setDefaults(elasticsearchConfig);
     String indicesPrefix = testName();
     ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
-    ElasticTestUtils.createAllIndexes(nodeInfo, indicesPrefix);
     return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
   }
 
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticQueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticQueryGroupsTest.java
index a1c331d..fe0f7dd 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticQueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticQueryGroupsTest.java
@@ -23,7 +23,6 @@
 import com.google.inject.Injector;
 import java.util.concurrent.ExecutionException;
 import org.eclipse.jgit.lib.Config;
-import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 
@@ -57,11 +56,10 @@
     return testName.getMethodName().toLowerCase() + "_";
   }
 
-  @After
-  public void cleanupIndex() {
-    if (nodeInfo != null) {
-      ElasticTestUtils.deleteAllIndexes(nodeInfo, testName());
-    }
+  @Override
+  protected void initAfterLifecycleStart() throws Exception {
+    super.initAfterLifecycleStart();
+    ElasticTestUtils.createAllIndexes(injector);
   }
 
   @Override
@@ -70,7 +68,6 @@
     InMemoryModule.setDefaults(elasticsearchConfig);
     String indicesPrefix = testName();
     ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
-    ElasticTestUtils.createAllIndexes(nodeInfo, indicesPrefix);
     return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
   }
 }
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticQueryProjectsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticQueryProjectsTest.java
index 07fbf56..285c013 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticQueryProjectsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticQueryProjectsTest.java
@@ -23,7 +23,6 @@
 import com.google.inject.Injector;
 import java.util.concurrent.ExecutionException;
 import org.eclipse.jgit.lib.Config;
-import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 
@@ -57,11 +56,10 @@
     return testName.getMethodName().toLowerCase() + "_";
   }
 
-  @After
-  public void cleanupIndex() {
-    if (nodeInfo != null) {
-      ElasticTestUtils.deleteAllIndexes(nodeInfo, testName());
-    }
+  @Override
+  protected void initAfterLifecycleStart() throws Exception {
+    super.initAfterLifecycleStart();
+    ElasticTestUtils.createAllIndexes(injector);
   }
 
   @Override
@@ -70,7 +68,6 @@
     InMemoryModule.setDefaults(elasticsearchConfig);
     String indicesPrefix = testName();
     ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
-    ElasticTestUtils.createAllIndexes(nodeInfo, indicesPrefix);
     return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
   }
 }
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticTestUtils.java b/javatests/com/google/gerrit/elasticsearch/ElasticTestUtils.java
index ed21e6e..00d1c7a 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticTestUtils.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticTestUtils.java
@@ -15,34 +15,21 @@
 package com.google.gerrit.elasticsearch;
 
 import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.elasticsearch.ElasticAccountIndex.ACCOUNTS;
-import static com.google.gerrit.elasticsearch.ElasticChangeIndex.CHANGES;
-import static com.google.gerrit.elasticsearch.ElasticChangeIndex.CLOSED_CHANGES;
-import static com.google.gerrit.elasticsearch.ElasticChangeIndex.OPEN_CHANGES;
-import static com.google.gerrit.elasticsearch.ElasticGroupIndex.GROUPS;
-import static com.google.gerrit.elasticsearch.ElasticProjectIndex.PROJECTS;
 
 import com.google.common.base.Strings;
 import com.google.common.io.Files;
-import com.google.gerrit.elasticsearch.ElasticAccountIndex.AccountMapping;
-import com.google.gerrit.elasticsearch.ElasticChangeIndex.ChangeMapping;
-import com.google.gerrit.elasticsearch.ElasticGroupIndex.GroupMapping;
-import com.google.gerrit.elasticsearch.ElasticProjectIndex.ProjectMapping;
-import com.google.gerrit.index.Schema;
-import com.google.gerrit.index.project.ProjectData;
-import com.google.gerrit.index.project.ProjectSchemaDefinitions;
-import com.google.gerrit.server.account.AccountState;
-import com.google.gerrit.server.group.InternalGroup;
+import com.google.gerrit.index.IndexDefinition;
 import com.google.gerrit.server.index.IndexModule.IndexType;
-import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
-import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
-import com.google.gerrit.server.index.group.GroupSchemaDefinitions;
-import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gson.FieldNamingPolicy;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
 import java.io.File;
+import java.io.IOException;
 import java.nio.file.Path;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
@@ -52,16 +39,11 @@
 import org.elasticsearch.node.Node;
 import org.elasticsearch.node.NodeBuilder;
 
-final class ElasticTestUtils {
-  static final Gson gson =
-      new GsonBuilder()
-          .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
-          .create();
-
-  static class ElasticNodeInfo {
-    final Node node;
-    final String port;
-    final File elasticDir;
+public final class ElasticTestUtils {
+  public static class ElasticNodeInfo {
+    public final Node node;
+    public final String port;
+    public final File elasticDir;
 
     private ElasticNodeInfo(Node node, File rootDir, String port) {
       this.node = node;
@@ -110,48 +92,6 @@
     return new ElasticNodeInfo(node, elasticDir, getHttpPort(node));
   }
 
-  static void deleteAllIndexes(ElasticNodeInfo nodeInfo, String prefix) {
-    Schema<ChangeData> changeSchema = ChangeSchemaDefinitions.INSTANCE.getLatest();
-    nodeInfo
-        .node
-        .client()
-        .admin()
-        .indices()
-        .prepareDelete(String.format("%s%s_%04d", prefix, CHANGES, changeSchema.getVersion()))
-        .execute()
-        .actionGet();
-
-    Schema<AccountState> accountSchema = AccountSchemaDefinitions.INSTANCE.getLatest();
-    nodeInfo
-        .node
-        .client()
-        .admin()
-        .indices()
-        .prepareDelete(String.format("%s%s_%04d", prefix, ACCOUNTS, accountSchema.getVersion()))
-        .execute()
-        .actionGet();
-
-    Schema<InternalGroup> groupSchema = GroupSchemaDefinitions.INSTANCE.getLatest();
-    nodeInfo
-        .node
-        .client()
-        .admin()
-        .indices()
-        .prepareDelete(String.format("%s%s_%04d", prefix, GROUPS, groupSchema.getVersion()))
-        .execute()
-        .actionGet();
-
-    Schema<ProjectData> projectSchema = ProjectSchemaDefinitions.INSTANCE.getLatest();
-    nodeInfo
-        .node
-        .client()
-        .admin()
-        .indices()
-        .prepareDelete(String.format("%s%s_%04d", prefix, PROJECTS, projectSchema.getVersion()))
-        .execute()
-        .actionGet();
-  }
-
   static class NodeInfo {
     String httpAddress;
   }
@@ -160,58 +100,12 @@
     Map<String, NodeInfo> nodes;
   }
 
-  static void createAllIndexes(ElasticNodeInfo nodeInfo, String prefix) {
-    Schema<ChangeData> changeSchema = ChangeSchemaDefinitions.INSTANCE.getLatest();
-    ChangeMapping openChangesMapping = new ChangeMapping(changeSchema);
-    ChangeMapping closedChangesMapping = new ChangeMapping(changeSchema);
-    openChangesMapping.closedChanges = null;
-    closedChangesMapping.openChanges = null;
-    nodeInfo
-        .node
-        .client()
-        .admin()
-        .indices()
-        .prepareCreate(String.format("%s%s_%04d", prefix, CHANGES, changeSchema.getVersion()))
-        .addMapping(OPEN_CHANGES, gson.toJson(openChangesMapping))
-        .addMapping(CLOSED_CHANGES, gson.toJson(closedChangesMapping))
-        .execute()
-        .actionGet();
-
-    Schema<AccountState> accountSchema = AccountSchemaDefinitions.INSTANCE.getLatest();
-    AccountMapping accountMapping = new AccountMapping(accountSchema);
-    nodeInfo
-        .node
-        .client()
-        .admin()
-        .indices()
-        .prepareCreate(String.format("%s%s_%04d", prefix, ACCOUNTS, accountSchema.getVersion()))
-        .addMapping(ElasticAccountIndex.ACCOUNTS, gson.toJson(accountMapping))
-        .execute()
-        .actionGet();
-
-    Schema<InternalGroup> groupSchema = GroupSchemaDefinitions.INSTANCE.getLatest();
-    GroupMapping groupMapping = new GroupMapping(groupSchema);
-    nodeInfo
-        .node
-        .client()
-        .admin()
-        .indices()
-        .prepareCreate(String.format("%s%s_%04d", prefix, GROUPS, groupSchema.getVersion()))
-        .addMapping(ElasticGroupIndex.GROUPS, gson.toJson(groupMapping))
-        .execute()
-        .actionGet();
-
-    Schema<ProjectData> projectSchema = ProjectSchemaDefinitions.INSTANCE.getLatest();
-    ProjectMapping projectMapping = new ProjectMapping(projectSchema);
-    nodeInfo
-        .node
-        .client()
-        .admin()
-        .indices()
-        .prepareCreate(String.format("%s%s_%04d", prefix, PROJECTS, projectSchema.getVersion()))
-        .addMapping(ElasticProjectIndex.PROJECTS, gson.toJson(projectMapping))
-        .execute()
-        .actionGet();
+  public static void createAllIndexes(Injector injector) throws IOException {
+    Collection<IndexDefinition<?, ?, ?>> indexDefs =
+        injector.getInstance(Key.get(new TypeLiteral<Collection<IndexDefinition<?, ?, ?>>>() {}));
+    for (IndexDefinition<?, ?, ?> indexDef : indexDefs) {
+      indexDef.getIndexCollection().getSearchIndex().deleteAll();
+    }
   }
 
   private static String getHttpPort(Node node) throws InterruptedException, ExecutionException {
diff --git a/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java b/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
index 8a8c66e..f6d2568 100644
--- a/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
+++ b/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
@@ -152,6 +152,7 @@
     lifecycle.add(injector);
     injector.injectMembers(this);
     lifecycle.start();
+    initAfterLifecycleStart();
     setUpDatabase();
   }
 
@@ -171,6 +172,8 @@
     currentUserInfo = gApi.accounts().id(adminId.get()).get();
   }
 
+  protected void initAfterLifecycleStart() throws Exception {}
+
   protected RequestContext newRequestContext(Account.Id requestUserId) {
     final CurrentUser requestUser = userFactory.create(requestUserId);
     return new RequestContext() {
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index ba6c732..db71a63 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -216,6 +216,7 @@
     lifecycle.add(injector);
     injector.injectMembers(this);
     lifecycle.start();
+    initAfterLifecycleStart();
     setUpDatabase();
   }
 
@@ -225,6 +226,8 @@
     db.close();
   }
 
+  protected void initAfterLifecycleStart() throws Exception {}
+
   protected void setUpDatabase() throws Exception {
     try (ReviewDb underlyingDb = inMemoryDatabase.getDatabase().open()) {
       schemaCreator.create(underlyingDb);
diff --git a/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java b/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java
index 686dd145..bacbb60 100644
--- a/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java
+++ b/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java
@@ -119,6 +119,7 @@
     lifecycle.add(injector);
     injector.injectMembers(this);
     lifecycle.start();
+    initAfterLifecycleStart();
     setUpDatabase();
   }
 
@@ -139,6 +140,8 @@
     currentUserInfo = gApi.accounts().id(userId.get()).get();
   }
 
+  protected void initAfterLifecycleStart() throws Exception {}
+
   protected RequestContext newRequestContext(Account.Id requestUserId) {
     final CurrentUser requestUser = userFactory.create(requestUserId);
     return new RequestContext() {
diff --git a/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java b/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
index 8727afd..e34746c 100644
--- a/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
+++ b/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
@@ -102,6 +102,7 @@
     lifecycle.add(injector);
     injector.injectMembers(this);
     lifecycle.start();
+    initAfterLifecycleStart();
     setUpDatabase();
   }
 
@@ -121,6 +122,8 @@
     currentUserInfo = gApi.accounts().id(userId.get()).get();
   }
 
+  protected void initAfterLifecycleStart() throws Exception {}
+
   protected RequestContext newRequestContext(Account.Id requestUserId) {
     final CurrentUser requestUser = userFactory.create(requestUserId);
     return new RequestContext() {