@Test
  public void testRemoteLocks() throws Exception {
    String namespace = "preQueueNs";
    final TableName tableName = TableName.valueOf(namespace, name.getMethodName());
    RegionInfo[] regionInfos = new RegionInfo[] { RegionInfoBuilder.newBuilder(tableName).build() };

    // Setup Users
    // User will be granted ADMIN and CREATE on namespace. Should be denied before grant.
    User namespaceUser = User.createUserForTesting(conf, "qLNSUser", new String[0]);
    // User will be granted ADMIN and CREATE on table. Should be denied before grant.
    User tableACUser = User.createUserForTesting(conf, "qLTableACUser", new String[0]);
    // User will be granted READ, WRITE, EXECUTE on table. Should be denied.
    User tableRWXUser = User.createUserForTesting(conf, "qLTableRWXUser", new String[0]);
    grantOnTable(TEST_UTIL, tableRWXUser.getShortName(), tableName, null, null, Action.READ,
      Action.WRITE, Action.EXEC);
    // User with global READ, WRITE, EXECUTE should be denied lock access.
    User globalRWXUser = User.createUserForTesting(conf, "qLGlobalRWXUser", new String[0]);
    grantGlobal(TEST_UTIL, globalRWXUser.getShortName(), Action.READ, Action.WRITE, Action.EXEC);

    AccessTestAction namespaceLockAction = new AccessTestAction() {
      @Override
      public Object run() throws Exception {
        ACCESS_CONTROLLER.preRequestLock(ObserverContextImpl.createAndPrepare(CP_ENV), namespace,
          null, null, null);
        return null;
      }
    };
    verifyAllowed(namespaceLockAction, SUPERUSER, USER_ADMIN);
    verifyDenied(namespaceLockAction, globalRWXUser, tableACUser, namespaceUser, tableRWXUser);
    grantOnNamespace(TEST_UTIL, namespaceUser.getShortName(), namespace, Action.ADMIN);
    // Why I need this pause? I don't need it elsewhere.
    Threads.sleep(1000);
    verifyAllowed(namespaceLockAction, namespaceUser);

    AccessTestAction tableLockAction = new AccessTestAction() {
      @Override
      public Object run() throws Exception {
        ACCESS_CONTROLLER.preRequestLock(ObserverContextImpl.createAndPrepare(CP_ENV), null,
          tableName, null, null);
        return null;
      }
    };
    verifyAllowed(tableLockAction, SUPERUSER, USER_ADMIN, namespaceUser);
    verifyDenied(tableLockAction, globalRWXUser, tableACUser, tableRWXUser);
    grantOnTable(TEST_UTIL, tableACUser.getShortName(), tableName, null, null, Action.ADMIN,
      Action.CREATE);
    // See if this can fail (flakie) because grant hasn't propagated yet.
    for (int i = 0; i < 10; i++) {
      try {
        verifyAllowed(tableLockAction, tableACUser);
      } catch (AssertionError e) {
        LOG.warn("Retrying assertion error", e);
        Threads.sleep(1000);
        continue;
      }
    }

    AccessTestAction regionsLockAction = new AccessTestAction() {
      @Override
      public Object run() throws Exception {
        ACCESS_CONTROLLER.preRequestLock(ObserverContextImpl.createAndPrepare(CP_ENV), null, null,
          regionInfos, null);
        return null;
      }
    };
    verifyAllowed(regionsLockAction, SUPERUSER, USER_ADMIN, namespaceUser, tableACUser);
    verifyDenied(regionsLockAction, globalRWXUser, tableRWXUser);

    // Test heartbeats
    // Create a lock procedure and try sending heartbeat to it. It doesn't matter how the lock
    // was created, we just need namespace from the lock's tablename.
    LockProcedure proc = new LockProcedure(conf, tableName, LockType.EXCLUSIVE, "test", null);
    AccessTestAction regionLockHeartbeatAction = new AccessTestAction() {
      @Override
      public Object run() throws Exception {
        ACCESS_CONTROLLER.preLockHeartbeat(ObserverContextImpl.createAndPrepare(CP_ENV),
          proc.getTableName(), proc.getDescription());
        return null;
      }
    };
    verifyAllowed(regionLockHeartbeatAction, SUPERUSER, USER_ADMIN, namespaceUser, tableACUser);
    verifyDenied(regionLockHeartbeatAction, globalRWXUser, tableRWXUser);
  }
List all user permissions match the given regular expression for namespace and verify each of
them.
@param namespaceRegexWithoutPrefix the regualar expression for namespace, without
                                   NAMESPACE_PREFIX
@param expectedAmount              the expected amount of user permissions returned
@param expectedNamespace           the expected namespace of each user permission returned
@throws HBaseException in the case of any HBase exception when accessing hbase:acl table
hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java