You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by cg...@apache.org on 2023/02/15 04:06:13 UTC

[drill] branch master updated: DRILL-8117: Upgrade unit tests to the cluster fixture framework (#2756)

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

cgivre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/drill.git


The following commit(s) were added to refs/heads/master by this push:
     new 95c9beabc8 DRILL-8117: Upgrade unit tests to the cluster fixture framework (#2756)
95c9beabc8 is described below

commit 95c9beabc8094dd0ad5f73f3f7be377388140c60
Author: James Turton <91...@users.noreply.github.com>
AuthorDate: Wed Feb 15 06:06:06 2023 +0200

    DRILL-8117: Upgrade unit tests to the cluster fixture framework (#2756)
    
    
    ---------
    
    Co-authored-by: kingswanwho <ji...@u.northwestern.edu>
    Co-authored-by: kingswanwho <ch...@gmail.com>
---
 .github/workflows/ci.yml                           |   2 +-
 common/pom.xml                                     |   5 +
 .../org/apache/drill/common/PlanStringBuilder.java |   2 +-
 .../apache/drill/common/config/DrillConfig.java    |   2 +-
 .../apache/drill/common/util/DrillStringUtils.java |   2 +-
 .../common/util/function/TestCheckedFunction.java  |  15 +-
 .../test/java/org/apache/drill/test/DrillTest.java |   8 -
 .../apache/drill/test/UserExceptionMatcher.java    |  71 ----
 .../drill/exec/store/log/TestLogReaderIssue.java   |  16 +-
 .../exec/TestHiveDrillNativeParquetReader.java     |   3 +-
 .../hive/BaseTestHiveImpersonation.java            |  39 +-
 .../hive/TestSqlStdBasedAuthorization.java         | 205 +++++++----
 .../hive/TestStorageBasedHiveAuthorization.java    | 399 ++++++++++++---------
 .../drill/exec/store/splunk/SplunkWriterTest.java  |   2 +
 .../org/apache/drill/exec/TestWindowFunctions.java | 336 ++++++++++++-----
 .../drill/exec/client/DrillClientStateTest.java    |  19 +-
 .../exec/impersonation/BaseTestImpersonation.java  |  64 ++--
 .../TestImpersonationDisabledWithMiniDFS.java      |  10 +-
 .../impersonation/TestImpersonationMetadata.java   | 360 ++++++++++---------
 .../impersonation/TestImpersonationQueries.java    | 131 ++++---
 .../impersonation/TestInboundImpersonation.java    | 224 ++++++------
 .../drill/exec/planner/sql/CrossJoinTest.java      |  69 ++--
 .../org/apache/drill/exec/server/TestOptions.java  |  76 ++--
 .../java/org/apache/drill/test/ClientFixture.java  |   7 +-
 .../java/org/apache/drill/test/ClusterFixture.java |  15 +
 .../java/org/apache/drill/test/QueryBuilder.java   |  85 ++++-
 pom.xml                                            |   4 +-
 27 files changed, 1299 insertions(+), 872 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 265f87985f..e83615ec90 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,7 +29,7 @@ jobs:
   build:
     name: Main Build
     runs-on: ubuntu-latest
-    timeout-minutes: 120
+    timeout-minutes: 150
     strategy:
       matrix:
         # Java versions to run unit tests
diff --git a/common/pom.xml b/common/pom.xml
index 2fc89d3c9d..7590bc0f64 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -47,6 +47,11 @@
       <artifactId>commons-lang3</artifactId>
     </dependency>
 
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-text</artifactId>
+    </dependency>
+
     <dependency>
       <groupId>org.msgpack</groupId>
       <artifactId>msgpack</artifactId>
diff --git a/common/src/main/java/org/apache/drill/common/PlanStringBuilder.java b/common/src/main/java/org/apache/drill/common/PlanStringBuilder.java
index c4f58fddf5..5b5e2baaa3 100644
--- a/common/src/main/java/org/apache/drill/common/PlanStringBuilder.java
+++ b/common/src/main/java/org/apache/drill/common/PlanStringBuilder.java
@@ -17,7 +17,7 @@
  */
 package org.apache.drill.common;
 
-import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.text.StringEscapeUtils;
 
 /**
  * Builds a string in Drill's "plan string" format: that shown in the
diff --git a/common/src/main/java/org/apache/drill/common/config/DrillConfig.java b/common/src/main/java/org/apache/drill/common/config/DrillConfig.java
index 71a0697596..e9e8f70b38 100644
--- a/common/src/main/java/org/apache/drill/common/config/DrillConfig.java
+++ b/common/src/main/java/org/apache/drill/common/config/DrillConfig.java
@@ -317,7 +317,7 @@ public class DrillConfig extends NestedConfig {
   public <T> T getInstanceOf(String location, Class<T> clazz) throws DrillConfigurationException{
     final Class<T> c = getClassAt(location, clazz);
     try {
-      return c.newInstance();
+      return c.getDeclaredConstructor().newInstance();
     } catch (Exception ex) {
       throw new DrillConfigurationException(String.format("Failure while instantiating class [%s] located at '%s.", clazz.getCanonicalName(), location), ex);
     }
diff --git a/common/src/main/java/org/apache/drill/common/util/DrillStringUtils.java b/common/src/main/java/org/apache/drill/common/util/DrillStringUtils.java
index de65ff862c..9bf3ad3988 100644
--- a/common/src/main/java/org/apache/drill/common/util/DrillStringUtils.java
+++ b/common/src/main/java/org/apache/drill/common/util/DrillStringUtils.java
@@ -19,7 +19,7 @@ package org.apache.drill.common.util;
 
 import io.netty.buffer.ByteBuf;
 
-import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.text.StringEscapeUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import java.util.Arrays;
diff --git a/common/src/test/java/org/apache/drill/common/util/function/TestCheckedFunction.java b/common/src/test/java/org/apache/drill/common/util/function/TestCheckedFunction.java
index 0ded4ce086..62f3ab7740 100644
--- a/common/src/test/java/org/apache/drill/common/util/function/TestCheckedFunction.java
+++ b/common/src/test/java/org/apache/drill/common/util/function/TestCheckedFunction.java
@@ -18,17 +18,16 @@
 package org.apache.drill.common.util.function;
 
 import org.apache.drill.test.BaseTest;
-import org.junit.Rule;
+import org.hamcrest.MatcherAssert;
+import org.junit.Assert;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
 import java.util.HashMap;
 import java.util.Map;
 
-public class TestCheckedFunction extends BaseTest {
+import static org.hamcrest.CoreMatchers.containsString;
 
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
+public class TestCheckedFunction extends BaseTest {
 
   @Test
   public void testComputeIfAbsentWithCheckedFunction() {
@@ -37,10 +36,8 @@ public class TestCheckedFunction extends BaseTest {
     String message = "Exception message";
     CheckedFunction<String, String, Exception> function = producer::failWithMessage;
 
-    thrown.expect(Exception.class);
-    thrown.expectMessage(message);
-
-    map.computeIfAbsent(message, function);
+    Exception exception = Assert.assertThrows(Exception.class, () -> map.computeIfAbsent(message, function));
+    MatcherAssert.assertThat(exception.getMessage(), containsString(message));
   }
 
   private class ExceptionProducer {
diff --git a/common/src/test/java/org/apache/drill/test/DrillTest.java b/common/src/test/java/org/apache/drill/test/DrillTest.java
index 43015a26bc..f009d2a5f0 100644
--- a/common/src/test/java/org/apache/drill/test/DrillTest.java
+++ b/common/src/test/java/org/apache/drill/test/DrillTest.java
@@ -27,7 +27,6 @@ import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.rules.DisableOnDebug;
-import org.junit.rules.ExpectedException;
 import org.junit.rules.TestRule;
 import org.junit.rules.TestWatcher;
 import org.junit.runner.Description;
@@ -58,13 +57,6 @@ public class DrillTest extends BaseTest {
 
   @Rule public final TestRule REPEAT_RULE = TestTools.getRepeatRule(false);
 
-  /**
-   * Rule for tests that verify {@link org.apache.drill.common.exceptions.UserException} type and message. See
-   * {@link UserExceptionMatcher} and e.g. apache.drill.exec.server.TestOptions#checkValidationException.
-   * Tests that do not use this rule are not affected.
-   */
-  @Rule public final ExpectedException thrownException = ExpectedException.none();
-
   @BeforeClass
   public static void initDrillTest() {
     memWatcher = new MemWatcher();
diff --git a/common/src/test/java/org/apache/drill/test/UserExceptionMatcher.java b/common/src/test/java/org/apache/drill/test/UserExceptionMatcher.java
deleted file mode 100644
index 36525c966e..0000000000
--- a/common/src/test/java/org/apache/drill/test/UserExceptionMatcher.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.drill.test;
-
-
-import org.apache.drill.common.exceptions.UserException;
-import org.apache.drill.exec.proto.UserBitShared.DrillPBError.ErrorType;
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
-
-/**
- * Matcher for UserException that matches if expected type and actual type are the same, and expected message is
- * contained in the actual message.
- */
-public class UserExceptionMatcher extends TypeSafeMatcher<UserException> {
-
-  private final ErrorType expectedType;
-  private final String expectedMessage;
-
-  public UserExceptionMatcher(final ErrorType expectedType, final String expectedMessage) {
-    this.expectedType = expectedType;
-    this.expectedMessage = expectedMessage;
-  }
-
-  public UserExceptionMatcher(final ErrorType expectedType) {
-    this(expectedType, null);
-  }
-
-  @Override
-  protected boolean matchesSafely(final UserException e) {
-    // Use .contains(...) to compare expected and actual message as the exact messages may differ.
-    return expectedType == e.getErrorType() && (expectedMessage == null || e.getMessage().contains(expectedMessage));
-  }
-
-  @Override
-  public void describeTo(final Description description) {
-    description.appendText("UserException of type: ")
-      .appendValue(expectedType.toString());
-    if (expectedMessage != null) {
-      description.appendText(" with message that contains: \"")
-        .appendText(expectedMessage)
-        .appendText("\"");
-    }
-  }
-
-  @Override
-  protected void describeMismatchSafely(final UserException e, final Description description) {
-    description.appendText("UserException thrown was of type: ")
-      .appendValue(e.getErrorType().toString());
-    if (expectedMessage != null) {
-      description.appendText(" with message: \"")
-        .appendText(e.getMessage())
-      .appendText("\"");
-    }
-  }
-}
diff --git a/contrib/format-log/src/test/java/org/apache/drill/exec/store/log/TestLogReaderIssue.java b/contrib/format-log/src/test/java/org/apache/drill/exec/store/log/TestLogReaderIssue.java
index 0834b67aa2..db9aff818c 100644
--- a/contrib/format-log/src/test/java/org/apache/drill/exec/store/log/TestLogReaderIssue.java
+++ b/contrib/format-log/src/test/java/org/apache/drill/exec/store/log/TestLogReaderIssue.java
@@ -17,7 +17,7 @@
  */
 package org.apache.drill.exec.store.log;
 
-import static org.junit.Assert.assertEquals;
+import static org.hamcrest.CoreMatchers.containsString;
 
 import java.io.File;
 import java.util.HashMap;
@@ -32,11 +32,13 @@ import org.apache.drill.exec.physical.rowSet.RowSet;
 import org.apache.drill.exec.physical.rowSet.RowSetBuilder;
 import org.apache.drill.exec.record.metadata.SchemaBuilder;
 import org.apache.drill.exec.record.metadata.TupleMetadata;
+import org.apache.drill.exec.rpc.RpcException;
 import org.apache.drill.exec.store.easy.text.compliant.BaseCsvTest;
 import org.apache.drill.shaded.guava.com.google.common.collect.Lists;
 import org.apache.drill.test.QueryBuilder;
-import org.apache.drill.test.QueryBuilder.QuerySummary;
 import org.apache.drill.test.rowSet.RowSetComparison;
+import org.hamcrest.MatcherAssert;
+import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
@@ -106,10 +108,12 @@ public class TestLogReaderIssue extends BaseCsvTest {
 
   @Test
   public void testIssue7853() throws Exception {
-    thrownException.expect(UserRemoteException.class);
-    thrownException.expectMessage("is not valid for type TIMESTAMP");
     String sql = "SELECT type, `time` FROM `dfs.data`.`root/issue7853.log2`";
-    QuerySummary result = client.queryBuilder().sql(sql).run();
-    assertEquals(2, result.recordCount());
+    UserRemoteException userRemoteException = Assert.assertThrows(UserRemoteException.class, () -> client.queryBuilder().sql(sql).run());
+    MatcherAssert.assertThat(userRemoteException.getMessage(), containsString("is not valid for type TIMESTAMP"));
+
+    try {
+      client.testBuilder().sqlQuery(sql).expectsNumRecords(2).go();
+    } catch (UserRemoteException | RpcException ignored) {}
   }
 }
diff --git a/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/TestHiveDrillNativeParquetReader.java b/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/TestHiveDrillNativeParquetReader.java
index 9c7f7bbcbb..935489c749 100644
--- a/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/TestHiveDrillNativeParquetReader.java
+++ b/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/TestHiveDrillNativeParquetReader.java
@@ -26,6 +26,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.drill.PlanTestBase;
+import org.apache.drill.categories.EasyOutOfMemory;
 import org.apache.drill.categories.HiveStorageTest;
 import org.apache.drill.categories.SlowTest;
 import org.apache.drill.common.exceptions.UserRemoteException;
@@ -40,7 +41,7 @@ import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.rules.ExpectedException;
 
-@Category({SlowTest.class, HiveStorageTest.class})
+@Category({SlowTest.class, HiveStorageTest.class, EasyOutOfMemory.class})
 public class TestHiveDrillNativeParquetReader extends HiveTestBase {
 
   @BeforeClass
diff --git a/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/BaseTestHiveImpersonation.java b/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/BaseTestHiveImpersonation.java
index 33e77ea638..44cfad422b 100644
--- a/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/BaseTestHiveImpersonation.java
+++ b/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/BaseTestHiveImpersonation.java
@@ -19,6 +19,7 @@ package org.apache.drill.exec.impersonation.hive;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Paths;
 import java.util.List;
 import java.util.Map;
 
@@ -26,6 +27,7 @@ import org.apache.calcite.schema.Schema.TableType;
 import org.apache.drill.exec.hive.HiveTestUtilities;
 import org.apache.drill.exec.impersonation.BaseTestImpersonation;
 import org.apache.drill.exec.store.hive.HiveStoragePluginConfig;
+import org.apache.drill.test.ClientFixture;
 import org.apache.drill.test.TestBuilder;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
@@ -94,8 +96,10 @@ public class BaseTestHiveImpersonation extends BaseTestImpersonation {
     whDir = hiveConf.get(ConfVars.METASTOREWAREHOUSE.varname);
     FileSystem.mkdirs(fs, new Path(whDir), new FsPermission((short) 0777));
 
-    studentData = getPhysicalFileFromResource("student.txt");
-    voterData = getPhysicalFileFromResource("voter.txt");
+    dirTestWatcher.copyResourceToRoot(Paths.get("student.txt"));
+    dirTestWatcher.copyResourceToRoot(Paths.get("voter.txt"));
+    studentData = dirTestWatcher.getRootDir() + "/student.txt";
+    voterData = dirTestWatcher.getRootDir() + "/voter.txt";
   }
 
   protected static void startHiveMetaStore() throws Exception {
@@ -143,12 +147,13 @@ public class BaseTestHiveImpersonation extends BaseTestImpersonation {
   }
 
   protected static void addHiveStoragePlugin(final Map<String, String> hiveConfig) throws Exception {
-    getDrillbitContext().getStorage().put(hivePluginName, createHiveStoragePlugin(hiveConfig));
+    cluster.storageRegistry().put(hivePluginName, createHiveStoragePlugin(hiveConfig));
   }
 
-  protected void showTablesHelper(final String db, List<String> expectedTables) throws Exception {
+  protected void showTablesHelper(final String db, List<String> expectedTables, ClientFixture
+client) throws Exception {
     final String dbQualified = hivePluginName + "." + db;
-    final TestBuilder testBuilder = testBuilder()
+    final TestBuilder testBuilder = client.testBuilder()
         .sqlQuery("SHOW TABLES IN " + dbQualified)
         .unOrdered()
         .baselineColumns("TABLE_SCHEMA", "TABLE_NAME");
@@ -164,9 +169,10 @@ public class BaseTestHiveImpersonation extends BaseTestImpersonation {
     testBuilder.go();
   }
 
-  protected void fromInfoSchemaHelper(final String db, List<String> expectedTables, List<TableType> expectedTableTypes) throws Exception {
+  protected void fromInfoSchemaHelper(final String db, List<String> expectedTables, List<TableType>
+expectedTableTypes, ClientFixture client) throws Exception {
     final String dbQualified = hivePluginName + "." + db;
-    final TestBuilder testBuilder = testBuilder()
+    final TestBuilder testBuilder = client.testBuilder()
         .sqlQuery("SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE \n" +
             "FROM INFORMATION_SCHEMA.`TABLES` \n" +
             "WHERE TABLE_SCHEMA = '" + dbQualified + "'")
@@ -190,9 +196,9 @@ public class BaseTestHiveImpersonation extends BaseTestImpersonation {
     // server instances this should be ok.
   }
 
-  static void queryView(String viewName) throws Exception {
+  static void queryView(String viewName, ClientFixture client) throws Exception {
     String query = String.format("SELECT rownum FROM %s.tmp.%s ORDER BY rownum LIMIT 1", MINI_DFS_STORAGE_PLUGIN_NAME, viewName);
-    testBuilder()
+    client.testBuilder()
         .sqlQuery(query)
         .unOrdered()
         .baselineColumns("rownum")
@@ -200,10 +206,19 @@ public class BaseTestHiveImpersonation extends BaseTestImpersonation {
         .go();
   }
 
-  static void queryViewNotAuthorized(String viewName) throws Exception {
+  static void queryViewNotAuthorized(String viewName, ClientFixture client) throws Exception {
     String query = String.format("SELECT rownum FROM %s.tmp.%s ORDER BY rownum LIMIT 1", MINI_DFS_STORAGE_PLUGIN_NAME, viewName);
-    errorMsgTestHelper(query, String.format(
-        "Not authorized to read view [%s] in schema [%s.tmp]", viewName, MINI_DFS_STORAGE_PLUGIN_NAME));
+    String expectedMsg = String.format(
+      "Not authorized to read view [%s] in schema [%s.tmp]",
+      viewName,
+      MINI_DFS_STORAGE_PLUGIN_NAME
+    );
+
+    client.queryBuilder()
+      .sql(query)
+      .userExceptionMatcher()
+      .include(expectedMsg)
+      .match();
   }
 
   static void createTableWithStoragePermissions(final Driver hiveDriver, final String db, final String tbl, final String tblDef,
diff --git a/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/TestSqlStdBasedAuthorization.java b/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/TestSqlStdBasedAuthorization.java
index ca16677d32..0e3c59f5dc 100644
--- a/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/TestSqlStdBasedAuthorization.java
+++ b/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/TestSqlStdBasedAuthorization.java
@@ -19,6 +19,7 @@ package org.apache.drill.exec.impersonation.hive;
 
 import org.apache.drill.shaded.guava.com.google.common.collect.ImmutableList;
 import org.apache.drill.shaded.guava.com.google.common.collect.Maps;
+import org.apache.drill.test.ClientFixture;
 import org.apache.drill.categories.HiveStorageTest;
 import org.apache.drill.categories.SlowTest;
 import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
@@ -189,8 +190,8 @@ public class TestSqlStdBasedAuthorization extends BaseTestHiveImpersonation {
 
   @Test
   public void user0_showTables() throws Exception {
-    updateClient(org1Users[0]);
-    showTablesHelper(db_general,
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      showTablesHelper(db_general,
         // Users are expected to see all tables in a database even if they don't have permissions to read from tables.
         ImmutableList.of(
             g_student_user0,
@@ -199,15 +200,19 @@ public class TestSqlStdBasedAuthorization extends BaseTestHiveImpersonation {
             vw_student_user0,
             vw_voter_role0,
             vw_student_user2
-        ));
+        ),
+        client
+      );
+    }
   }
 
   @Test
   public void user0_allowed_g_student_user0() throws Exception {
     // SELECT on "student_user0" table is granted to user "user0"
-    updateClient(org1Users[0]);
-    test("USE " + hivePluginName + "." + db_general);
-    test(String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_student_user0));
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      client.run("USE " + hivePluginName + "." + db_general);
+      client.run(String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_student_user0));
+    }
   }
 
   @Test
@@ -219,11 +224,18 @@ public class TestSqlStdBasedAuthorization extends BaseTestHiveImpersonation {
   public void user0_forbidden_g_voter_role0() throws Exception {
     // SELECT on table "student_user0" is NOT granted to user "user0" directly or indirectly through role "role0" as
     // user "user0" is not part of role "role0"
-    updateClient(org1Users[0]);
-    test("USE " + hivePluginName + "." + db_general);
-    final String query = String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_voter_role0);
-    errorMsgTestHelper(query, "Principal [name=user0_1, type=USER] does not have following privileges for " +
-        "operation QUERY [[SELECT] on Object [type=TABLE_OR_VIEW, name=db_general.voter_role0]]\n");
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      client.run("USE " + hivePluginName + "." + db_general);
+      final String query = String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_voter_role0);
+      String expectedMsg = "Principal [name=user0_1, type=USER] does not have following privileges for " +
+          "operation QUERY [[SELECT] on Object [type=TABLE_OR_VIEW, name=db_general.voter_role0]]\n";
+
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include(expectedMsg)
+        .match();
+    }
   }
 
   @Test
@@ -233,39 +245,51 @@ public class TestSqlStdBasedAuthorization extends BaseTestHiveImpersonation {
 
   @Test
   public void user0_forbidden_v_student_u1g1_750() throws Exception {
-    updateClient(org1Users[0]);
-    queryViewNotAuthorized(v_student_u1g1_750);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryViewNotAuthorized(v_student_u1g1_750, client);
+    }
   }
 
   @Test
   public void user0_allowed_v_student_u0g0_750() throws Exception {
-    updateClient(org1Users[0]);
-    queryView(v_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryView(v_student_u0g0_750, client);
+    }
   }
 
   @Test
   public void user1_showTables() throws Exception {
-    updateClient(org1Users[1]);
-    showTablesHelper(db_general,
-        // Users are expected to see all tables in a database even if they don't have permissions to read from tables.
-        ImmutableList.of(
-            g_student_user0,
-            g_student_user2,
-            g_voter_role0,
-            vw_student_user0,
-            vw_voter_role0,
-            vw_student_user2
-        ));
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      showTablesHelper(db_general,
+          // Users are expected to see all tables in a database even if they don't have permissions to read from tables.
+          ImmutableList.of(
+              g_student_user0,
+              g_student_user2,
+              g_voter_role0,
+              vw_student_user0,
+              vw_voter_role0,
+              vw_student_user2
+          ),
+          client
+      );
+    }
   }
 
   @Test
   public void user1_forbidden_g_student_user0() throws Exception {
     // SELECT on table "student_user0" is NOT granted to user "user1"
-    updateClient(org1Users[1]);
-    test("USE " + hivePluginName + "." + db_general);
-    final String query = String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_student_user0);
-    errorMsgTestHelper(query, "Principal [name=user1_1, type=USER] does not have following privileges for " +
-        "operation QUERY [[SELECT] on Object [type=TABLE_OR_VIEW, name=db_general.student_user0]]\n");
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      client.run("USE " + hivePluginName + "." + db_general);
+      final String query = String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_student_user0);
+      String expectedMsg = "Principal [name=user1_1, type=USER] does not have following privileges for " +
+          "operation QUERY [[SELECT] on Object [type=TABLE_OR_VIEW, name=db_general.student_user0]]\n";
+
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include(expectedMsg)
+        .match();
+    }
   }
 
   @Test
@@ -276,9 +300,10 @@ public class TestSqlStdBasedAuthorization extends BaseTestHiveImpersonation {
   @Test
   public void user1_allowed_g_voter_role0() throws Exception {
     // SELECT on "voter_role0" table is granted to role "role0" and user "user1" is part the role "role0"
-    updateClient(org1Users[1]);
-    test("USE " + hivePluginName + "." + db_general);
-    test(String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_voter_role0));
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      client.run("USE " + hivePluginName + "." + db_general);
+      client.run(String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_voter_role0));
+    }
   }
 
   @Test
@@ -290,44 +315,62 @@ public class TestSqlStdBasedAuthorization extends BaseTestHiveImpersonation {
   public void user1_allowed_g_voter_role0_but_forbidden_g_student_user2() throws Exception {
     // SELECT on "voter_role0" table is granted to role "role0" and user "user1" is part the role "role0"
     // SELECT on "student_user2" table is NOT granted to either role "role0" or user "user1"
-    updateClient(org1Users[1]);
-    test("USE " + hivePluginName + "." + db_general);
-    final String query =
-        String.format("SELECT * FROM %s v JOIN %s s on v.name = s.name limit 2;", g_voter_role0, g_student_user2);
-    errorMsgTestHelper(query, "Principal [name=user1_1, type=USER] does not have following privileges for " +
-        "operation QUERY [[SELECT] on Object [type=TABLE_OR_VIEW, name=db_general.student_user2]]");
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      client.run("USE " + hivePluginName + "." + db_general);
+      final String query =
+          String.format("SELECT * FROM %s v JOIN %s s on v.name = s.name limit 2", g_voter_role0, g_student_user2);
+      String expectedMsg = "Principal [name=user1_1, type=USER] does not have following privileges for " +
+          "operation QUERY [[SELECT] on Object [type=TABLE_OR_VIEW, name=db_general.student_user2]]";
+
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include(expectedMsg)
+        .match();
+    }
   }
 
+
   @Test
   public void user1_allowed_vw_voter_role0_but_forbidden_vw_student_user2() throws Exception {
     // SELECT on "vw_voter_role0" table is granted to role "role0" and user "user1" is part the role "role0"
     // SELECT on "vw_student_user2" table is NOT granted to either role "role0" or user "user1"
-    updateClient(org1Users[1]);
-    test("USE " + hivePluginName + "." + db_general);
-    final String query =
-        String.format("SELECT * FROM %s v JOIN %s s on v.name = s.name limit 2;", vw_voter_role0, vw_student_user2);
-    errorMsgTestHelper(query, "Principal [name=user1_1, type=USER] does not have following privileges for " +
-        "operation QUERY [[SELECT] on Object [type=TABLE_OR_VIEW, name=db_general.vw_student_user2]]");
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      client.run("USE " + hivePluginName + "." + db_general);
+      final String query =
+          String.format("SELECT * FROM %s v JOIN %s s on v.name = s.name limit 2", vw_voter_role0, vw_student_user2);
+      String expectedMsg = "Principal [name=user1_1, type=USER] does not have following privileges for " +
+          "operation QUERY [[SELECT] on Object [type=TABLE_OR_VIEW, name=db_general.vw_student_user2]]";
+
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include(expectedMsg)
+        .match();
+    }
   }
 
   @Test
   public void user1_allowed_v_student_u0g0_750() throws Exception {
-    updateClient(org1Users[1]);
-    queryView(v_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryView(v_student_u0g0_750, client);
+    }
   }
 
   @Test
   public void user1_allowed_v_student_u1g1_750() throws Exception {
-    updateClient(org1Users[1]);
-    queryView(v_student_u1g1_750);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryView(v_student_u1g1_750, client);
+    }
   }
 
   @Test
   public void user2_allowed_g_voter_role0() throws Exception {
     // SELECT on "voter_role0" table is granted to role "role0" and user "user2" is part the role "role0"
-    updateClient(org1Users[2]);
-    test("USE " + hivePluginName + "." + db_general);
-    test(String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_voter_role0));
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      client.run("USE " + hivePluginName + "." + db_general);
+      client.run(String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_voter_role0));
+    }
   }
 
   @Test
