public void testListener() throws Exception {
    String dbName = "tmpdb";
    String tblName = "tmptbl";
    String renamed = "tmptbl2";
    int listSize = 0;

    List<ListenerEvent> notifyList = DummyListener.notifyList;
    assertEquals(notifyList.size(), listSize);
    List<PreEventContext> preNotifyList = DummyPreListener.notifyList;
    assertEquals(preNotifyList.size(), listSize);

    driver.run("create database " + dbName);
    listSize++;
    Database db = msc.getDatabase(dbName);
    assertEquals(listSize, notifyList.size());
    assertEquals(listSize, preNotifyList.size());

    CreateDatabaseEvent dbEvent = (CreateDatabaseEvent) (notifyList.get(listSize - 1));
    assert dbEvent.getStatus();
    validateCreateDb(db, dbEvent.getDatabase());

    PreCreateDatabaseEvent preDbEvent = (PreCreateDatabaseEvent) (preNotifyList.get(listSize - 1));
    validateCreateDb(db, preDbEvent.getDatabase());

    driver.run("use " + dbName);
    driver.run(String.format("create table %s (a string) partitioned by (b string)", tblName));
    listSize++;
    Table tbl = msc.getTable(dbName, tblName);
    assertEquals(notifyList.size(), listSize);
    assertEquals(preNotifyList.size(), listSize);

    CreateTableEvent tblEvent = (CreateTableEvent) (notifyList.get(listSize - 1));
    assert tblEvent.getStatus();
    validateCreateTable(tbl, tblEvent.getTable());

    PreCreateTableEvent preTblEvent = (PreCreateTableEvent) (preNotifyList.get(listSize - 1));
    validateCreateTable(tbl, preTblEvent.getTable());

    driver.run("alter table tmptbl add partition (b='2011')");
    listSize++;
    Partition part = msc.getPartition("tmpdb", "tmptbl", "b=2011");
    assertEquals(notifyList.size(), listSize);
    assertEquals(preNotifyList.size(), listSize);

    AddPartitionEvent partEvent = (AddPartitionEvent) (notifyList.get(listSize - 1));
    assert partEvent.getStatus();
    validateAddPartition(part, partEvent.getPartition());
    validateTableInAddPartition(tbl, partEvent.getTable());

    PreAddPartitionEvent prePartEvent = (PreAddPartitionEvent) (preNotifyList.get(listSize - 1));
    validateAddPartition(part, prePartEvent.getPartition());

    driver.run(String.format("alter table %s touch partition (%s)", tblName, "b='2011'"));
    listSize++;
    assertEquals(notifyList.size(), listSize);
    assertEquals(preNotifyList.size(), listSize);

    // the partition did not change,
    // so the new partition should be similar to the original partition
    Partition origP = msc.getPartition(dbName, tblName, "b=2011");

    AlterPartitionEvent alterPartEvent = (AlterPartitionEvent) notifyList.get(listSize - 1);
    assert alterPartEvent.getStatus();
    validateAlterPartition(
        origP,
        origP,
        alterPartEvent.getOldPartition().getDbName(),
        alterPartEvent.getOldPartition().getTableName(),
        alterPartEvent.getOldPartition().getValues(),
        alterPartEvent.getNewPartition());

    PreAlterPartitionEvent preAlterPartEvent =
        (PreAlterPartitionEvent) preNotifyList.get(listSize - 1);
    validateAlterPartition(
        origP,
        origP,
        preAlterPartEvent.getDbName(),
        preAlterPartEvent.getTableName(),
        preAlterPartEvent.getNewPartition().getValues(),
        preAlterPartEvent.getNewPartition());

    driver.run(String.format("alter table %s rename to %s", tblName, renamed));
    listSize++;
    assertEquals(notifyList.size(), listSize);
    assertEquals(preNotifyList.size(), listSize);

    Table renamedTable = msc.getTable(dbName, renamed);

    AlterTableEvent alterTableE = (AlterTableEvent) notifyList.get(listSize - 1);
    assert alterTableE.getStatus();
    validateAlterTable(tbl, renamedTable, alterTableE.getOldTable(), alterTableE.getNewTable());

    PreAlterTableEvent preAlterTableE = (PreAlterTableEvent) preNotifyList.get(listSize - 1);
    validateAlterTable(
        tbl, renamedTable, preAlterTableE.getOldTable(), preAlterTableE.getNewTable());

    // change the table name back
    driver.run(String.format("alter table %s rename to %s", renamed, tblName));
    listSize++;
    assertEquals(notifyList.size(), listSize);
    assertEquals(preNotifyList.size(), listSize);

    driver.run(String.format("alter table %s ADD COLUMNS (c int)", tblName));
    listSize++;
    assertEquals(notifyList.size(), listSize);
    assertEquals(preNotifyList.size(), listSize);

    Table altTable = msc.getTable(dbName, tblName);

    alterTableE = (AlterTableEvent) notifyList.get(listSize - 1);
    assert alterTableE.getStatus();
    validateAlterTableColumns(tbl, altTable, alterTableE.getOldTable(), alterTableE.getNewTable());

    preAlterTableE = (PreAlterTableEvent) preNotifyList.get(listSize - 1);
    validateAlterTableColumns(
        tbl, altTable, preAlterTableE.getOldTable(), preAlterTableE.getNewTable());

    Map<String, String> kvs = new HashMap<String, String>(1);
    kvs.put("b", "2011");
    msc.markPartitionForEvent("tmpdb", "tmptbl", kvs, PartitionEventType.LOAD_DONE);
    listSize++;
    assertEquals(notifyList.size(), listSize);
    assertEquals(preNotifyList.size(), listSize);

    LoadPartitionDoneEvent partMarkEvent = (LoadPartitionDoneEvent) notifyList.get(listSize - 1);
    assert partMarkEvent.getStatus();
    validateLoadPartitionDone(
        "tmptbl", kvs, partMarkEvent.getTable().getTableName(), partMarkEvent.getPartitionName());

    PreLoadPartitionDoneEvent prePartMarkEvent =
        (PreLoadPartitionDoneEvent) preNotifyList.get(listSize - 1);
    validateLoadPartitionDone(
        "tmptbl", kvs, prePartMarkEvent.getTableName(), prePartMarkEvent.getPartitionName());

    driver.run(String.format("alter table %s drop partition (b='2011')", tblName));
    listSize++;
    assertEquals(notifyList.size(), listSize);
    assertEquals(preNotifyList.size(), listSize);

    DropPartitionEvent dropPart = (DropPartitionEvent) notifyList.get(listSize - 1);
    assert dropPart.getStatus();
    validateDropPartition(part, dropPart.getPartition());
    validateTableInDropPartition(tbl, dropPart.getTable());

    PreDropPartitionEvent preDropPart = (PreDropPartitionEvent) preNotifyList.get(listSize - 1);
    validateDropPartition(part, preDropPart.getPartition());

    driver.run("drop table " + tblName);
    listSize++;
    assertEquals(notifyList.size(), listSize);
    assertEquals(preNotifyList.size(), listSize);

    DropTableEvent dropTbl = (DropTableEvent) notifyList.get(listSize - 1);
    assert dropTbl.getStatus();
    validateDropTable(tbl, dropTbl.getTable());

    PreDropTableEvent preDropTbl = (PreDropTableEvent) preNotifyList.get(listSize - 1);
    validateDropTable(tbl, preDropTbl.getTable());

    driver.run("drop database " + dbName);
    listSize++;
    assertEquals(notifyList.size(), listSize);
    assertEquals(preNotifyList.size(), listSize);

    DropDatabaseEvent dropDB = (DropDatabaseEvent) notifyList.get(listSize - 1);
    assert dropDB.getStatus();
    validateDropDb(db, dropDB.getDatabase());

    PreDropDatabaseEvent preDropDB = (PreDropDatabaseEvent) preNotifyList.get(listSize - 1);
    assert dropDB.getStatus();
    validateDropDb(db, preDropDB.getDatabase());
  }