@Test
  public void testComplexGrantRevoke() {
    // 1. test complex privilege on single path :"root.**"
    Set<String> allPriv = new HashSet<>();
    for (PrivilegeType type : PrivilegeType.values()) {
      if (type.isRelationalPrivilege()) {
        continue;
      }
      allPriv.add(type.toString());
    }

    for (PrivilegeType type : PrivilegeType.values()) {
      if (type.isRelationalPrivilege()) {
        continue;
      }
      {
        AuthorStatement stmt =
            createAuthDclStmt(
                String.format("GRANT ALL,%s on root.** to USER `user1` with grant option", type));
        assertEquals(allPriv, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));
        Assert.assertTrue(stmt.getGrantOpt());
        assertEquals(StatementType.GRANT_USER_PRIVILEGE, stmt.getType());
      }
      {
        AuthorStatement stmt =
            createAuthDclStmt(String.format("REVOKE ALL,%s on root.** from USER `user1`;", type));
        assertEquals(allPriv, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));
        assertEquals(StatementType.REVOKE_USER_PRIVILEGE, stmt.getType());
      }
      {
        AuthorStatement stmt =
            createAuthDclStmt(String.format("GRANT ALL,%s on root.** to ROLE `role1`;", type));
        assertEquals(allPriv, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));
        assertFalse(stmt.getGrantOpt());
        assertEquals(StatementType.GRANT_ROLE_PRIVILEGE, stmt.getType());
      }
    }

    AuthorStatement stmt =
        createAuthDclStmt("GRANT ALL ON root.** to user `user1` with grant option;");
    assertEquals(allPriv, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));
    Assert.assertTrue(stmt.getGrantOpt());
    assertEquals(allPriv, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));

    // 2. complex privilege on a single wrong path
    assertThrows(
        SemanticException.class,
        () -> createAuthDclStmt("grant all on root.t1.** to USER `user1` with grant option;"));
    assertThrows(
        SemanticException.class,
        () -> createAuthDclStmt("grant all on root.t1.** to ROLE `user1` with grant option;"));
    assertThrows(
        SemanticException.class,
        () ->
            createAuthDclStmt(
                "grant all,READ_DATA on root.t1.** to USER `user1` with grant option"));
    assertThrows(
        SemanticException.class,
        () ->
            createAuthDclStmt(
                "grant all,READ_DATA on root.t1.** to ROLE `user1` with grant option"));
    assertThrows(
        SemanticException.class,
        () -> createAuthDclStmt("grant all on root.t1.** to USER `user1`;"));
    assertThrows(
        SemanticException.class,
        () -> createAuthDclStmt("grant all on root.t1.** to ROLE `user1`;"));
    assertThrows(
        SemanticException.class,
        () -> createAuthDclStmt("grant all,READ_DATA on root.t1.** to USER `user1`;"));
    assertThrows(
        SemanticException.class,
        () -> createAuthDclStmt("grant all,READ_DATA on root.t1.** to ROLE `user1`;"));
    assertThrows(
        SemanticException.class,
        () -> createAuthDclStmt("revoke all on root.t1.** from USER `user1`;"));
    assertThrows(
        SemanticException.class,
        () -> createAuthDclStmt("revoke all on root.t1.** from ROLE `user1`;"));
    assertThrows(
        SemanticException.class,
        () -> createAuthDclStmt("revoke all,READ_DATA on root.t1.** from USER `user1`;"));
    assertThrows(
        SemanticException.class,
        () -> createAuthDclStmt("revoke all,READ_DATA on root.t1.** from ROLE `user1`;"));
    try {
      createAuthDclStmt("grant all on root.t1.**, root.** to USER `user1` with grant option;");
    } catch (SemanticException e) {
      assertEquals("[ALL] can only be set on path: root.**", e.getMessage());
    }

    try {
      createAuthDclStmt("grant MANAGE_ROLE on root.t1.** to USER `user1` with grant option;");
    } catch (SemanticException e) {
      assertEquals("[MANAGE_ROLE] can only be set on path: root.**", e.getMessage());
    }

    // 3. complex privilege on complex paths.
    assertThrows(
        SemanticException.class,
        () ->
            createAuthDclStmt(
                "grant all on root.t1.**, root.** to USER `user1` with grant option;"));
    assertThrows(
        SemanticException.class,
        () ->
            createAuthDclStmt(
                "grant MANAGE_ROLE on root.t1.**, root.** to USER `user1` with grant option;"));

    // 4.  READ privilege can be parsed successfully.
    stmt = createAuthDclStmt("GRANT READ ON root.** TO USER `user1`;");
    Set<String> readSet = new HashSet<>();
    readSet.add("READ_DATA");
    readSet.add("READ_SCHEMA");
    assertEquals(readSet, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));

    stmt = createAuthDclStmt("GRANT READ,READ_DATA ON root.** TO USER `user1`;");
    assertEquals(readSet, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));

    stmt = createAuthDclStmt("GRANT READ,READ_DATA ON root.**,root.t1.t2 TO USER `user1`;");
    assertEquals(readSet, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));
    assertEquals(2, stmt.getPaths().size());

    // 5. WRITE privilege can be parsed successfully.
    stmt = createAuthDclStmt("GRANT WRITE ON root.** TO USER `user1`;");
    Set<String> writeSet = new HashSet<>();
    writeSet.add("WRITE_DATA");
    writeSet.add("WRITE_SCHEMA");
    assertEquals(writeSet, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));

    stmt = createAuthDclStmt("GRANT WRITE,WRITE_DATA ON root.** TO USER `user1`;");
    assertEquals(writeSet, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));

    stmt = createAuthDclStmt("GRANT WRITE,WRITE ON root.**,root.t1.t2 TO USER `user1`;");
    assertEquals(writeSet, new HashSet<>(Arrays.asList(stmt.getPrivilegeList())));
    assertEquals(2, stmt.getPaths().size());
  }
This test will check grant/revoke simple privilege on/from paths.
iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGeneratorTest.java