@@ -338,9 +381,10 @@ public class TestSqlStdBasedAuthorization extends BaseTestHiveImpersonation {
   @Test
   public void user2_allowed_g_student_user2() throws Exception {
     // SELECT on "student_user2" table is granted to user "user2"
-    updateClient(org1Users[2]);
-    test("USE " + hivePluginName + "." + db_general);
-    test(String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_student_user2));
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      client.run("USE " + hivePluginName + "." + db_general);
+      client.run(String.format("SELECT * FROM %s ORDER BY name LIMIT 2", g_student_user2));
+    }
   }
 
   @Test
@@ -352,28 +396,32 @@ public class TestSqlStdBasedAuthorization extends BaseTestHiveImpersonation {
   public void user2_allowed_g_voter_role0_and_g_student_user2() throws Exception {
     // SELECT on "voter_role0" table is granted to role "role0" and user "user2" is part the role "role0"
     // SELECT on "student_user2" table is granted to user "user2"
-    updateClient(org1Users[2]);
-    test("USE " + hivePluginName + "." + db_general);
-    test(String.format("SELECT * FROM %s v JOIN %s s on v.name = s.name limit 2;", g_voter_role0, g_student_user2));
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      client.run("USE " + hivePluginName + "." + db_general);
+      client.run(String.format("SELECT * FROM %s v JOIN %s s on v.name = s.name limit 2", g_voter_role0, g_student_user2));
+    }
   }
 
   @Test
   public void user2_allowed_vw_voter_role0_and_vw_student_user2() throws Exception {
-    updateClient(org1Users[2]);
-    test("USE " + hivePluginName + "." + db_general);
-    test(String.format("SELECT * FROM %s v JOIN %s s on v.name = s.name limit 2;", vw_voter_role0, vw_student_user2));
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      client.run("USE " + hivePluginName + "." + db_general);
+      client.run(String.format("SELECT * FROM %s v JOIN %s s on v.name = s.name limit 2", vw_voter_role0, vw_student_user2));
+    }
   }
 
   @Test
   public void user2_forbidden_v_student_u0g0_750() throws Exception {
-    updateClient(org1Users[2]);
-    queryViewNotAuthorized(v_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryViewNotAuthorized(v_student_u0g0_750, client);
+    }
   }
 
   @Test
   public void user2_allowed_v_student_u1g1_750() throws Exception {
-    updateClient(org1Users[2]);
-    queryView(v_student_u1g1_750);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryView(v_student_u1g1_750, client);
+    }
   }
 
   @AfterClass
