This is an automated email from the ASF dual-hosted git repository.

adelapena pushed a commit to branch cep-7-sai
in repository https://gitbox.apache.org/repos/asf/cassandra.git

commit 2a21b349afab10a6d885571bdd8f348a0d8252b5
Author: Andrés de la Peña <a.penya.gar...@gmail.com>
AuthorDate: Thu May 11 15:01:00 2023 +0100

    Unify CQLTester#waitForIndex and SAITester#waitForIndexQueryable
    
    patch by Andrés de la Peña; reviewed by Caleb Rackliffe for CASSANDRA-18521
---
 .../cassandra/cql3/functions/types/ParseUtils.java |   4 +-
 test/unit/org/apache/cassandra/cql3/CQLTester.java | 241 +++++++++++++++------
 .../org/apache/cassandra/cql3/CQLTesterTest.java   |  82 +++++++
 .../org/apache/cassandra/cql3/KeyCacheCqlTest.java |   4 +-
 .../entities/SecondaryIndexOnMapEntriesTest.java   |   2 +-
 .../validation/entities/SecondaryIndexTest.java    |  38 ++--
 .../operations/InsertUpdateIfConditionTest.java    |   2 -
 .../db/guardrails/GuardrailTablesTest.java         |   2 +-
 .../cassandra/index/SecondaryIndexManagerTest.java | 127 +++++------
 .../index/internal/CassandraIndexTest.java         |   9 +-
 .../org/apache/cassandra/index/sai/SAITester.java  |  41 +---
 .../index/sai/cql/AllowFilteringTest.java          |   6 -
 .../cassandra/index/sai/cql/BaseDataModel.java     |  29 ++-
 .../cassandra/index/sai/cql/BooleanTypeTest.java   |   1 -
 .../index/sai/cql/CollectionIndexingTest.java      |   3 -
 .../index/sai/cql/DecimalLargeValueTest.java       |   2 -
 .../index/sai/cql/DuplicateRowIDTest.java          |   1 -
 .../sai/cql/MixedIndexImplementationsTest.java     |   4 -
 .../index/sai/cql/MultipleColumnIndexTest.java     |   2 -
 .../index/sai/cql/SingleNodeExecutor.java          |   4 +-
 .../index/sai/cql/StorageAttachedIndexDDLTest.java |  36 ++-
 .../index/sai/cql/types/IndexingTypeSupport.java   |   2 -
 .../cassandra/index/sai/disk/NodeStartupTest.java  |   5 +-
 .../index/sai/disk/SelectiveIntersectionTest.java  |   2 -
 .../index/sai/disk/SingleNodeQueryFailureTest.java |   1 -
 .../index/sai/functional/CompactionTest.java       |   2 -
 .../index/sai/functional/DiskSpaceTest.java        |   1 -
 .../index/sai/functional/DropTableTest.java        |   1 -
 .../index/sai/functional/FailureTest.java          |   2 +-
 .../index/sai/functional/GroupComponentsTest.java  |   3 -
 .../index/sai/functional/NodeRestartTest.java      |   9 +-
 .../index/sai/functional/SnapshotTest.java         |   2 -
 .../index/sai/metrics/QueryMetricsTest.java        |   1 -
 .../sai/metrics/SegmentFlushingFailureTester.java  |   1 -
 .../index/sai/metrics/StateMetricsTest.java        |   6 +-
 .../cassandra/index/sai/plan/OperationTest.java    |   2 +-
 .../index/sai/virtual/IndexesSystemViewTest.java   |   4 +-
 .../index/sai/virtual/SSTablesSystemViewTest.java  |   2 -
 .../index/sai/virtual/SegmentsSystemViewTest.java  |   1 -
 39 files changed, 383 insertions(+), 304 deletions(-)

diff --git a/src/java/org/apache/cassandra/cql3/functions/types/ParseUtils.java 
b/src/java/org/apache/cassandra/cql3/functions/types/ParseUtils.java
index 8972beed15..8d0f29b45b 100644
--- a/src/java/org/apache/cassandra/cql3/functions/types/ParseUtils.java
+++ b/src/java/org/apache/cassandra/cql3/functions/types/ParseUtils.java
@@ -292,7 +292,7 @@ public abstract class ParseUtils
      * @param value The string to un-double quote.
      * @return The un-double quoted string.
      */
-    static String unDoubleQuote(String value)
+    public static String unDoubleQuote(String value)
     {
         return unquote(value, '"');
     }
@@ -482,7 +482,7 @@ public abstract class ParseUtils
      * @return {@code true} if the given string is surrounded by the quote 
character, and {@code
      * false} otherwise.
      */
