public static void deleteTaskMetadata(HelixPropertyStore<ZNRecord> propertyStore, String taskType,
      String tableNameWithType) {
    String newPath = ZKMetadataProvider.constructPropertyStorePathForMinionTaskMetadata(tableNameWithType, taskType);
    String oldPath =
        ZKMetadataProvider.constructPropertyStorePathForMinionTaskMetadataDeprecated(taskType, tableNameWithType);
    boolean newPathDeleted = propertyStore.remove(newPath, AccessOption.PERSISTENT);
    boolean oldPathDeleted = propertyStore.remove(oldPath, AccessOption.PERSISTENT);
    if (!newPathDeleted || !oldPathDeleted) {
      throw new ZkException("Failed to delete task metadata: " + taskType + ", " + tableNameWithType);
    }
  }
@Test
  public void testDeleteTaskMetadata() {
    // no error
    HelixPropertyStore<ZNRecord> propertyStore = new FakePropertyStore();
    MinionTaskMetadataUtils.deleteTaskMetadata(propertyStore, TASK_TYPE, TABLE_NAME_WITH_TYPE);

    // both metadata paths will be removed
    propertyStore = new FakePropertyStore();
    propertyStore.set(OLD_MINION_METADATA_PATH, OLD_TASK_METADATA.toZNRecord(), EXPECTED_VERSION, ACCESS_OPTION);
    propertyStore.set(NEW_MINION_METADATA_PATH, NEW_TASK_METADATA.toZNRecord(), EXPECTED_VERSION, ACCESS_OPTION);
    assertTrue(propertyStore.exists(OLD_MINION_METADATA_PATH, ACCESS_OPTION));
    assertTrue(propertyStore.exists(NEW_MINION_METADATA_PATH, ACCESS_OPTION));
    MinionTaskMetadataUtils.deleteTaskMetadata(propertyStore, TASK_TYPE, TABLE_NAME_WITH_TYPE);
    assertFalse(propertyStore.exists(OLD_MINION_METADATA_PATH, ACCESS_OPTION));
    assertFalse(propertyStore.exists(NEW_MINION_METADATA_PATH, ACCESS_OPTION));

    // 1. ZNode MINION_TASK_METADATA/TestTable_OFFLINE and its descendants will be removed
    // 2. ZNode MINION_TASK_METADATA/<any task type>/TestTable_OFFLINE will also be removed
    String anotherTable = "anotherTable_OFFLINE";
    String anotherOldMinionMetadataPath =
        ZKMetadataProvider.constructPropertyStorePathForMinionTaskMetadataDeprecated(TASK_TYPE, anotherTable);
    DummyTaskMetadata anotherOldTaskMetadata = new DummyTaskMetadata(anotherTable, 20);
    String anotherNewMinionMetadataPath =
        ZKMetadataProvider.constructPropertyStorePathForMinionTaskMetadata(anotherTable, TASK_TYPE);
    DummyTaskMetadata anotherNewTaskMetadata = new DummyTaskMetadata(anotherTable, 200);
    propertyStore = new FakePropertyStore();
    propertyStore.set(OLD_MINION_METADATA_PATH, OLD_TASK_METADATA.toZNRecord(), EXPECTED_VERSION, ACCESS_OPTION);
    propertyStore.set(NEW_MINION_METADATA_PATH, NEW_TASK_METADATA.toZNRecord(), EXPECTED_VERSION, ACCESS_OPTION);
    propertyStore.set(anotherOldMinionMetadataPath, anotherOldTaskMetadata.toZNRecord(),
        EXPECTED_VERSION, ACCESS_OPTION);
    propertyStore.set(anotherNewMinionMetadataPath, anotherNewTaskMetadata.toZNRecord(),
        EXPECTED_VERSION, ACCESS_OPTION);
    assertTrue(propertyStore.exists(OLD_MINION_METADATA_PATH, ACCESS_OPTION));
    assertTrue(propertyStore.exists(NEW_MINION_METADATA_PATH, ACCESS_OPTION));
    assertTrue(propertyStore.exists(anotherOldMinionMetadataPath, ACCESS_OPTION));
    assertTrue(propertyStore.exists(anotherNewMinionMetadataPath, ACCESS_OPTION));
    MinionTaskMetadataUtils.deleteTaskMetadata(propertyStore, TABLE_NAME_WITH_TYPE);
    assertFalse(propertyStore.exists(OLD_MINION_METADATA_PATH, ACCESS_OPTION));
    assertFalse(propertyStore.exists(NEW_MINION_METADATA_PATH, ACCESS_OPTION));
    assertTrue(propertyStore.exists(anotherOldMinionMetadataPath, ACCESS_OPTION));
    assertTrue(propertyStore.exists(anotherNewMinionMetadataPath, ACCESS_OPTION));
  }