@@ -385,13 +433,14 @@ public class TestSqlStdBasedAuthorization extends BaseTestHiveImpersonation {
   private static void queryHiveView(String usr, String viewName) throws Exception {
     String query = String.format("SELECT COUNT(*) AS rownum FROM %s.%s.%s",
         hivePluginName, db_general, viewName);
-    updateClient(usr);
-    testBuilder()
-        .sqlQuery(query)
-        .unOrdered()
-        .baselineColumns("rownum")
-        .baselineValues(1L)
-        .go();
+    try (ClientFixture client = cluster.client(usr, "")) {
+      client.testBuilder()
+          .sqlQuery(query)
+          .unOrdered()
+          .baselineColumns("rownum")
+          .baselineValues(1L)
+          .go();
+    }
   }
 
   private static void queryHiveViewNotAuthorized(String usr, String viewName) throws Exception {
@@ -399,9 +448,13 @@ public class TestSqlStdBasedAuthorization extends BaseTestHiveImpersonation {
     final String expectedError = String.format("Principal [name=%s, type=USER] does not have following privileges for " +
             "operation QUERY [[SELECT] on Object [type=TABLE_OR_VIEW, name=db_general.%s]]\n",
         usr, viewName);
-
-    updateClient(usr);
-    errorMsgTestHelper(query, expectedError);
+    try (ClientFixture client = cluster.client(usr, "")) {
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include(expectedError)
+        .match();
+    }
   }
 
   private static void createHiveView(Driver driver, String db, String viewName, String tblName) {
diff --git a/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/TestStorageBasedHiveAuthorization.java b/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/TestStorageBasedHiveAuthorization.java
index e721ab1452..c4691642eb 100644
--- a/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/TestStorageBasedHiveAuthorization.java
+++ b/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/impersonation/hive/TestStorageBasedHiveAuthorization.java
@@ -27,6 +27,7 @@ import org.apache.drill.categories.HiveStorageTest;
 import org.apache.drill.categories.SlowTest;
 import org.apache.drill.shaded.guava.com.google.common.collect.ImmutableList;
 import org.apache.drill.shaded.guava.com.google.common.collect.Maps;
+import org.apache.drill.test.ClientFixture;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.permission.FsPermission;
 import org.apache.hadoop.hive.ql.Driver;
@@ -379,14 +380,16 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_db_general_showTables() throws Exception {
-    updateClient(org1Users[0]);
-    showTablesHelper(db_general, all_tables_in_db_general);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      showTablesHelper(db_general, all_tables_in_db_general, client);
+    }
   }
 
   @Test
   public void user0_db_u0_only_showTables() throws Exception {
-    updateClient(org1Users[0]);
-    showTablesHelper(db_u0_only, all_tables_in_db_u0_only);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      showTablesHelper(db_u0_only, all_tables_in_db_u0_only, client);
+    }
   }
 
   /**
@@ -395,30 +398,35 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_db_u1g1_only_showTables() throws Exception {
-    updateClient(org1Users[0]);
-    showTablesHelper(db_u1g1_only, all_tables_in_db_u1g1_only);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      showTablesHelper(db_u1g1_only, all_tables_in_db_u1g1_only, client);
+    }
   }
 
   @Test
   public void user0_db_general_infoSchema() throws Exception {
-    updateClient(org1Users[0]);
-    fromInfoSchemaHelper(db_general,
-        all_tables_in_db_general,
-        all_tables_type_in_db_general);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      fromInfoSchemaHelper(db_general,
+          all_tables_in_db_general,
+          all_tables_type_in_db_general, client);
+    }
   }
 
   @Test
   public void user0_db_u0_only_infoSchema() throws Exception {
-    updateClient(org1Users[0]);
-    fromInfoSchemaHelper(db_u0_only,
-        all_tables_in_db_u0_only,
-        all_tables_type_in_db_u0_only);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      fromInfoSchemaHelper(db_u0_only,
+          all_tables_in_db_u0_only,
+          all_tables_type_in_db_u0_only, client);
+    }
   }
 
   @Test
   public void user0_db_u1g1_only_infoSchema() throws Exception {
-    updateClient(org1Users[0]);
-    fromInfoSchemaHelper(db_u1g1_only, all_tables_in_db_u1g1_only, all_tables_type_db_u1g1_only);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      fromInfoSchemaHelper(db_u1g1_only, all_tables_in_db_u1g1_only, all_tables_type_db_u1g1_only,
+      client);
+    }
   }
 
   /**
@@ -426,50 +434,59 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_allowed_g_student_u0_700() throws Exception {
-    updateClient(org1Users[0]);
-    queryHiveTableOrView(db_general, g_student_u0_700);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryHiveTableOrView(db_general, g_student_u0_700, client);
+    }
   }
 
   @Test
   public void user0_allowed_g_vw_u0_700_over_g_student_u0_700() throws Exception {
-    updateClient(org1Users[0]);
-    queryHiveTableOrView(db_general, g_vw_g_student_u0_700);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryHiveTableOrView(db_general, g_vw_g_student_u0_700, client);
+    }
   }
 
   @Test
   public void user1_forbidden_g_vw_u0_700_over_g_student_u0_700() throws Exception {
-    updateClient(org1Users[1]);
-    queryHiveViewFailed(db_general, g_vw_g_student_u0_700);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryHiveViewFailed(db_general, g_vw_g_student_u0_700, client);
+    }
   }
 
   @Test
   public void user2_forbidden_g_vw_u0_700_over_g_student_u0_700() throws Exception {
-    updateClient(org1Users[2]);
-    queryHiveViewFailed(db_general, g_vw_g_student_u0_700);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryHiveViewFailed(db_general, g_vw_g_student_u0_700, client);
+    }
   }
 
   @Test
   public void user0_allowed_u0_vw_voter_all_755() throws Exception {
-    updateClient(org1Users[0]);
-    queryHiveTableOrView(db_u0_only, u0_vw_voter_all_755);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryHiveTableOrView(db_u0_only, u0_vw_voter_all_755, client);
+    }
   }
 
   @Test
   public void user1_forbidden_u0_vw_voter_all_755() throws Exception {
-    updateClient(org1Users[1]);
-    queryHiveViewFailed(db_u0_only, u0_vw_voter_all_755);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryHiveViewFailed(db_u0_only, u0_vw_voter_all_755, client);
+    }
   }
 
   @Test
   public void user2_forbidden_u0_vw_voter_all_755() throws Exception {
-    updateClient(org1Users[2]);
-    queryHiveViewFailed(db_u0_only, u0_vw_voter_all_755);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryHiveViewFailed(db_u0_only, u0_vw_voter_all_755, client);
+    }
   }
 
-  private void queryHiveViewFailed(String db, String viewName) throws Exception {
-    errorMsgTestHelper(
-        String.format("SELECT * FROM hive.%s.%s LIMIT 2", db, viewName),
-        "Failure validating a view your query is dependent upon.");
+  private void queryHiveViewFailed(String db, String viewName, ClientFixture client) throws Exception {
+    client.queryBuilder()
+      .sql(String.format("SELECT * FROM hive.%s.%s LIMIT 2", db, viewName))
+      .userExceptionMatcher()
+      .include("Failure validating a view your query is dependent upon.")
+      .match();
   }
 
   /**
@@ -477,8 +494,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_allowed_g_student_u0g0_750() throws Exception {
-    updateClient(org1Users[0]);
-    queryHiveTableOrView(db_general, g_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryHiveTableOrView(db_general, g_student_u0g0_750, client);
+    }
   }
 
   /**
@@ -487,8 +505,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_allowed_g_student_all_755() throws Exception {
-    updateClient(org1Users[0]);
-    queryHiveTableOrView(db_general, g_student_all_755);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryHiveTableOrView(db_general, g_student_all_755, client);
+    }
   }
 
   /**
@@ -496,8 +515,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_forbidden_g_voter_u1_700() throws Exception{
-    updateClient(org1Users[0]);
-    queryTableNotFound(db_general, g_voter_u1_700);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryTableNotFound(db_general, g_voter_u1_700, client);
+    }
   }
 
   /**
@@ -505,8 +525,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_forbidden_g_voter_u2g1_750() throws Exception{
-    updateClient(org1Users[0]);
-    queryTableNotFound(db_general, g_voter_u2g1_750);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryTableNotFound(db_general, g_voter_u2g1_750, client);
+    }
   }
 
   /**
@@ -515,8 +536,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_allowed_g_voter_all_755() throws Exception {
-    updateClient(org1Users[0]);
-    queryHiveTableOrView(db_general, g_voter_all_755);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryHiveTableOrView(db_general, g_voter_all_755, client);
+    }
   }
 
   /**
@@ -524,8 +546,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_allowed_u0_student_all_755() throws Exception {
-    updateClient(org1Users[0]);
-    queryHiveTableOrView(db_u0_only, u0_student_all_755);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryHiveTableOrView(db_u0_only, u0_student_all_755, client);
+    }
   }
 
   /**
@@ -533,8 +556,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_allowed_u0_voter_all_755() throws Exception {
-    updateClient(org1Users[0]);
-    queryHiveTableOrView(db_u0_only, u0_voter_all_755);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryHiveTableOrView(db_u0_only, u0_voter_all_755, client);
+    }
   }
 
   /**
@@ -542,8 +566,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_allowed_g_partitioned_student_u0_700() throws Exception {
-    updateClient(org1Users[0]);
-    queryHiveTableOrView(db_general, g_partitioned_student_u0_700);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryHiveTableOrView(db_general, g_partitioned_student_u0_700, client);
+    }
   }
 
   /**
@@ -551,84 +576,99 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user0_forbidden_u1g1_student_all_755() throws Exception {
-    updateClient(org1Users[0]);
-    queryTableNotFound(db_u1g1_only, u1g1_student_all_755);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryTableNotFound(db_u1g1_only, u1g1_student_all_755, client);
+    }
   }
 
   @Test
   public void user0_allowed_v_student_u0g0_750() throws Exception {
-    updateClient(org1Users[0]);
-    queryView(v_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryView(v_student_u0g0_750, client);
+    }
   }
 
   @Test
   public void user0_forbidden_v_student_u1g1_750() throws Exception {
-    updateClient(org1Users[0]);
-    queryViewNotAuthorized(v_student_u1g1_750);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryViewNotAuthorized(v_student_u1g1_750, client);
+    }
   }
 
   @Test
   public void user0_allowed_v_partitioned_student_u0g0_750() throws Exception {
-    updateClient(org1Users[0]);
-    queryView(v_partitioned_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryView(v_partitioned_student_u0g0_750, client);
+    }
   }
 
   @Test
   public void user0_forbidden_v_partitioned_student_u1g1_750() throws Exception {
-    updateClient(org1Users[0]);
-    queryViewNotAuthorized(v_partitioned_student_u1g1_750);
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      queryViewNotAuthorized(v_partitioned_student_u1g1_750, client);
+    }
   }
 
   @Test
   public void user1_db_general_showTables() throws Exception {
-    updateClient(org1Users[1]);
-    showTablesHelper(db_general, all_tables_in_db_general);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      showTablesHelper(db_general, all_tables_in_db_general, client);
+    }
   }
 
   @Test
   public void user1_db_u1g1_only_showTables() throws Exception {
-    updateClient(org1Users[1]);
-    showTablesHelper(db_u1g1_only, all_tables_in_db_u1g1_only);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      showTablesHelper(db_u1g1_only, all_tables_in_db_u1g1_only, client);
+    }
   }
 
   @Test
   public void user1_db_u0_only_showTables() throws Exception {
-    updateClient(org1Users[1]);
-    showTablesHelper(db_u0_only, all_tables_in_db_u0_only);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      showTablesHelper(db_u0_only, all_tables_in_db_u0_only, client);
+    }
   }
 
   @Test
   public void user1_db_general_infoSchema() throws Exception {
-    updateClient(org1Users[1]);
-    fromInfoSchemaHelper(db_general,
-        all_tables_in_db_general,
-        all_tables_type_in_db_general);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      fromInfoSchemaHelper(db_general,
+          all_tables_in_db_general,
+          all_tables_type_in_db_general, client);
+    }
   }
 
   @Test
   public void user1_db_u1g1_only_infoSchema() throws Exception {
-    updateClient(org1Users[1]);
-    fromInfoSchemaHelper(db_u1g1_only,
-        ImmutableList.of(
-            u1g1_student_all_755,
-            u1g1_student_u1_700,
-            u1g1_voter_all_755,
-            u1g1_voter_u1_700
-        ),
-        ImmutableList.of(
-            TableType.TABLE,
-            TableType.TABLE,
-            TableType.TABLE,
-            TableType.TABLE
-        ));
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      fromInfoSchemaHelper(db_u1g1_only,
+          ImmutableList.of(
+              u1g1_student_all_755,
+              u1g1_student_u1_700,
+              u1g1_voter_all_755,
+              u1g1_voter_u1_700
+          ),
+          ImmutableList.of(
+              TableType.TABLE,
+              TableType.TABLE,
+              TableType.TABLE,
+              TableType.TABLE
+          ),
+          client
+      );
+    }
   }
 
   @Test
   public void user1_db_u0_only_infoSchema() throws Exception {
-    updateClient(org1Users[1]);
-    fromInfoSchemaHelper(db_u0_only,
-        newArrayList(u0_vw_voter_all_755, u0_student_all_755, u0_voter_all_755),
-        newArrayList(TableType.VIEW, TableType.TABLE, TableType.TABLE));
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      fromInfoSchemaHelper(db_u0_only,
+          newArrayList(u0_vw_voter_all_755, u0_student_all_755, u0_voter_all_755),
+          newArrayList(TableType.VIEW, TableType.TABLE, TableType.TABLE),
+          client
+      );
+    }
   }
 
   /**
@@ -636,8 +676,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user1_forbidden_g_student_u0_700() throws Exception {
-    updateClient(org1Users[1]);
-    queryTableNotFound(db_general, g_student_u0_700);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryTableNotFound(db_general, g_student_u0_700, client);
+    }
   }
 
   /**
@@ -645,8 +686,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user1_allowed_g_student_u0g0_750() throws Exception {
-    updateClient(org1Users[1]);
-    queryHiveTableOrView(db_general, g_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryHiveTableOrView(db_general, g_student_u0g0_750, client);
+    }
   }
 
   /**
@@ -654,8 +696,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user1_allowed_g_student_all_755() throws Exception {
-    updateClient(org1Users[1]);
-    queryHiveTableOrView(db_general, g_student_all_755);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryHiveTableOrView(db_general, g_student_all_755, client);
+    }
   }
 
   /**
@@ -663,8 +706,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user1_allowed_g_voter_u1_700() throws Exception {
-    updateClient(org1Users[1]);
-    queryHiveTableOrView(db_general, g_voter_u1_700);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryHiveTableOrView(db_general, g_voter_u1_700, client);
+    }
   }
 
   /**
@@ -672,8 +716,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user1_allowed_g_voter_u2g1_750() throws Exception {
-    updateClient(org1Users[1]);
-    queryHiveTableOrView(db_general, g_voter_u2g1_750);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryHiveTableOrView(db_general, g_voter_u2g1_750, client);
+    }
   }
 
   /**
@@ -681,8 +726,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user1_allowed_g_voter_all_755() throws Exception {
-    updateClient(org1Users[1]);
-    queryHiveTableOrView(db_general, g_voter_all_755);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryHiveTableOrView(db_general, g_voter_all_755, client);
+    }
   }
 
   /**
@@ -690,8 +736,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user1_forbidden_u0_student_all_755() throws Exception {
-    updateClient(org1Users[1]);
-    queryTableNotFound(db_u0_only, u0_student_all_755);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryTableNotFound(db_u0_only, u0_student_all_755, client);
+    }
   }
 
   /**
@@ -699,74 +746,91 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user1_forbidden_u0_voter_all_755() throws Exception {
-    updateClient(org1Users[1]);
-    queryTableNotFound(db_u0_only, u0_voter_all_755);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryTableNotFound(db_u0_only, u0_voter_all_755, client);
+    }
   }
 
   @Test
   public void user1_allowed_v_student_u0g0_750() throws Exception {
-    updateClient(org1Users[1]);
-    queryView(v_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryView(v_student_u0g0_750, client);
+    }
   }
 
   @Test
   public void user1_allowed_v_student_u1g1_750() throws Exception {
-    updateClient(org1Users[1]);
-    queryView(v_student_u1g1_750);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryView(v_student_u1g1_750, client);
+    }
   }
 
   @Test
   public void user1_allowed_v_partitioned_student_u0g0_750() throws Exception {
-    updateClient(org1Users[1]);
-    queryView(v_partitioned_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryView(v_partitioned_student_u0g0_750, client);
+    }
   }
 
   @Test
   public void user1_allowed_v_partitioned_student_u1g1_750() throws Exception {
-    updateClient(org1Users[1]);
-    queryView(v_partitioned_student_u1g1_750);
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      queryView(v_partitioned_student_u1g1_750, client);
+    }
   }
 
   @Test
   public void user2_db_general_showTables() throws Exception {
-    updateClient(org1Users[2]);
-    showTablesHelper(db_general, all_tables_in_db_general);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      showTablesHelper(db_general, all_tables_in_db_general, client);
+    }
   }
 
   @Test
   public void user2_db_u1g1_only_showTables() throws Exception {
-    updateClient(org1Users[2]);
-    showTablesHelper(db_u1g1_only, all_tables_in_db_u1g1_only);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      showTablesHelper(db_u1g1_only, all_tables_in_db_u1g1_only, client);
+    }
   }
 
   @Test
   public void user2_db_u0_only_showTables() throws Exception {
-    updateClient(org1Users[2]);
-    showTablesHelper(db_u0_only, all_tables_in_db_u0_only);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      showTablesHelper(db_u0_only, all_tables_in_db_u0_only, client);
+    }
   }
 
   @Test
   public void user2_db_general_infoSchema() throws Exception {
-    updateClient(org1Users[2]);
-    fromInfoSchemaHelper(db_general,
-        all_tables_in_db_general,
-        all_tables_type_in_db_general);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      fromInfoSchemaHelper(db_general,
+          all_tables_in_db_general,
+          all_tables_type_in_db_general,
+          client
+      );
+    }
   }
 
   @Test
   public void user2_db_u1g1_only_infoSchema() throws Exception {
-    updateClient(org1Users[2]);
-    fromInfoSchemaHelper(db_u1g1_only,
-        all_tables_in_db_u1g1_only,
-        all_tables_type_db_u1g1_only);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      fromInfoSchemaHelper(db_u1g1_only,
+          all_tables_in_db_u1g1_only,
+          all_tables_type_db_u1g1_only,
+          client
+      );
+    }
   }
 
   @Test
   public void user2_db_u0_only_infoSchema() throws Exception {
-    updateClient(org1Users[2]);
-    fromInfoSchemaHelper(db_u0_only,
-        newArrayList(all_tables_in_db_u0_only),
-        newArrayList(all_tables_type_in_db_u0_only));
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      fromInfoSchemaHelper(db_u0_only,
+          newArrayList(all_tables_in_db_u0_only),
+          newArrayList(all_tables_type_in_db_u0_only),
+          client
+      );
+    }
   }
 
   /**
@@ -774,8 +838,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user2_forbidden_g_student_u0_700() throws Exception {
-    updateClient(org1Users[2]);
-    queryTableNotFound(db_general, g_student_u0_700);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryTableNotFound(db_general, g_student_u0_700, client);
+    }
   }
 
   /**
@@ -783,8 +848,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user2_forbidden_g_student_u0g0_750() throws Exception {
-    updateClient(org1Users[2]);
-    queryTableNotFound(db_general, g_student_u0_700);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryTableNotFound(db_general, g_student_u0_700, client);
+    }
   }
 
   /**
@@ -792,8 +858,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user2_allowed_g_student_all_755() throws Exception {
-    updateClient(org1Users[2]);
-    queryHiveTableOrView(db_general, g_student_all_755);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryHiveTableOrView(db_general, g_student_all_755, client);
+    }
   }
 
   /**
@@ -801,8 +868,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user2_forbidden_g_voter_u1_700() throws Exception {
-    updateClient(org1Users[2]);
-    queryTableNotFound(db_general, g_voter_u1_700);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryTableNotFound(db_general, g_voter_u1_700, client);
+    }
   }
 
   /**
@@ -810,8 +878,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user2_allowed_g_voter_u2g1_750() throws Exception {
-    updateClient(org1Users[2]);
-    queryHiveTableOrView(db_general, g_voter_u2g1_750);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryHiveTableOrView(db_general, g_voter_u2g1_750, client);
+    }
   }
 
   /**
@@ -819,8 +888,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user2_allowed_g_voter_all_755() throws Exception {
-    updateClient(org1Users[2]);
-    queryHiveTableOrView(db_general, g_voter_all_755);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryHiveTableOrView(db_general, g_voter_all_755, client);
+    }
   }
 
   /**
@@ -828,8 +898,9 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user2_forbidden_u0_student_all_755() throws Exception {
-    updateClient(org1Users[2]);
-    queryTableNotFound(db_u0_only, u0_student_all_755);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryTableNotFound(db_u0_only, u0_student_all_755, client);
+    }
   }
 
   /**
@@ -837,32 +908,37 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
    */
   @Test
   public void user2_forbidden_u0_voter_all_755() throws Exception {
-    updateClient(org1Users[2]);
-    queryTableNotFound(db_u0_only, u0_voter_all_755);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryTableNotFound(db_u0_only, u0_voter_all_755, client);
+    }
   }
 
   @Test
   public void user2_forbidden_v_student_u0g0_750() throws Exception {
-    updateClient(org1Users[2]);
-    queryViewNotAuthorized(v_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryViewNotAuthorized(v_student_u0g0_750, client);
+    }
   }
 
   @Test
   public void user2_allowed_v_student_u1g1_750() throws Exception {
-    updateClient(org1Users[2]);
-    queryView(v_student_u1g1_750);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryView(v_student_u1g1_750, client);
+    }
   }
 
   @Test
   public void user2_forbidden_v_partitioned_student_u0g0_750() throws Exception {
-    updateClient(org1Users[2]);
-    queryViewNotAuthorized(v_partitioned_student_u0g0_750);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryViewNotAuthorized(v_partitioned_student_u0g0_750, client);
+    }
   }
 
   @Test
   public void user2_allowed_v_partitioned_student_u1g1_750() throws Exception {
-    updateClient(org1Users[2]);
-    queryView(v_partitioned_student_u1g1_750);
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      queryView(v_partitioned_student_u1g1_750, client);
+    }
   }
 
   @AfterClass
@@ -871,14 +947,15 @@ public class TestStorageBasedHiveAuthorization extends BaseTestHiveImpersonation
     stopHiveMetaStore();
   }
 