-    private static boolean isQuoted(String value, char quoteChar)
+    public static boolean isQuoted(String value, char quoteChar)
     {
         return value != null
                && value.length() > 1
diff --git a/test/unit/org/apache/cassandra/cql3/CQLTester.java 
b/test/unit/org/apache/cassandra/cql3/CQLTester.java
index fa34d5cdc7..c5da07aeb8 100644
--- a/test/unit/org/apache/cassandra/cql3/CQLTester.java
+++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java
@@ -51,7 +51,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-
+import javax.annotation.Nullable;
 import javax.management.MBeanServerConnection;
 import javax.management.remote.JMXConnector;
 import javax.management.remote.JMXConnectorFactory;
@@ -103,6 +103,7 @@ import org.apache.cassandra.config.DataStorageSpec;
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.config.EncryptionOptions;
 import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.cql3.functions.types.ParseUtils;
 import org.apache.cassandra.db.ColumnFamilyStore;
 import org.apache.cassandra.db.Directories;
 import org.apache.cassandra.db.Keyspace;
@@ -137,6 +138,7 @@ import org.apache.cassandra.dht.Murmur3Partitioner;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.exceptions.InvalidRequestException;
 import org.apache.cassandra.exceptions.SyntaxException;
+import org.apache.cassandra.index.Index;
 import org.apache.cassandra.index.SecondaryIndexManager;
 import org.apache.cassandra.io.filesystem.ListenableFileSystem;
 import org.apache.cassandra.io.util.File;
@@ -177,7 +179,6 @@ import static 
org.apache.cassandra.config.CassandraRelevantProperties.TEST_DRIVE
 import static 
org.apache.cassandra.config.CassandraRelevantProperties.TEST_REUSE_PREPARED;
 import static 
org.apache.cassandra.config.CassandraRelevantProperties.TEST_ROW_CACHE_SIZE;
 import static 
org.apache.cassandra.config.CassandraRelevantProperties.TEST_USE_PREPARED;
-import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -205,6 +206,7 @@ public abstract class CQLTester
     public static final String DATA_CENTER = ServerTestUtils.DATA_CENTER;
     public static final String DATA_CENTER_REMOTE = 
ServerTestUtils.DATA_CENTER_REMOTE;
     public static final String RACK1 = ServerTestUtils.RACK1;
+    protected static final int ASSERTION_TIMEOUT_SECONDS = 15;
 
     private static org.apache.cassandra.transport.Server server;
     private static JMXConnectorServer jmxServer;
@@ -1136,122 +1138,229 @@ public abstract class CQLTester
 
     protected void dropTable(String query)
     {
-        dropFormattedTable(String.format(query, KEYSPACE + "." + 
currentTable()));
+        dropTable(KEYSPACE, query);
+    }
+
+    protected void dropTable(String keyspace, String query)
+    {
+        dropFormattedTable(String.format(query, keyspace + "." + 
currentTable()));
     }
 
-    protected void dropFormattedTable(String formattedQuery)
+    private void dropFormattedTable(String formattedQuery)
     {
         logger.info(formattedQuery);
         schemaChange(formattedQuery);
     }
 
+    /**
+     * Creates a secondary index, waiting for it to become queryable.
+     *
+     * @param query the index creation query
+     * @return the name of the created index
+     */
     protected String createIndex(String query)
     {
         return createIndex(KEYSPACE, query);
     }
 
+    /**
+     * Creates a secondary index, waiting for it to become queryable.
+     *
+     * @param keyspace the keyspace the created index should belong to
+     * @param query the index creation query
+     * @return the name of the created index
+     */
     protected String createIndex(String keyspace, String query)
     {
         String formattedQuery = formatQuery(keyspace, query);
-        return createFormattedIndex(formattedQuery);
+        Pair<String, String> qualifiedIndexName = 
createFormattedIndex(keyspace, formattedQuery);
+        waitForIndexQueryable(qualifiedIndexName.left, 
qualifiedIndexName.right);
+        return qualifiedIndexName.right;
+    }
+
+    /**
+     * Creates a secondary index without waiting for it to become queryable.
+     *
+     * @param query the index creation query
+     * @return the name of the created index
+     */
+    protected String createIndexAsync(String query)
+    {
+        return createIndexAsync(KEYSPACE, query);
+    }
+
+    /**
+     * Creates a secondary index without waiting for it to become queryable.
+     *
+     * @param keyspace the keyspace the created index should belong to
+     * @param query the index creation query
+     * @return the name of the created index
+     */
+    protected String createIndexAsync(String keyspace, String query)
+    {
+        String formattedQuery = formatQuery(keyspace, query);
+        return createFormattedIndex(keyspace, formattedQuery).right;
     }
 
-    protected String createFormattedIndex(String formattedQuery)
+    private Pair<String, String> createFormattedIndex(String keyspace, String 
formattedQuery)
     {
         logger.info(formattedQuery);
-        String indexName = getCreateIndexName(formattedQuery);
+        Pair<String, String> qualifiedIndexName = getCreateIndexName(keyspace, 
formattedQuery);
         schemaChange(formattedQuery);
-        return indexName;
+        return qualifiedIndexName;
     }
 
-    protected static String getCreateIndexName(String formattedQuery)
+    protected static Pair<String, String> getCreateIndexName(String keyspace, 
String formattedQuery)
     {
         Matcher matcher = CREATE_INDEX_PATTERN.matcher(formattedQuery);
         if (!matcher.find())
             throw new IllegalArgumentException("Expected valid create index 
query but found: " + formattedQuery);
 
+        String parsedKeyspace = matcher.group(5);
+        if (!Strings.isNullOrEmpty(parsedKeyspace))
+            keyspace = parsedKeyspace;
+
         String index = matcher.group(2);
-        if (!Strings.isNullOrEmpty(index))
-            return index;
+        if (Strings.isNullOrEmpty(index))
+        {
+            String table = matcher.group(7);
+            if (Strings.isNullOrEmpty(table))
+                throw new IllegalArgumentException("Table name should be 
specified: " + formattedQuery);
 
-        String keyspace = matcher.group(5);
-        if (Strings.isNullOrEmpty(keyspace))
-            throw new IllegalArgumentException("Keyspace name should be 
specified: " + formattedQuery);
+            String column = matcher.group(9);
 
-        String table = matcher.group(7);
-        if (Strings.isNullOrEmpty(table))
-            throw new IllegalArgumentException("Table name should be 
specified: " + formattedQuery);
+            String baseName = Strings.isNullOrEmpty(column)
+                              ? IndexMetadata.generateDefaultIndexName(table)
+                              : IndexMetadata.generateDefaultIndexName(table, 
new ColumnIdentifier(column, true));
 
-        String column = matcher.group(9);
+            KeyspaceMetadata ks = 
Schema.instance.getKeyspaceMetadata(keyspace);
+            assertNotNull(ks);
+            index = ks.findAvailableIndexName(baseName);
+        }
 
-        String baseName = Strings.isNullOrEmpty(column)
-                        ? IndexMetadata.generateDefaultIndexName(table)
-                        : IndexMetadata.generateDefaultIndexName(table, new 
ColumnIdentifier(column, true));
+        index = ParseUtils.isQuoted(index, '\"')
+                ? ParseUtils.unDoubleQuote(index)
+                : index.toLowerCase();
 
-        KeyspaceMetadata ks = Schema.instance.getKeyspaceMetadata(keyspace);
-        return ks.findAvailableIndexName(baseName);
+        return Pair.create(keyspace, index);
+    }
+
+    public void waitForTableIndexesQueryable()
+    {
+        waitForTableIndexesQueryable(currentTable());
+    }
+
+    public void waitForTableIndexesQueryable(String table)
+    {
+        waitForTableIndexesQueryable(KEYSPACE, table);
     }
 
     /**
-     * Index creation is asynchronous, this method searches in the system 
table IndexInfo
-     * for the specified index and returns true if it finds it, which 
indicates the
-     * index was built. If we haven't found it after 5 seconds we give-up.
+     * Index creation is asynchronous. This method waits until all the indexes 
in the specified table are queryable.
+     *
+     * @param keyspace the table keyspace name
+     * @param table the table name
      */
-    protected boolean waitForIndex(String keyspace, String table, String 
index) throws Throwable
+    public void waitForTableIndexesQueryable(String keyspace, String table)
     {
-        long start = currentTimeMillis();
-        boolean indexCreated = false;
-        while (!indexCreated)
-        {
-            Object[][] results = getRows(execute("select index_name from 
system.\"IndexInfo\" where table_name = ?", keyspace));
-            for(int i = 0; i < results.length; i++)
-            {
-                if (index.equals(results[i][0]))
-                {
-                    indexCreated = true;
-                    break;
-                }
-            }
+        waitForAssert(() -> 
Assertions.assertThat(getNotQueryableIndexes(keyspace, table)).isEmpty(), 60, 
TimeUnit.SECONDS);
+    }
 
-            if (currentTimeMillis() - start > 5000)
-                break;
+    public void waitForIndexQueryable(String index)
+    {
+        waitForIndexQueryable(KEYSPACE, index);
+    }
 
-            Thread.sleep(10);
-        }
+    /**
+     * Index creation is asynchronous. This method waits until the specified 
index is queryable.
+     *
+     * @param keyspace the index keyspace name
+     * @param index the index name
+     */
+    public void waitForIndexQueryable(String keyspace, String index)
+    {
+        waitForAssert(() -> assertTrue(isIndexQueryable(keyspace, index)), 60, 
TimeUnit.SECONDS);
+    }
 
-        return indexCreated;
+    protected void waitForIndexBuilds(String index)
+    {
+        waitForIndexBuilds(KEYSPACE, index);
     }
 
     /**
-     * Index creation is asynchronous, this method waits until the specified 
index hasn't any building task running.
+     * Index creation is asynchronous. This method waits until the specified 
index hasn't any building task running.
      * <p>
-     * This method differs from {@link #waitForIndex(String, String, String)} 
in that it doesn't require the index to be
-     * fully nor successfully built, so it can be used to wait for failing 
index builds.
+     * This method differs from {@link #waitForIndexQueryable(String, String)} 
in that it doesn't require the
+     * index to be fully nor successfully built, so it can be used to wait for 
failing index builds.
      *
      * @param keyspace the index keyspace name
-     * @param indexName the index name
-     * @return {@code true} if the index build tasks have finished in 5 
seconds, {@code false} otherwise
+     * @param index the index name
      */
-    protected boolean waitForIndexBuilds(String keyspace, String indexName) 
throws InterruptedException
+    protected void waitForIndexBuilds(String keyspace, String index)
+    {
+        waitForAssert(() -> assertFalse(isIndexBuilding(keyspace, index)), 60, 
TimeUnit.SECONDS);
+    }
+
+    /**
+     * @return the names of the indexes in the current table that are not 
queryable
+     */
+    protected Set<String> getNotQueryableIndexes()
+    {
+        return getNotQueryableIndexes(KEYSPACE, currentTable());
+    }
+
+    /**
+     * @param keyspace the table keyspace name
+     * @param table the table name
+     * @return the names of the indexes in the specified table that are not 
queryable
+     */
+    protected Set<String> getNotQueryableIndexes(String keyspace, String table)
+    {
+        SecondaryIndexManager sim = 
Keyspace.open(keyspace).getColumnFamilyStore(table).indexManager;
+        return sim.listIndexes()
+                  .stream()
+                  .filter(index -> !sim.isIndexQueryable(index))
+                  .map(index -> index.getIndexMetadata().name)
+                  .collect(Collectors.toSet());
+    }
+
+    protected boolean isIndexBuilding(String keyspace, String indexName)
+    {
+        SecondaryIndexManager manager = getIndexManager(keyspace, indexName);
+        assertNotNull(manager);
+
+        return manager.isIndexBuilding(indexName);
+    }
+
+    protected boolean isIndexQueryable(String keyspace, String indexName)
     {
-        long start = currentTimeMillis();
-        SecondaryIndexManager indexManager = 
getCurrentColumnFamilyStore(keyspace).indexManager;
+        SecondaryIndexManager manager = getIndexManager(keyspace, indexName);
+        assertNotNull(manager);
 
-        while (true)
+        Index index = manager.getIndexByName(indexName);
+        return manager.isIndexQueryable(index);
+    }
+
+    @Nullable
+    protected SecondaryIndexManager getIndexManager(String keyspace, String 
indexName)
+    {
+        for (ColumnFamilyStore cfs : 
Keyspace.open(keyspace).getColumnFamilyStores())
         {
-            if (!indexManager.isIndexBuilding(indexName))
-            {
-                return true;
-            }
-            else if (currentTimeMillis() - start > 5000)
-            {
-                return false;
-            }
-            else
-            {
-                Thread.sleep(10);
-            }
+            Index index = cfs.indexManager.getIndexByName(indexName);
+            if (index != null)
+                return cfs.indexManager;
         }
+        return null;
+    }
+
+    protected void waitForAssert(Runnable runnableAssert, long timeout, 
TimeUnit unit)
+    {
+        Awaitility.await().dontCatchUncaughtExceptions().atMost(timeout, 
unit).untilAsserted(runnableAssert::run);
+    }
+
+    protected void waitForAssert(Runnable assertion)
+    {
+        waitForAssert(assertion, ASSERTION_TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
 
     protected void createIndexMayThrow(String query) throws Throwable
diff --git a/test/unit/org/apache/cassandra/cql3/CQLTesterTest.java 
b/test/unit/org/apache/cassandra/cql3/CQLTesterTest.java
new file mode 100644
index 0000000000..052ced34da
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/CQLTesterTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.cql3;
+
+import org.junit.Test;
+
+import org.apache.cassandra.utils.Pair;
+import org.assertj.core.api.Assertions;
+
+public class CQLTesterTest extends CQLTester
+{
+    @Test
+    public void testGetCreateIndexName()
+    {
+        schemaChange("CREATE KEYSPACE k WITH replication = {'class': 
'SimpleStrategy', 'replication_factor': '1'}");
+        schemaChange("CREATE KEYSPACE k2 WITH replication = {'class': 
'SimpleStrategy', 'replication_factor': '1'}");
+        String table = createTable("CREATE TABLE %s (k int PRIMARY KEY, c 
int)");
+
+        // standard index with explicit name
+        testGetCreateIndexName("k", "idx", "CREATE INDEX idx ON k.t (c)");
+        testGetCreateIndexName(KEYSPACE, "idx", "CREATE INDEX idx ON t (c)");
+        testGetCreateIndexName(KEYSPACE, "idx", "CREATE INDEX idx ON %s (c)");
+
+        // custom index with explicit name
+        testGetCreateIndexName("k", "idx", "CREATE CUSTOM INDEX idx ON k.t (c) 
USING 'class'");
+        testGetCreateIndexName(KEYSPACE, "idx", "CREATE CUSTOM INDEX idx ON t 
(c) USING 'class'");
+        testGetCreateIndexName(KEYSPACE, "idx", "CREATE CUSTOM INDEX idx ON %s 
(c) USING 'class'");
+
+        // with an unqouted case-sensitive index name
+        testGetCreateIndexName("k", "idx", "CREATE INDEX iDx ON k.t (c)");
+        testGetCreateIndexName(KEYSPACE, "idx", "CREATE INDEX iDx ON t (c)");
+        testGetCreateIndexName(KEYSPACE, "idx", "CREATE INDEX iDx ON %s (c)");
+
+        // with a quoted case-sensitive index name
+        testGetCreateIndexName("k", "iDx", "CREATE INDEX \"iDx\" ON k.t (c)");
+        testGetCreateIndexName(KEYSPACE, "iDx", "CREATE INDEX \"iDx\" ON t 
(c)");
+        testGetCreateIndexName(KEYSPACE, "iDx", "CREATE INDEX \"iDx\" ON %s 
(c)");
+
+        // standard index with autogenerated name
+        testGetCreateIndexName("k", "t_c_idx", "CREATE INDEX ON k.t (c)");
+        testGetCreateIndexName(KEYSPACE, "t_c_idx", "CREATE INDEX ON t (c)");
+        testGetCreateIndexName(KEYSPACE, table + "_c_idx", "CREATE INDEX ON %s 
(c)");
+
+        // custom index with autogenerated name
+        testGetCreateIndexName("k", "t_c_idx", "CREATE CUSTOM INDEX ON k.t (c) 
USING 'class'");
+        testGetCreateIndexName(KEYSPACE, "t_c_idx", "CREATE CUSTOM INDEX ON t 
(c) USING 'class'");
+        testGetCreateIndexName(KEYSPACE, table + "_c_idx", "CREATE CUSTOM 
INDEX ON %s (c) USING 'class'");
+
+        // with a not-default working keyspace
+        testGetCreateIndexName("k", "t_c_idx", "k2", "CREATE INDEX ON k.t 
(c)");
+        testGetCreateIndexName("k2", "t_c_idx", "k2", "CREATE INDEX ON t (c)");
+        testGetCreateIndexName("k2", table + "_c_idx", "k2", "CREATE INDEX ON 
%s (c)");
+    }
+
+    private void testGetCreateIndexName(String expectedKeyspaceName, String 
expectedIndexName, String query)
+    {
+        testGetCreateIndexName(expectedKeyspaceName, expectedIndexName, 
KEYSPACE, query);
+    }
+
+    private void testGetCreateIndexName(String expectedKeyspaceName, String 
expectedIndexName, String keyspace, String query)
+    {
+        Pair<String, String> name = getCreateIndexName(keyspace, 
formatQuery(keyspace, query));
+        Assertions.assertThat(name.left).isEqualTo(expectedKeyspaceName);
+        Assertions.assertThat(name.right).isEqualTo(expectedIndexName);
+    }
+}
diff --git a/test/unit/org/apache/cassandra/cql3/KeyCacheCqlTest.java 
b/test/unit/org/apache/cassandra/cql3/KeyCacheCqlTest.java
index 9c7dac159c..3f5f75abd8 100644
--- a/test/unit/org/apache/cassandra/cql3/KeyCacheCqlTest.java
+++ b/test/unit/org/apache/cassandra/cql3/KeyCacheCqlTest.java
@@ -127,13 +127,13 @@ public class KeyCacheCqlTest extends CQLTester
     @Override
     protected String createIndex(String query)
     {
-        return createFormattedIndex(formatQuery(KEYSPACE_PER_TEST, query));
+        return createIndex(KEYSPACE_PER_TEST, query);
     }
 
     @Override
     protected void dropTable(String query)
     {
-        dropFormattedTable(String.format(query, KEYSPACE_PER_TEST + "." + 
currentTable()));
+        dropTable(KEYSPACE_PER_TEST, query);
     }
 
     @Test
diff --git 
a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexOnMapEntriesTest.java
 
b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexOnMapEntriesTest.java
index b69948fa07..53d752e3ae 100644
--- 
a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexOnMapEntriesTest.java
+++ 
b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexOnMapEntriesTest.java
@@ -256,7 +256,7 @@ public class SecondaryIndexOnMapEntriesTest extends 
CQLTester
         assertRows(execute(query, params));
     }
 
-    private void createSimpleTableAndIndex() throws Throwable
+    private void createSimpleTableAndIndex()
     {
         createTable("CREATE TABLE %s (k TEXT PRIMARY KEY, v MAP<TEXT, INT>)");
         createIndex("CREATE INDEX ON %s(ENTRIES(v))");
diff --git 
a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
 
b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
index 5fde1d87fe..d87855a8bd 100644
--- 
a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
+++ 
b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
@@ -107,8 +107,8 @@ public class SecondaryIndexTest extends CQLTester
                              format("DROP INDEX %s.%s", KEYSPACE, indexName));
 
         createTable("CREATE TABLE %s (a int primary key, b int);");
-        createIndex("CREATE INDEX " + indexName + " ON %s(b);");
-        createIndex("CREATE INDEX IF NOT EXISTS " + indexName + " ON %s(b);");
+        createIndexAsync("CREATE INDEX " + indexName + " ON %s(b);");
+        createIndexAsync("CREATE INDEX IF NOT EXISTS " + indexName + " ON 
%s(b);");
 
         assertInvalidMessage(format("Index '%s' already exists",
                                     
removeQuotes(indexName.toLowerCase(Locale.US))),
@@ -117,7 +117,7 @@ public class SecondaryIndexTest extends CQLTester
         // IF NOT EXISTS should apply in cases where the new index differs 
from an existing one in name only
         String otherIndexName = "index_" + nanoTime();
         assertEquals(1, 
getCurrentColumnFamilyStore().metadata().indexes.size());
-        createIndex("CREATE INDEX IF NOT EXISTS " + otherIndexName + " ON 
%s(b)");
+        createIndexAsync("CREATE INDEX IF NOT EXISTS " + otherIndexName + " ON 
%s(b)");
         assertEquals(1, 
getCurrentColumnFamilyStore().metadata().indexes.size());
         assertInvalidMessage(format("Index %s is a duplicate of existing index 
%s",
                                     
removeQuotes(otherIndexName.toLowerCase(Locale.US)),
@@ -254,7 +254,7 @@ public class SecondaryIndexTest extends CQLTester
     @Test
     public void testIndexOnComposite() throws Throwable
     {
-        String tableName = createTable("CREATE TABLE %s (blog_id int, 
timestamp int, author text, content text, PRIMARY KEY (blog_id, timestamp))");
+        createTable("CREATE TABLE %s (blog_id int, timestamp int, author text, 
content text, PRIMARY KEY (blog_id, timestamp))");
 
         execute("INSERT INTO %s (blog_id, timestamp, author, content) VALUES 
(?, ?, ?, ?)", 0, 0, "bob", "1st post");
         execute("INSERT INTO %s (blog_id, timestamp, author, content) VALUES 
(?, ?, ?, ?)", 0, 1, "tom", "2nd post");
@@ -264,8 +264,6 @@ public class SecondaryIndexTest extends CQLTester
 
         createIndex("CREATE INDEX authoridx ON %s (author)");
 
-        assertTrue(waitForIndex(keyspace(), tableName, "authoridx"));
-
         beforeAndAfterFlush(() -> {
             assertRows(execute("SELECT blog_id, timestamp FROM %s WHERE author 
= 'bob'"),
                        row(1, 0),
@@ -618,14 +616,13 @@ public class SecondaryIndexTest extends CQLTester
     @Test
     public void testCanQuerySecondaryIndex() throws Throwable
     {
-        String tableName = createTable("CREATE TABLE %s (k int PRIMARY KEY, v 
int,)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v int,)");
 
         execute("ALTER TABLE %s WITH CACHING = { 'keys': 'ALL', 
'rows_per_partition': 'ALL' }");
         execute("INSERT INTO %s (k,v) VALUES (0,0)");
         execute("INSERT INTO %s (k,v) VALUES (1,1)");
 
         createIndex("CREATE INDEX testindex on %s (v)");
-        assertTrue(waitForIndex(keyspace(), tableName, "testindex"));
 
         assertRows(execute("SELECT k FROM %s WHERE v = 0"), row(0));
         cleanupCache();
@@ -1040,7 +1037,7 @@ public class SecondaryIndexTest extends CQLTester
             for (int j = 0; j < 10; j++)
                 execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", i, 
j, i + j);
 
-        createIndex("CREATE CUSTOM INDEX testIndex ON %s (value) USING '" + 
IndexBlockingOnInitialization.class.getName() + "'");
+        createIndexAsync("CREATE CUSTOM INDEX testIndex ON %s (value) USING '" 
+ IndexBlockingOnInitialization.class.getName() + "'");
         try
         {
             execute("SELECT value FROM %s WHERE value = 2");
@@ -1060,9 +1057,8 @@ public class SecondaryIndexTest extends CQLTester
     public void testReadOnlyIndex() throws Throwable
     {
         // On successful initialization both reads and writes go through
-        String tableName = createTable("CREATE TABLE %s (pk int, ck int, value 
int, PRIMARY KEY (pk, ck))");
+        createTable("CREATE TABLE %s (pk int, ck int, value int, PRIMARY KEY 
(pk, ck))");
         String indexName = createIndex("CREATE CUSTOM INDEX ON %s (value) 
USING '" + ReadOnlyOnFailureIndex.class.getName() + "'");
-        assertTrue(waitForIndex(keyspace(), tableName, indexName));
         execute("SELECT value FROM %s WHERE value = 1");
         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 1);
         ReadOnlyOnFailureIndex index = (ReadOnlyOnFailureIndex) 
getCurrentColumnFamilyStore().indexManager.getIndexByName(indexName);
@@ -1078,9 +1074,9 @@ public class SecondaryIndexTest extends CQLTester
 
         // On bad initial build writes are not forwarded to the index
         ReadOnlyOnFailureIndex.failInit = true;
-        indexName = createIndex("CREATE CUSTOM INDEX ON %s (value) USING '" + 
ReadOnlyOnFailureIndex.class.getName() + "'");
+        indexName = createIndexAsync("CREATE CUSTOM INDEX ON %s (value) USING 
'" + ReadOnlyOnFailureIndex.class.getName() + "'");
         index = (ReadOnlyOnFailureIndex) 
getCurrentColumnFamilyStore().indexManager.getIndexByName(indexName);
-        assertTrue(waitForIndexBuilds(keyspace(), indexName));
+        waitForIndexBuilds(indexName);
         assertInvalidThrow(IndexNotAvailableException.class, "SELECT value 
FROM %s WHERE value = 1");
         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 1);
         assertEquals(0, index.rowsInserted.size());
@@ -1099,9 +1095,8 @@ public class SecondaryIndexTest extends CQLTester
     public void testWriteOnlyIndex() throws Throwable
     {
         // On successful initialization both reads and writes go through
-        String tableName = createTable("CREATE TABLE %s (pk int, ck int, value 
int, PRIMARY KEY (pk, ck))");
+        createTable("CREATE TABLE %s (pk int, ck int, value int, PRIMARY KEY 
(pk, ck))");
         String indexName = createIndex("CREATE CUSTOM INDEX ON %s (value) 
USING '" + WriteOnlyOnFailureIndex.class.getName() + "'");
-        assertTrue(waitForIndex(keyspace(), tableName, indexName));
         execute("SELECT value FROM %s WHERE value = 1");
         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 1);
         WriteOnlyOnFailureIndex index = (WriteOnlyOnFailureIndex) 
getCurrentColumnFamilyStore().indexManager.getIndexByName(indexName);
@@ -1117,9 +1112,9 @@ public class SecondaryIndexTest extends CQLTester
 
         // On bad initial build writes are forwarded to the index
         WriteOnlyOnFailureIndex.failInit = true;
-        indexName = createIndex("CREATE CUSTOM INDEX ON %s (value) USING '" + 
WriteOnlyOnFailureIndex.class.getName() + "'");
+        indexName = createIndexAsync("CREATE CUSTOM INDEX ON %s (value) USING 
'" + WriteOnlyOnFailureIndex.class.getName() + "'");
         index = (WriteOnlyOnFailureIndex) 
getCurrentColumnFamilyStore().indexManager.getIndexByName(indexName);
-        assertTrue(waitForIndexBuilds(keyspace(), indexName));
+        waitForIndexBuilds(indexName);
         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 1);
         assertEquals(1, index.rowsInserted.size());
         assertInvalidThrow(IndexNotAvailableException.class, "SELECT value 
FROM %s WHERE value = 1");
@@ -1449,7 +1444,7 @@ public class SecondaryIndexTest extends CQLTester
     public void testIndexOnFrozenUDT() throws Throwable
     {
         String type = createType("CREATE TYPE %s (a int)");
-        String tableName = createTable("CREATE TABLE %s (k int PRIMARY KEY, v 
frozen<" + type + ">)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v frozen<" + type + 
">)");
 
         Object udt1 = userType("a", 1);
         Object udt2 = userType("a", 2);
@@ -1459,7 +1454,6 @@ public class SecondaryIndexTest extends CQLTester
 
         execute("INSERT INTO %s (k, v) VALUES (?, ?)", 1, udt2);
         execute("INSERT INTO %s (k, v) VALUES (?, ?)", 1, udt1);
-        assertTrue(waitForIndex(keyspace(), tableName, indexName));
 
         assertRows(execute("SELECT * FROM %s WHERE v = ?", udt1), row(1, 
udt1), row(0, udt1));
         assertEmpty(execute("SELECT * FROM %s WHERE v = ?", udt2));
@@ -1478,7 +1472,7 @@ public class SecondaryIndexTest extends CQLTester
     public void testIndexOnFrozenCollectionOfUDT() throws Throwable
     {
         String type = createType("CREATE TYPE %s (a int)");
-        String tableName = createTable("CREATE TABLE %s (k int PRIMARY KEY, v 
frozen<set<frozen<" + type + ">>>)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v frozen<set<frozen<" 
+ type + ">>>)");
 
         Object udt1 = userType("a", 1);
         Object udt2 = userType("a", 2);
@@ -1489,7 +1483,6 @@ public class SecondaryIndexTest extends CQLTester
         String indexName = createIndex("CREATE INDEX ON %s (full(v))");
 
         execute("INSERT INTO %s (k, v) VALUES (?, ?)", 2, set(udt2));
-        assertTrue(waitForIndex(keyspace(), tableName, indexName));
 
         
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
                              "SELECT * FROM %s WHERE v CONTAINS ?", udt1);
@@ -1511,7 +1504,7 @@ public class SecondaryIndexTest extends CQLTester
     public void testIndexOnNonFrozenCollectionOfFrozenUDT() throws Throwable
     {
         String type = createType("CREATE TYPE %s (a int)");
-        String tableName = createTable("CREATE TABLE %s (k int PRIMARY KEY, v 
set<frozen<" + type + ">>)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v set<frozen<" + type 
+ ">>)");
 
         Object udt1 = userType("a", 1);
         Object udt2 = userType("a", 2);
@@ -1525,7 +1518,6 @@ public class SecondaryIndexTest extends CQLTester
 
         execute("INSERT INTO %s (k, v) VALUES (?, ?)", 2, set(udt2));
         execute("UPDATE %s SET v = v + ? WHERE k = ?", set(udt2), 1);
-        assertTrue(waitForIndex(keyspace(), tableName, indexName));
 
         assertRows(execute("SELECT * FROM %s WHERE v CONTAINS ?", udt1), 
row(1, set(udt1, udt2)));
         assertRows(execute("SELECT * FROM %s WHERE v CONTAINS ?", udt2), 
row(1, set(udt1, udt2)), row(2, set(udt2)));
diff --git 
a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
 
b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
index c617544684..531c1f6c02 100644
--- 
a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ 
b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@ -466,8 +466,6 @@ public class InsertUpdateIfConditionTest extends CQLTester
         // create and confirm
         createIndex("CREATE INDEX IF NOT EXISTS myindex ON %s (value1)");
 
-        assertTrue(waitForIndex(KEYSPACE, tableName, "myindex"));
-
         // unsuccessful create since it's already there
         execute("CREATE INDEX IF NOT EXISTS myindex ON %s (value1)");
 
diff --git 
a/test/unit/org/apache/cassandra/db/guardrails/GuardrailTablesTest.java 
b/test/unit/org/apache/cassandra/db/guardrails/GuardrailTablesTest.java
index cd57e36ed6..352af8f2db 100644
--- a/test/unit/org/apache/cassandra/db/guardrails/GuardrailTablesTest.java
+++ b/test/unit/org/apache/cassandra/db/guardrails/GuardrailTablesTest.java
@@ -94,7 +94,7 @@ public class GuardrailTablesTest extends ThresholdTester
     @Override
     protected void dropTable(String tableName)
     {
-        dropFormattedTable(format("DROP TABLE %s.%s", KEYSPACE_PER_TEST, 
tableName));
+        super.dropTable(format("DROP TABLE %s.%s", KEYSPACE_PER_TEST, 
tableName));
     }
 
     private String assertCreateTableValid() throws Throwable
diff --git 
a/test/unit/org/apache/cassandra/index/SecondaryIndexManagerTest.java 
b/test/unit/org/apache/cassandra/index/SecondaryIndexManagerTest.java
index 0ab2f82440..d63d63840c 100644
--- a/test/unit/org/apache/cassandra/index/SecondaryIndexManagerTest.java
+++ b/test/unit/org/apache/cassandra/index/SecondaryIndexManagerTest.java
@@ -57,22 +57,20 @@ public class SecondaryIndexManagerTest extends CQLTester
     }
 
     @Test
-    public void creatingIndexMarksTheIndexAsBuilt() throws Throwable
+    public void creatingIndexMarksTheIndexAsBuilt()
     {
-        String tableName = createTable("CREATE TABLE %s (a int, b int, c int, 
PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         String indexName = createIndex("CREATE INDEX ON %s(c)");
 
-        waitForIndex(KEYSPACE, tableName, indexName);
         assertMarkedAsBuilt(indexName);
     }
 
     @Test
     public void rebuilOrRecoveringIndexMarksTheIndexAsBuilt() throws Throwable
     {
-        String tableName = createTable("CREATE TABLE %s (a int, b int, c int, 
PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         String indexName = createIndex("CREATE INDEX ON %s(c)");
 
-        waitForIndex(KEYSPACE, tableName, indexName);
         assertMarkedAsBuilt(indexName);
         
         assertTrue(tryRebuild(indexName, false));
@@ -82,10 +80,9 @@ public class SecondaryIndexManagerTest extends CQLTester
     @Test
     public void recreatingIndexMarksTheIndexAsBuilt() throws Throwable
     {
-        String tableName = createTable("CREATE TABLE %s (a int, b int, c int, 
PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         String indexName = createIndex("CREATE INDEX ON %s(c)");
 
-        waitForIndex(KEYSPACE, tableName, indexName);
         assertMarkedAsBuilt(indexName);
 
         // drop the index and verify that it has been removed from the built 
indexes table
@@ -94,17 +91,15 @@ public class SecondaryIndexManagerTest extends CQLTester
 
         // create the index again and verify that it's added to the built 
indexes table
         createIndex(String.format("CREATE INDEX %s ON %%s(c)", indexName));
-        waitForIndex(KEYSPACE, tableName, indexName);
         assertMarkedAsBuilt(indexName);
     }
 
     @Test
-    public void addingSSTablesMarksTheIndexAsBuilt() throws Throwable
+    public void addingSSTablesMarksTheIndexAsBuilt()
     {
-        String tableName = createTable("CREATE TABLE %s (a int, b int, c int, 
PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         String indexName = createIndex("CREATE INDEX ON %s(c)");
 
-        waitForIndex(KEYSPACE, tableName, indexName);
         assertMarkedAsBuilt(indexName);
 
         ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
@@ -123,10 +118,10 @@ public class SecondaryIndexManagerTest extends CQLTester
     {
         // create an index which blocks on creation
         TestingIndex.blockCreate();
-        String tableName = createTable("CREATE TABLE %s (a int, b int, c int, 
PRIMARY KEY (a, b))");
-        String defaultIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
-        String readOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(b) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
-        String writeOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(b) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
+        String defaultIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
+        String readOnlyIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(b) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
+        String writeOnlyIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(b) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
 
         // try to rebuild/recover the index before the index creation task has 
finished
         assertFalse(tryRebuild(defaultIndexName, false));
@@ -138,9 +133,9 @@ public class SecondaryIndexManagerTest extends CQLTester
 
         // check that the index is marked as built when the creation finishes
         TestingIndex.unblockCreate();
-        waitForIndex(KEYSPACE, tableName, defaultIndexName);
-        waitForIndex(KEYSPACE, tableName, readOnlyIndexName);
-        waitForIndex(KEYSPACE, tableName, writeOnlyIndexName);
+        waitForIndexQueryable(defaultIndexName);
+        waitForIndexQueryable(readOnlyIndexName);
+        waitForIndexQueryable(writeOnlyIndexName);
         assertMarkedAsBuilt(defaultIndexName);
         assertMarkedAsBuilt(readOnlyIndexName);
         assertMarkedAsBuilt(writeOnlyIndexName);
@@ -157,16 +152,13 @@ public class SecondaryIndexManagerTest extends CQLTester
     @Test
     public void cannotRebuildOrRecoverWhileAnotherRebuildIsInProgress() throws 
Throwable
     {
-        String tableName = createTable("CREATE TABLE %s (a int, b int, c int, 
PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         String defaultIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
         String readOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(b) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
         String writeOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(b) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
         final AtomicBoolean error = new AtomicBoolean();
 
-        // wait for index initialization and verify it's built:
-        waitForIndex(KEYSPACE, tableName, defaultIndexName);
-        waitForIndex(KEYSPACE, tableName, readOnlyIndexName);
-        waitForIndex(KEYSPACE, tableName, writeOnlyIndexName);
+        // verify it's built after initialization:
         assertMarkedAsBuilt(defaultIndexName);
         assertMarkedAsBuilt(readOnlyIndexName);
         assertMarkedAsBuilt(writeOnlyIndexName);
@@ -214,12 +206,11 @@ public class SecondaryIndexManagerTest extends CQLTester
     @Test
     public void cannotRebuildWhileAnSSTableBuildIsInProgress() throws Throwable
     {
-        final String tableName = createTable("CREATE TABLE %s (a int, b int, c 
int, PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         final String indexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
         final AtomicBoolean error = new AtomicBoolean();
 
-        // wait for index initialization and verify it's built:
-        waitForIndex(KEYSPACE, tableName, indexName);
+        // verify it's built after initialization:
         assertMarkedAsBuilt(indexName);
 
         // add sstables in another thread, but make it block:
@@ -260,12 +251,11 @@ public class SecondaryIndexManagerTest extends CQLTester
     @Test
     public void addingSSTableWhileRebuildIsInProgress() throws Throwable
     {
-        final String tableName = createTable("CREATE TABLE %s (a int, b int, c 
int, PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         final String indexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
         final AtomicBoolean error = new AtomicBoolean();
 
-        // wait for index initialization and verify it's built:
-        waitForIndex(KEYSPACE, tableName, indexName);
+        // verify it's built after initialization:
         assertMarkedAsBuilt(indexName);
 
         // rebuild the index in another thread, but make it block:
@@ -308,12 +298,11 @@ public class SecondaryIndexManagerTest extends CQLTester
     @Test
     public void addingSSTableWithBuildFailureWhileRebuildIsInProgress() throws 
Throwable
     {
-        final String tableName = createTable("CREATE TABLE %s (a int, b int, c 
int, PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         final String indexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
         final AtomicBoolean error = new AtomicBoolean();
 
-        // wait for index initialization and verify it's built:
-        waitForIndex(KEYSPACE, tableName, indexName);
+        // verify it's built after initialization:
         assertMarkedAsBuilt(indexName);
 
         // rebuild the index in another thread, but make it block:
@@ -362,11 +351,10 @@ public class SecondaryIndexManagerTest extends CQLTester
     }
 
     @Test
-    public void rebuildWithFailure() throws Throwable
+    public void rebuildWithFailure()
     {
-        final String tableName = createTable("CREATE TABLE %s (a int, b int, c 
int, PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         final String indexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
-        waitForIndex(KEYSPACE, tableName, indexName);
 
         // Rebuild the index with failure and verify it is not marked as built
         TestingIndex.shouldFailBuild = true;
@@ -384,13 +372,13 @@ public class SecondaryIndexManagerTest extends CQLTester
     }
 
     @Test
-    public void initializingIndexNotQueryableButMaybeWritable() throws 
Throwable
+    public void initializingIndexNotQueryableButMaybeWritable()
     {
         TestingIndex.blockCreate();
-        String tableName = createTable("CREATE TABLE %s (a int, b int, c int, 
PRIMARY KEY (a, b))");
-        String defaultIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
-        String readOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
-        String writeOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
+        String defaultIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
+        String readOnlyIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
+        String writeOnlyIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
 
         // the index shouldn't be queryable while the initialization hasn't 
finished
         assertFalse(isQueryable(defaultIndexName));
@@ -402,9 +390,9 @@ public class SecondaryIndexManagerTest extends CQLTester
 
         // the index should be queryable once the initialization has finished
         TestingIndex.unblockCreate();
-        waitForIndex(KEYSPACE, tableName, defaultIndexName);
-        waitForIndex(KEYSPACE, tableName, readOnlyIndexName);
-        waitForIndex(KEYSPACE, tableName, writeOnlyIndexName);
+        waitForIndexQueryable(defaultIndexName);
+        waitForIndexQueryable(readOnlyIndexName);
+        waitForIndexQueryable(writeOnlyIndexName);
         assertTrue(isQueryable(defaultIndexName));
         assertTrue(isQueryable(readOnlyIndexName));
         assertTrue(isQueryable(writeOnlyIndexName));
@@ -414,13 +402,13 @@ public class SecondaryIndexManagerTest extends CQLTester
     }
 
     @Test
-    public void 
initializingIndexNotQueryableButMaybeNotWritableAfterPartialRebuild() throws 
Throwable
+    public void 
initializingIndexNotQueryableButMaybeNotWritableAfterPartialRebuild()
     {
         TestingIndex.blockCreate();
-        String tableName = createTable("CREATE TABLE %s (a int, b int, c int, 
PRIMARY KEY (a, b))");
-        String defaultIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
-        String readOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
-        String writeOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
+        String defaultIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
+        String readOnlyIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
+        String writeOnlyIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
 
         // the index should never be queryable while the initialization hasn't 
finished
         assertFalse(isQueryable(defaultIndexName));
@@ -463,7 +451,7 @@ public class SecondaryIndexManagerTest extends CQLTester
 
         // the index should be queryable once the initialization has finished
         TestingIndex.unblockCreate();
-        waitForIndex(KEYSPACE, tableName, defaultIndexName);
+        waitForIndexQueryable(defaultIndexName);
         assertTrue(isQueryable(defaultIndexName));
         assertTrue(isQueryable(readOnlyIndexName));
         assertTrue(isQueryable(writeOnlyIndexName));
@@ -477,12 +465,12 @@ public class SecondaryIndexManagerTest extends CQLTester
     {
         TestingIndex.shouldFailCreate = true;
         createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
-        String defaultIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
-        String readOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
-        String writeOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
-        assertTrue(waitForIndexBuilds(KEYSPACE, defaultIndexName));
-        assertTrue(waitForIndexBuilds(KEYSPACE, readOnlyIndexName));
-        assertTrue(waitForIndexBuilds(KEYSPACE, writeOnlyIndexName));
+        String defaultIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
+        String readOnlyIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
+        String writeOnlyIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
+        waitForIndexBuilds(defaultIndexName);
+        waitForIndexBuilds(readOnlyIndexName);
+        waitForIndexBuilds(writeOnlyIndexName);
 
         tryRebuild(defaultIndexName, true);
         tryRebuild(readOnlyIndexName, true);
@@ -501,16 +489,16 @@ public class SecondaryIndexManagerTest extends CQLTester
     }
 
     @Test
-    public void 
indexWithFailedInitializationDoesNotChangeQueryabilityNorWritabilityAfterPartialRebuild()
 throws Throwable
+    public void 
indexWithFailedInitializationDoesNotChangeQueryabilityNorWritabilityAfterPartialRebuild()
     {
         TestingIndex.shouldFailCreate = true;
         createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
-        String defaultIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
-        String readOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
-        String writeOnlyIndexName = createIndex(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
-        assertTrue(waitForIndexBuilds(KEYSPACE, defaultIndexName));
-        assertTrue(waitForIndexBuilds(KEYSPACE, readOnlyIndexName));
-        assertTrue(waitForIndexBuilds(KEYSPACE, writeOnlyIndexName));
+        String defaultIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
+        String readOnlyIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
+        String writeOnlyIndexName = createIndexAsync(String.format("CREATE 
CUSTOM INDEX ON %%s(c) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
+        waitForIndexBuilds(defaultIndexName);
+        waitForIndexBuilds(readOnlyIndexName);
+        waitForIndexBuilds(writeOnlyIndexName);
         TestingIndex.shouldFailCreate = false;
 
         // the index should never be queryable, but it could be writable after 
the failed initialization
@@ -524,9 +512,9 @@ public class SecondaryIndexManagerTest extends CQLTester
         // a successful partial build doesn't set the index as queryable nor 
writable
         ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
         cfs.indexManager.handleNotification(new 
SSTableAddedNotification(cfs.getLiveSSTables(), null), this);
-        assertTrue(waitForIndexBuilds(KEYSPACE, defaultIndexName));
-        assertTrue(waitForIndexBuilds(KEYSPACE, readOnlyIndexName));
-        assertTrue(waitForIndexBuilds(KEYSPACE, writeOnlyIndexName));
+        waitForIndexBuilds(defaultIndexName);
+        waitForIndexBuilds(readOnlyIndexName);
+        waitForIndexBuilds(writeOnlyIndexName);
         assertFalse(isQueryable(defaultIndexName));
         assertFalse(isQueryable(readOnlyIndexName));
         assertFalse(isQueryable(writeOnlyIndexName));
@@ -556,7 +544,7 @@ public class SecondaryIndexManagerTest extends CQLTester
             TestingIndex.failedCreateThrowable = throwable;
 
             createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
-            String indexName = createIndex(String.format("CREATE CUSTOM INDEX 
ON %%s(c) USING '%s'", TestingIndex.class.getName()));
+            String indexName = createIndexAsync(String.format("CREATE CUSTOM 
INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
             tryRebuild(indexName, true);
             fail("Should have failed!");
         }
@@ -573,7 +561,7 @@ public class SecondaryIndexManagerTest extends CQLTester
     }
 
     @Test
-    public void handleJVMStablityOnFailedRebuild() throws Throwable
+    public void handleJVMStablityOnFailedRebuild()
     {
         handleJVMStablityOnFailedRebuild(new SocketException("Should not 
fail"), false);
         handleJVMStablityOnFailedRebuild(new FileNotFoundException("Should not 
fail"), false);
@@ -582,11 +570,10 @@ public class SecondaryIndexManagerTest extends CQLTester
         handleJVMStablityOnFailedRebuild(new RuntimeException("Should not 
fail"), false);
     }
 
-    private void handleJVMStablityOnFailedRebuild(Throwable throwable, boolean 
shouldKillJVM) throws Throwable
+    private void handleJVMStablityOnFailedRebuild(Throwable throwable, boolean 
shouldKillJVM)
     {
-        String tableName = createTable("CREATE TABLE %s (a int, b int, c int, 
PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         String indexName = createIndex(String.format("CREATE CUSTOM INDEX ON 
%%s(c) USING '%s'", TestingIndex.class.getName()));
-        waitForIndex(KEYSPACE, tableName, indexName);
 
         KillerForTests killerForTests = new KillerForTests();
         JVMStabilityInspector.Killer originalKiller = 
JVMStabilityInspector.replaceKiller(killerForTests);
diff --git 
a/test/unit/org/apache/cassandra/index/internal/CassandraIndexTest.java 
b/test/unit/org/apache/cassandra/index/internal/CassandraIndexTest.java
index 84eb8d0746..292b25a7d0 100644
--- a/test/unit/org/apache/cassandra/index/internal/CassandraIndexTest.java
+++ b/test/unit/org/apache/cassandra/index/internal/CassandraIndexTest.java
@@ -50,7 +50,6 @@ import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 /**
@@ -426,7 +425,7 @@ public class CassandraIndexTest extends CQLTester
         Object[] row2 = row("k0", "c1");
         Object[] row3 = row("k1", "c0");
         Object[] row4 = row("k1", "c1");
-        String tableName = createTable("CREATE TABLE %s (k text, c text, 
PRIMARY KEY(k, c))");
+        createTable("CREATE TABLE %s (k text, c text, PRIMARY KEY(k, c))");
         createIndex("CREATE INDEX no_regulars_idx ON %s(c)");
 
         execute("INSERT INTO %s (k, c) VALUES (?, ?)", row1);
@@ -440,7 +439,6 @@ public class CassandraIndexTest extends CQLTester
 
         dropIndex("DROP INDEX %s.no_regulars_idx");
         createIndex("CREATE INDEX no_regulars_idx ON %s(c)");
-        assertTrue(waitForIndex(keyspace(), tableName, "no_regulars_idx"));
 
         assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE c = ?", "c0"), 
row1, row3);
         assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE c = ?", "c1"), 
row2, row4);
@@ -572,16 +570,15 @@ public class CassandraIndexTest extends CQLTester
                   .untilAsserted(() -> 
assertRows(execute(selectBuiltIndexesQuery), row("system", 
"PaxosUncommittedIndex", null)));
 
         String indexName = "build_remove_test_idx";
-        String tableName = createTable("CREATE TABLE %s (a int, b int, c int, 
PRIMARY KEY (a, b))");
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
         createIndex(String.format("CREATE INDEX %s ON %%s(c)", indexName));
-        waitForIndex(KEYSPACE, tableName, indexName);
 
         // check that there are no other rows in the built indexes table
         assertRows(execute(selectBuiltIndexesQuery), row(KEYSPACE, indexName, 
null), row("system", "PaxosUncommittedIndex", null));
 
         // rebuild the index and verify the built status table
         getCurrentColumnFamilyStore().rebuildSecondaryIndex(indexName);
-        waitForIndex(KEYSPACE, tableName, indexName);
+        waitForIndexQueryable(indexName);
 
         // check that there are no other rows in the built indexes table
         assertRows(execute(selectBuiltIndexesQuery), row(KEYSPACE, indexName, 
null), row("system", "PaxosUncommittedIndex", null));
diff --git a/test/unit/org/apache/cassandra/index/sai/SAITester.java 
b/test/unit/org/apache/cassandra/index/sai/SAITester.java
index b6a9fe75cc..90d0564df9 100644
--- a/test/unit/org/apache/cassandra/index/sai/SAITester.java
+++ b/test/unit/org/apache/cassandra/index/sai/SAITester.java
@@ -97,7 +97,6 @@ import org.apache.cassandra.service.snapshot.TableSnapshot;
 import org.apache.cassandra.utils.JVMStabilityInspector;
 import org.apache.cassandra.utils.Throwables;
 import org.apache.lucene.codecs.CodecUtil;
-import org.awaitility.Awaitility;
 
 import static org.apache.cassandra.inject.ActionBuilder.newActionBuilder;
 import static org.apache.cassandra.inject.Expression.quote;
@@ -119,8 +118,6 @@ public abstract class SAITester extends CQLTester
 
     protected static final ColumnIdentifier V1_COLUMN_IDENTIFIER = 
ColumnIdentifier.getInterned("v1", true);
 
-    protected static final int ASSERTION_TIMEOUT_SECONDS = 15;
-
     protected static final Injections.Counter indexBuildCounter = 
Injections.newCounter("IndexBuildCounter")
                                                                             
.add(newInvokePoint().onClass(CompactionManager.class)
                                                                                
                  .onMethod("submitIndexBuild",
@@ -273,7 +270,7 @@ public abstract class SAITester extends CQLTester
         cfs.indexManager.executePreJoinTasksBlocking(true);
         if (wait)
         {
-            waitForIndexQueryable();
+            waitForTableIndexesQueryable();
         }
     }
 
@@ -297,38 +294,12 @@ public abstract class SAITester extends CQLTester
         }
     }
 
-    protected void waitForAssert(Runnable runnableAssert, long timeout, 
TimeUnit unit)
-    {
-        Awaitility.await().dontCatchUncaughtExceptions().atMost(timeout, 
unit).untilAsserted(runnableAssert::run);
-    }
-
-    protected void waitForAssert(Runnable assertion)
-    {
-        waitForAssert(assertion, ASSERTION_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-    }
-
     protected boolean indexNeedsFullRebuild(String index)
     {
         ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
         return cfs.indexManager.needsFullRebuild(index);
     }
 
-    protected boolean isIndexQueryable()
-    {
-        return isIndexQueryable(KEYSPACE, currentTable());
-    }
-
-    protected boolean isIndexQueryable(String keyspace, String table)
-    {
-        ColumnFamilyStore cfs = 
Keyspace.open(keyspace).getColumnFamilyStore(table);
-        for (Index index : cfs.indexManager.listIndexes())
-        {
-            if (!cfs.indexManager.isIndexQueryable(index))
-                return false;
-        }
-        return true;
-    }
-
     protected void verifyInitialIndexFailed(String indexName)
     {
         // Verify that the initial index build fails...
@@ -388,16 +359,6 @@ public abstract class SAITester extends CQLTester
         return metricValue;
     }
 
-    public void waitForIndexQueryable()
-    {
-        waitForIndexQueryable(KEYSPACE, currentTable());
-    }
-
-    public void waitForIndexQueryable(String keyspace, String table)
-    {
-        waitForAssert(() -> assertTrue(isIndexQueryable(keyspace, table)), 60, 
TimeUnit.SECONDS);
-    }
-
     public void waitForCompactions()
     {
         waitForAssert(() -> 
assertFalse(CompactionManager.instance.isCompacting(ColumnFamilyStore.all(), 
ssTableReader -> true)), 10, TimeUnit.SECONDS);
diff --git 
a/test/unit/org/apache/cassandra/index/sai/cql/AllowFilteringTest.java 
b/test/unit/org/apache/cassandra/index/sai/cql/AllowFilteringTest.java
index 13b0f6148b..f80d07eeb7 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/AllowFilteringTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/AllowFilteringTest.java
@@ -38,7 +38,6 @@ public class AllowFilteringTest extends SAITester
         createTable("CREATE TABLE %s (k1 int, k2 int, c1 int, c2 int, c3 int, 
v1 int, " +
                     "PRIMARY KEY ((k1, k2), c1, c2, c3))");
         createIndex(format("CREATE CUSTOM INDEX ON %%s(c1) USING '%s'", 
StorageAttachedIndex.class.getName()));
-        waitForIndexQueryable();
 
         // with only index restrictions
         test("SELECT * FROM %s WHERE c1=0", false);
@@ -83,7 +82,6 @@ public class AllowFilteringTest extends SAITester
         createTable("CREATE TABLE %s (k1 int, k2 int, c1 int, c2 int, c3 int, 
c4 int, v1 int, " +
                     "PRIMARY KEY ((k1, k2), c1, c2, c3, c4))");
         createIndex(format("CREATE CUSTOM INDEX ON %%s(c3) USING '%s'", 
StorageAttachedIndex.class.getName()));
-        waitForIndexQueryable();
 
         // with only index restrictions
         test("SELECT * FROM %s WHERE c3=0", false);
@@ -129,7 +127,6 @@ public class AllowFilteringTest extends SAITester
                     "PRIMARY KEY ((k1, k2), c1, c2, c3, c4))");
         createIndex(format("CREATE CUSTOM INDEX ON %%s(c2) USING '%s'", 
StorageAttachedIndex.class.getName()));
         createIndex(format("CREATE CUSTOM INDEX ON %%s(c4) USING '%s'", 
StorageAttachedIndex.class.getName()));
-        waitForIndexQueryable();
 
         // with only index restrictions
         test("SELECT * FROM %s WHERE c2=0 AND c4=0", false);
@@ -175,7 +172,6 @@ public class AllowFilteringTest extends SAITester
     {
         createTable("CREATE TABLE %s (k1 int, k2 int, c1 int, c2 int, v1 int, 
v2 int, PRIMARY KEY ((k1, k2), c1, c2))");
         createIndex(format("CREATE CUSTOM INDEX ON %%s(v1) USING '%s'", 
StorageAttachedIndex.class.getName()));
-        waitForIndexQueryable();
 
         // with only index restrictions
         test("SELECT * FROM %s WHERE v1=0", false);
@@ -219,7 +215,6 @@ public class AllowFilteringTest extends SAITester
                     "PRIMARY KEY ((k1, k2), c1, c2))");
         createIndex(format("CREATE CUSTOM INDEX ON %%s(v1) USING '%s'", 
StorageAttachedIndex.class.getName()));
         createIndex(format("CREATE CUSTOM INDEX ON %%s(v2) USING '%s'", 
StorageAttachedIndex.class.getName()));
-        waitForIndexQueryable();
 
         // with only index restrictions
         test("SELECT * FROM %s WHERE v1=0 AND v2=0", false);
@@ -268,7 +263,6 @@ public class AllowFilteringTest extends SAITester
         createIndex(format("CREATE CUSTOM INDEX ON %%s(c4) USING '%s'", 
StorageAttachedIndex.class.getName()));
         createIndex(format("CREATE CUSTOM INDEX ON %%s(v1) USING '%s'", 
StorageAttachedIndex.class.getName()));
         createIndex(format("CREATE CUSTOM INDEX ON %%s(v2) USING '%s'", 
StorageAttachedIndex.class.getName()));
-        waitForIndexQueryable();
 
         // with only index restrictions
         test("SELECT * FROM %s WHERE c2=0 AND c4=0 AND v1=0 AND v2=0", false);
diff --git a/test/unit/org/apache/cassandra/index/sai/cql/BaseDataModel.java 
b/test/unit/org/apache/cassandra/index/sai/cql/BaseDataModel.java
index 67621c3b9a..e9287e178f 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/BaseDataModel.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/BaseDataModel.java
@@ -169,14 +169,22 @@ class BaseDataModel
 
     public void createIndexes(Executor tester) throws Throwable
     {
-        String template = "CREATE CUSTOM INDEX ndi_%s_index_%s ON %%s (%s) 
USING 'StorageAttachedIndex'";
+        createIndexes(tester, columns);
+    }
+
+    protected void createIndexes(Executor tester, List<Pair<String, String>> 
columns) throws Throwable
+    {
+        String indexNameTemplate = "sai_%s_index_%s";
+        String createIndexTemplate = "CREATE CUSTOM INDEX %s ON %%s (%s) USING 
'StorageAttachedIndex'";
 
         for (Pair<String, String> column : columns)
         {
-            if (!skipColumns.contains(column.left))
+            String columnName = column.left;
+            if (!skipColumns.contains(columnName))
             {
-                executeLocalIndexed(tester, String.format(template, 
column.left, indexedTable, column.left));
-                tester.waitForIndexQueryable(KEYSPACE, indexedTable);
+                String indexName = String.format(indexNameTemplate, 
columnName, indexedTable);
+                executeLocalIndexed(tester, String.format(createIndexTemplate, 
indexName, columnName));
+                tester.waitForIndexQueryable(KEYSPACE, indexName);
             }
         }
     }
@@ -294,16 +302,7 @@ class BaseDataModel
         public void createIndexes(Executor tester) throws Throwable
         {
             super.createIndexes(tester);
-            String template = "CREATE CUSTOM INDEX ndi_%s_index_%s ON %%s (%s) 
USING 'StorageAttachedIndex'";
-
-            for (Pair<String, String> column : keyColumns)
-            {
-                if (!skipColumns.contains(column.left))
-                {
-                    executeLocalIndexed(tester, String.format(template, 
column.left, indexedTable, column.left));
-                    tester.waitForIndexQueryable(KEYSPACE, indexedTable);
-                }
-            }
+            createIndexes(tester, keyColumns);
         }
 
         @Override
@@ -383,7 +382,7 @@ class BaseDataModel
     {
         void createTable(String statement);
 
-        void waitForIndexQueryable(String keyspace, String table);
+        void waitForIndexQueryable(String keyspace, String index);
 
         void executeLocal(String query, Object...values) throws Throwable;
 
diff --git a/test/unit/org/apache/cassandra/index/sai/cql/BooleanTypeTest.java 
b/test/unit/org/apache/cassandra/index/sai/cql/BooleanTypeTest.java
index 3131414418..75e72b1686 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/BooleanTypeTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/BooleanTypeTest.java
@@ -32,7 +32,6 @@ public class BooleanTypeTest extends SAITester
         createTable("CREATE TABLE %s (id text PRIMARY KEY, val boolean)");
 
         createIndex("CREATE CUSTOM INDEX ON %s(val) USING 
'StorageAttachedIndex'");
-        waitForIndexQueryable();
 
         execute("INSERT INTO %s (id, val) VALUES ('0', false)");
         execute("INSERT INTO %s (id, val) VALUES ('1', true)");
diff --git 
a/test/unit/org/apache/cassandra/index/sai/cql/CollectionIndexingTest.java 
b/test/unit/org/apache/cassandra/index/sai/cql/CollectionIndexingTest.java
index a3906ab6dc..8bc9efb1ca 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/CollectionIndexingTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/CollectionIndexingTest.java
@@ -178,7 +178,6 @@ public class CollectionIndexingTest extends SAITester
     {
         createTable("CREATE TABLE %s (pk int primary key, value map<int, 
text>)");
         createIndex(createIndex);
-        waitForIndexQueryable();
         execute("INSERT INTO %s (pk, value) VALUES (?, ?)", 1, new 
HashMap<Integer, String>() {{
             put(1, "v1");
             put(2, "v2");
@@ -194,7 +193,6 @@ public class CollectionIndexingTest extends SAITester
     {
         createTable("CREATE TABLE %s (pk int primary key, value 
frozen<map<int, text>>)");
         createIndex(createIndex);
-        waitForIndexQueryable();
         execute("INSERT INTO %s (pk, value) VALUES (?, ?)", 1, new 
HashMap<Integer, String>() {{
             put(1, "v1");
             put(2, "v2");
@@ -210,7 +208,6 @@ public class CollectionIndexingTest extends SAITester
     {
         createTable("CREATE TABLE %s (pk int primary key, value 
frozen<list<int>>)");
         createIndex(createIndex);
-        waitForIndexQueryable();
         execute("INSERT INTO %s (pk, value) VALUES (?, ?)", 1, 
Arrays.asList(1, 2, 3));
         execute("INSERT INTO %s (pk, value) VALUES (?, ?)", 2, 
Arrays.asList(1, 2, 3));
         execute("INSERT INTO %s (pk, value) VALUES (?, ?)", 3, 
Arrays.asList(4, 5, 6));
diff --git 
a/test/unit/org/apache/cassandra/index/sai/cql/DecimalLargeValueTest.java 
b/test/unit/org/apache/cassandra/index/sai/cql/DecimalLargeValueTest.java
index 97a51827fd..107dae1c0a 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/DecimalLargeValueTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/DecimalLargeValueTest.java
@@ -37,8 +37,6 @@ public class DecimalLargeValueTest extends SAITester
 
         createIndex("CREATE CUSTOM INDEX ON %s(dec) USING 
'StorageAttachedIndex'");
 
-        waitForIndexQueryable();
-
         disableCompaction();
     }
 
diff --git 
a/test/unit/org/apache/cassandra/index/sai/cql/DuplicateRowIDTest.java 
b/test/unit/org/apache/cassandra/index/sai/cql/DuplicateRowIDTest.java
index 36da00b586..fd13e33473 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/DuplicateRowIDTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/DuplicateRowIDTest.java
@@ -40,7 +40,6 @@ public class DuplicateRowIDTest extends SAITester
     {
         createTable("CREATE TABLE %s (id1 TEXT PRIMARY KEY, v1 INT)");
         createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
-        waitForIndexQueryable();
 
         for (int i = 0; i < 2048; ++i)
         {
diff --git 
a/test/unit/org/apache/cassandra/index/sai/cql/MixedIndexImplementationsTest.java
 
b/test/unit/org/apache/cassandra/index/sai/cql/MixedIndexImplementationsTest.java
index f705240d68..cb3ef36e99 100644
--- 
a/test/unit/org/apache/cassandra/index/sai/cql/MixedIndexImplementationsTest.java
+++ 
b/test/unit/org/apache/cassandra/index/sai/cql/MixedIndexImplementationsTest.java
@@ -41,7 +41,6 @@ public class MixedIndexImplementationsTest extends SAITester
         String ossIndex = createIndex("CREATE INDEX ON %s(v1)");
         String ndiIndex = createIndex(
                 String.format("CREATE CUSTOM INDEX ON %%s(v2) USING '%s'", 
StorageAttachedIndex.class.getName()));
-        waitForIndexQueryable();
 
         // drop non-storage-attached index when a SAI index exists
         dropIndex("DROP INDEX %s." + ossIndex);
@@ -68,8 +67,6 @@ public class MixedIndexImplementationsTest extends SAITester
         execute(insert, 2, 1, 0);
         execute(insert, 3, 1, 1);
 
-        waitForIndexQueryable();
-
         String ossSelect = "SELECT * FROM %s WHERE v1 = ?";
         assertRowsIgnoringOrder(execute(ossSelect, 0), new Object[][]{{0, 0, 
0}, {1, 0, 1}});
         assertRowsIgnoringOrder(execute(ossSelect, 1), new Object[][]{{2, 1, 
0}, {3, 1, 1}});
@@ -99,7 +96,6 @@ public class MixedIndexImplementationsTest extends SAITester
         createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c3) USING '%s'", 
StorageAttachedIndex.class.getName()));
         createIndex(String.format("CREATE CUSTOM INDEX ON %%s(r1) USING '%s'", 
StorageAttachedIndex.class.getName()));
         createIndex(String.format("CREATE CUSTOM INDEX ON %%s(r2) USING '%s'", 
StorageAttachedIndex.class.getName()));
-        waitForIndexQueryable();
 
         // without using the not-SAI index
         testAllowFiltering("SELECT * FROM %s", false);
diff --git 
a/test/unit/org/apache/cassandra/index/sai/cql/MultipleColumnIndexTest.java 
b/test/unit/org/apache/cassandra/index/sai/cql/MultipleColumnIndexTest.java
index c29b909c8c..97f93e29aa 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/MultipleColumnIndexTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/MultipleColumnIndexTest.java
@@ -46,8 +46,6 @@ public class MultipleColumnIndexTest extends SAITester
         createIndex("CREATE CUSTOM INDEX ON %s(values(text_map)) USING 
'StorageAttachedIndex'");
         createIndex("CREATE CUSTOM INDEX ON %s(entries(text_map)) USING 
'StorageAttachedIndex'");
 
-        waitForIndexQueryable();
-
         execute("INSERT INTO %s(id, text_map) values (1, {'k1':'v1', 
'k2':'v2'})");
         execute("INSERT INTO %s(id, text_map) values (2, {'k1':'v1', 
'k3':'v3'})");
         execute("INSERT INTO %s(id, text_map) values (3, {'k4':'v4', 
'k5':'v5'})");
diff --git 
a/test/unit/org/apache/cassandra/index/sai/cql/SingleNodeExecutor.java 
b/test/unit/org/apache/cassandra/index/sai/cql/SingleNodeExecutor.java
index 54f96bc6d8..1e86eb4c15 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/SingleNodeExecutor.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/SingleNodeExecutor.java
@@ -43,9 +43,9 @@ public class SingleNodeExecutor implements 
BaseDataModel.Executor
     }
 
     @Override
-    public void waitForIndexQueryable(String keyspace, String table)
+    public void waitForIndexQueryable(String keyspace, String index)
     {
-        tester.waitForIndexQueryable(keyspace, table);
+        tester.waitForIndexQueryable(keyspace, index);
     }
 
     @Override
diff --git 
a/test/unit/org/apache/cassandra/index/sai/cql/StorageAttachedIndexDDLTest.java 
b/test/unit/org/apache/cassandra/index/sai/cql/StorageAttachedIndexDDLTest.java
index a828592374..52d364c210 100644
--- 
a/test/unit/org/apache/cassandra/index/sai/cql/StorageAttachedIndexDDLTest.java
+++ 
b/test/unit/org/apache/cassandra/index/sai/cql/StorageAttachedIndexDDLTest.java
@@ -70,6 +70,7 @@ import org.apache.cassandra.schema.IndexMetadata;
 import org.apache.cassandra.schema.SchemaConstants;
 import org.apache.cassandra.schema.TableMetadata;
 import org.apache.cassandra.utils.Throwables;
+import org.assertj.core.api.Assertions;
 import org.mockito.Mockito;
 
 import static java.util.Collections.singletonList;
@@ -257,7 +258,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
 
         createIndex("CREATE CUSTOM INDEX IF NOT EXISTS ON %s(val) USING 
'StorageAttachedIndex' ");
 
-        createIndex("CREATE CUSTOM INDEX IF NOT EXISTS ON %s(val) USING 
'StorageAttachedIndex' ");
+        createIndexAsync("CREATE CUSTOM INDEX IF NOT EXISTS ON %s(val) USING 
'StorageAttachedIndex' ");
 
         assertEquals(1, saiCreationCounter.get());
     }
@@ -334,7 +335,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
         flush();
 
         executeNet("CREATE CUSTOM INDEX index_1 ON %s(v1) USING 
'StorageAttachedIndex'");
-        waitForIndexQueryable();
+        waitForTableIndexesQueryable();
 
         // same name
         assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX index_1 ON 
%s(v1) USING 'StorageAttachedIndex'"))
@@ -365,7 +366,6 @@ public class StorageAttachedIndexDDLTest extends SAITester
             execute("INSERT INTO %s (id1, v1) VALUES ('" + i + "', '0')");
 
         createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
-        waitForIndexQueryable();
 
         ResultSet rows = executeNet("SELECT id1 FROM %s WHERE v1='0'");
         assertEquals(rowCount, rows.all().size());
@@ -384,7 +384,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
 
         // Create the index, but do not allow the initial index build to begin:
         Injections.inject(delayInitializationTask);
-        createIndex("CREATE CUSTOM INDEX ON %s(val) USING 
'StorageAttachedIndex'");
+        createIndexAsync("CREATE CUSTOM INDEX ON %s(val) USING 
'StorageAttachedIndex'");
 
         // Flush the Memtable's contents, which will feed data to the index as 
the SSTable is written:
         flush();
@@ -392,7 +392,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
         // Allow the initialization task, which builds the index, to continue:
         delayInitializationTask.countDown();
 
-        waitForIndexQueryable();
+        waitForTableIndexesQueryable();
 
         ResultSet rows = executeNet("SELECT id FROM %s WHERE val = 'Camel'");
         assertEquals(1, rows.all().size());
@@ -410,7 +410,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
             execute("INSERT INTO %s (id1, v1) VALUES ('" + i + "', '0')");
 
         Injections.inject(forceFlushPause);
-        createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
+        createIndexAsync(String.format(CREATE_INDEX_TEMPLATE, "v1"));
 
         assertThatThrownBy(() -> executeNet("SELECT id1 FROM %s WHERE 
v1='0'")).isInstanceOf(ReadFailureException.class);
     }
@@ -427,7 +427,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
         flush();
 
         Injections.inject(failSAIInitialializaion);
-        createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
+        createIndexAsync(String.format(CREATE_INDEX_TEMPLATE, "v1"));
         waitForAssert(() -> assertEquals(1, indexBuildCounter.get()));
         waitForCompactions();
 
@@ -478,7 +478,6 @@ public class StorageAttachedIndexDDLTest extends SAITester
         verifyNoIndexFiles();
 
         IndexContext literalIndexContext = 
createIndexContext(createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1")), 
UTF8Type.instance);
-        waitForIndexQueryable();
         verifyIndexFiles(literalIndexContext, 2);
         ResultSet rows = executeNet("SELECT id1 FROM %s WHERE v1='0'");
         assertEquals(2, rows.all().size());
@@ -501,7 +500,6 @@ public class StorageAttachedIndexDDLTest extends SAITester
         verifyNoIndexFiles();
 
         IndexContext literalIndexContext = 
createIndexContext(createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1")), 
UTF8Type.instance);
-        waitForIndexQueryable();
         verifyIndexFiles(literalIndexContext, 2);
         ResultSet rows = executeNet("SELECT id1 FROM %s WHERE v1='0'");
         assertEquals(2, rows.all().size());
@@ -571,9 +569,9 @@ public class StorageAttachedIndexDDLTest extends SAITester
 
         if (concurrentTruncate)
         {
-            createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
+            createIndexAsync(String.format(CREATE_INDEX_TEMPLATE, "v1"));
             truncate(true);
-            waitForIndexQueryable();
+            waitForTableIndexesQueryable();
         }
         else
         {
@@ -721,7 +719,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
         try
         {
             // Create a new index, which will actuate a build compaction and 
fail, but leave the node running...
-            IndexContext literalIndexContext = 
createIndexContext(createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1")), 
UTF8Type.instance);
+            IndexContext literalIndexContext = 
createIndexContext(createIndexAsync(String.format(CREATE_INDEX_TEMPLATE, 
"v1")), UTF8Type.instance);
             // two index builders running in different compaction threads 
because of parallelised index initial build
             waitForAssert(() -> assertEquals(2, indexBuildCounter.get()));
             waitForCompactionsFinished();
@@ -729,7 +727,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
             // Only token/primary key files for the first SSTable in the 
compaction task should exist, while column-specific files are blown away:
             verifyIndexFiles(literalIndexContext, 2, 0, 0);
 
-            assertFalse(isIndexQueryable());
+            Assertions.assertThat(getNotQueryableIndexes()).isNotEmpty();
 
             assertZeroSegmentBuilderUsage();
         }
@@ -757,7 +755,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
         try
         {
             // Create a new index, which will actuate a build compaction and 
fail, but leave the node running...
-            createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
+            createIndexAsync(String.format(CREATE_INDEX_TEMPLATE, "v1"));
             // two index builders running in different compaction threads 
because of parallelised index initial build
             waitForAssert(() -> assertEquals(2, indexBuildCounter.get()));
             waitForAssert(() -> assertEquals(0, getCompactionTasks()));
@@ -765,7 +763,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
             // SSTable-level token/offset file(s) should be removed, while 
column-specific files never existed:
             verifyNoIndexFiles();
 
-            assertFalse(isIndexQueryable());
+            Assertions.assertThat(getNotQueryableIndexes()).isNotEmpty();
 
             assertZeroSegmentBuilderUsage();
         }
@@ -857,7 +855,6 @@ public class StorageAttachedIndexDDLTest extends SAITester
 
 
         IndexContext literalIndexContext = 
createIndexContext(createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1")), 
UTF8Type.instance);
-        waitForIndexQueryable();
 
         populateData.run();
         
verifySSTableIndexes(IndexMetadata.generateDefaultIndexName(currentTable(), 
V1_COLUMN_IDENTIFIER), 2, 0);
@@ -895,7 +892,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
                                                                    .build();
 
         Injections.inject(delayIndexBuilderCompletion);
-        String indexName = createIndex(String.format(CREATE_INDEX_TEMPLATE, 
"v1"));
+        String indexName = 
createIndexAsync(String.format(CREATE_INDEX_TEMPLATE, "v1"));
         waitForAssert(() -> assertEquals(1, 
delayIndexBuilderCompletion.getCount()));
 
         dropIndex("DROP INDEX %s." + indexName);
@@ -911,7 +908,6 @@ public class StorageAttachedIndexDDLTest extends SAITester
 
         // create index again, it should succeed
         indexName = createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
-        waitForIndexQueryable();
         verifySSTableIndexes(indexName, 1);
 
         ResultSet rows = executeNet("SELECT id1 FROM %s WHERE v1='0'");
@@ -940,7 +936,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
 
         Injections.inject(delayIndexBuilderCompletion);
 
-        IndexContext literalIndexContext = 
createIndexContext(createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1")), 
UTF8Type.instance);
+        IndexContext literalIndexContext = 
createIndexContext(createIndexAsync(String.format(CREATE_INDEX_TEMPLATE, 
"v1")), UTF8Type.instance);
 
         waitForAssert(() -> assertTrue(getCompactionTasks() > 0), 1000, 
TimeUnit.MILLISECONDS);
 
@@ -963,7 +959,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
 
         // initial index builder should have stopped abruptly resulting in the 
index not being queryable
         verifyInitialIndexFailed(literalIndexContext.getIndexName());
-        assertFalse(isIndexQueryable());
+        Assertions.assertThat(getNotQueryableIndexes()).isNotEmpty();
 
         ColumnFamilyStore cfs = 
Keyspace.open(KEYSPACE).getColumnFamilyStore(currentTable());
         for (Index i : cfs.indexManager.listIndexes())
diff --git 
a/test/unit/org/apache/cassandra/index/sai/cql/types/IndexingTypeSupport.java 
b/test/unit/org/apache/cassandra/index/sai/cql/types/IndexingTypeSupport.java
index 267d37c1c5..15acbdaa8d 100644
--- 
a/test/unit/org/apache/cassandra/index/sai/cql/types/IndexingTypeSupport.java
+++ 
b/test/unit/org/apache/cassandra/index/sai/cql/types/IndexingTypeSupport.java
@@ -97,7 +97,6 @@ public abstract class IndexingTypeSupport extends SAITester
         {
             for (String index : dataset.decorateIndexColumn("value"))
                 createIndex(String.format("CREATE CUSTOM INDEX ON %%s(%s) 
USING 'StorageAttachedIndex'", index));
-            waitForIndexQueryable();
         }
 
         insertData(this, allRows, scenario);
@@ -115,7 +114,6 @@ public abstract class IndexingTypeSupport extends SAITester
                 flush();
                 for (String index : dataset.decorateIndexColumn("value"))
                     createIndex(String.format("CREATE CUSTOM INDEX ON %%s(%s) 
USING 'StorageAttachedIndex'", index));
-                waitForIndexQueryable();
                 break;
         }
 
diff --git a/test/unit/org/apache/cassandra/index/sai/disk/NodeStartupTest.java 
b/test/unit/org/apache/cassandra/index/sai/disk/NodeStartupTest.java
index 8b3b768e5e..6855b0eb92 100644
--- a/test/unit/org/apache/cassandra/index/sai/disk/NodeStartupTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/disk/NodeStartupTest.java
@@ -47,6 +47,7 @@ import org.apache.cassandra.inject.Injection;
 import org.apache.cassandra.inject.Injections;
 import org.apache.cassandra.inject.InvokePointBuilder;
 import org.apache.cassandra.schema.Schema;
+import org.assertj.core.api.Assertions;
 
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -241,7 +242,7 @@ public class NodeStartupTest extends SAITester
     {
         populator.populate(this);
 
-        assertTrue(isIndexQueryable());
+        Assertions.assertThat(getNotQueryableIndexes()).isEmpty();
         assertTrue(isGroupIndexComplete());
         assertTrue(isColumnIndexComplete());
         Assert.assertEquals(expectedDocuments, execute("SELECT * FROM %s WHERE 
v1 = '0'").size());
@@ -252,7 +253,7 @@ public class NodeStartupTest extends SAITester
 
         simulateNodeRestart();
 
-        assertTrue(isIndexQueryable());
+        Assertions.assertThat(getNotQueryableIndexes()).isEmpty();
         assertTrue(isGroupIndexComplete());
         assertTrue(isColumnIndexComplete());
         Assert.assertEquals(expectedDocuments, execute("SELECT * FROM %s WHERE 
v1 = '0'").size());
diff --git 
a/test/unit/org/apache/cassandra/index/sai/disk/SelectiveIntersectionTest.java 
b/test/unit/org/apache/cassandra/index/sai/disk/SelectiveIntersectionTest.java
index 349a24b98c..51c7637754 100644
--- 
a/test/unit/org/apache/cassandra/index/sai/disk/SelectiveIntersectionTest.java
+++ 
b/test/unit/org/apache/cassandra/index/sai/disk/SelectiveIntersectionTest.java
@@ -63,8 +63,6 @@ public class SelectiveIntersectionTest extends SAITester
         createIndex(String.format(CREATE_INDEX_TEMPLATE, "v2"));
         createIndex(String.format(CREATE_INDEX_TEMPLATE, "v3"));
 
-        waitForIndexQueryable();
-
         for (int i = 0; i < 100; ++i)
         {
             execute("INSERT INTO %s(pk,v1,v2,v3) VALUES (?, ?, ?, ?)", i, 
Integer.toString(i), Integer.toString(i / 20), Integer.toString(i % 10));
diff --git 
a/test/unit/org/apache/cassandra/index/sai/disk/SingleNodeQueryFailureTest.java 
b/test/unit/org/apache/cassandra/index/sai/disk/SingleNodeQueryFailureTest.java
index a208aa9770..e49a9fe249 100644
--- 
a/test/unit/org/apache/cassandra/index/sai/disk/SingleNodeQueryFailureTest.java
+++ 
b/test/unit/org/apache/cassandra/index/sai/disk/SingleNodeQueryFailureTest.java
@@ -73,7 +73,6 @@ public class SingleNodeQueryFailureTest extends SAITester
 
         createTable(CREATE_TABLE_TEMPLATE);
         createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
-        waitForIndexQueryable();
 
         execute("INSERT INTO %s (id, v1) VALUES ('1', '0')");
         flush();
diff --git 
a/test/unit/org/apache/cassandra/index/sai/functional/CompactionTest.java 
b/test/unit/org/apache/cassandra/index/sai/functional/CompactionTest.java
index 82f0c512a0..dfb22ac74a 100644
--- a/test/unit/org/apache/cassandra/index/sai/functional/CompactionTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/functional/CompactionTest.java
@@ -121,7 +121,6 @@ public class CompactionTest extends SAITester
     {
         createTable(CREATE_TABLE_TEMPLATE);
         String v1IndexName = createIndex(String.format(CREATE_INDEX_TEMPLATE, 
"v1"));
-        waitForIndexQueryable();
 
         int num = 10;
         for (int i = 0; i < num; i++)
@@ -249,7 +248,6 @@ public class CompactionTest extends SAITester
 
                             // build indexes on SSTables that will be 
compacted soon
                             createIndex(String.format(CREATE_INDEX_TEMPLATE, 
"v1"));
-                            waitForIndexQueryable();
 
                             // continue in-progress compaction
                             compactionLatch.countDown();
diff --git 
a/test/unit/org/apache/cassandra/index/sai/functional/DiskSpaceTest.java 
b/test/unit/org/apache/cassandra/index/sai/functional/DiskSpaceTest.java
index 254f4179a7..152d472b00 100644
--- a/test/unit/org/apache/cassandra/index/sai/functional/DiskSpaceTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/functional/DiskSpaceTest.java
@@ -41,7 +41,6 @@ public class DiskSpaceTest extends SAITester
 
         // create index, disk space should include index components
         String indexName = createIndex(String.format(CREATE_INDEX_TEMPLATE, 
"v1"));
-        waitForIndexQueryable();
 
         long indexSize = indexDiskSpaceUse();
         long sstableSizeWithIndex = totalDiskSpaceUsed();
diff --git 
a/test/unit/org/apache/cassandra/index/sai/functional/DropTableTest.java 
b/test/unit/org/apache/cassandra/index/sai/functional/DropTableTest.java
index ae8c7670e6..191525e171 100644
--- a/test/unit/org/apache/cassandra/index/sai/functional/DropTableTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/functional/DropTableTest.java
@@ -50,7 +50,6 @@ public class DropTableTest extends SAITester
     {
         createTable(CREATE_TABLE_TEMPLATE);
         createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
-        waitForIndexQueryable();
 
         int rows = 100;
         for (int j = 0; j < rows; j++)
diff --git 
a/test/unit/org/apache/cassandra/index/sai/functional/FailureTest.java 
b/test/unit/org/apache/cassandra/index/sai/functional/FailureTest.java
index 3650e28621..893e304e65 100644
--- a/test/unit/org/apache/cassandra/index/sai/functional/FailureTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/functional/FailureTest.java
@@ -110,7 +110,7 @@ public class FailureTest extends SAITester
         Injection ssTableContextCreationFailure = 
newFailureOnEntry("context_failure_on_creation", SSTableContext.class, 
"<init>", RuntimeException.class);
         Injections.inject(ssTableContextCreationFailure);
 
-        String v1IndexName = createIndex(String.format(CREATE_INDEX_TEMPLATE, 
"v1"));
+        String v1IndexName = 
createIndexAsync(String.format(CREATE_INDEX_TEMPLATE, "v1"));
 
         // Verify that the initial index build fails...
         verifyInitialIndexFailed(v1IndexName);
diff --git 
a/test/unit/org/apache/cassandra/index/sai/functional/GroupComponentsTest.java 
b/test/unit/org/apache/cassandra/index/sai/functional/GroupComponentsTest.java
index a6d426e05e..b8049b7d0f 100644
--- 
a/test/unit/org/apache/cassandra/index/sai/functional/GroupComponentsTest.java
+++ 
b/test/unit/org/apache/cassandra/index/sai/functional/GroupComponentsTest.java
@@ -46,7 +46,6 @@ public class GroupComponentsTest extends SAITester
     {
         createTable("CREATE TABLE %s (pk int primary key, value text)");
         createIndex("CREATE CUSTOM INDEX ON %s(value) USING 
'StorageAttachedIndex'");
-        waitForIndexQueryable();
         execute("INSERT INTO %s (pk) VALUES (1)");
         flush();
 
@@ -72,7 +71,6 @@ public class GroupComponentsTest extends SAITester
     {
         createTable("CREATE TABLE %s (pk int primary key, value text)");
         createIndex("CREATE CUSTOM INDEX ON %s(value) USING 
'StorageAttachedIndex'");
-        waitForIndexQueryable();
         execute("INSERT INTO %s (pk) VALUES (1)");
         flush();
 
@@ -94,7 +92,6 @@ public class GroupComponentsTest extends SAITester
     {
         createTable("CREATE TABLE %s (pk int primary key, value text)");
         IndexContext indexContext = createIndexContext(createIndex("CREATE 
CUSTOM INDEX ON %s(value) USING 'StorageAttachedIndex'"), UTF8Type.instance);
-        waitForIndexQueryable();
         execute("INSERT INTO %s (pk, value) VALUES (1, '1')");
         flush();
 
diff --git 
a/test/unit/org/apache/cassandra/index/sai/functional/NodeRestartTest.java 
b/test/unit/org/apache/cassandra/index/sai/functional/NodeRestartTest.java
index 76461238fc..1766b69768 100644
--- a/test/unit/org/apache/cassandra/index/sai/functional/NodeRestartTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/functional/NodeRestartTest.java
@@ -30,8 +30,7 @@ import org.apache.cassandra.index.sai.StorageAttachedIndex;
 import org.apache.cassandra.inject.Injection;
 import org.apache.cassandra.inject.Injections;
 import org.apache.cassandra.inject.InvokePointBuilder;
-
-import static org.junit.Assert.assertFalse;
+import org.assertj.core.api.Assertions;
 
 public class NodeRestartTest extends SAITester
 {
@@ -65,7 +64,7 @@ public class NodeRestartTest extends SAITester
         // We should have completed no actual SSTable validations:
         assertValidationCount(0, 0);
 
-        assertFalse(isIndexQueryable());
+        Assertions.assertThat(getNotQueryableIndexes()).isNotEmpty();
     }
 
     // We don't allow the node to actually join the ring before a valid index 
is ready to accept queries.
@@ -113,7 +112,6 @@ public class NodeRestartTest extends SAITester
         flush();
 
         IndexContext literalIndexContext = 
createIndexContext(createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1")), 
UTF8Type.instance);
-        waitForIndexQueryable();
         verifyIndexFiles(literalIndexContext, 1);
         assertNumRows(1, "SELECT * FROM %%s WHERE v1 = '0'");
         assertValidationCount(0, 0);
@@ -124,7 +122,7 @@ public class NodeRestartTest extends SAITester
 
         assertNumRows(1, "SELECT * FROM %%s WHERE v1 = '0'");
 
-        waitForIndexQueryable();
+        waitForTableIndexesQueryable();
 
         // index components are included after restart
         verifyIndexComponentsIncludedInSSTable();
@@ -172,7 +170,6 @@ public class NodeRestartTest extends SAITester
         flush();
 
         IndexContext literalIndexContext = 
createIndexContext(createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1")), 
UTF8Type.instance);
-        waitForIndexQueryable();
         verifyIndexFiles(literalIndexContext, 1);
         assertNumRows(1, "SELECT * FROM %%s WHERE v1 = '0'");
         assertValidationCount(0, 0);
diff --git 
a/test/unit/org/apache/cassandra/index/sai/functional/SnapshotTest.java 
b/test/unit/org/apache/cassandra/index/sai/functional/SnapshotTest.java
index f0c78986bc..769435d309 100644
--- a/test/unit/org/apache/cassandra/index/sai/functional/SnapshotTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/functional/SnapshotTest.java
@@ -52,7 +52,6 @@ public class SnapshotTest extends SAITester
         // Insert some initial data and create the index over it
         execute("INSERT INTO %s (id1, v1) VALUES ('0', '0');");
         IndexContext literalIndexContext = 
createIndexContext(createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1")), 
UTF8Type.instance);
-        waitForIndexQueryable();
         flush();
         verifyIndexFiles(literalIndexContext, 1, 1, 1);
         // Note: This test will fail here if it is run on its own because the 
per-index validation
@@ -130,7 +129,6 @@ public class SnapshotTest extends SAITester
 
         // create index
         IndexContext literalIndexContext = 
createIndexContext(createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1")), 
UTF8Type.instance);
-        waitForIndexQueryable();
         verifyIndexFiles(literalIndexContext, 2);
         assertValidationCount(0, 0);
 
diff --git 
a/test/unit/org/apache/cassandra/index/sai/metrics/QueryMetricsTest.java 
b/test/unit/org/apache/cassandra/index/sai/metrics/QueryMetricsTest.java
index ade72d9f18..14931b173b 100644
--- a/test/unit/org/apache/cassandra/index/sai/metrics/QueryMetricsTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/metrics/QueryMetricsTest.java
@@ -83,7 +83,6 @@ public class QueryMetricsTest extends AbstractMetricsTest
 
         createTable(String.format(CREATE_TABLE_TEMPLATE, keyspace, table));
         createIndex(String.format(CREATE_INDEX_TEMPLATE, index, keyspace, 
table, "v1"));
-        waitForIndexQueryable(keyspace, table);
 
         execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) 
VALUES ('0', 0, '0')");
 
diff --git 
a/test/unit/org/apache/cassandra/index/sai/metrics/SegmentFlushingFailureTester.java
 
b/test/unit/org/apache/cassandra/index/sai/metrics/SegmentFlushingFailureTester.java
index 98ae5a4d3e..6bc6c996fa 100644
--- 
a/test/unit/org/apache/cassandra/index/sai/metrics/SegmentFlushingFailureTester.java
+++ 
b/test/unit/org/apache/cassandra/index/sai/metrics/SegmentFlushingFailureTester.java
@@ -169,7 +169,6 @@ public abstract class SegmentFlushingFailureTester extends 
SAITester
         createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
         String table2 = createTable(CREATE_TABLE_TEMPLATE);
         createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1"));
-        waitForIndexQueryable();
 
         assertEquals(expectedBytesLimit(), getSegmentBufferSpaceLimit());
         assertEquals("Segment buffer memory tracker should start at zero!", 
0L, getSegmentBufferUsedBytes());
diff --git 
a/test/unit/org/apache/cassandra/index/sai/metrics/StateMetricsTest.java 
b/test/unit/org/apache/cassandra/index/sai/metrics/StateMetricsTest.java
index fc5e41bce6..e6ecda02fb 100644
--- a/test/unit/org/apache/cassandra/index/sai/metrics/StateMetricsTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/metrics/StateMetricsTest.java
@@ -48,7 +48,6 @@ public class StateMetricsTest extends AbstractMetricsTest
 
         createTable(String.format(CREATE_TABLE_TEMPLATE, keyspace, table));
         createIndex(String.format(CREATE_INDEX_TEMPLATE, index, keyspace, 
table, "v1"));
-        waitForIndexQueryable(keyspace, table);
 
         execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) 
VALUES ('0', 0, '0')");
 
@@ -73,9 +72,8 @@ public class StateMetricsTest extends AbstractMetricsTest
 
         String keyspace = createKeyspace(CREATE_KEYSPACE_TEMPLATE);
         createTable(String.format(CREATE_TABLE_TEMPLATE, keyspace, table));
-        createIndex(String.format(CREATE_INDEX_TEMPLATE, index+"_v1", 
keyspace, table, "v1"));
-        createIndex(String.format(CREATE_INDEX_TEMPLATE, index+"_v2", 
keyspace, table, "v2"));
-        waitForIndexQueryable(keyspace, table);
+        createIndex(String.format(CREATE_INDEX_TEMPLATE, index + "_v1", 
keyspace, table, "v1"));
+        createIndex(String.format(CREATE_INDEX_TEMPLATE, index + "_v2", 
keyspace, table, "v2"));
 
         execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) 
VALUES ('0', 0, '0')");
         execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) 
VALUES ('1', 1, '1')");
diff --git a/test/unit/org/apache/cassandra/index/sai/plan/OperationTest.java 
b/test/unit/org/apache/cassandra/index/sai/plan/OperationTest.java
index f957ddd3f2..10ed7f5035 100644
--- a/test/unit/org/apache/cassandra/index/sai/plan/OperationTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/plan/OperationTest.java
@@ -78,7 +78,7 @@ public class OperationTest
     private static final String KS_NAME = "sai";
     private static final String CF_NAME = "test_cf";
     private static final String CLUSTERING_CF_NAME = "clustering_test_cf";
-    private static final String STATIC_CF_NAME = "static_ndi_test_cf";
+    private static final String STATIC_CF_NAME = "static_sai_test_cf";
 
     private static ColumnFamilyStore BACKEND;
     private static ColumnFamilyStore CLUSTERING_BACKEND;
diff --git 
a/test/unit/org/apache/cassandra/index/sai/virtual/IndexesSystemViewTest.java 
b/test/unit/org/apache/cassandra/index/sai/virtual/IndexesSystemViewTest.java
index aabbb13078..a8f5bf9a58 100644
--- 
a/test/unit/org/apache/cassandra/index/sai/virtual/IndexesSystemViewTest.java
+++ 
b/test/unit/org/apache/cassandra/index/sai/virtual/IndexesSystemViewTest.java
@@ -73,14 +73,14 @@ public class IndexesSystemViewTest extends SAITester
 
         // create the index simulating a long build and verify that there is 
an empty record in the virtual table
         Injections.inject(blockIndexBuild);
-        String v1IndexName = createIndex(String.format("CREATE CUSTOM INDEX ON 
%%s(v1) USING '%s'", StorageAttachedIndex.class.getName()));
+        String v1IndexName = createIndexAsync(String.format("CREATE CUSTOM 
INDEX ON %%s(v1) USING '%s'", StorageAttachedIndex.class.getName()));
 
         assertRows(execute(SELECT), row(v1IndexName, "v1", false, true, true));
 
         // unblock the long build and verify that there is a finished empty 
record in the virtual table
         blockIndexBuild.countDown();
         blockIndexBuild.disable();
-        waitForIndexQueryable();
+        waitForTableIndexesQueryable();
         assertRows(execute(SELECT), row(v1IndexName, "v1", true, false, true));
 
         // insert some data and verify that virtual table record is still 
empty since we haven't flushed yet
diff --git 
a/test/unit/org/apache/cassandra/index/sai/virtual/SSTablesSystemViewTest.java 
b/test/unit/org/apache/cassandra/index/sai/virtual/SSTablesSystemViewTest.java
index f35de185bd..eebcdf6561 100644
--- 
a/test/unit/org/apache/cassandra/index/sai/virtual/SSTablesSystemViewTest.java
+++ 
b/test/unit/org/apache/cassandra/index/sai/virtual/SSTablesSystemViewTest.java
@@ -74,7 +74,6 @@ public class SSTablesSystemViewTest extends SAITester
     {
         createTable("CREATE TABLE %s (k text, c text, v1 text, v2 text, 
PRIMARY KEY (k, c))");
         String v1IndexName = createIndex("CREATE CUSTOM INDEX ON %s(v1) USING 
'StorageAttachedIndex'");
-        waitForIndexQueryable();
 
         String insert = "INSERT INTO %s(k, c, v1, v2) VALUES (?, ?, ?, ?)";
 
@@ -101,7 +100,6 @@ public class SSTablesSystemViewTest extends SAITester
 
         // create a second index, this should create a new additional entry in 
the table for each sstable
         String v2IndexName = createIndex("CREATE CUSTOM INDEX ON %s(v2) USING 
'StorageAttachedIndex'");
-        waitForIndexQueryable();
         Object[] row3 = readRow(v2IndexName, id1, "v2", 1L, 0L, 0L);
         Object[] row4 = readRow(v2IndexName, id2, "v2", 2L, 0L, 1L);
         assertRowsIgnoringOrder(execute(SELECT), row1, row2, row3, row4);
diff --git 
a/test/unit/org/apache/cassandra/index/sai/virtual/SegmentsSystemViewTest.java 
b/test/unit/org/apache/cassandra/index/sai/virtual/SegmentsSystemViewTest.java
index fd6046ee49..f37dcf86f0 100644
--- 
a/test/unit/org/apache/cassandra/index/sai/virtual/SegmentsSystemViewTest.java
+++ 
b/test/unit/org/apache/cassandra/index/sai/virtual/SegmentsSystemViewTest.java
@@ -92,7 +92,6 @@ public class SegmentsSystemViewTest extends SAITester
     {
         createTable("CREATE TABLE %s (k int, c int, v1 text, PRIMARY KEY (k, 
c))");
         String literalIndex = createIndex("CREATE CUSTOM INDEX ON %s(v1) USING 
'StorageAttachedIndex'");
-        waitForIndexQueryable();
 
         int num = 100;
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to