@Override
  public List<FileMetadata> listFilesWithMetadata(URI fileUri, boolean recursive)
      throws IOException {
    ImmutableList.Builder<FileMetadata> listBuilder = ImmutableList.builder();
    visitFiles(fileUri, recursive, s3Object -> {
      if (!s3Object.key().equals(fileUri.getPath())) {
        FileMetadata.Builder fileBuilder = new FileMetadata.Builder().setFilePath(
                S3_SCHEME + fileUri.getHost() + DELIMITER + getNormalizedFileKey(s3Object))
            .setLastModifiedTime(s3Object.lastModified().toEpochMilli()).setLength(s3Object.size())
            .setIsDirectory(s3Object.key().endsWith(DELIMITER));
        listBuilder.add(fileBuilder.build());
      }
    });
    ImmutableList<FileMetadata> listedFiles = listBuilder.build();
    LOGGER.info("Listed {} files from URI: {}, is recursive: {}", listedFiles.size(), fileUri, recursive);
    return listedFiles;
  }
@Test
  public void testListFilesWithMetadataInFolderNonRecursive()
      throws Exception {
    String folder = "list-files-with-md";
    String[] originalFiles = new String[]{"a-list-2.txt", "b-list-2.txt", "c-list-2.txt"};
    for (String fileName : originalFiles) {
      createEmptyFile(folder, fileName);
    }
    // Files in sub folders should be skipped.
    createEmptyFile(folder + DELIMITER + "subfolder1", "a-sub-file.txt");
    createEmptyFile(folder + DELIMITER + "subfolder2", "a-sub-file.txt");
    List<FileMetadata> actualFiles =
        _s3PinotFS.listFilesWithMetadata(URI.create(String.format(FILE_FORMAT, SCHEME, BUCKET, folder)), false);
    Assert.assertEquals(actualFiles.size(), originalFiles.length);
    List<String> actualFilePaths =
        actualFiles.stream().map(FileMetadata::getFilePath).filter(fp -> fp.contains("list-2"))
            .collect(Collectors.toList());
    Assert.assertEquals(actualFilePaths.size(), originalFiles.length);
    Assert.assertEquals(Arrays.stream(originalFiles)
        .map(fileName -> String.format(FILE_FORMAT, SCHEME, BUCKET, folder + DELIMITER + fileName))
        .collect(Collectors.toList()), actualFilePaths);
  }