-  private static void queryHiveTableOrView(String db, String table) throws Exception {
-    test(String.format("SELECT * FROM hive.%s.%s LIMIT 2", db, table));
+  private static void queryHiveTableOrView(String db, String table, ClientFixture client) throws Exception {
+    client.run(String.format("SELECT * FROM hive.%s.%s LIMIT 2", db, table));
   }
 
-  private static void queryTableNotFound(String db, String table) throws Exception {
-    errorMsgTestHelper(
-        String.format("SELECT * FROM hive.%s.%s LIMIT 2", db, table),
-        String.format("Object '%s' not found within 'hive.%s'", table, db));
+  private static void queryTableNotFound(String db, String table, ClientFixture client) throws Exception {
+    client.queryBuilder()
+      .sql(String.format("SELECT * FROM hive.%s.%s LIMIT 2", db, table))
+      .userExceptionMatcher()
+      .include(String.format("Object '%s' not found within 'hive.%s'", table, db))
+      .match();
   }
-
 }
diff --git a/contrib/storage-splunk/src/test/java/org/apache/drill/exec/store/splunk/SplunkWriterTest.java b/contrib/storage-splunk/src/test/java/org/apache/drill/exec/store/splunk/SplunkWriterTest.java
index 7c8e04b377..f5d399cd23 100644
--- a/contrib/storage-splunk/src/test/java/org/apache/drill/exec/store/splunk/SplunkWriterTest.java
+++ b/contrib/storage-splunk/src/test/java/org/apache/drill/exec/store/splunk/SplunkWriterTest.java
@@ -29,6 +29,7 @@ import org.apache.drill.exec.record.metadata.TupleMetadata;
 import org.apache.drill.test.QueryBuilder.QuerySummary;
 import org.apache.drill.test.rowSet.RowSetUtilities;
 import org.junit.FixMethodOrder;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runners.MethodSorters;
@@ -96,6 +97,7 @@ public class SplunkWriterTest extends SplunkBaseTest {
   }
 
   @Test
+  @Ignore("Run manually because of an unpredictable delay before newly inserted data gets indexed.")
   public void testBasicCTASWithScalarDataTypes() throws Exception {
     String query = "CREATE TABLE splunk.t2 AS " +
       "SELECT CAST(1 AS INTEGER) AS int_field," +
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java
index 2ffbe4aa3f..19303cbf12 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java
@@ -17,29 +17,29 @@
  */
 package org.apache.drill.exec;
 
-import org.apache.drill.test.BaseTestQuery;
+import org.apache.drill.test.ClusterFixture;
+import org.apache.drill.test.ClusterTest;
 import org.apache.drill.categories.UnlikelyTest;
 import org.apache.drill.common.exceptions.UserException;
 import org.apache.drill.exec.proto.UserBitShared;
 import org.apache.drill.exec.work.foreman.SqlUnsupportedException;
 import org.apache.drill.exec.work.foreman.UnsupportedFunctionException;
-import org.apache.drill.PlanTestBase;
 
-import org.apache.drill.test.UserExceptionMatcher;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
 import java.nio.file.Paths;
 
-public class TestWindowFunctions extends BaseTestQuery {
+public class TestWindowFunctions extends ClusterTest {
   private static void throwAsUnsupportedException(UserException ex) throws Exception {
     SqlUnsupportedException.errorClassNameToException(ex.getOrCreatePBError(false).getException().getExceptionClass());
     throw ex;
   }
 
   @BeforeClass
-  public static void setupTestFiles() {
+  public static void setupTestFiles() throws Exception {
+    startCluster(ClusterFixture.builder(dirTestWatcher));
     dirTestWatcher.copyResourceToRoot(Paths.get("multilevel/parquet"));
     dirTestWatcher.copyResourceToRoot(Paths.get("window"));
   }
@@ -53,7 +53,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan = {"Window.*partition \\{0\\} aggs .*\\[SUM\\(\\$0\\), COUNT\\(\\)",
         "Scan.*columns=\\[`n_nationKey`\\].*"};
     final String[] excludedPatterns = {"Scan.*columns=\\[`\\*`\\].*"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, excludedPatterns);
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(excludedPatterns)
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -98,7 +104,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan = {"Window.*partition \\{0\\} order by \\[0\\].*SUM\\(\\$0\\)",
         "Scan.*columns=\\[`n_nationKey`\\].*"};
     final String[] excludedPatterns = {"Scan.*columns=\\[`\\*`\\].*"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, excludedPatterns);
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(excludedPatterns)
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -139,7 +151,7 @@ public class TestWindowFunctions extends BaseTestQuery {
       final String query = "explain plan for select a2, count(distinct b2) over(partition by a2) \n" +
           "from cp.`tpch/nation.parquet`";
 
-      test(query);
+      run(query);
     } catch(UserException ex) {
       throwAsUnsupportedException(ex);
       throw ex;
@@ -153,7 +165,7 @@ public class TestWindowFunctions extends BaseTestQuery {
           "from cp.`tpch/nation.parquet` t \n" +
           "order by a2";
 
-      test(query);
+      run(query);
     } catch(UserException ex) {
         throwAsUnsupportedException(ex);
         throw ex;
@@ -166,7 +178,7 @@ public class TestWindowFunctions extends BaseTestQuery {
       String query = "explain plan for SELECT sum(n_nationkey) OVER (PARTITION BY n_name ORDER BY n_name ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) as col2 \n" +
           "from cp.`tpch/nation.parquet`";
 
-      test(query);
+      run(query);
     } catch(UserException ex) {
       throwAsUnsupportedException(ex);
       throw ex;
@@ -181,7 +193,7 @@ public class TestWindowFunctions extends BaseTestQuery {
           "from cp.`tpch/nation.parquet` \n" +
           "order by n_nationKey";
 
-      test(query);
+      run(query);
     } catch(UserException ex) {
       throwAsUnsupportedException(ex);
       throw ex;
@@ -190,65 +202,83 @@ public class TestWindowFunctions extends BaseTestQuery {
 
   @Test // DRILL-3360
   public void testWindowInWindow() throws Exception {
-    thrownException.expect(new UserExceptionMatcher(UserBitShared.DrillPBError.ErrorType.VALIDATION));
     String query = "select rank() over(order by row_number() over(order by n_nationkey)) \n" +
-        "from cp.`tpch/nation.parquet`";
+      "from cp.`tpch/nation.parquet`";
 
-    test(query);
+    client.queryBuilder()
+      .sql(query)
+      .userExceptionMatcher()
+      .expectedType(UserBitShared.DrillPBError.ErrorType.VALIDATION)
+      .match();
   }
 
   @Test // DRILL-3280
   public void testMissingOverWithWindowClause() throws Exception {
-    thrownException.expect(new UserExceptionMatcher(UserBitShared.DrillPBError.ErrorType.VALIDATION));
     String query = "select rank(), cume_dist() over w \n" +
-        "from cp.`tpch/nation.parquet` \n" +
-        "window w as (partition by n_name order by n_nationkey)";
-
-    test(query);
+      "from cp.`tpch/nation.parquet` \n" +
+      "window w as (partition by n_name order by n_nationkey)";
+
+    client.queryBuilder()
+      .sql(query)
+      .userExceptionMatcher()
+      .expectedType(UserBitShared.DrillPBError.ErrorType.VALIDATION)
+      .match();
   }
 
   @Test // DRILL-3601
   public void testLeadMissingOver() throws Exception {
-    thrownException.expect(new UserExceptionMatcher(UserBitShared.DrillPBError.ErrorType.VALIDATION));
     String query = "select lead(n_nationkey) from cp.`tpch/nation.parquet`";
 
-    test(query);
+    client.queryBuilder()
+      .sql(query)
+      .userExceptionMatcher()
+      .expectedType(UserBitShared.DrillPBError.ErrorType.VALIDATION)
+      .match();
   }
 
   @Test // DRILL-3649
   public void testMissingOverWithConstant() throws Exception {
-    thrownException.expect(new UserExceptionMatcher(UserBitShared.DrillPBError.ErrorType.VALIDATION));
     String query = "select NTILE(1) from cp.`tpch/nation.parquet`";
 
-    test(query);
+    client.queryBuilder()
+      .sql(query)
+      .userExceptionMatcher()
+      .expectedType(UserBitShared.DrillPBError.ErrorType.VALIDATION)
+      .match();
   }
 
   @Test // DRILL-3344
   public void testWindowGroupBy() throws Exception {
-    thrownException.expect(new UserExceptionMatcher(UserBitShared.DrillPBError.ErrorType.VALIDATION));
     String query = "explain plan for SELECT max(n_nationkey) OVER (), n_name as col2 \n" +
         "from cp.`tpch/nation.parquet` \n" +
         "group by n_name";
 
-    test(query);
+    client.queryBuilder()
+      .sql(query)
+      .userExceptionMatcher()
+      .expectedType(UserBitShared.DrillPBError.ErrorType.VALIDATION)
+      .match();
   }
 
   @Test // DRILL-3346
   @Category(UnlikelyTest.class)
   public void testWindowGroupByOnView() throws Exception {
     try {
-      thrownException.expect(new UserExceptionMatcher(UserBitShared.DrillPBError.ErrorType.VALIDATION));
       String createView = "create view testWindowGroupByOnView(a, b) as \n" +
           "select n_nationkey, n_name from cp.`tpch/nation.parquet`";
       String query = "explain plan for SELECT max(a) OVER (), b as col2 \n" +
           "from testWindowGroupByOnView \n" +
           "group by b";
 
-      test("use dfs.tmp");
-      test(createView);
-      test(query);
+      client.runSqlSilently("use dfs.tmp");
+      client.runSqlSilently(createView);
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .expectedType(UserBitShared.DrillPBError.ErrorType.VALIDATION)
+        .match();
     } finally {
-      test("drop view testWindowGroupByOnView");
+      run("drop view testWindowGroupByOnView");
     }
   }
 
@@ -272,7 +302,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan1 = {"Window.*partition \\{0\\} order by \\[0\\].*SUM\\(\\$0\\)",
         "Scan.*columns=\\[`n_nationKey`\\].*"};
     final String[] excludedPatterns1 = {"Scan.*columns=\\[`\\*`\\].*"};
-    PlanTestBase.testPlanMatchingPatterns(query1, expectedPlan1, excludedPatterns1);
+
+    client.queryBuilder()
+      .sql(query1)
+      .planMatcher()
+      .include(expectedPlan1)
+      .exclude(excludedPatterns1)
+      .match();
 
     testBuilder()
         .sqlQuery(query1)
@@ -309,7 +345,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan2 = {"Window.*partition \\{0\\} order by \\[0\\].*SUM\\(\\$0\\)",
         "Scan.*columns=\\[`n_nationKey`\\].*"};
     final String[] excludedPatterns2 = {"Scan.*columns=\\[`\\*`\\].*"};
-    PlanTestBase.testPlanMatchingPatterns(query2, expectedPlan2, excludedPatterns2);
+
+    client.queryBuilder()
+      .sql(query2)
+      .planMatcher()
+      .include(expectedPlan2)
+      .exclude(excludedPatterns2)
+      .match();
 
     testBuilder()
         .sqlQuery(query2)
@@ -346,7 +388,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan3 = {"Window.*partition \\{0\\}.*SUM\\(\\$0\\)",
         "Scan.*columns=\\[`n_nationKey`\\].*"};
     final String[] excludedPatterns3 = {"Scan.*columns=\\[`\\*`\\].*"};
-    PlanTestBase.testPlanMatchingPatterns(query3, expectedPlan3, excludedPatterns3);
+
+    client.queryBuilder()
+      .sql(query3)
+      .planMatcher()
+      .include(expectedPlan3)
+      .exclude(excludedPatterns3)
+      .match();
 
     testBuilder()
         .sqlQuery(query3)
@@ -393,7 +441,13 @@ public class TestWindowFunctions extends BaseTestQuery {
         "Scan.*columns=\\[`n_nationKey`\\].*",
         "Scan.*columns=\\[`n_nationKey`\\].*"};
     final String[] excludedPatterns = {"Scan.*columns=\\[`\\*`\\].*"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, excludedPatterns);
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(excludedPatterns)
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -416,7 +470,13 @@ public class TestWindowFunctions extends BaseTestQuery {
       final String[] expectedPlan = {"Window.*order by \\[0\\].*COUNT\\(\\)",
           "Scan.*columns=\\[`o_custkey`, `o_orderpriority`\\]"};
       final String[] excludedPatterns = {"Scan.*columns=\\[`\\*`\\]"};
-      PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, excludedPatterns);
+
+      client.queryBuilder()
+        .sql(query)
+        .planMatcher()
+        .include(expectedPlan)
+        .exclude(excludedPatterns)
+        .match();
 
       testBuilder()
           .sqlQuery(query)
@@ -430,7 +490,7 @@ public class TestWindowFunctions extends BaseTestQuery {
           .build()
           .run();
     } finally {
-      test("alter session set `planner.slice_target` = " + ExecConstants.SLICE_TARGET_DEFAULT);
+      run("alter session set `planner.slice_target` = " + ExecConstants.SLICE_TARGET_DEFAULT);
     }
   }
 
@@ -448,7 +508,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan1 = {"Window.*partition \\{0\\} aggs .*SUM\\(\\$0\\), COUNT\\(\\$0\\)",
         "Scan.*columns=\\[`n_nationkey`\\]"};
     final String[] excludedPatterns1 = {"Scan.*columns=\\[`\\*`\\]"};
-    PlanTestBase.testPlanMatchingPatterns(avgQuery, expectedPlan1, excludedPatterns1);
+
+    client.queryBuilder()
+      .sql(avgQuery)
+      .planMatcher()
+      .include(expectedPlan1)
+      .exclude(excludedPatterns1)
+      .match();
 
     testBuilder()
         .sqlQuery(avgQuery)
@@ -465,7 +531,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan2 = {"Window.*partition \\{0\\} aggs .*SUM\\(\\$2\\), SUM\\(\\$1\\), COUNT\\(\\$1\\)",
         "Scan.*columns=\\[`n_nationkey`\\]"};
     final String[] excludedPatterns2 = {"Scan.*columns=\\[`\\*`\\]"};
-    PlanTestBase.testPlanMatchingPatterns(varianceQuery, expectedPlan2, excludedPatterns2);
+
+    client.queryBuilder()
+      .sql(varianceQuery)
+      .planMatcher()
+      .include(expectedPlan2)
+      .exclude(excludedPatterns2)
+      .match();
 
     testBuilder()
         .sqlQuery(varianceQuery)
@@ -484,7 +556,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan1 = {"Window.*partition \\{0\\} aggs .*SUM\\(\\$1\\)",
         "Scan.*columns=\\[`col_varchar`, `col_int`\\]"};
     final String[] excludedPatterns1 = {"Scan.*columns=\\[`\\*`\\]"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan1, excludedPatterns1);
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan1)
+      .exclude(excludedPatterns1)
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -500,7 +578,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan2 = {"Window.*partition \\{0\\} aggs .*SUM\\(\\$1\\), COUNT\\(\\$1\\)",
         "Scan.*columns=\\[`col_varchar`, `col_int`\\]"};
     final String[] excludedPatterns2 = {"Scan.*columns=\\[`\\*`\\]"};
-    PlanTestBase.testPlanMatchingPatterns(avgQuery, expectedPlan2, excludedPatterns2);
+
+    client.queryBuilder()
+      .sql(avgQuery)
+      .planMatcher()
+      .include(expectedPlan2)
+      .exclude(excludedPatterns2)
+      .match();
 
     testBuilder()
         .sqlQuery(avgQuery)
@@ -521,7 +605,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan = {"Window.*partition \\{1\\} order by \\[0 DESC\\].*COUNT\\(\\)",
         "Scan.*columns=\\[`columns`\\[0\\], `columns`\\[1\\]\\]"};
     final String[] excludedPatterns = {"Scan.*columns=\\[`\\*`\\]"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, excludedPatterns);
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(excludedPatterns)
+      .match();
 
     // Validate the result
     testBuilder()
@@ -552,7 +642,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan = {"Window.*order by \\[1\\].*DENSE_RANK\\(\\)",
         "Scan.*columns=\\[`l_partkey`, `l_suppkey`\\]"};
     final String[] excludedPatterns = {"Scan.*columns=\\[`\\*`\\]"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, excludedPatterns);
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(excludedPatterns)
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -570,7 +666,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan = {"Window.*partition \\{1\\} order by \\[0 ASC-nulls-first\\].*SUM\\(\\$0\\)",
         "Scan.*columns=\\[`c1`, `c2`\\]"};
     final String[] excludedPatterns = {"Scan.*columns=\\[`\\*`\\]"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, excludedPatterns);
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(excludedPatterns)
+      .match();
 
     testBuilder()
       .sqlQuery(query)
@@ -593,7 +695,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     final String[] expectedPlan = {"Window.*partition \\{0\\} order by \\[1\\].*RANK\\(\\), \\$SUM0\\(\\$2\\), SUM\\(\\$1\\), \\$SUM0\\(\\$3\\)",
         "Scan.*columns=\\[`position_id`, `employee_id`\\]"};
     final String[] excludedPatterns = {"Scan.*columns=\\[`\\*`\\]"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, excludedPatterns);
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(excludedPatterns)
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -622,7 +730,13 @@ public class TestWindowFunctions extends BaseTestQuery {
         "Window.*partition \\{0\\} order by \\[1\\].*COUNT\\(\\), SUM\\(\\$2\\)",
         "Scan.*columns=\\[`b1`, `c1`, `a1`\\]"};
     final String[] excludedPatterns = {"Scan.*columns=\\[`\\*`\\]"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, excludedPatterns);
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(excludedPatterns)
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -655,7 +769,13 @@ public class TestWindowFunctions extends BaseTestQuery {
         "Window.*partition \\{0\\} order by \\[1\\].*COUNT\\(\\), SUM\\(\\$2\\)",
         "Scan.*columns=\\[`b1`, `c1`, `a1`\\]"};
     final String[] excludedPatterns = {"Scan.*columns=\\[`\\*`\\]"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, excludedPatterns);
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(excludedPatterns)
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -681,12 +801,18 @@ public class TestWindowFunctions extends BaseTestQuery {
     String query = String.format("select sum(a1) over(partition by b1, c1) as s1, sum(a1) over() as s2 \n" +
         "from cp.`%s` \n" +
         "order by a1", root);
-    test("alter session set `planner.slice_target` = 1");
+    run("alter session set `planner.slice_target` = 1");
 
     // Validate the plan
     final String[] expectedPlan = {"Window\\(window#0=\\[window\\(aggs .*\n" +
         ".*UnionExchange"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, new String[]{});
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(new String[]{})
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -720,7 +846,13 @@ public class TestWindowFunctions extends BaseTestQuery {
         ".*Sort.*\n" +
         ".*Window.*\\$SUM0\\(\\$2\\).*"
     };
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, new String[]{});
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(new String[]{})
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -748,7 +880,13 @@ public class TestWindowFunctions extends BaseTestQuery {
 
     // Validate the plan
     final String[] expectedPlan = {"Window\\(window#0=\\[window\\(partition \\{0\\} aggs .*\\[SUM\\(\\$1\\), SUM\\(\\$2\\)\\]"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, new String[]{});
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(new String[]{})
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -777,7 +915,13 @@ public class TestWindowFunctions extends BaseTestQuery {
 
     // Validate the plan
     final String[] expectedPlan = {"Scan.*columns=\\[`n_nationkey`\\].*"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, new String[]{});
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(new String[]{})
+      .match();
 
     testBuilder()
         .sqlQuery(query)
@@ -802,7 +946,7 @@ public class TestWindowFunctions extends BaseTestQuery {
         "          ntile(3) over(PARTITION BY n_regionkey ORDER BY n_nationkey) " +
         "       FROM cp.`tpch/nation.parquet`) " +
         " order by n_regionkey, n_nationkey";
-    test(query);
+    run(query);
 
     final String baselineQuery =
         "select n_nationkey , n_regionkey , " +
@@ -867,7 +1011,13 @@ public class TestWindowFunctions extends BaseTestQuery {
     // Validate the plan
     final String[] expectedPlan = {"Window.*partition \\{0\\} order by \\[0\\].*SUM\\(\\$1\\).*",
             "HashAgg\\(group=\\[\\{0\\}\\].*\\[MIN\\(\\$1\\)\\]\\)"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, new String[]{});
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(new String[]{})
+      .match();
 
     // Validate the results
     testBuilder()
@@ -889,57 +1039,71 @@ public class TestWindowFunctions extends BaseTestQuery {
 
   @Test // DRILL-4795, DRILL-4796
   public void testNestedAggregates1() throws Exception {
-    try {
+    {
       String query = "select sum(min(l_extendedprice)) over (partition by l_suppkey)\n"
               + " from cp.`tpch/nation.parquet` where l_suppkey <= 10";
-      test(query);
-    } catch(UserException ex) {
-      assert(ex.getMessage().contains("Expression 'l_suppkey' is not being grouped"));
-    }
 
-    try {
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include("Expression 'l_suppkey' is not being grouped")
+        .match();
+    }
+    {
       String query = "select sum(min(l_extendedprice)) over (partition by l_suppkey) as totprice\n"
           + " from cp.`tpch/nation.parquet` where l_suppkey <= 10";
-      test(query);
-    } catch(UserException ex) {
-      assert(ex.getMessage().contains("Expression 'l_suppkey' is not being grouped"));
-    }
 
-    try {
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include("Expression 'l_suppkey' is not being grouped")
+        .match();
+    }
+    {
       String query = "select sum(min(l_extendedprice)) over w1 as totprice\n"
           + " from cp.`tpch/nation.parquet` where l_suppkey <= 10\n"
           + " window w1 as (partition by l_suppkey)";
-      test(query);
-    } catch(UserException ex) {
-      assert(ex.getMessage().contains("Expression 'l_suppkey' is not being grouped"));
-    }
 
-    try {
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include("Expression 'l_suppkey' is not being grouped")
+        .match();
+    }
+    {
       String query = "select sum(min(l_extendedprice)) over (partition by n_nationkey)\n"
               + " from cp.`tpch/nation.parquet` where l_suppkey <= 10 group by l_suppkey";
-      test(query);
-    } catch(UserException ex) {
-      assert(ex.getMessage().contains("Expression 'n_nationkey' is not being grouped"));
-    }
 
-    try {
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include("Expression 'n_nationkey' is not being grouped")
+        .match();
+    }
+    {
       String query = "select sum(min(l_extendedprice)) over (partition by n_nationkey) as totprice\n"
           + " from cp.`tpch/nation.parquet` where l_suppkey <= 10 group by l_suppkey";
-      test(query);
-    } catch(UserException ex) {
-      assert(ex.getMessage().contains("Expression 'n_nationkey' is not being grouped"));
-    }
 
-    try {
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include("Expression 'n_nationkey' is not being grouped")
+        .match();
+    }
+    {
       String query = "select sum(min(l_extendedprice)) over w2 as totprice\n"
           + " from cp.`tpch/nation.parquet` where l_suppkey <= 10 group by l_suppkey\n"
           + " window w2 as (partition by n_nationkey)";
-      test(query);
-    } catch(UserException ex) {
-      assert(ex.getMessage().contains("Expression 'n_nationkey' is not being grouped"));
+
+      client.queryBuilder()
+        .sql(query)
+        .userExceptionMatcher()
+        .include("Expression 'n_nationkey' is not being grouped")
+        .match();
     }
   }
 
+
   @Test // DRILL-4469
   public void testWindowOnSubqueryWithStar() throws Exception {
     String query = "SELECT SUM(n_nationkey) OVER w as s\n" +
@@ -948,7 +1112,13 @@ public class TestWindowFunctions extends BaseTestQuery {
         "limit 1";
 
     final String[] expectedPlan = {"Scan.*columns=\\[`n_nationkey`, `region`\\].*"};
-    PlanTestBase.testPlanMatchingPatterns(query, expectedPlan, new String[]{});
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(new String[]{})
+      .match();
 
     testBuilder()
         .sqlQuery(query)
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/client/DrillClientStateTest.java b/exec/java-exec/src/test/java/org/apache/drill/exec/client/DrillClientStateTest.java
index 0a25e6e8d4..f5db7053a3 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/client/DrillClientStateTest.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/client/DrillClientStateTest.java
@@ -22,22 +22,29 @@ import org.apache.drill.common.config.DrillConfig;
 import org.apache.drill.exec.ExecConstants;
 import org.apache.drill.exec.TestWithZookeeper;
 import org.apache.drill.exec.coord.zk.ZKClusterCoordinator;
+import org.hamcrest.MatcherAssert;
+import org.junit.Assert;
 import org.junit.Test;
 
+import static org.hamcrest.core.Is.is;
+
 public class DrillClientStateTest extends TestWithZookeeper {
 
   @Test
   public void testNotExistZkRoot() throws Exception {
     // There is no drillbit startup, therefore the root path is not saved in ZK.
-    thrownException.expect(NullPointerException.class);
-    thrownException.expectMessage("root path does not exist");
     DrillConfig config = DrillConfig.create();
     String connString = zkHelper.getConnectionString();
     String zkRoot = config.getString(ExecConstants.ZK_ROOT); // does not exist
-    connString = connString + ZKPaths.PATH_SEPARATOR + zkRoot;
-    try (ZKClusterCoordinator coordinator = new ZKClusterCoordinator(config, connString)) {
-      coordinator.start(10000);
-    }
+    String connStringWithZKRoot = connString + ZKPaths.PATH_SEPARATOR + zkRoot;
+
+    NullPointerException nullPointerException = Assert.assertThrows(NullPointerException.class, () -> {
+      try (ZKClusterCoordinator coordinator = new ZKClusterCoordinator(config, connStringWithZKRoot)) {
+        coordinator.start(10000);
+      }
+    });
+
+    MatcherAssert.assertThat(nullPointerException.getMessage(), is("The root path does not exist in the Zookeeper."));
   }
 
 }
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/BaseTestImpersonation.java b/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/BaseTestImpersonation.java
index 6ae2869b71..f1d471d09e 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/BaseTestImpersonation.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/BaseTestImpersonation.java
@@ -17,16 +17,19 @@
  */
 package org.apache.drill.exec.impersonation;
 
-import org.apache.drill.shaded.guava.com.google.common.base.Preconditions;
-import org.apache.drill.shaded.guava.com.google.common.base.Strings;
 import org.apache.commons.io.FileUtils;
-import org.apache.drill.PlanTestBase;
 import org.apache.drill.common.config.DrillConfig;
 import org.apache.drill.exec.ExecConstants;
 import org.apache.drill.exec.dotdrill.DotDrillType;
 import org.apache.drill.exec.store.StoragePluginRegistry;
 import org.apache.drill.exec.store.dfs.FileSystemConfig;
 import org.apache.drill.exec.store.dfs.WorkspaceConfig;
+import org.apache.drill.shaded.guava.com.google.common.base.Preconditions;
+import org.apache.drill.shaded.guava.com.google.common.base.Strings;
+import org.apache.drill.test.ClientFixture;
+import org.apache.drill.test.ClusterFixture;
+import org.apache.drill.test.ClusterFixtureBuilder;
+import org.apache.drill.test.ClusterTest;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileSystem;
@@ -43,7 +46,7 @@ import java.util.Properties;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-public class BaseTestImpersonation extends PlanTestBase {
+public class BaseTestImpersonation extends ClusterTest {
   protected static final String MINI_DFS_STORAGE_PLUGIN_NAME = "mini_dfs_plugin";
   protected static final String processUser = System.getProperty("user.name");
 
@@ -112,19 +115,28 @@ public class BaseTestImpersonation extends PlanTestBase {
   }
 
   protected static void startDrillCluster(final boolean isImpersonationEnabled) throws Exception {
-    final Properties props = cloneDefaultTestConfigProperties();
+    final Properties props = new Properties();
     props.setProperty(ExecConstants.IMPERSONATION_ENABLED, Boolean.toString(isImpersonationEnabled));
-    startDrillCluster(props);
+    startDrillCluster(1, props);
   }
 
-  protected static void startDrillCluster(final Properties props) throws Exception {
-    updateTestCluster(1, DrillConfig.create(props));
+  protected static void startDrillCluster(int newDrillbitCount, final Properties props) throws Exception {
+    startDrillCluster(newDrillbitCount, null, props);
+  }
+
+  protected static void startDrillCluster(int newDrillbitCount, final DrillConfig configs, final Properties props) throws Exception {
+    ClusterFixtureBuilder builder = ClusterFixture.builder(dirTestWatcher).clusterSize(newDrillbitCount);
+    builder.configBuilder().configProps(props);
+    if (configs != null) {
+      builder.configBuilder().configProps(configs);
+    }
+    startCluster(builder);
   }
 
   protected static void addMiniDfsBasedStorage(final Map<String, WorkspaceConfig> workspaces) throws Exception {
     // Create a HDFS based storage plugin based on local storage plugin and add it to plugin registry (connection string
     // for mini dfs is varies for each run).
-    StoragePluginRegistry pluginRegistry = getDrillbitContext().getStorage();
+    StoragePluginRegistry pluginRegistry = cluster.storageRegistry();
     FileSystemConfig lfsPluginConfig = (FileSystemConfig) pluginRegistry.getPlugin("dfs").getConfig();
 
     String connection = dfsConf.get(FileSystem.FS_DEFAULT_NAME_KEY);
@@ -177,25 +189,27 @@ public class BaseTestImpersonation extends PlanTestBase {
 
   protected static void createView(final String viewOwner, final String viewGroup, final short viewPerms,
                                  final String newViewName, final String fromSourceSchema, final String fromSourceTableName) throws Exception {
-    updateClient(viewOwner);
-    test(String.format("ALTER SESSION SET `%s`='%o';", ExecConstants.NEW_VIEW_DEFAULT_PERMS_KEY, viewPerms));
-    test(String.format("CREATE VIEW %s.%s AS SELECT * FROM %s.%s;",
-      getWSSchema(viewOwner), newViewName, fromSourceSchema, fromSourceTableName));
-
-    // Verify the view file created has the expected permissions and ownership
-    Path viewFilePath = new Path(getUserHome(viewOwner), newViewName + DotDrillType.VIEW.getEnding());
-    FileStatus status = fs.getFileStatus(viewFilePath);
-    assertEquals(viewGroup, status.getGroup());
-    assertEquals(viewOwner, status.getOwner());
-    assertEquals(viewPerms, status.getPermission().toShort());
+    try (ClientFixture client = cluster.client(viewOwner, "")) {
+      client.run(String.format("ALTER SESSION SET `%s`='%o'", ExecConstants.NEW_VIEW_DEFAULT_PERMS_KEY, viewPerms));
+      client.run(String.format("CREATE VIEW %s.%s AS SELECT * FROM %s.%s",
+        getWSSchema(viewOwner), newViewName, fromSourceSchema, fromSourceTableName));
+
+      // Verify the view file created has the expected permissions and ownership
+      Path viewFilePath = new Path(getUserHome(viewOwner), newViewName + DotDrillType.VIEW.getEnding());
+      FileStatus status = fs.getFileStatus(viewFilePath);
+      assertEquals(viewGroup, status.getGroup());
+      assertEquals(viewOwner, status.getOwner());
+      assertEquals(viewPerms, status.getPermission().toShort());
+    }
   }
 
   protected static void createView(final String viewOwner, final String viewGroup, final String viewName,
                                  final String viewDef) throws Exception {
-    updateClient(viewOwner);
-    test(String.format("ALTER SESSION SET `%s`='%o';", ExecConstants.NEW_VIEW_DEFAULT_PERMS_KEY, (short) 0750));
-    test("CREATE VIEW %s.%s.%s AS %s", MINI_DFS_STORAGE_PLUGIN_NAME, "tmp", viewName, viewDef);
-    final Path viewFilePath = new Path("/tmp/", viewName + DotDrillType.VIEW.getEnding());
-    fs.setOwner(viewFilePath, viewOwner, viewGroup);
+    try (ClientFixture client = cluster.client(viewOwner, "")) {
+      client.run(String.format("ALTER SESSION SET `%s`='%o'", ExecConstants.NEW_VIEW_DEFAULT_PERMS_KEY, (short) 0750));
+      client.run("CREATE VIEW %s.%s.%s AS %s", MINI_DFS_STORAGE_PLUGIN_NAME, "tmp", viewName, viewDef);
+      final Path viewFilePath = new Path("/tmp/", viewName + DotDrillType.VIEW.getEnding());
+      fs.setOwner(viewFilePath, viewOwner, viewGroup);
+    }
   }
 }
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationDisabledWithMiniDFS.java b/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationDisabledWithMiniDFS.java
index 10f5d49e59..49e1b4a3a8 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationDisabledWithMiniDFS.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationDisabledWithMiniDFS.java
@@ -45,11 +45,11 @@ public class TestImpersonationDisabledWithMiniDFS extends BaseTestImpersonation
 
   private static void createTestData() throws Exception {
     // Create test table in minidfs.tmp schema for use in test queries
-    test(String.format("CREATE TABLE %s.tmp.dfsRegion AS SELECT * FROM cp.`region.json`", MINI_DFS_STORAGE_PLUGIN_NAME));
+    run(String.format("CREATE TABLE %s.tmp.dfsRegion AS SELECT * FROM cp.`region.json`", MINI_DFS_STORAGE_PLUGIN_NAME));
 
     // generate a large enough file that the DFS will not fulfill requests to read a
     // page of data all at once, see notes above testReadLargeParquetFileFromDFS()
-    test(String.format(
+    run(String.format(
         "CREATE TABLE %s.tmp.large_employee AS " +
             "(SELECT employee_id, full_name FROM cp.`employee.json`) " +
             "UNION ALL (SELECT employee_id, full_name FROM cp.`employee.json`)" +
@@ -75,8 +75,8 @@ public class TestImpersonationDisabledWithMiniDFS extends BaseTestImpersonation
    */
   @Test
   public void testReadLargeParquetFileFromDFS() throws Exception {
-    test(String.format("USE %s", MINI_DFS_STORAGE_PLUGIN_NAME));
-    test("SELECT * FROM tmp.`large_employee`");
+    run(String.format("USE %s", MINI_DFS_STORAGE_PLUGIN_NAME));
+    run("SELECT * FROM tmp.`large_employee`");
   }
 
   @Test // DRILL-3037
@@ -96,7 +96,7 @@ public class TestImpersonationDisabledWithMiniDFS extends BaseTestImpersonation
 
   @AfterClass
   public static void removeMiniDfsBasedStorage() throws Exception {
-    getDrillbitContext().getStorage().remove(MINI_DFS_STORAGE_PLUGIN_NAME);
+    cluster.storageRegistry().remove(MINI_DFS_STORAGE_PLUGIN_NAME);
     stopMiniDfsCluster();
   }
 }
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationMetadata.java b/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationMetadata.java
index b9b191958f..ed25a6453a 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationMetadata.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationMetadata.java
@@ -17,32 +17,37 @@
  */
 package org.apache.drill.exec.impersonation;
 
-import java.util.Map;
 import org.apache.drill.categories.SecurityTest;
 import org.apache.drill.categories.SlowTest;
 import org.apache.drill.categories.UnlikelyTest;
 import org.apache.drill.common.exceptions.UserException;
 import org.apache.drill.common.exceptions.UserRemoteException;
 import org.apache.drill.exec.dotdrill.DotDrillType;
+import org.apache.drill.exec.rpc.user.QueryDataBatch;
 import org.apache.drill.exec.store.StoragePluginRegistry.PluginException;
 import org.apache.drill.exec.store.dfs.WorkspaceConfig;
 import org.apache.drill.shaded.guava.com.google.common.base.Joiner;
 import org.apache.drill.shaded.guava.com.google.common.collect.Maps;
+import org.apache.drill.test.ClientFixture;
 import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.permission.FsPermission;
 import org.apache.hadoop.security.UserGroupInformation;
-import static org.hamcrest.core.StringContains.containsString;
-import org.junit.AfterClass;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import org.junit.BeforeClass;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.rules.ExpectedException;
 
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
 /**
  * Tests impersonation on metadata related queries as SHOW FILES, SHOW TABLES, CREATE VIEW, CREATE TABLE and DROP TABLE
  */
@@ -62,8 +67,8 @@ public class TestImpersonationMetadata extends BaseTestImpersonation {
   @Rule
   public ExpectedException thrown = ExpectedException.none();
 
-  @BeforeClass
-  public static void setup() throws Exception {
+  @Before
+  public void setup() throws Exception {
     startMiniDfsCluster(TestImpersonationMetadata.class.getSimpleName());
     startDrillCluster(true);
     addMiniDfsBasedStorage(createTestWorkspaces());
@@ -108,78 +113,100 @@ public class TestImpersonationMetadata extends BaseTestImpersonation {
   public void testDropTable() throws Exception {
 
     // create tables as user2
-    updateClient(user2);
-    test("use `%s.user2_workspace1`", MINI_DFS_STORAGE_PLUGIN_NAME);
-    // create a table that can be dropped by another user in a different group
-    test("create table parquet_table_775 as select * from cp.`employee.json`");
-
-    // create a table that cannot be dropped by another user
-    test("use `%s.user2_workspace2`", MINI_DFS_STORAGE_PLUGIN_NAME);
-    test("create table parquet_table_700 as select * from cp.`employee.json`");
+    try (ClientFixture client = cluster.client(user2, "")) {
+      client.run("use `%s.user2_workspace1`", MINI_DFS_STORAGE_PLUGIN_NAME);
+      // create a table that can be dropped by another user in a different group
+      client.run("create table parquet_table_775 as select * from cp.`employee.json`");
+
+      // create a table that cannot be dropped by another user
+      client.run("use `%s.user2_workspace2`", MINI_DFS_STORAGE_PLUGIN_NAME);
+      client.run("create table parquet_table_700 as select * from cp.`employee.json`");
+    }
 
     // Drop tables as user1
-    updateClient(user1);
-    test("use `%s.user2_workspace1`", MINI_DFS_STORAGE_PLUGIN_NAME);
-    testBuilder()
-        .sqlQuery("drop table parquet_table_775")
-        .unOrdered()
-        .baselineColumns("ok", "summary")
-        .baselineValues(true, String.format("Table [%s] dropped", "parquet_table_775"))
-        .go();
-
-    test("use `%s.user2_workspace2`", MINI_DFS_STORAGE_PLUGIN_NAME);
-    boolean dropFailed = false;
-    try {
-      test("drop table parquet_table_700");
-    } catch (UserException e) {
-      assertTrue(e.getMessage().contains("PERMISSION ERROR"));
-      dropFailed = true;
+    try (ClientFixture client = cluster.client(user1, "")) {
+      client.run("use `%s.user2_workspace1`", MINI_DFS_STORAGE_PLUGIN_NAME);
+      client.testBuilder()
+          .sqlQuery("drop table parquet_table_775")
+          .unOrdered()
+          .baselineColumns("ok", "summary")
+          .baselineValues(true, String.format("Table [%s] dropped", "parquet_table_775"))
+          .go();
+
+      client.run("use `%s.user2_workspace2`", MINI_DFS_STORAGE_PLUGIN_NAME);
+      boolean dropFailed = false;
+      try {
+        client.run("drop table parquet_table_700");
+      } catch (UserException e) {
+        assertTrue(e.getMessage().contains("PERMISSION ERROR"));
+        dropFailed = true;
+      }
+      assertTrue("Permission checking failed during drop table", dropFailed);
     }
-    assertTrue("Permission checking failed during drop table", dropFailed);
   }
 
   @Test // DRILL-3037
   @Category(UnlikelyTest.class)
   public void testImpersonatingProcessUser() throws Exception {
-    updateClient(processUser);
-
-    // Process user start the mini dfs, he has read/write permissions by default
-    final String viewName = String.format("%s.drill_test_grp_0_700.testView", MINI_DFS_STORAGE_PLUGIN_NAME);
-    try {
-      test("CREATE VIEW " + viewName + " AS SELECT * FROM cp.`region.json`");
-      test("SELECT * FROM " + viewName + " LIMIT 2");
-    } finally {
-      test("DROP VIEW " + viewName);
+    try (ClientFixture client = cluster.client(processUser, "")) {
+
+      // Process user start the mini dfs, he has read/write permissions by default
+      final String viewName = String.format("%s.drill_test_grp_0_700.testView", MINI_DFS_STORAGE_PLUGIN_NAME);
+      try {
+        client.run("CREATE VIEW " + viewName + " AS SELECT * FROM cp.`region.json`");
+        client.run("SELECT * FROM " + viewName + " LIMIT 2");
+      } finally {
+        client.run("DROP VIEW " + viewName);
+      }
     }
   }
 
   @Test
   public void testShowFilesInWSWithUserAndGroupPermissionsForQueryUser() throws Exception {
-    updateClient(user1);
-
-    // Try show tables in schema "drill_test_grp_1_700" which is owned by "user1"
-    int count = testSql(String.format("SHOW FILES IN %s.drill_test_grp_1_700", MINI_DFS_STORAGE_PLUGIN_NAME));
-    assertTrue(count > 0);
-
-    // Try show tables in schema "drill_test_grp_0_750" which is owned by "processUser" and has group permissions for "user1"
-    count = testSql(String.format("SHOW FILES IN %s.drill_test_grp_0_750", MINI_DFS_STORAGE_PLUGIN_NAME));
-    assertTrue(count > 0);
+    try (ClientFixture client = cluster.client(user1, "")) {
+      {
+        // Try show tables in schema "drill_test_grp_1_700" which is owned by
+        // "user1"
+        List<QueryDataBatch> results = client
+          .queryBuilder()
+          .sql("SHOW FILES IN %s.drill_test_grp_1_700", MINI_DFS_STORAGE_PLUGIN_NAME)
+          .results();
+        assertTrue(client.countResults(results) > 0);
+        results.forEach(r -> r.release());
+      }
+      {
+        // Try show tables in schema "drill_test_grp_0_750" which is owned by
+        // "processUser" and has group permissions for "user1"
+        List<QueryDataBatch> results = client
+          .queryBuilder()
+          .sql("SHOW FILES IN %s.drill_test_grp_0_750", MINI_DFS_STORAGE_PLUGIN_NAME)
+          .results();
+        assertTrue(client.countResults(results) > 0);
+        results.forEach(r -> r.release());
+      }
+    }
   }
 
   @Test
   public void testShowFilesInWSWithOtherPermissionsForQueryUser() throws Exception {
-    updateClient(user2);
-    // Try show tables in schema "drill_test_grp_0_755" which is owned by "processUser" and group0. "user2" is not part of the "group0"
-    int count = testSql(String.format("SHOW FILES IN %s.drill_test_grp_0_755", MINI_DFS_STORAGE_PLUGIN_NAME));
-    assertTrue(count > 0);
+    try (ClientFixture client = cluster.client(user2, "")) {
+      // Try show tables in schema "drill_test_grp_0_755" which is owned by "processUser" and group0. "user2" is not part of the "group0"
+      List<QueryDataBatch> results = client.queryBuilder().sql(
+        String.format("SHOW FILES IN %s.drill_test_grp_0_755", MINI_DFS_STORAGE_PLUGIN_NAME)).results();
+      assertTrue(client.countResults(results) > 0);
+      results.forEach(r -> r.release());
+    }
   }
 
   @Test
   public void testShowFilesInWSWithNoPermissionsForQueryUser() throws Exception {
-    updateClient(user2);
-    // Try show tables in schema "drill_test_grp_1_700" which is owned by "user1"
-    int count = testSql(String.format("SHOW FILES IN %s.drill_test_grp_1_700", MINI_DFS_STORAGE_PLUGIN_NAME));
-    assertEquals(0, count);
+    try (ClientFixture client = cluster.client(user2, "")) {
+      // Try show tables in schema "drill_test_grp_1_700" which is owned by "user1"
+      List<QueryDataBatch> results = client.queryBuilder().sql(
+        String.format("SHOW FILES IN %s.drill_test_grp_1_700", MINI_DFS_STORAGE_PLUGIN_NAME)).results();
+      assertEquals(0, client.countResults(results));
+      results.forEach(r -> r.release());
+    }
   }
 
   @Test
@@ -188,31 +215,33 @@ public class TestImpersonationMetadata extends BaseTestImpersonation {
     // drill_test_grp_1_700 (through ownership)
     // drill_test_grp_0_750, drill_test_grp_0_770 (through "group" category permissions)
     // drill_test_grp_0_755, drill_test_grp_0_777 (through "others" category permissions)
-    updateClient(user1);
-    testBuilder()
-        .sqlQuery("SHOW SCHEMAS LIKE '%drill_test%'")
-        .unOrdered()
-        .baselineColumns("SCHEMA_NAME")
-        .baselineValues(String.format("%s.drill_test_grp_0_750", MINI_DFS_STORAGE_PLUGIN_NAME))
-        .baselineValues(String.format("%s.drill_test_grp_0_755", MINI_DFS_STORAGE_PLUGIN_NAME))
-        .baselineValues(String.format("%s.drill_test_grp_0_770", MINI_DFS_STORAGE_PLUGIN_NAME))
-        .baselineValues(String.format("%s.drill_test_grp_0_777", MINI_DFS_STORAGE_PLUGIN_NAME))
-        .baselineValues(String.format("%s.drill_test_grp_1_700", MINI_DFS_STORAGE_PLUGIN_NAME))
-        .go();
+    try (ClientFixture client = cluster.client(user1, "")) {
+      client.testBuilder()
+          .sqlQuery("SHOW SCHEMAS LIKE '%drill_test%'")
+          .unOrdered()
+          .baselineColumns("SCHEMA_NAME")
+          .baselineValues(String.format("%s.drill_test_grp_0_750", MINI_DFS_STORAGE_PLUGIN_NAME))
+          .baselineValues(String.format("%s.drill_test_grp_0_755", MINI_DFS_STORAGE_PLUGIN_NAME))
+          .baselineValues(String.format("%s.drill_test_grp_0_770", MINI_DFS_STORAGE_PLUGIN_NAME))
+          .baselineValues(String.format("%s.drill_test_grp_0_777", MINI_DFS_STORAGE_PLUGIN_NAME))
+          .baselineValues(String.format("%s.drill_test_grp_1_700", MINI_DFS_STORAGE_PLUGIN_NAME))
+          .go();
+    }
   }
 
   @Test
   public void testShowSchemasAsUser2() throws Exception {
     // "user2" is part of "group0", but part of "group1" and has access to following workspaces
     // drill_test_grp_0_755, drill_test_grp_0_777 (through "others" category permissions)
-    updateClient(user2);
-    testBuilder()
-        .sqlQuery("SHOW SCHEMAS LIKE '%drill_test%'")
-        .unOrdered()
-        .baselineColumns("SCHEMA_NAME")
-        .baselineValues(String.format("%s.drill_test_grp_0_755", MINI_DFS_STORAGE_PLUGIN_NAME))
-        .baselineValues(String.format("%s.drill_test_grp_0_777", MINI_DFS_STORAGE_PLUGIN_NAME))
-        .go();
+    try (ClientFixture client = cluster.client(user2, "")) {
+      client.testBuilder()
+          .sqlQuery("SHOW SCHEMAS LIKE '%drill_test%'")
+          .unOrdered()
+          .baselineColumns("SCHEMA_NAME")
+          .baselineValues(String.format("%s.drill_test_grp_0_755", MINI_DFS_STORAGE_PLUGIN_NAME))
+          .baselineValues(String.format("%s.drill_test_grp_0_777", MINI_DFS_STORAGE_PLUGIN_NAME))
+          .go();
+    }
   }
 
   @Test
@@ -237,32 +266,31 @@ public class TestImpersonationMetadata extends BaseTestImpersonation {
 
   private static void testCreateViewTestHelper(String user, String viewSchema,
       String viewName) throws Exception {
-    try {
-      updateClient(user);
-
-      test("USE " + viewSchema);
-
-      test("CREATE VIEW " + viewName + " AS SELECT " +
-          "c_custkey, c_nationkey FROM cp.`tpch/customer.parquet` ORDER BY c_custkey;");
-
-      testBuilder()
-          .sqlQuery("SHOW TABLES")
-          .unOrdered()
-          .baselineColumns("TABLE_SCHEMA", "TABLE_NAME")
-          .baselineValues(viewSchema, viewName)
-          .go();
-
-      test("SHOW FILES");
-
-      testBuilder()
-          .sqlQuery("SELECT * FROM " + viewName + " LIMIT 1")
-          .ordered()
-          .baselineColumns("c_custkey", "c_nationkey")
-          .baselineValues(1, 15)
-          .go();
-
-    } finally {
-      test("DROP VIEW " + viewSchema + "." + viewName);
+    try (ClientFixture client = cluster.client(user, "")) {
+      try {
+        client.run("USE " + viewSchema);
+        client.run("CREATE VIEW " + viewName + " AS SELECT " +
+            "c_custkey, c_nationkey FROM cp.`tpch/customer.parquet` ORDER BY c_custkey");
+
+        client.testBuilder()
+            .sqlQuery("SHOW TABLES")
+            .unOrdered()
+            .baselineColumns("TABLE_SCHEMA", "TABLE_NAME")
+            .baselineValues(viewSchema, viewName)
+            .go();
+
+        client.run("SHOW FILES");
+
+        client.testBuilder()
+            .sqlQuery("SELECT * FROM " + viewName + " LIMIT 1")
+            .ordered()
+            .baselineColumns("c_custkey", "c_nationkey")
+            .baselineValues(1, 15)
+            .go();
+
+      } finally {
+        client.run("DROP VIEW " + viewSchema + "." + viewName);
+      }
     }
   }
 
@@ -273,24 +301,25 @@ public class TestImpersonationMetadata extends BaseTestImpersonation {
     final String viewSchema = MINI_DFS_STORAGE_PLUGIN_NAME + "." + tableWS;
     final String viewName = "view1";
 
-    updateClient(user2);
+    try (ClientFixture client = cluster.client(user2, "")) {
 
-    test("USE " + viewSchema);
+      client.run("USE " + viewSchema);
 
-    String expErrorMsg = "PERMISSION ERROR: Permission denied: user=drillTestUser2, access=WRITE, inode=\"/" + tableWS;
-    thrown.expect(UserRemoteException.class);
-    thrown.expectMessage(containsString(expErrorMsg));
+      String expErrorMsg = "PERMISSION ERROR: Permission denied: user=drillTestUser2, access=WRITE, inode=\"/" + tableWS;
+      thrown.expect(UserRemoteException.class);
+      thrown.expectMessage(containsString(expErrorMsg));
 
-    test("CREATE VIEW %s AS" +
-        " SELECT c_custkey, c_nationkey FROM cp.`tpch/customer.parquet` ORDER BY c_custkey", viewName);
+      client.run("CREATE VIEW %s AS" +
+          " SELECT c_custkey, c_nationkey FROM cp.`tpch/customer.parquet` ORDER BY c_custkey", viewName);
 
-    // SHOW TABLES is expected to return no records as view creation fails above.
-    testBuilder()
-        .sqlQuery("SHOW TABLES")
-        .expectsEmptyResultSet()
-        .go();
+      // SHOW TABLES is expected to return no records as view creation fails above.
+      client.testBuilder()
+          .sqlQuery("SHOW TABLES")
+          .expectsEmptyResultSet()
+          .go();
 
-    test("SHOW FILES");
+      client.run("SHOW FILES");
+    }
   }
 
   @Test
@@ -316,21 +345,22 @@ public class TestImpersonationMetadata extends BaseTestImpersonation {
   private static void testCreateTableTestHelper(String user, String tableWS,
       String tableName) throws Exception {
     try {
-      updateClient(user);
+      try (ClientFixture client = cluster.client(user, "")) {
 
-      test("USE " + Joiner.on(".").join(MINI_DFS_STORAGE_PLUGIN_NAME, tableWS));
+        client.run("USE " + Joiner.on(".").join(MINI_DFS_STORAGE_PLUGIN_NAME, tableWS));
 
-      test("CREATE TABLE " + tableName + " AS SELECT " +
-          "c_custkey, c_nationkey FROM cp.`tpch/customer.parquet` ORDER BY c_custkey;");
+        client.run("CREATE TABLE " + tableName + " AS SELECT " +
+            "c_custkey, c_nationkey FROM cp.`tpch/customer.parquet` ORDER BY c_custkey");
 
-      test("SHOW FILES");
+        client.run("SHOW FILES");
 
-      testBuilder()
-          .sqlQuery("SELECT * FROM " + tableName + " LIMIT 1")
-          .ordered()
-          .baselineColumns("c_custkey", "c_nationkey")
-          .baselineValues(1, 15)
-          .go();
+        client.testBuilder()
+            .sqlQuery("SELECT * FROM " + tableName + " LIMIT 1")
+            .ordered()
+            .baselineColumns("c_custkey", "c_nationkey")
+            .baselineValues(1, 15)
+            .go();
+      }
 
     } finally {
       // There is no drop table, we need to delete the table directory through FileSystem object
@@ -347,15 +377,16 @@ public class TestImpersonationMetadata extends BaseTestImpersonation {
     String tableWS = "drill_test_grp_0_755";
     String tableName = "table1";
 
-    updateClient(user2);
-    test("use %s.`%s`", MINI_DFS_STORAGE_PLUGIN_NAME, tableWS);
+    try (ClientFixture client = cluster.client(user2, "")) {
+      client.run("use %s.`%s`", MINI_DFS_STORAGE_PLUGIN_NAME, tableWS);
 
-    thrown.expect(UserRemoteException.class);
-    thrown.expectMessage(containsString("Permission denied: user=drillTestUser2, " +
-        "access=WRITE, inode=\"/" + tableWS));
+      thrown.expect(UserRemoteException.class);
+      thrown.expectMessage(containsString("Permission denied: user=drillTestUser2, " +
+          "access=WRITE, inode=\"/" + tableWS));
 
-    test("CREATE TABLE %s AS SELECT c_custkey, c_nationkey " +
-        "FROM cp.`tpch/customer.parquet` ORDER BY c_custkey", tableName);
+      client.run("CREATE TABLE %s AS SELECT c_custkey, c_nationkey " +
+          "FROM cp.`tpch/customer.parquet` ORDER BY c_custkey", tableName);
+    }
   }
 
   @Test
@@ -363,22 +394,22 @@ public class TestImpersonationMetadata extends BaseTestImpersonation {
     final String tableName = "nation1";
     final String tableWS = "drill_test_grp_1_700";
 
-    updateClient(user1);
-    test("USE " + Joiner.on(".").join(MINI_DFS_STORAGE_PLUGIN_NAME, tableWS));
-
-    test("CREATE TABLE " + tableName + " partition by (n_regionkey) AS SELECT * " +
-              "FROM cp.`tpch/nation.parquet`;");
+    try (ClientFixture client = cluster.client(user1, "")) {
+      client.run("USE " + Joiner.on(".").join(MINI_DFS_STORAGE_PLUGIN_NAME, tableWS));
 
-    test( "refresh table metadata " + tableName + ";");
+      client.run("CREATE TABLE " + tableName + " partition by (n_regionkey) AS SELECT * " +
+                "FROM cp.`tpch/nation.parquet`");
 
-    test("SELECT * FROM " + tableName + ";");
+      client.run( "refresh table metadata " + tableName);
 
-    final Path tablePath = new Path(Path.SEPARATOR + tableWS + Path.SEPARATOR + tableName);
-    assertTrue ( fs.exists(tablePath) && fs.isDirectory(tablePath));
-    fs.mkdirs(new Path(tablePath, "tmp5"));
+      client.run("SELECT * FROM " + tableName);
 
-    test("SELECT * from " + tableName + ";");
+      final Path tablePath = new Path(Path.SEPARATOR + tableWS + Path.SEPARATOR + tableName);
+      assertTrue ( fs.exists(tablePath) && fs.isDirectory(tablePath));
+      fs.mkdirs(new Path(tablePath, "tmp5"));
 
+      client.run("SELECT * from " + tableName);
+    }
   }
 
   @Test
@@ -386,29 +417,30 @@ public class TestImpersonationMetadata extends BaseTestImpersonation {
     final String tableName = "nation1_stats";
     final String tableWS = "drill_test_grp_1_700";
 
-    updateClient(user1);
-    test("USE " + Joiner.on(".").join(MINI_DFS_STORAGE_PLUGIN_NAME, tableWS));
-    test("ALTER SESSION SET `store.format` = 'parquet'");
-    test("CREATE TABLE " + tableName + " AS SELECT * FROM cp.`tpch/nation.parquet`;");
-    test("ANALYZE TABLE " + tableName + " COMPUTE STATISTICS;");
-    test("SELECT * FROM " + tableName + ";");
+    try (ClientFixture client = cluster.client(user1, "")) {
+      client.run("USE " + Joiner.on(".").join(MINI_DFS_STORAGE_PLUGIN_NAME, tableWS));
+      client.run("ALTER SESSION SET `store.format` = 'parquet'");
+      client.run("CREATE TABLE " + tableName + " AS SELECT * FROM cp.`tpch/nation.parquet`");
+      client.run("ANALYZE TABLE " + tableName + " COMPUTE STATISTICS");
+      client.run("SELECT * FROM " + tableName);
 
-    final Path statsFilePath = new Path(Path.SEPARATOR + tableWS + Path.SEPARATOR + tableName
-        + Path.SEPARATOR + DotDrillType.STATS.getEnding());
-    assertTrue (fs.exists(statsFilePath) && fs.isDirectory(statsFilePath));
-    FileStatus status = fs.getFileStatus(statsFilePath);
-    // Verify process user is the directory owner
-    assert(processUser.equalsIgnoreCase(status.getOwner()));
+      final Path statsFilePath = new Path(Path.SEPARATOR + tableWS + Path.SEPARATOR + tableName
+          + Path.SEPARATOR + DotDrillType.STATS.getEnding());
+      assertTrue (fs.exists(statsFilePath) && fs.isDirectory(statsFilePath));
+      FileStatus status = fs.getFileStatus(statsFilePath);
+      // Verify process user is the directory owner
+      assert(processUser.equalsIgnoreCase(status.getOwner()));
 
-    fs.mkdirs(new Path(statsFilePath, "tmp5"));
+      fs.mkdirs(new Path(statsFilePath, "tmp5"));
 
-    test("SELECT * from " + tableName + ";");
-    test("DROP TABLE " + tableName);
+      client.run("SELECT * from " + tableName);
+      client.run("DROP TABLE " + tableName);
+    }
   }
 
-  @AfterClass
-  public static void removeMiniDfsBasedStorage() throws PluginException {
-    getDrillbitContext().getStorage().remove(MINI_DFS_STORAGE_PLUGIN_NAME);
+  @After
+  public void removeMiniDfsBasedStorage() throws PluginException {
+    cluster.storageRegistry().remove(MINI_DFS_STORAGE_PLUGIN_NAME);
     stopMiniDfsCluster();
   }
 }
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationQueries.java b/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationQueries.java
index d149689d5c..fcaeac246c 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationQueries.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestImpersonationQueries.java
@@ -17,14 +17,15 @@
  */
 package org.apache.drill.exec.impersonation;
 
-import org.apache.drill.exec.store.StoragePluginRegistry.PluginException;
-import org.apache.drill.exec.store.avro.AvroDataGenerator;
-import org.apache.drill.shaded.guava.com.google.common.collect.Maps;
 import org.apache.drill.categories.SecurityTest;
+import org.apache.drill.categories.SlowTest;
 import org.apache.drill.common.exceptions.UserRemoteException;
 import org.apache.drill.common.util.DrillFileUtils;
+import org.apache.drill.exec.store.StoragePluginRegistry.PluginException;
+import org.apache.drill.exec.store.avro.AvroDataGenerator;
 import org.apache.drill.exec.store.dfs.WorkspaceConfig;
-import org.apache.drill.categories.SlowTest;
+import org.apache.drill.shaded.guava.com.google.common.collect.Maps;
+import org.apache.drill.test.ClientFixture;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.permission.FsPermission;
@@ -35,9 +36,9 @@ import org.junit.experimental.categories.Category;
 
 import java.util.Map;
 
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.StringContains.containsString;
 import static org.junit.Assert.assertNotNull;
-import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertNull;
 
 /**
@@ -96,16 +97,16 @@ public class TestImpersonationQueries extends BaseTestImpersonation {
   }
 
   private static void createTestTable(String user, String group, String tableName) throws Exception {
-    updateClient(user);
-    test("USE " + getWSSchema(user));
-    test("CREATE TABLE %s as SELECT * FROM cp.`tpch/%s.parquet`", tableName, tableName);
-
-    // Change the ownership and permissions manually. Currently there is no option to specify the default permissions
-    // and ownership for new tables.
-    final Path tablePath = new Path(getUserHome(user), tableName);
-
-    fs.setOwner(tablePath, user, group);
-    fs.setPermission(tablePath, new FsPermission((short)0750));
+    try (ClientFixture client = cluster.client(user, "")) {
+      client.run("USE " + getWSSchema(user));
+      client.run("CREATE TABLE %s as SELECT * FROM cp.`tpch/%s.parquet`", tableName, tableName);
+      // Change the ownership and permissions manually. Currently there is no option to specify the default permissions
+      // and ownership for new tables.
+      final Path tablePath = new Path(getUserHome(user), tableName);
+
+      fs.setOwner(tablePath, user, group);
+      fs.setPermission(tablePath, new FsPermission((short)0750));
+    }
   }
 
   private static void createNestedTestViewsOnLineItem() throws Exception {
@@ -162,35 +163,38 @@ public class TestImpersonationQueries extends BaseTestImpersonation {
 
   private static void createRecordReadersData(String user, String group) throws Exception {
     // copy sequence file
-    updateClient(user);
-    Path localFile = new Path(DrillFileUtils.getResourceAsFile("/sequencefiles/simple.seq").toURI().toString());
-    Path dfsFile = new Path(getUserHome(user), "simple.seq");
-    fs.copyFromLocalFile(localFile, dfsFile);
-    fs.setOwner(dfsFile, user, group);
-    fs.setPermission(dfsFile, new FsPermission((short) 0700));
-
-    AvroDataGenerator avroDataGenerator = new AvroDataGenerator(dirTestWatcher);
-    localFile = new Path(avroDataGenerator.generateSimplePrimitiveSchema_NoNullValues().getFilePath());
-    dfsFile = new Path(getUserHome(user), "simple.avro");
-    fs.copyFromLocalFile(localFile, dfsFile);
-    fs.setOwner(dfsFile, user, group);
-    fs.setPermission(dfsFile, new FsPermission((short) 0700));
+    try (ClientFixture client = cluster.client(user, "")) {
+      Path localFile = new Path(DrillFileUtils.getResourceAsFile("/sequencefiles/simple.seq").toURI().toString());
+      Path dfsFile = new Path(getUserHome(user), "simple.seq");
+      fs.copyFromLocalFile(localFile, dfsFile);
+      fs.setOwner(dfsFile, user, group);
+      fs.setPermission(dfsFile, new FsPermission((short) 0700));
+
+      AvroDataGenerator avroDataGenerator = new AvroDataGenerator(dirTestWatcher);
+      localFile = new Path(avroDataGenerator.generateSimplePrimitiveSchema_NoNullValues().getFilePath());
+      dfsFile = new Path(getUserHome(user), "simple.avro");
+      fs.copyFromLocalFile(localFile, dfsFile);
+      fs.setOwner(dfsFile, user, group);
+      fs.setPermission(dfsFile, new FsPermission((short) 0700));
+    }
   }
 
   @Test
   public void testDirectImpersonation_HasUserReadPermissions() throws Exception {
     // Table lineitem is owned by "user0_1:group0_1" with permissions 750. Try to read the table as "user0_1". We
     // shouldn't expect any errors.
-    updateClient(org1Users[0]);
-    test("SELECT * FROM %s.lineitem ORDER BY l_orderkey LIMIT 1", getWSSchema(org1Users[0]));
+    try (ClientFixture client = cluster.client(org1Users[0], "")) {
+      client.run("SELECT * FROM %s.lineitem ORDER BY l_orderkey LIMIT 1", getWSSchema(org1Users[0]));
+    }
   }
 
   @Test
   public void testDirectImpersonation_HasGroupReadPermissions() throws Exception {
     // Table lineitem is owned by "user0_1:group0_1" with permissions 750. Try to read the table as "user1_1". We
     // shouldn't expect any errors as "user1_1" is part of the "group0_1"
-    updateClient(org1Users[1]);
-    test("SELECT * FROM %s.lineitem ORDER BY l_orderkey LIMIT 1", getWSSchema(org1Users[0]));
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      client.run("SELECT * FROM %s.lineitem ORDER BY l_orderkey LIMIT 1", getWSSchema(org1Users[0]));
+    }
   }
 
   @Test
@@ -199,8 +203,9 @@ public class TestImpersonationQueries extends BaseTestImpersonation {
     try {
       // Table lineitem is owned by "user0_1:group0_1" with permissions 750. Now try to read the table as "user2_1". We
       // should expect a permission denied error as "user2_1" is not part of the "group0_1"
-      updateClient(org1Users[2]);
-      test("SELECT * FROM %s.lineitem ORDER BY l_orderkey LIMIT 1", getWSSchema(org1Users[0]));
+      try (ClientFixture client = cluster.client(org1Users[2], "")) {
+        client.run("SELECT * FROM %s.lineitem ORDER BY l_orderkey LIMIT 1", getWSSchema(org1Users[0]));
+      }
     } catch(UserRemoteException e) {
       ex = e;
     }
@@ -212,8 +217,9 @@ public class TestImpersonationQueries extends BaseTestImpersonation {
 
   @Test
   public void testMultiLevelImpersonationEqualToMaxUserHops() throws Exception {
-    updateClient(org1Users[4]);
-    test("SELECT * from %s.u4_lineitem LIMIT 1;", getWSSchema(org1Users[4]));
+    try (ClientFixture client = cluster.client(org1Users[4], "")) {
+      client.run("SELECT * from %s.u4_lineitem LIMIT 1", getWSSchema(org1Users[4]));
+    }
   }
 
   @Test
@@ -221,8 +227,9 @@ public class TestImpersonationQueries extends BaseTestImpersonation {
     UserRemoteException ex = null;
 
     try {
-      updateClient(org1Users[5]);
-      test("SELECT * from %s.u4_lineitem LIMIT 1;", getWSSchema(org1Users[4]));
+      try (ClientFixture client = cluster.client(org1Users[5], "")) {
+        client.run("SELECT * from %s.u4_lineitem LIMIT 1", getWSSchema(org1Users[4]));
+      }
     } catch (UserRemoteException e) {
       ex = e;
     }
@@ -235,9 +242,10 @@ public class TestImpersonationQueries extends BaseTestImpersonation {
 
   @Test
   public void testMultiLevelImpersonationJoinEachSideReachesMaxUserHops() throws Exception {
-    updateClient(org1Users[4]);
-    test("SELECT * from %s.u4_lineitem l JOIN %s.u3_orders o ON l.l_orderkey = o.o_orderkey LIMIT 1",
-      getWSSchema(org1Users[4]), getWSSchema(org2Users[3]));
+    try (ClientFixture client = cluster.client(org1Users[4], "")) {
+      client.run("SELECT * from %s.u4_lineitem l JOIN %s.u3_orders o ON l.l_orderkey = o.o_orderkey LIMIT 1",
+        getWSSchema(org1Users[4]), getWSSchema(org2Users[3]));
+    }
   }
 
   @Test
@@ -245,9 +253,10 @@ public class TestImpersonationQueries extends BaseTestImpersonation {
     UserRemoteException ex = null;
 
     try {
-      updateClient(org1Users[4]);
-      test("SELECT * from %s.u4_lineitem l JOIN %s.u4_orders o ON l.l_orderkey = o.o_orderkey LIMIT 1",
-          getWSSchema(org1Users[4]), getWSSchema(org2Users[4]));
+      try (ClientFixture client = cluster.client(org1Users[4], "")) {
+        client.run("SELECT * from %s.u4_lineitem l JOIN %s.u4_orders o ON l.l_orderkey = o.o_orderkey LIMIT 1",
+            getWSSchema(org1Users[4]), getWSSchema(org2Users[4]));
+      }
     } catch(UserRemoteException e) {
       ex = e;
     }
@@ -265,16 +274,18 @@ public class TestImpersonationQueries extends BaseTestImpersonation {
       String.format("SELECT convert_from(t.binary_key, 'UTF8') as k FROM %s.`%s` t", MINI_DFS_STORAGE_PLUGIN_NAME,
         new Path(getUserHome(org1Users[0]), "simple.seq")));
     try {
-      updateClient(org1Users[1]);
-      test("SELECT k FROM %s.%s.%s", MINI_DFS_STORAGE_PLUGIN_NAME, "tmp", "simple_seq_view");
+      try (ClientFixture client = cluster.client(org1Users[1], "")) {
+        client.run("SELECT k FROM %s.%s.%s", MINI_DFS_STORAGE_PLUGIN_NAME, "tmp", "simple_seq_view");
+      }
     } catch (UserRemoteException e) {
       assertNull("This test should pass.", e);
     }
     createView(org1Users[1], org1Groups[1], "simple_seq_view_2",
       String.format("SELECT k FROM %s.%s.%s", MINI_DFS_STORAGE_PLUGIN_NAME, "tmp", "simple_seq_view"));
     try {
-      updateClient(org1Users[2]);
-      test("SELECT k FROM %s.%s.%s", MINI_DFS_STORAGE_PLUGIN_NAME, "tmp", "simple_seq_view_2");
+      try (ClientFixture client = cluster.client(org1Users[2], "")) {
+        client.run("SELECT k FROM %s.%s.%s", MINI_DFS_STORAGE_PLUGIN_NAME, "tmp", "simple_seq_view_2");
+      }
     } catch (UserRemoteException e) {
       assertNull("This test should pass.", e);
     }
@@ -286,27 +297,29 @@ public class TestImpersonationQueries extends BaseTestImpersonation {
       String.format("SELECT h_boolean, e_double FROM %s.`%s` t", MINI_DFS_STORAGE_PLUGIN_NAME,
         new Path(getUserHome(org1Users[0]), "simple.avro")));
 
-    updateClient(org1Users[1]);
-    test("SELECT h_boolean FROM %s.%s.%s", MINI_DFS_STORAGE_PLUGIN_NAME, "tmp", "simple_avro_view");
+    try (ClientFixture client = cluster.client(org1Users[1], "")) {
+      client.run("SELECT h_boolean FROM %s.%s.%s", MINI_DFS_STORAGE_PLUGIN_NAME, "tmp", "simple_avro_view");
+    }
   }
 
   @Test // DRILL-7250
   public void testCTEWithImpersonation() throws Exception {
     // Table lineitem is owned by "user0_1:group0_1" with permissions 750. "user2_1" doesn't have access to it,
     // but query uses CTE with the same name as the table, so query shouldn't look for lineitem table
-    updateClient(org1Users[2]);
-    test("use %s", getWSSchema(org1Users[0]));
-    testBuilder()
-        .sqlQuery("with lineitem as (SELECT 1 as a) select * from lineitem")
-        .unOrdered()
-        .baselineColumns("a")
-        .baselineValues(1)
-        .go();
+    try (ClientFixture client = cluster.client(org1Users[2], "")) {
+      client.run("use %s", getWSSchema(org1Users[0]));
+      testBuilder()
+          .sqlQuery("with lineitem as (SELECT 1 as a) select * from lineitem")
+          .unOrdered()
+          .baselineColumns("a")
+          .baselineValues(1)
+          .go();
+    }
   }
 
   @AfterClass
   public static void removeMiniDfsBasedStorage() throws PluginException {
-    getDrillbitContext().getStorage().remove(MINI_DFS_STORAGE_PLUGIN_NAME);
+    cluster.storageRegistry().remove(MINI_DFS_STORAGE_PLUGIN_NAME);
     stopMiniDfsCluster();
   }
 }
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestInboundImpersonation.java b/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestInboundImpersonation.java
index 22d3b0bde9..18b1684a93 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestInboundImpersonation.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/impersonation/TestInboundImpersonation.java
@@ -17,31 +17,28 @@
  */
 package org.apache.drill.exec.impersonation;
 
-import org.apache.drill.shaded.guava.com.google.common.collect.Maps;
-import com.typesafe.config.ConfigValueFactory;
 import org.apache.drill.categories.SecurityTest;
 import org.apache.drill.categories.SlowTest;
-import org.apache.drill.common.config.DrillConfig;
 import org.apache.drill.common.config.DrillProperties;
 import org.apache.drill.exec.ExecConstants;
 import org.apache.drill.exec.dotdrill.DotDrillType;
 import org.apache.drill.exec.proto.UserBitShared;
-import org.apache.drill.exec.rpc.RpcException;
-import org.apache.drill.exec.rpc.user.security.testing.UserAuthenticatorTestImpl;
 import org.apache.drill.exec.store.dfs.WorkspaceConfig;
-import org.apache.drill.test.UserExceptionMatcher;
+import org.apache.drill.shaded.guava.com.google.common.collect.Maps;
+import org.apache.drill.test.ClientFixture;
+import org.apache.drill.test.ClusterFixtureBuilder;
 import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.permission.FsPermission;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
 import java.util.Map;
-import java.util.Properties;
 
 import static org.junit.Assert.assertEquals;
+import static org.apache.drill.exec.rpc.user.security.testing.UserAuthenticatorTestImpl.PROCESS_USER;
+import static org.apache.drill.exec.rpc.user.security.testing.UserAuthenticatorTestImpl.PROCESS_USER_PASSWORD;
+import static org.apache.drill.exec.rpc.user.security.testing.UserAuthenticatorTestImpl.TYPE;
 
 @Category({SlowTest.class, SecurityTest.class})
 public class TestInboundImpersonation extends BaseTestImpersonation {
@@ -57,121 +54,132 @@ public class TestInboundImpersonation extends BaseTestImpersonation {
   public static final String PROXY_NAME = org1Users[2];
   public static final String PROXY_PASSWORD = "proxy";
 
-  @BeforeClass
-  public static void setup() throws Exception {
+  // Because cluster fixture save client properties even client closed,
+  // Use a dedicated cluster fixture for each test case so that the client fixture has clean properties.
+  @Test
+  public void selectChainedView() throws Exception {
     startMiniDfsCluster(TestInboundImpersonation.class.getSimpleName());
-    final DrillConfig newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
-        .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
-            ConfigValueFactory.fromAnyRef(true))
-        .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
-            ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
-        .withValue(ExecConstants.IMPERSONATION_ENABLED,
-            ConfigValueFactory.fromAnyRef(true)));
-
-    final Properties connectionProps = new Properties();
-    connectionProps.setProperty(DrillProperties.USER, "anonymous");
-    connectionProps.setProperty(DrillProperties.PASSWORD, "anything works!");
-    updateTestCluster(1, newConfig, connectionProps);
+    ClusterFixtureBuilder builder = new ClusterFixtureBuilder(dirTestWatcher)
+      .configProperty(ExecConstants.USER_AUTHENTICATION_ENABLED, true)
+      .configProperty(ExecConstants.USER_AUTHENTICATOR_IMPL, TYPE)
+      .configProperty(ExecConstants.IMPERSONATION_ENABLED, true)
+      .configClientProperty(DrillProperties.USER, PROXY_NAME)
+      .configClientProperty(DrillProperties.PASSWORD, PROXY_PASSWORD);
+
+    startCluster(builder);
     addMiniDfsBasedStorage(createTestWorkspaces());
     createTestData();
-  }
-
-  private static Map<String, WorkspaceConfig> createTestWorkspaces() throws Exception {
-    Map<String, WorkspaceConfig> workspaces = Maps.newHashMap();
-    createAndAddWorkspace(OWNER, getUserHome(OWNER), (short) 0755, OWNER, DATA_GROUP, workspaces);
-    createAndAddWorkspace(PROXY_NAME, getUserHome(PROXY_NAME), (short) 0755, PROXY_NAME, DATA_GROUP,
-        workspaces);
-    return workspaces;
-  }
-
-  private static void createTestData() throws Exception {
-    // Create table accessible only by OWNER
-    final String tableName = "lineitem";
-    updateClient(OWNER, OWNER_PASSWORD);
-    test("USE " + getWSSchema(OWNER));
-    test("CREATE TABLE %s as SELECT * FROM cp.`tpch/%s.parquet`", tableName, tableName);
-
-    // Change the ownership and permissions manually.
-    // Currently there is no option to specify the default permissions and ownership for new tables.
-    final Path tablePath = new Path(getUserHome(OWNER), tableName);
-    fs.setOwner(tablePath, OWNER, DATA_GROUP);
-    fs.setPermission(tablePath, new FsPermission((short) 0700));
-
-    // Create a view on top of lineitem table; allow IMPERSONATION_TARGET to read the view
-    // /user/user0_1    u0_lineitem    750    user0_1:group0_1
-    final String viewName = "u0_lineitem";
-    test("ALTER SESSION SET `%s`='%o';", ExecConstants.NEW_VIEW_DEFAULT_PERMS_KEY, (short) 0750);
-    test("CREATE VIEW %s.%s AS SELECT l_orderkey, l_partkey FROM %s.%s",
-        getWSSchema(OWNER), viewName, getWSSchema(OWNER), "lineitem");
-    // Verify the view file created has the expected permissions and ownership
-    final Path viewFilePath = new Path(getUserHome(OWNER), viewName + DotDrillType.VIEW.getEnding());
-    final FileStatus status = fs.getFileStatus(viewFilePath);
-    assertEquals(org1Groups[0], status.getGroup());
-    assertEquals(OWNER, status.getOwner());
-    assertEquals((short) 0750, status.getPermission().toShort());
-
     // Authorize PROXY_NAME to impersonate TARGET_NAME
-    updateClient(UserAuthenticatorTestImpl.PROCESS_USER,
-        UserAuthenticatorTestImpl.PROCESS_USER_PASSWORD);
-    test("ALTER SYSTEM SET `%s`='%s'", ExecConstants.IMPERSONATION_POLICIES_KEY,
-        "[ { proxy_principals : { users: [\"" + PROXY_NAME + "\" ] },"
-            + "target_principals : { users : [\"" + TARGET_NAME + "\"] } } ]");
+    try (ClientFixture adminClient = cluster.client(PROCESS_USER, PROCESS_USER_PASSWORD)) {
+      adminClient.alterSystem(
+          ExecConstants.IMPERSONATION_POLICIES_KEY,
+          "[ { proxy_principals : { users: [\"" + PROXY_NAME + "\" ] },"
+              + "target_principals : { users : [\"" + TARGET_NAME + "\"] } } ]"
+      );
+
+      // Connect as PROXY_NAME and query for IMPERSONATION_TARGET
+      // data belongs to OWNER, however a view is shared with IMPERSONATION_TARGET
+      ClientFixture.ClientBuilder clientBuilder = cluster.clientBuilder()
+          .property(DrillProperties.USER, PROXY_NAME)
+          .property(DrillProperties.PASSWORD, PROXY_PASSWORD)
+          .property(DrillProperties.IMPERSONATION_TARGET, TARGET_NAME);
+      try (ClientFixture client = clientBuilder.build()) {
+        client.testBuilder()
+            .sqlQuery("SELECT * FROM %s.u0_lineitem ORDER BY l_orderkey LIMIT 1", getWSSchema(OWNER))
+            .ordered()
+            .baselineColumns("l_orderkey", "l_partkey")
+            .baselineValues(1, 1552)
+            .go();
+      }
+      adminClient.resetSystem(ExecConstants.IMPERSONATION_POLICIES_KEY);
+    }
   }
 
-  @AfterClass
-  public static void tearDown() throws Exception {
-    updateClient(UserAuthenticatorTestImpl.PROCESS_USER,
-        UserAuthenticatorTestImpl.PROCESS_USER_PASSWORD);
-    test("ALTER SYSTEM RESET `%s`", ExecConstants.IMPERSONATION_POLICIES_KEY);
-  }
-
-  @Test
-  public void selectChainedView() throws Exception {
-    // Connect as PROXY_NAME and query for IMPERSONATION_TARGET
-    // data belongs to OWNER, however a view is shared with IMPERSONATION_TARGET
-    final Properties connectionProps = new Properties();
-    connectionProps.setProperty(DrillProperties.USER, PROXY_NAME);
-    connectionProps.setProperty(DrillProperties.PASSWORD, PROXY_PASSWORD);
-    connectionProps.setProperty(DrillProperties.IMPERSONATION_TARGET, TARGET_NAME);
-    updateClient(connectionProps);
-
-    testBuilder()
-        .sqlQuery("SELECT * FROM %s.u0_lineitem ORDER BY l_orderkey LIMIT 1", getWSSchema(OWNER))
-        .ordered()
-        .baselineColumns("l_orderkey", "l_partkey")
-        .baselineValues(1, 1552)
-        .go();
-  }
-
-  @Test(expected = RpcException.class)
+  @Test(expected = IllegalStateException.class)
   // PERMISSION ERROR: Proxy user 'user2_1' is not authorized to impersonate target user 'user0_2'.
   public void unauthorizedTarget() throws Exception {
     final String unauthorizedTarget = org2Users[0];
-    final Properties connectionProps = new Properties();
-    connectionProps.setProperty(DrillProperties.USER, PROXY_NAME);
-    connectionProps.setProperty(DrillProperties.PASSWORD, PROXY_PASSWORD);
-    connectionProps.setProperty(DrillProperties.IMPERSONATION_TARGET, unauthorizedTarget);
-    updateClient(connectionProps); // throws up
+    ClusterFixtureBuilder builder = new ClusterFixtureBuilder(dirTestWatcher)
+      .configProperty(ExecConstants.USER_AUTHENTICATION_ENABLED, true)
+      .configProperty(ExecConstants.USER_AUTHENTICATOR_IMPL, TYPE)
+      .configProperty(ExecConstants.IMPERSONATION_ENABLED, true)
+      .configClientProperty(DrillProperties.USER, PROXY_NAME)
+      .configClientProperty(DrillProperties.PASSWORD, PROXY_PASSWORD)
+      .configClientProperty(DrillProperties.IMPERSONATION_TARGET, unauthorizedTarget);
+    startCluster(builder);
   }
 
   @Test
   public void invalidPolicy() throws Exception {
-    thrownException.expect(new UserExceptionMatcher(UserBitShared.DrillPBError.ErrorType.VALIDATION,
-        "Invalid impersonation policies."));
-    updateClient(UserAuthenticatorTestImpl.PROCESS_USER,
-        UserAuthenticatorTestImpl.PROCESS_USER_PASSWORD);
-    test("ALTER SYSTEM SET `%s`='%s'", ExecConstants.IMPERSONATION_POLICIES_KEY,
-        "[ invalid json ]");
+    ClusterFixtureBuilder builder = new ClusterFixtureBuilder(dirTestWatcher)
+      .configProperty(ExecConstants.USER_AUTHENTICATION_ENABLED, true)
+      .configProperty(ExecConstants.USER_AUTHENTICATOR_IMPL, TYPE)
+      .configProperty(ExecConstants.IMPERSONATION_ENABLED, true)
+      .configClientProperty(DrillProperties.USER, PROCESS_USER)
+      .configClientProperty(DrillProperties.PASSWORD, PROCESS_USER_PASSWORD);
+    startCluster(builder);
+
+    client.queryBuilder()
+      .sql("ALTER SYSTEM SET `%s`='%s'", ExecConstants.IMPERSONATION_POLICIES_KEY,
+        "[ invalid json ]")
+      .userExceptionMatcher()
+      .expectedType(UserBitShared.DrillPBError.ErrorType.VALIDATION)
+      .include("Invalid impersonation policies.")
+      .match();
   }
 
   @Test
   public void invalidProxy() throws Exception {
-    thrownException.expect(new UserExceptionMatcher(UserBitShared.DrillPBError.ErrorType.VALIDATION,
-        "Proxy principals cannot have a wildcard entry."));
-    updateClient(UserAuthenticatorTestImpl.PROCESS_USER,
-        UserAuthenticatorTestImpl.PROCESS_USER_PASSWORD);
-    test("ALTER SYSTEM SET `%s`='%s'", ExecConstants.IMPERSONATION_POLICIES_KEY,
-        "[ { proxy_principals : { users: [\"*\" ] },"
-            + "target_principals : { users : [\"" + TARGET_NAME + "\"] } } ]");
+    ClusterFixtureBuilder builder = new ClusterFixtureBuilder(dirTestWatcher)
+      .configProperty(ExecConstants.USER_AUTHENTICATION_ENABLED, true)
+      .configProperty(ExecConstants.USER_AUTHENTICATOR_IMPL, TYPE)
+      .configProperty(ExecConstants.IMPERSONATION_ENABLED, true)
+      .configClientProperty(DrillProperties.USER, PROCESS_USER)
+      .configClientProperty(DrillProperties.PASSWORD, PROCESS_USER_PASSWORD);
+    startCluster(builder);
+
+    client.queryBuilder()
+      .sql("ALTER SYSTEM SET `%s`='%s'", ExecConstants.IMPERSONATION_POLICIES_KEY,
+        "[ { proxy_principals : { users: [\"*\" ] }," + "target_principals : { users : [\"" + TARGET_NAME + "\"] } } ]")
+      .userExceptionMatcher()
+      .expectedType(UserBitShared.DrillPBError.ErrorType.VALIDATION)
+      .include("Proxy principals cannot have a wildcard entry.")
+      .match();
+  }
+
+  private static Map<String, WorkspaceConfig> createTestWorkspaces() throws Exception {
+    Map<String, WorkspaceConfig> workspaces = Maps.newHashMap();
+    createAndAddWorkspace(OWNER, getUserHome(OWNER), (short) 0755, OWNER, DATA_GROUP, workspaces);
+    createAndAddWorkspace(PROXY_NAME, getUserHome(PROXY_NAME), (short) 0755, PROXY_NAME, DATA_GROUP,
+        workspaces);
+    return workspaces;
+  }
+
+  private static void createTestData() throws Exception {
+    // Create table accessible only by OWNER
+    final String tableName = "lineitem";
+    try (ClientFixture client = cluster.client(OWNER, OWNER_PASSWORD)) {
+      client.run("USE " + getWSSchema(OWNER));
+      client.run("CREATE TABLE %s as SELECT * FROM cp.`tpch/%s.parquet`", tableName, tableName);
+
+      // Change the ownership and permissions manually.
+      // Currently there is no option to specify the default permissions and ownership for new tables.
+      final Path tablePath = new Path(getUserHome(OWNER), tableName);
+      fs.setOwner(tablePath, OWNER, DATA_GROUP);
+      fs.setPermission(tablePath, new FsPermission((short) 0700));
+
+      // Create a view on top of lineitem table; allow IMPERSONATION_TARGET to read the view
+      // /user/user0_1    u0_lineitem    750    user0_1:group0_1
+      final String viewName = "u0_lineitem";
+      client.alterSession(ExecConstants.NEW_VIEW_DEFAULT_PERMS_KEY, "0750");
+      client.run("CREATE VIEW %s.%s AS SELECT l_orderkey, l_partkey FROM %s.%s",
+          getWSSchema(OWNER), viewName, getWSSchema(OWNER), "lineitem");
+      // Verify the view file created has the expected permissions and ownership
+      final Path viewFilePath = new Path(getUserHome(OWNER), viewName + DotDrillType.VIEW.getEnding());
+      final FileStatus status = fs.getFileStatus(viewFilePath);
+      assertEquals(org1Groups[0], status.getGroup());
+      assertEquals(OWNER, status.getOwner());
+      assertEquals(0750, status.getPermission().toShort());
+    }
   }
 }
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/planner/sql/CrossJoinTest.java b/exec/java-exec/src/test/java/org/apache/drill/exec/planner/sql/CrossJoinTest.java
index 348df328c9..cc96d098e3 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/planner/sql/CrossJoinTest.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/planner/sql/CrossJoinTest.java
@@ -18,16 +18,20 @@
 package org.apache.drill.exec.planner.sql;
 
 import org.apache.drill.categories.SqlTest;
+import org.apache.drill.common.exceptions.UserException;
 import org.apache.drill.common.exceptions.UserRemoteException;
 import org.apache.drill.exec.planner.physical.PlannerSettings;
 import org.apache.drill.test.ClusterFixture;
 import org.apache.drill.test.ClusterTest;
+import org.hamcrest.MatcherAssert;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
 import static org.apache.drill.exec.physical.impl.join.JoinUtils.FAILED_TO_PLAN_CARTESIAN_JOIN;
+import static org.hamcrest.CoreMatchers.containsString;
 
 @Category(SqlTest.class)
 public class CrossJoinTest extends ClusterTest {
@@ -49,15 +53,12 @@ public class CrossJoinTest extends ClusterTest {
   @Test
   public void testCrossJoinFailsForEnabledOption() throws Exception {
     enableNlJoinForScalarOnly();
+    String sql = "SELECT l.n_name, r.n_name " +
+      "FROM cp.`tpch/nation.parquet` l " +
+      "CROSS JOIN cp.`tpch/nation.parquet` r";
 
-    thrownException.expect(UserRemoteException.class);
-    thrownException.expectMessage(FAILED_TO_PLAN_CARTESIAN_JOIN);
-
-    queryBuilder().sql(
-        "SELECT l.n_name, r.n_name " +
-            "FROM cp.`tpch/nation.parquet` l " +
-            "CROSS JOIN cp.`tpch/nation.parquet` r")
-        .run();
+    UserRemoteException UserRemoteException = Assert.assertThrows(UserRemoteException.class, () ->  queryBuilder().sql(sql).run());
+    MatcherAssert.assertThat(UserRemoteException.getMessage(), containsString(FAILED_TO_PLAN_CARTESIAN_JOIN));
   }
 
   @Test
@@ -75,13 +76,11 @@ public class CrossJoinTest extends ClusterTest {
   public void testCommaJoinFailsForEnabledOption() throws Exception {
     enableNlJoinForScalarOnly();
 
-    thrownException.expect(UserRemoteException.class);
-    thrownException.expectMessage(FAILED_TO_PLAN_CARTESIAN_JOIN);
+    String sql = "SELECT l.n_name,r.n_name " +
+      "FROM cp.`tpch/nation.parquet` l, cp.`tpch/nation.parquet` r";
 
-    queryBuilder().sql(
-        "SELECT l.n_name,r.n_name " +
-            "FROM cp.`tpch/nation.parquet` l, cp.`tpch/nation.parquet` r")
-        .run();
+    UserException UserRemoteException = Assert.assertThrows(UserRemoteException.class, () -> queryBuilder().sql(sql).run());
+    MatcherAssert.assertThat(UserRemoteException.getMessage(), containsString(FAILED_TO_PLAN_CARTESIAN_JOIN));
   }
 
   @Test
@@ -98,17 +97,15 @@ public class CrossJoinTest extends ClusterTest {
   public void testSubSelectCrossJoinFailsForEnabledOption() throws Exception {
     enableNlJoinForScalarOnly();
 
-    thrownException.expect(UserRemoteException.class);
-    thrownException.expectMessage(FAILED_TO_PLAN_CARTESIAN_JOIN);
+    String sql = "SELECT COUNT(*) c " +
+      "FROM (" +
+      "SELECT l.n_name,r.n_name " +
+      "FROM cp.`tpch/nation.parquet` l " +
+      "CROSS JOIN cp.`tpch/nation.parquet` r" +
+      ")";
 
-    queryBuilder().sql(
-        "SELECT COUNT(*) c " +
-            "FROM (" +
-            "SELECT l.n_name,r.n_name " +
-            "FROM cp.`tpch/nation.parquet` l " +
-            "CROSS JOIN cp.`tpch/nation.parquet` r" +
-            ")")
-        .run();
+    UserException UserRemoteException = Assert.assertThrows(UserRemoteException.class, () -> queryBuilder().sql(sql).run());
+    MatcherAssert.assertThat(UserRemoteException.getMessage(), containsString(FAILED_TO_PLAN_CARTESIAN_JOIN));
   }
 
   @Test
@@ -131,14 +128,12 @@ public class CrossJoinTest extends ClusterTest {
   public void textCrossAndCommaJoinFailsForEnabledOption() throws Exception {
     enableNlJoinForScalarOnly();
 
-    thrownException.expect(UserRemoteException.class);
-    thrownException.expectMessage(FAILED_TO_PLAN_CARTESIAN_JOIN);
+    String sql = "SELECT * " +
+      "FROM cp.`tpch/nation.parquet` a, cp.`tpch/nation.parquet` b " +
+      "CROSS JOIN cp.`tpch/nation.parquet` c";
 
-    queryBuilder().sql(
-        "SELECT * " +
-            "FROM cp.`tpch/nation.parquet` a, cp.`tpch/nation.parquet` b " +
-            "CROSS JOIN cp.`tpch/nation.parquet` c")
-        .run();
+    UserException UserRemoteException = Assert.assertThrows(UserRemoteException.class, () -> queryBuilder().sql(sql).run());
+    MatcherAssert.assertThat(UserRemoteException.getMessage(), containsString(FAILED_TO_PLAN_CARTESIAN_JOIN));
   }
 
   @Test
@@ -157,14 +152,12 @@ public class CrossJoinTest extends ClusterTest {
   public void testCrossApplyFailsForEnabledOption() throws Exception {
     enableNlJoinForScalarOnly();
 
-    thrownException.expect(UserRemoteException.class);
-    thrownException.expectMessage(FAILED_TO_PLAN_CARTESIAN_JOIN);
+    String sql =  "SELECT * " +
+      "FROM cp.`tpch/nation.parquet` l " +
+      "CROSS APPLY cp.`tpch/nation.parquet` r";
 
-    queryBuilder().sql(
-        "SELECT * " +
-            "FROM cp.`tpch/nation.parquet` l " +
-            "CROSS APPLY cp.`tpch/nation.parquet` r")
-        .run();
+    UserException UserRemoteException = Assert.assertThrows(UserRemoteException.class, () -> queryBuilder().sql(sql).run());
+    MatcherAssert.assertThat(UserRemoteException.getMessage(), containsString(FAILED_TO_PLAN_CARTESIAN_JOIN));
   }
 
   @Test
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/server/TestOptions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/server/TestOptions.java
index 2544324cdf..467b7acb56 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/server/TestOptions.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/server/TestOptions.java
@@ -19,27 +19,35 @@ package org.apache.drill.exec.server;
 
 import static org.apache.drill.exec.ExecConstants.ENABLE_VERBOSE_ERRORS_KEY;
 import static org.apache.drill.exec.ExecConstants.SLICE_TARGET;
-import static org.apache.drill.exec.proto.UserBitShared.DrillPBError.ErrorType.VALIDATION;
 
 import org.apache.drill.categories.OptionsTest;
 import org.apache.drill.exec.ExecConstants;
-import org.apache.drill.test.BaseTestQuery;
-import org.apache.drill.test.UserExceptionMatcher;
+import org.apache.drill.exec.proto.UserBitShared.DrillPBError.ErrorType;
+import org.apache.drill.test.ClusterFixture;
+import org.apache.drill.test.ClusterTest;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
 @Category(OptionsTest.class)
-public class TestOptions extends BaseTestQuery {
+public class TestOptions extends ClusterTest {
 //  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TestOptions.class);
 
+  @BeforeClass
+  public static void setUp() throws Exception {
+    startCluster(ClusterFixture.builder(dirTestWatcher));
+  }
+
   @Test
-  public void testDrillbits() throws Exception{
-    test("select * from sys.drillbits;");
+  public void testDrillbits() throws Exception {
+    run("select * from sys.drillbits");
   }
 
   @Test
   public void testOptions() throws Exception{
-    test(
+    // We don't make use of client.alterSystem and alterSession because ALTER
+    // statement execution is part of what we're testing in this class.
+    client.exec(
         "select * from sys.options;" +
         "ALTER SYSTEM set `planner.disable_exchanges` = true;" +
         "select * from sys.options;" +
@@ -50,13 +58,16 @@ public class TestOptions extends BaseTestQuery {
 
   @Test
   public void checkValidationException() throws Exception {
-    thrownException.expect(new UserExceptionMatcher(VALIDATION));
-    test("ALTER session SET %s = '%s';", SLICE_TARGET, "fail");
+    client.queryBuilder()
+      .sql("ALTER session SET %s = '%s'", SLICE_TARGET, "fail")
+      .userExceptionMatcher()
+      .expectedType(ErrorType.VALIDATION)
+      .match();
   }
 
   @Test // DRILL-3122
   public void checkChangedColumn() throws Exception {
-    test("ALTER session SET `%s` = %d;", SLICE_TARGET,
+    run("ALTER session SET `%s` = %d", SLICE_TARGET,
       ExecConstants.SLICE_TARGET_DEFAULT);
     testBuilder()
         .sqlQuery("SELECT status FROM sys.options WHERE name = '%s' AND optionScope = 'SESSION'", SLICE_TARGET)
@@ -78,9 +89,9 @@ public class TestOptions extends BaseTestQuery {
       .run();
 
     // change option
-    test("SET `%s` = %d;", SLICE_TARGET, 10);
+    run("SET `%s` = %d", SLICE_TARGET, 10);
     // check changed
-    test("SELECT status, accessibleScopes, name FROM sys.options WHERE optionScope = 'SESSION';");
+    run("SELECT status, accessibleScopes, name FROM sys.options WHERE optionScope = 'SESSION'");
     testBuilder()
       .sqlQuery("SELECT val FROM sys.options WHERE name = '%s' AND optionScope = 'SESSION'", SLICE_TARGET)
       .unOrdered()
@@ -90,7 +101,7 @@ public class TestOptions extends BaseTestQuery {
       .run();
 
     // reset option
-    test("RESET `%s`;", SLICE_TARGET);
+    run("RESET `%s`", SLICE_TARGET);
     // check reverted
     testBuilder()
       .sqlQuery("SELECT status FROM sys.options WHERE name = '%s' AND optionScope = 'SESSION'", SLICE_TARGET)
@@ -112,7 +123,7 @@ public class TestOptions extends BaseTestQuery {
       .run();
 
     // change option
-    test("ALTER system SET `%s` = %b;", ENABLE_VERBOSE_ERRORS_KEY, true);
+    run("ALTER system SET `%s` = %b", ENABLE_VERBOSE_ERRORS_KEY, true);
     // check changed
     testBuilder()
       .sqlQuery("SELECT val FROM sys.options WHERE name = '%s' AND optionScope = 'SYSTEM'", ENABLE_VERBOSE_ERRORS_KEY)
@@ -123,7 +134,7 @@ public class TestOptions extends BaseTestQuery {
       .run();
 
     // reset option
-    test("ALTER system RESET `%s`;", ENABLE_VERBOSE_ERRORS_KEY);
+    run("ALTER system RESET `%s`", ENABLE_VERBOSE_ERRORS_KEY);
     // check reverted
     testBuilder()
       .sqlQuery("SELECT status FROM sys.options WHERE name = '%s' AND optionScope = 'BOOT'", ENABLE_VERBOSE_ERRORS_KEY)
@@ -137,7 +148,7 @@ public class TestOptions extends BaseTestQuery {
   @Test
   public void testResetAllSessionOptions() throws Exception {
     // change options
-    test("SET `%s` = %b;", ENABLE_VERBOSE_ERRORS_KEY, true);
+    run("SET `%s` = %b", ENABLE_VERBOSE_ERRORS_KEY, true);
     // check changed
     testBuilder()
       .sqlQuery("SELECT val FROM sys.options WHERE optionScope = 'SESSION' AND name = '%s'", ENABLE_VERBOSE_ERRORS_KEY)
@@ -148,7 +159,7 @@ public class TestOptions extends BaseTestQuery {
       .run();
 
     // reset all options
-    test("RESET ALL;");
+    run("RESET ALL");
     // check no session options changed
     testBuilder()
       .sqlQuery("SELECT status FROM sys.options WHERE status <> 'DEFAULT' AND optionScope = 'SESSION'")
@@ -161,8 +172,8 @@ public class TestOptions extends BaseTestQuery {
   @Test
   public void changeSessionAndSystemButRevertSession() throws Exception {
     // change options
-    test("ALTER SESSION SET `%s` = %b;", ENABLE_VERBOSE_ERRORS_KEY, true);
-    test("ALTER SYSTEM SET `%s` = %b;", ENABLE_VERBOSE_ERRORS_KEY, true);
+    run("ALTER SESSION SET `%s` = %b", ENABLE_VERBOSE_ERRORS_KEY, true);
+    run("ALTER SYSTEM SET `%s` = %b", ENABLE_VERBOSE_ERRORS_KEY, true);
     // check changed
     testBuilder()
       .sqlQuery("SELECT bool_val FROM sys.options_old WHERE optionScope = 'SESSION' AND name = '%s'", ENABLE_VERBOSE_ERRORS_KEY)
@@ -190,7 +201,7 @@ public class TestOptions extends BaseTestQuery {
 
 
     // reset session option
-    test("RESET `%s`;", ENABLE_VERBOSE_ERRORS_KEY);
+    run("RESET `%s`", ENABLE_VERBOSE_ERRORS_KEY);
     // check reverted
     testBuilder()
       .sqlQuery("SELECT status FROM sys.options WHERE name = '%s' AND optionScope = 'SESSION'", ENABLE_VERBOSE_ERRORS_KEY)
@@ -207,14 +218,14 @@ public class TestOptions extends BaseTestQuery {
       .build()
       .run();
     // reset system option
-    test("ALTER SYSTEM RESET `%s`;", ENABLE_VERBOSE_ERRORS_KEY);
+    run("ALTER SYSTEM RESET `%s`", ENABLE_VERBOSE_ERRORS_KEY);
   }
 
   @Test
   public void changeSessionAndNotSystem() throws Exception {
     // change options
-    test("ALTER SESSION SET `%s` = %b;", ENABLE_VERBOSE_ERRORS_KEY, true);
-    test("ALTER SYSTEM SET `%s` = %b;", ENABLE_VERBOSE_ERRORS_KEY, true);
+    run("ALTER SESSION SET `%s` = %b", ENABLE_VERBOSE_ERRORS_KEY, true);
+    run("ALTER SYSTEM SET `%s` = %b", ENABLE_VERBOSE_ERRORS_KEY, true);
     // check changed
     testBuilder()
       .sqlQuery("SELECT bool_val FROM sys.options_old WHERE optionScope = 'SESSION' AND name = '%s'", ENABLE_VERBOSE_ERRORS_KEY)
@@ -241,7 +252,7 @@ public class TestOptions extends BaseTestQuery {
       .run();
 
     // reset all session options
-    test("ALTER SESSION RESET ALL;");
+    run("ALTER SESSION RESET ALL");
     // check no session options changed
     testBuilder()
       .sqlQuery("SELECT status FROM sys.options WHERE status <> 'DEFAULT' AND optionScope = 'SESSION'")
@@ -262,8 +273,8 @@ public class TestOptions extends BaseTestQuery {
   @Test
   public void changeSystemAndNotSession() throws Exception {
     // change options
-    test("ALTER SESSION SET `%s` = %b;", ENABLE_VERBOSE_ERRORS_KEY, true);
-    test("ALTER SYSTEM SET `%s` = %b;", ENABLE_VERBOSE_ERRORS_KEY, true);
+    run("ALTER SESSION SET `%s` = %b", ENABLE_VERBOSE_ERRORS_KEY, true);
+    run("ALTER SYSTEM SET `%s` = %b", ENABLE_VERBOSE_ERRORS_KEY, true);
     // check changed
     testBuilder()
       .sqlQuery("SELECT bool_val FROM sys.options_old WHERE optionScope = 'SESSION' AND name = '%s'", ENABLE_VERBOSE_ERRORS_KEY)
@@ -290,7 +301,7 @@ public class TestOptions extends BaseTestQuery {
       .run();
 
     // reset option
-    test("ALTER system RESET `%s`;", ENABLE_VERBOSE_ERRORS_KEY);
+    run("ALTER system RESET `%s`", ENABLE_VERBOSE_ERRORS_KEY);
     // check reverted
     testBuilder()
       .sqlQuery("SELECT status FROM sys.options_old WHERE optionScope = 'BOOT' AND name = '%s'", ENABLE_VERBOSE_ERRORS_KEY)
@@ -311,8 +322,13 @@ public class TestOptions extends BaseTestQuery {
 
   @Test
   public void unsupportedLiteralValidation() throws Exception {
-    thrownException.expect(new UserExceptionMatcher(VALIDATION,
-      "Drill doesn't support assigning literals of type"));
-    test("ALTER session SET `%s` = DATE '1995-01-01';", ENABLE_VERBOSE_ERRORS_KEY);
+    String query = "ALTER session SET `%s` = %s";
+
+    client.queryBuilder()
+      .sql(query, ENABLE_VERBOSE_ERRORS_KEY, "DATE '1995-01-01'")
+      .userExceptionMatcher()
+      .expectedType(ErrorType.VALIDATION)
+      .include("Drill doesn't support assigning literals of type")
+      .match();
   }
 }
diff --git a/exec/java-exec/src/test/java/org/apache/drill/test/ClientFixture.java b/exec/java-exec/src/test/java/org/apache/drill/test/ClientFixture.java
index 1a55c4fe2e..308522f40d 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/test/ClientFixture.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/test/ClientFixture.java
@@ -151,6 +151,10 @@ public class ClientFixture implements AutoCloseable {
     runSqlSilently("ALTER SYSTEM RESET `" + key + "`");
   }
 
+  public void run(String sql, Object...args)  throws Exception {
+    queryBuilder().sql(sql, args).run();
+  }
+
   /**
    * Run SQL silently (discard results).
    *
@@ -160,7 +164,7 @@ public class ClientFixture implements AutoCloseable {
    */
   public void runSqlSilently(String sql, Object... args) {
     try {
-      queryBuilder().sql(sql, args).run();
+      run(sql, args);
     } catch (Exception e) {
       // Should not fail during tests. Convert exception to unchecked
       // to simplify test code.
@@ -411,4 +415,5 @@ public class ClientFixture implements AutoCloseable {
       throw new IllegalStateException(e);
     }
   }
+
 }
diff --git a/exec/java-exec/src/test/java/org/apache/drill/test/ClusterFixture.java b/exec/java-exec/src/test/java/org/apache/drill/test/ClusterFixture.java
index c1f17b1084..60951060c8 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/test/ClusterFixture.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/test/ClusterFixture.java
@@ -350,6 +350,21 @@ public class ClusterFixture extends BaseFixture implements AutoCloseable {
       .build();
   }
 
+  /**
+   * Create a test client for a specific username and password.
+   *
+   * @param Drill username
+   * @param password Drill password
+   * @return a test client. Client will be closed when this cluster
+   * fixture closes, or can be closed early.
+   */
+  public ClientFixture client(String username, String password) {
+    return clientBuilder()
+      .property(DrillProperties.USER, username)
+      .property(DrillProperties.PASSWORD, password)
+      .build();
+  }
+
   public RestClientFixture restClientFixture() {
     if (restClientFixture == null) {
       restClientFixture = restClientBuilder().build();
diff --git a/exec/java-exec/src/test/java/org/apache/drill/test/QueryBuilder.java b/exec/java-exec/src/test/java/org/apache/drill/test/QueryBuilder.java
index 996c5c4008..9e6d57a844 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/test/QueryBuilder.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/test/QueryBuilder.java
@@ -17,14 +17,16 @@
  */
 package org.apache.drill.test;
 
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Future;
@@ -45,6 +47,7 @@ import org.apache.drill.exec.proto.BitControl.PlanFragment;
 import org.apache.drill.exec.proto.UserBitShared.QueryId;
 import org.apache.drill.exec.proto.UserBitShared.QueryResult.QueryState;
 import org.apache.drill.exec.proto.UserBitShared.QueryType;
+import org.apache.drill.exec.proto.UserBitShared.DrillPBError.ErrorType;
 import org.apache.drill.exec.proto.helper.QueryIdHelper;
 import org.apache.drill.exec.record.RecordBatchLoader;
 import org.apache.drill.exec.record.VectorContainer;
@@ -696,6 +699,24 @@ public class QueryBuilder {
     return new PlanMatcher(plan);
   }
 
+  /**
+   * Executes the query, checks that an exception is thrown and creates a
+   * UserExceptionMatcher based on the thrown exception.
+   *
+   * @return user exception matcher
+   * @throws Exception if the query succeeds
+   */
+  public UserExceptionMatcher userExceptionMatcher() throws Exception {
+    try {
+      run();
+    } catch (Exception ex) {
+      return new UserExceptionMatcher(ex);
+    }
+    throw new AssertionError(
+      String.format("Expected an exception to be thrown when running %s", queryText)
+    );
+  }
+
   private QuerySummary produceSummary(BufferingQueryEventListener listener) throws Exception {
     long start = System.currentTimeMillis();
     int recordCount = 0;
@@ -787,8 +808,8 @@ public class QueryBuilder {
     private static final String UNEXPECTED_FOUND = "Found unwanted pattern";
 
     private final String plan;
-    private final List<String> included = new ArrayList<>();
-    private final List<String> excluded = new ArrayList<>();
+    private final List<String> included = new LinkedList<>();
+    private final List<String> excluded = new LinkedList<>();
 
     public PlanMatcher(String plan) {
       this.plan = plan;
@@ -846,4 +867,62 @@ public class QueryBuilder {
       assertEquals(message, expectedResult, matcher.find());
     }
   }
+
+  /**
+   * Collects expected and unexpected UserException message patterns.
+   * Upon {@link #match()} method call, matches given patterns to the
+   * UserException thrown by the query.
+   */
+  public static class UserExceptionMatcher {
+    private final UserException ex;
+    private final List<String> included = new LinkedList<>();
+    private final List<String> excluded = new LinkedList<>();
+    private ErrorType expectedType;
+
+    public UserExceptionMatcher(Exception ex) {
+      assertThat(ex, instanceOf(UserException.class));
+      this.ex = (UserException) ex;
+    }
+
+    public UserExceptionMatcher include(String... patterns) {
+      included.addAll(Arrays.asList(patterns));
+      return this;
+    }
+
+    public UserExceptionMatcher exclude(String... patterns) {
+      excluded.addAll(Arrays.asList(patterns));
+      return this;
+    }
+
+    public UserExceptionMatcher expectedType(ErrorType expectedType) {
+      this.expectedType = expectedType;
+      return this;
+    }
+
+    /**
+     * Checks if stored patterns (string parts) are included or excluded in the
+     * given exception's message. Will fail with {@link AssertionError}
+     * only if expected pattern was not matched or unexpected pattern was matched.
+     */
+    public void match() {
+      included.forEach(pattern -> match(pattern, true));
+      excluded.forEach(pattern -> match(pattern, false));
+
+      if (expectedType != null) {
+        assertEquals(expectedType, ex.getErrorType());
+      }
+    }
+
+    private void match(String patternString, boolean expectedResult) {
+      Pattern pattern = Pattern.compile(Pattern.quote(patternString));
+      Matcher matcher = pattern.matcher(ex.getMessage());
+      String message = String.format(
+        "%s in UserException message: %s\n%s",
+        expectedResult ? "Did not find expected pattern" : "Found unwanted pattern",
+        patternString,
+        ex.getMessage()
+      );
+      assertEquals(message, expectedResult, matcher.find());
+    }
+  }
 }
diff --git a/pom.xml b/pom.xml
index 235dfab97a..2435bef164 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3890,10 +3890,10 @@
       <properties>
         <maven.compiler.release>8</maven.compiler.release>
         <junit.args>
-          --add-opens=java.base/java.lang=ALL-UNNAMED
+          --add-opens java.base/java.lang=ALL-UNNAMED
           --add-opens java.base/java.net=ALL-UNNAMED
           --add-opens java.base/java.nio=ALL-UNNAMED
-          --add-opens=java.base/java.util=ALL-UNNAMED
+          --add-opens java.base/java.util=ALL-UNNAMED
           --add-opens java.base/sun.nio.ch=ALL-UNNAMED
           --add-opens java.security.jgss/sun.security.krb5=ALL-UNNAMED
         </junit.args>