public static String getDoneFileName(JobIndexInfo indexInfo)
      throws IOException {
    return getDoneFileName(indexInfo,
        JHAdminConfig.DEFAULT_MR_HS_JOBNAME_LIMIT);
  }
@Test
  public void testJobNameWithMultibyteChars() throws IOException {
    JobIndexInfo info = new JobIndexInfo();
    JobID oldJobId = JobID.forName(JOB_ID);
    JobId jobId = TypeConverter.toYarn(oldJobId);
    info.setJobId(jobId);
    info.setSubmitTime(Long.parseLong(SUBMIT_TIME));
    info.setUser(USER_NAME);

    StringBuilder sb = new StringBuilder();
    info.setFinishTime(Long.parseLong(FINISH_TIME));
    info.setNumMaps(Integer.parseInt(NUM_MAPS));
    info.setNumReduces(Integer.parseInt(NUM_REDUCES));
    info.setJobStatus(JOB_STATUS);
    info.setQueueName(QUEUE_NAME);
    info.setJobStartTime(Long.parseLong(JOB_START_TIME));

    // Test for 1 byte UTF-8 character
    // which is encoded into 1 x 3 = 3 characters by URL encode.
    for (int i = 0; i < 100; i++) {
      sb.append('%');
    }
    String longJobName = sb.toString();
    info.setJobName(longJobName);

    String jobHistoryFile =
        FileNameIndexUtils.getDoneFileName(info, 50);

    assertTrue(jobHistoryFile.length() <= 255);
    String trimedJobName = jobHistoryFile.split(
        FileNameIndexUtils.DELIMITER)[3]; // 3 is index of job name

    // 3 x 16 < 50 < 3 x 17 so the length of trimedJobName should be 48
    assertEquals(48, trimedJobName.getBytes(UTF_8).length);

    // validate whether trimmedJobName by testing reversibility
    byte[] trimedJobNameInByte = trimedJobName.getBytes(UTF_8);
    String reEncodedTrimedJobName = new String(trimedJobNameInByte, UTF_8);
    assertArrayEquals(trimedJobNameInByte,
        reEncodedTrimedJobName.getBytes(UTF_8));
    sb.setLength(0);

    // Test for 2 bytes UTF-8 character
    // which is encoded into 2 x 3 = 6 characters by URL encode.
    for (int i = 0; i < 100; i++) {
      sb.append('\u03A9'); // large omega
    }
    longJobName = sb.toString();
    info.setJobName(longJobName);

    jobHistoryFile =
        FileNameIndexUtils.getDoneFileName(info, 27);

    assertTrue(jobHistoryFile.length() <= 255);
    trimedJobName = jobHistoryFile.split(
        FileNameIndexUtils.DELIMITER)[3]; // 3 is index of job name

    // 6 x 4 < 27 < 6 x 5 so the length of trimedJobName should be 24
    assertEquals(24, trimedJobName.getBytes(UTF_8).length);

    // validate whether trimmedJobName by testing reversibility
    trimedJobNameInByte = trimedJobName.getBytes(UTF_8);
    reEncodedTrimedJobName = new String(trimedJobNameInByte, UTF_8);
    assertArrayEquals(trimedJobNameInByte,
        reEncodedTrimedJobName.getBytes(UTF_8));
    sb.setLength(0);

    // Test for 3 bytes UTF-8 character
    // which is encoded into 3 x 3 = 9 characters by URL encode.
    for (int i = 0; i < 100; i++) {
      sb.append('\u2192'); // rightwards arrow
    }
    longJobName = sb.toString();
    info.setJobName(longJobName);

    jobHistoryFile =
        FileNameIndexUtils.getDoneFileName(info, 40);

    assertTrue(jobHistoryFile.length() <= 255);
    trimedJobName = jobHistoryFile.split(
        FileNameIndexUtils.DELIMITER)[3]; // 3 is index of job name

    // 9 x 4 < 40 < 9 x 5 so the length of trimedJobName should be 36
    assertEquals(36, trimedJobName.getBytes(UTF_8).length);

    // validate whether trimmedJobName by testing reversibility
    trimedJobNameInByte = trimedJobName.getBytes(UTF_8);
    reEncodedTrimedJobName = new String(trimedJobNameInByte, UTF_8);
    assertArrayEquals(trimedJobNameInByte,
        reEncodedTrimedJobName.getBytes(UTF_8));
    sb.setLength(0);

    // Test for 4 bytes UTF-8 character
    // which is encoded into 4 x 3 = 12 characters by URL encode.
    for (int i = 0; i < 100; i++) {
      sb.append("\uD867\uDE3D"); // Mugil cephalus in Kanji.
    }
    longJobName = sb.toString();
    info.setJobName(longJobName);

    jobHistoryFile =
        FileNameIndexUtils.getDoneFileName(info, 49);

    assertTrue(jobHistoryFile.length() <= 255);
    trimedJobName = jobHistoryFile.split(
        FileNameIndexUtils.DELIMITER)[3]; // 3 is index of job name

    // 12 x 4 < 49 < 12 x 5 so the length of trimedJobName should be 48
    assertEquals(48, trimedJobName.getBytes(UTF_8).length);

    // validate whether trimmedJobName by testing reversibility
    trimedJobNameInByte = trimedJobName.getBytes(UTF_8);
    reEncodedTrimedJobName = new String(trimedJobNameInByte, UTF_8);
    assertArrayEquals(trimedJobNameInByte,
        reEncodedTrimedJobName.getBytes(UTF_8));
    sb.setLength(0);

    // Test for the combination of 1 to 4 bytes UTF-8 characters
    sb.append('\u732B') // cat in Kanji (encoded into 3 bytes x 3 characters)
        .append("[") // (encoded into 1 byte x 3 characters)
        .append('\u03BB') // small lambda (encoded into 2 bytes x 3 characters)
        .append('/') // (encoded into 1 byte x 3 characters)
        .append('A') // not url-encoded (1 byte x 1 character)
        .append("\ud867\ude49") // flying fish in
        // Kanji (encoded into 4 bytes x 3 characters)
        .append('\u72AC'); // dog in Kanji (encoded into 3 bytes x 3 characters)

    longJobName = sb.toString();
    info.setJobName(longJobName);

    jobHistoryFile =
        FileNameIndexUtils.getDoneFileName(info, 23);

    assertTrue(jobHistoryFile.length() <= 255);
    trimedJobName = jobHistoryFile.split(
        FileNameIndexUtils.DELIMITER)[3]; // 3 is index of job name

    // total size of the first 5 characters = 22
    // 23 < total size of the first 6 characters
    assertEquals(22, trimedJobName.getBytes(UTF_8).length);

    // validate whether trimmedJobName by testing reversibility
    trimedJobNameInByte = trimedJobName.getBytes(UTF_8);
    reEncodedTrimedJobName = new String(trimedJobNameInByte, UTF_8);
    assertArrayEquals(trimedJobNameInByte,
        reEncodedTrimedJobName.getBytes(UTF_8));
  }