@Test
  public void testGeneratePartitionOverrideMapFromStaticFile() throws Exception {
    List<PartitionId> writablePartitions =
        new ArrayList<>(testPartitionLayout.getPartitionLayout().getWritablePartitions(null));
    int partitionCount = testPartitionLayout.getPartitionCount();
    Utils.writeJsonObjectToFile(zkJson, zkLayoutPath);
    Utils.writeJsonObjectToFile(testHardwareLayout.getHardwareLayout().toJSONObject(), hardwareLayoutPath);
    Utils.writeJsonObjectToFile(testPartitionLayout.getPartitionLayout().toJSONObject(), partitionLayoutPath);
    Utils.writeStringToFile(String.valueOf(partitionCount + 1), adminConfigFilePath);
    // failure case 1: partition id is out of valid range
    try {
      HelixBootstrapUpgradeUtil.uploadOrDeleteAdminConfigs(hardwareLayoutPath, partitionLayoutPath, zkLayoutPath,
          CLUSTER_NAME_PREFIX, dcStr, false, new String[]{ClusterMapUtils.PARTITION_OVERRIDE_STR}, adminConfigFilePath);
      fail("should fail because input partition id is out of valid range");
    } catch (IllegalArgumentException e) {
      // expected
    }
    // failure case 2: partition id is non-numeric
    Utils.writeStringToFile("non-numeric", adminConfigFilePath);
    try {
      HelixBootstrapUpgradeUtil.uploadOrDeleteAdminConfigs(hardwareLayoutPath, partitionLayoutPath, zkLayoutPath,
          CLUSTER_NAME_PREFIX, dcStr, false, new String[]{ClusterMapUtils.PARTITION_OVERRIDE_STR}, adminConfigFilePath);
      fail("should fail because input partition id is not numeric");
    } catch (NumberFormatException e) {
      // expected
    }
    // success case: mark 1/10 partitions as RO
    Collections.shuffle(writablePartitions);
    int readOnlyCount = writablePartitions.size() / 10;
    StringBuilder sb = new StringBuilder();
    Set<String> readOnlyInFile = new HashSet<>();
    for (int i = 0; i < readOnlyCount; ++i) {
      sb.append(writablePartitions.get(i).toPathString()).append(",");
      readOnlyInFile.add(writablePartitions.get(i).toPathString());
    }
    Utils.writeStringToFile(sb.toString(), adminConfigFilePath);
    HelixBootstrapUpgradeUtil.uploadOrDeleteAdminConfigs(hardwareLayoutPath, partitionLayoutPath, zkLayoutPath,
        CLUSTER_NAME_PREFIX, dcStr, false, new String[]{ClusterMapUtils.PARTITION_OVERRIDE_STR}, adminConfigFilePath);
    // verify overridden partitions in Helix
    for (ZkInfo zkInfo : dcsToZkInfo.values()) {
      HelixPropertyStore<ZNRecord> propertyStore =
          CommonUtils.createHelixPropertyStore("localhost:" + zkInfo.getPort(), propertyStoreConfig,
              Collections.singletonList(propertyStoreConfig.rootPath));
      ZNRecord zNRecord =
          propertyStore.get(ClusterMapUtils.PARTITION_OVERRIDE_ZNODE_PATH, null, AccessOption.PERSISTENT);
      if (!activeDcSet.contains(zkInfo.getDcName())) {
        assertNull(zNRecord);
      } else {
        assertNotNull(zNRecord);
        Map<String, Map<String, String>> overridePartition = zNRecord.getMapFields();
        Set<String> readOnlyInDc = new HashSet<>();
        for (Map.Entry<String, Map<String, String>> entry : overridePartition.entrySet()) {
          if (entry.getValue().get(ClusterMapUtils.PARTITION_STATE).equals(ClusterMapUtils.READ_ONLY_STR)) {
            readOnlyInDc.add(entry.getKey());
          }
        }
        // Verify ReadOnly partitions in DC match that in static file
        assertEquals("Mismatch in ReadOnly partitions for static file and propertyStore", readOnlyInFile, readOnlyInDc);
      }
    }
  }
Test that bootstrap tool is able to generate partition override map from static file (if adminConfigFilePath is not
null). It tests both success and failure cases.
@throws Exception
ambry-tools/src/integration-test/java/com/github/ambry/clustermap/HelixBootstrapUpgradeToolTest.java