/*
 * Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.hadoop.fs.contract;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileContext;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocatedFileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.io.IOUtils;
import org.junit.Assert;
import org.junit.internal.AssumptionViolatedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;

import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_DEFAULT;
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_KEY;

/**
 * Utilities used across test cases.
 */
public class ContractTestUtils extends Assert {

  private static final Logger LOG =
      LoggerFactory.getLogger(ContractTestUtils.class);

  // For scale testing, we can repeatedly write small chunk data to generate
  // a large file.
  public static final String IO_CHUNK_BUFFER_SIZE = "io.chunk.buffer.size";
  public static final int DEFAULT_IO_CHUNK_BUFFER_SIZE = 128;
  public static final String IO_CHUNK_MODULUS_SIZE = "io.chunk.modulus.size";
  public static final int DEFAULT_IO_CHUNK_MODULUS_SIZE = 128;

  /**
   * Assert that a property in the property set matches the expected value.
   * @param props property set
   * @param key property name
   * @param expected expected value. If null, the property must not be in the
   *                 set
   */
  public static void assertPropertyEquals(Properties props,
                                          String key,
                                          String expected) {
    String val = props.getProperty(key);
    if (expected == null) {
      assertNull("Non null property " + key + " = " + val, val);
    } else {
      assertEquals("property " + key + " = " + val,
                          expected,
                          val);
    }
  }

  /**
   *
   * Write a file and read it in, validating the result. Optional flags control
   * whether file overwrite operations should be enabled, and whether the
   * file should be deleted afterwards.
   *
   * If there is a mismatch between what was written and what was expected,
   * a small range of bytes either side of the first error are logged to aid
   * diagnosing what problem occurred -whether it was a previous file
   * or a corrupting of the current file. This assumes that two
   * sequential runs to the same path use datasets with different character
   * moduli.
   *
   * @param fs filesystem
   * @param path path to write to
   * @param len length of data
   * @param overwrite should the create option allow overwrites?
   * @param delete should the file be deleted afterwards? -with a verification
   * that it worked. Deletion is not attempted if an assertion has failed
   * earlier -it is not in a <code>finally{}</code> block.
   * @throws IOException IO problems
   */
  public static void writeAndRead(FileSystem fs,
                                  Path path,
                                  byte[] src,
                                  int len,
                                  int blocksize,
                                  boolean overwrite,
                                  boolean delete) throws IOException {
    fs.mkdirs(path.getParent());

    writeDataset(fs, path, src, len, blocksize, overwrite);

    byte[] dest = readDataset(fs, path, len);

    compareByteArrays(src, dest, len);

    if (delete) {
      rejectRootOperation(path);
      boolean deleted = fs.delete(path, false);
      assertTrue("Deleted", deleted);
      assertPathDoesNotExist(fs, "Cleanup failed", path);
    }
  }

  /**
   * Write a file.
   * Optional flags control
   * whether file overwrite operations should be enabled
   * @param fs filesystem
   * @param path path to write to
   * @param len length of data
   * @param overwrite should the create option allow overwrites?
   * @throws IOException IO problems
   */
  public static void writeDataset(FileSystem fs,
                                   Path path,
                                   byte[] src,
                                   int len,
                                   int buffersize,
                                   boolean overwrite) throws IOException {
    writeDataset(fs, path, src, len, buffersize, overwrite, false);
  }

  /**
   * Write a file.
   * Optional flags control
   * whether file overwrite operations should be enabled
   * Optional using {@link org.apache.hadoop.fs.FSDataOutputStreamBuilder}
   *
   * @param fs filesystem
   * @param path path to write to
   * @param len length of data
   * @param overwrite should the create option allow overwrites?
   * @param useBuilder should use builder API to create file?
   * @throws IOException IO problems
   */
  public static void writeDataset(FileSystem fs, Path path, byte[] src,
      int len, int buffersize, boolean overwrite, boolean useBuilder)
      throws IOException {
    assertTrue(
      "Not enough data in source array to write " + len + " bytes",
      src.length >= len);
    FSDataOutputStream out;
    if (useBuilder) {
      out = fs.createFile(path)
          .overwrite(overwrite)
          .replication((short) 1)
          .bufferSize(buffersize)
          .blockSize(buffersize)
          .build();
    } else {
      out = fs.create(path,
          overwrite,
          fs.getConf()
              .getInt(IO_FILE_BUFFER_SIZE_KEY,
                  IO_FILE_BUFFER_SIZE_DEFAULT),
          (short) 1,
          buffersize);
    }
    try {
      out.write(src, 0, len);
    } finally {
      out.close();
    }
    assertFileHasLength(fs, path, len);
  }

  /**
   * Read the file and convert to a byte dataset.
   * This implements readfully internally, so that it will read
   * in the file without ever having to seek()
   * @param fs filesystem
   * @param path path to read from
   * @param len length of data to read
   * @return the bytes
   * @throws IOException IO problems
   */
  public static byte[] readDataset(FileSystem fs, Path path, int len)
      throws IOException {
    byte[] dest = new byte[len];
    int offset =0;
    int nread = 0;
    try (FSDataInputStream in = fs.open(path)) {
      while (nread < len) {
        int nbytes = in.read(dest, offset + nread, len - nread);
        if (nbytes < 0) {
          throw new EOFException("End of file reached before reading fully.");
        }
        nread += nbytes;
      }
    }
    return dest;
  }

  /**
   * Read a file, verify its length and contents match the expected array.
   * @param fs filesystem
   * @param path path to file
   * @param original original dataset
   * @throws IOException IO Problems
   */
  public static void verifyFileContents(FileSystem fs,
                                        Path path,
                                        byte[] original) throws IOException {
    FileStatus stat = fs.getFileStatus(path);
    String statText = stat.toString();
    assertTrue("not a file " + statText, stat.isFile());
    assertEquals("wrong length " + statText, original.length, stat.getLen());
    byte[] bytes = readDataset(fs, path, original.length);
    compareByteArrays(original, bytes, original.length);
  }

  /**
   * Verify that the read at a specific offset in a stream
   * matches that expected.
   * @param stm stream
   * @param fileContents original file contents
   * @param seekOff seek offset
   * @param toRead number of bytes to read
   * @throws IOException IO problems
   */
  public static void verifyRead(FSDataInputStream stm, byte[] fileContents,
                                int seekOff, int toRead) throws IOException {
    byte[] out = new byte[toRead];
    stm.seek(seekOff);
    stm.readFully(out);
    byte[] expected = Arrays.copyOfRange(fileContents, seekOff,
                                         seekOff + toRead);
    compareByteArrays(expected, out, toRead);
  }

  /**
   * Assert that tthe array original[0..len] and received[] are equal.
   * A failure triggers the logging of the bytes near where the first
   * difference surfaces.
   * @param original source data
   * @param received actual
   * @param len length of bytes to compare
   */
  public static void compareByteArrays(byte[] original,
                                       byte[] received,
                                       int len) {
    assertEquals("Number of bytes read != number written",
                        len, received.length);
    int errors = 0;
    int firstErrorByte = -1;
    for (int i = 0; i < len; i++) {
      if (original[i] != received[i]) {
        if (errors == 0) {
          firstErrorByte = i;
        }
        errors++;
      }
    }

    if (errors > 0) {
      String message = String.format(" %d errors in file of length %d",
                                     errors, len);
      LOG.warn(message);
      // the range either side of the first error to print
      // this is a purely arbitrary number, to aid user debugging
      final int overlap = 10;
      for (int i = Math.max(0, firstErrorByte - overlap);
           i < Math.min(firstErrorByte + overlap, len);
           i++) {
        byte actual = received[i];
        byte expected = original[i];
        String letter = toChar(actual);
        String line = String.format("[%04d] %2x %s%n", i, actual, letter);
        if (expected != actual) {
          line = String.format("[%04d] %2x %s -expected %2x %s%n",
                               i,
                               actual,
                               letter,
                               expected,
                               toChar(expected));
        }
        LOG.warn(line);
      }
      fail(message);
    }
  }

  /**
   * Convert a byte to a character for printing. If the
   * byte value is < 32 -and hence unprintable- the byte is
   * returned as a two digit hex value
   * @param b byte
   * @return the printable character string
   */
  public static String toChar(byte b) {
    if (b >= 0x20) {
      return Character.toString((char) b);
    } else {
      return String.format("%02x", b);
    }
  }

  /**
   * Convert a buffer to a string, character by character.
   * @param buffer input bytes
   * @return a string conversion
   */
  public static String toChar(byte[] buffer) {
    StringBuilder builder = new StringBuilder(buffer.length);
    for (byte b : buffer) {
      builder.append(toChar(b));
    }
    return builder.toString();
  }

  public static byte[] toAsciiByteArray(String s) {
    char[] chars = s.toCharArray();
    int len = chars.length;
    byte[] buffer = new byte[len];
    for (int i = 0; i < len; i++) {
      buffer[i] = (byte) (chars[i] & 0xff);
    }
    return buffer;
  }

  /**
   * Cleanup at the end of a test run.
   * @param action action triggering the operation (for use in logging)
   * @param fileSystem filesystem to work with. May be null
   * @param cleanupPath path to delete as a string
   */
  public static void cleanup(String action,
                             FileSystem fileSystem,
                             String cleanupPath) {
    if (fileSystem == null) {
      return;
    }
    Path path = new Path(cleanupPath).makeQualified(fileSystem.getUri(),
        fileSystem.getWorkingDirectory());
    cleanup(action, fileSystem, path);
  }

  /**
   * Cleanup at the end of a test run.
   * @param action action triggering the operation (for use in logging)
   * @param fileSystem filesystem to work with. May be null
   * @param path path to delete
   */
  public static void cleanup(String action, FileSystem fileSystem, Path path) {
    noteAction(action);
    try {
      rm(fileSystem, path, true, false);
    } catch (Exception e) {
      LOG.error("Error deleting in "+ action + " - "  + path + ": " + e, e);
    }
  }

  /**
   * Delete a directory. There's a safety check for operations against the
   * root directory -these are intercepted and rejected with an IOException
   * unless the allowRootDelete flag is true
   * @param fileSystem filesystem to work with. May be null
   * @param path path to delete
   * @param recursive flag to enable recursive delete
   * @param allowRootDelete can the root directory be deleted?
   * @throws IOException on any problem.
   */
  public static boolean rm(FileSystem fileSystem,
      Path path,
      boolean recursive,
      boolean allowRootDelete) throws
      IOException {
    if (fileSystem != null) {
      rejectRootOperation(path, allowRootDelete);
      if (fileSystem.exists(path)) {
        return fileSystem.delete(path, recursive);
      }
    }
    return false;

  }

  /**
   * Block any operation on the root path. This is a safety check
   * @param path path in the filesystem
   * @param allowRootOperation can the root directory be manipulated?
   * @throws IOException if the operation was rejected
   */
  public static void rejectRootOperation(Path path,
      boolean allowRootOperation) throws IOException {
    if (path.isRoot() && !allowRootOperation) {
      throw new IOException("Root directory operation rejected: " + path);
    }
  }

  /**
   * Block any operation on the root path. This is a safety check
   * @param path path in the filesystem
   * @throws IOException if the operation was rejected
   */
  public static void rejectRootOperation(Path path) throws IOException {
    rejectRootOperation(path, false);
  }

  /**
   * List then delete the children of a path, but not the path itself.
   * This can be used to delete the entries under a root path when that
   * FS does not support {@code delete("/")}.
   * @param fileSystem filesystem
   * @param path path to delete
   * @param recursive flag to indicate child entry deletion should be recursive
   * @return the immediate child entries found and deleted (not including
   * any recursive children of those entries)
   * @throws IOException problem in the deletion process.
   */
  public static FileStatus[] deleteChildren(FileSystem fileSystem,
      Path path,
      boolean recursive) throws IOException {
    FileStatus[] children = listChildren(fileSystem, path);
    for (FileStatus entry : children) {
      fileSystem.delete(entry.getPath(), recursive);
    }
    return children;
  }

  /**
   * List all children of a path, but not the path itself in the case
   * that the path refers to a file or empty directory.
   * @param fileSystem FS
   * @param path path
   * @return a list of children, and never the path itself.
   * @throws IOException problem in the list process
   */
  public static FileStatus[] listChildren(FileSystem fileSystem,
      Path path) throws IOException {
    FileStatus[] entries = fileSystem.listStatus(path);
    if (entries.length == 1 && path.equals(entries[0].getPath())) {
      // this is the path: ignore
      return new FileStatus[]{};
    } else {
      return entries;
    }
  }

  public static void noteAction(String action) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("==============  "+ action +" =============");
    }
  }

  /**
   * downgrade a failure to a message and a warning, then an
   * exception for the Junit test runner to mark as failed.
   * @param message text message
   * @param failure what failed
   * @throws AssumptionViolatedException always
   */
  public static void downgrade(String message, Throwable failure) {
    LOG.warn("Downgrading test " + message, failure);
    AssumptionViolatedException ave =
        new AssumptionViolatedException(failure, null);
    throw ave;
  }

  /**
   * report an overridden test as unsupported.
   * @param message message to use in the text
   * @throws AssumptionViolatedException always
   */
  public static void unsupported(String message) {
    skip(message);
  }

  /**
   * report a test has been skipped for some reason.
   * @param message message to use in the text
   * @throws AssumptionViolatedException always
   */
  public static void skip(String message) {
    LOG.info("Skipping: {}", message);
    throw new AssumptionViolatedException(message);
  }

  /**
   * Fail with an exception that was received.
   * @param text text to use in the exception
   * @param thrown a (possibly null) throwable to init the cause with
   * @throws AssertionError with the text and throwable -always
   */
  public static void fail(String text, Throwable thrown) {
    throw new AssertionError(text, thrown);
  }

  /**
   * Make an assertion about the length of a file.
   * @param fs filesystem
   * @param path path of the file
   * @param expected expected length
   * @throws IOException on File IO problems
   */
  public static void assertFileHasLength(FileSystem fs, Path path,
                                         int expected) throws IOException {
    FileStatus status = fs.getFileStatus(path);
    assertEquals(
        "Wrong file length of file " + path + " status: " + status,
        expected,
        status.getLen());
  }

  /**
   * Assert that a path refers to a directory.
   * @param fs filesystem
   * @param path path of the directory
   * @throws IOException on File IO problems
   */
  public static void assertIsDirectory(FileSystem fs,
                                       Path path) throws IOException {
    FileStatus fileStatus = fs.getFileStatus(path);
    assertIsDirectory(fileStatus);
  }

  /**
   * Assert that a path refers to a directory.
   * @param fileStatus stats to check
   */
  public static void assertIsDirectory(FileStatus fileStatus) {
    assertTrue("Should be a directory -but isn't: " + fileStatus,
               fileStatus.isDirectory());
  }

  /**
   * Write the text to a file, returning the converted byte array
   * for use in validating the round trip.
   * @param fs filesystem
   * @param path path of file
   * @param text text to write
   * @param overwrite should the operation overwrite any existing file?
   * @return the read bytes
   * @throws IOException on IO problems
   */
  public static byte[] writeTextFile(FileSystem fs,
                                   Path path,
                                   String text,
                                   boolean overwrite) throws IOException {
    byte[] bytes = new byte[0];
    if (text != null) {
      bytes = toAsciiByteArray(text);
    }
    createFile(fs, path, overwrite, bytes);
    return bytes;
  }

  /**
   * Create a file.
   * @param fs filesystem
   * @param path       path to write
   * @param overwrite overwrite flag
   * @param data source dataset. Can be null
   * @throws IOException on any problem
   */
  public static void createFile(FileSystem fs,
                                 Path path,
                                 boolean overwrite,
                                 byte[] data) throws IOException {
    FSDataOutputStream stream = fs.create(path, overwrite);
    try {
      if (data != null && data.length > 0) {
        stream.write(data);
      }
      stream.close();
    } finally {
      IOUtils.closeStream(stream);
    }
  }

  /**
   * Touch a file.
   * @param fs filesystem
   * @param path path
   * @throws IOException IO problems
   */
  public static void touch(FileSystem fs,
                           Path path) throws IOException {
    createFile(fs, path, true, null);
  }

  /**
   * Delete a file/dir and assert that delete() returned true
   * <i>and</i> that the path no longer exists. This variant rejects
   * all operations on root directories.
   * @param fs filesystem
   * @param file path to delete
   * @param recursive flag to enable recursive delete
   * @throws IOException IO problems
   */
  public static void assertDeleted(FileSystem fs,
                                   Path file,
                                   boolean recursive) throws IOException {
    assertDeleted(fs, file, recursive, false);
  }

  /**
   * Delete a file/dir and assert that delete() returned true
   * <i>and</i> that the path no longer exists. This variant rejects
   * all operations on root directories
   * @param fs filesystem
   * @param file path to delete
   * @param recursive flag to enable recursive delete
   * @param allowRootOperations can the root dir be deleted?
   * @throws IOException IO problems
   */
  public static void assertDeleted(FileSystem fs,
      Path file,
      boolean recursive,
      boolean allowRootOperations) throws IOException {
    rejectRootOperation(file, allowRootOperations);
    assertPathExists(fs, "about to be deleted file", file);
    boolean deleted = fs.delete(file, recursive);
    String dir = ls(fs, file.getParent());
    assertTrue("Delete failed on " + file + ": " + dir, deleted);
    assertPathDoesNotExist(fs, "Deleted file", file);
  }

  /**
   * Execute a {@link FileSystem#rename(Path, Path)}, and verify that the
   * outcome was as expected. There is no preflight checking of arguments;
   * everything is left to the rename() command.
   * @param fs filesystem
   * @param source source path
   * @param dest destination path
   * @param expectedResult expected return code
   * @throws IOException on any IO failure.
   */
  public static void assertRenameOutcome(FileSystem fs,
      Path source,
      Path dest,
      boolean expectedResult) throws IOException {
    boolean result = fs.rename(source, dest);
    if (expectedResult != result) {
      fail(String.format("Expected rename(%s, %s) to return %b,"
              + " but result was %b", source, dest, expectedResult, result));
    }
  }

  /**
   * Read in "length" bytes, convert to an ascii string.
   * @param fs filesystem
   * @param path path to read
   * @param length #of bytes to read.
   * @return the bytes read and converted to a string
   * @throws IOException IO problems
   */
  public static String readBytesToString(FileSystem fs,
                                  Path path,
                                  int length) throws IOException {
    try (FSDataInputStream in = fs.open(path)) {
      byte[] buf = new byte[length];
      in.readFully(0, buf);
      return toChar(buf);
    }
  }

  /**
   * Take an array of filestats and convert to a string
   * (prefixed with/ a [%02d] counter).
   * @param stats array of stats
   * @param separator separator after every entry
   * @return a stringified set
   */
  public static String fileStatsToString(FileStatus[] stats, String separator) {
    StringBuilder buf = new StringBuilder(stats.length * 128);
    for (int i = 0; i < stats.length; i++) {
      buf.append(String.format("[%02d] %s", i, stats[i])).append(separator);
    }
    return buf.toString();
  }

  /**
   * List a directory.
   * @param fileSystem FS
   * @param path path
   * @return a directory listing or failure message
   * @throws IOException
   */
  public static String ls(FileSystem fileSystem, Path path) throws IOException {
    if (path == null) {
      // surfaces when someone calls getParent() on something at the top of the
      // path
      return "/";
    }
    FileStatus[] stats;
    String pathtext = "ls " + path;
    try {
      stats = fileSystem.listStatus(path);
    } catch (FileNotFoundException e) {
      return pathtext + " -file not found";
    } catch (IOException e) {
      return pathtext + " -failed: " + e;
    }
    return dumpStats(pathtext, stats);
  }

  public static String dumpStats(String pathname, FileStatus[] stats) {
    return pathname + ' ' + fileStatsToString(stats,
        System.lineSeparator());
  }

   /**
   * Assert that a file exists and whose {@link FileStatus} entry
   * declares that this is a file and not a symlink or directory.
   * @param fileSystem filesystem to resolve path against
   * @param filename name of the file
   * @throws IOException IO problems during file operations
   */
  public static void assertIsFile(FileSystem fileSystem, Path filename)
      throws IOException {
    assertPathExists(fileSystem, "Expected file", filename);
    FileStatus status = fileSystem.getFileStatus(filename);
    assertIsFile(filename, status);
  }

  /**
   * Assert that a file exists and whose {@link FileStatus} entry
   * declares that this is a file and not a symlink or directory.
   *
   * @param fileContext filesystem to resolve path against
   * @param filename    name of the file
   * @throws IOException IO problems during file operations
   */
  public static void assertIsFile(FileContext fileContext, Path filename)
      throws IOException {
    assertPathExists(fileContext, "Expected file", filename);
    FileStatus status = fileContext.getFileStatus(filename);
    assertIsFile(filename, status);
  }

  /**
   * Assert that a file exists and whose {@link FileStatus} entry
   * declares that this is a file and not a symlink or directory.
   * @param filename name of the file
   * @param status file status
   */
  public static void assertIsFile(Path filename, FileStatus status) {
    String fileInfo = filename + "  " + status;
    assertFalse("File claims to be a directory " + fileInfo,
                status.isDirectory());
    assertFalse("File claims to be a symlink " + fileInfo,
                       status.isSymlink());
  }

  /**
   * Create a dataset for use in the tests; all data is in the range
   * base to (base+modulo-1) inclusive.
   * @param len length of data
   * @param base base of the data
   * @param modulo the modulo
   * @return the newly generated dataset
   */
  public static byte[] dataset(int len, int base, int modulo) {
    byte[] dataset = new byte[len];
    for (int i = 0; i < len; i++) {
      dataset[i] = (byte) (base + (i % modulo));
    }
    return dataset;
  }

  /**
   * Assert that a path exists -but make no assertions as to the
   * type of that entry.
   *
   * @param fileSystem filesystem to examine
   * @param message message to include in the assertion failure message
   * @param path path in the filesystem
   * @throws FileNotFoundException raised if the path is missing
   * @throws IOException IO problems
   */
  public static void assertPathExists(FileSystem fileSystem, String message,
                               Path path) throws IOException {
    if (!fileSystem.exists(path)) {
      //failure, report it
      ls(fileSystem, path.getParent());
      throw new FileNotFoundException(message + ": not found " + path
                                      + " in " + path.getParent());
    }
  }

  /**
   * Assert that a path exists -but make no assertions as to the
   * type of that entry.
   *
   * @param fileContext fileContext to examine
   * @param message     message to include in the assertion failure message
   * @param path        path in the filesystem
   * @throws FileNotFoundException raised if the path is missing
   * @throws IOException           IO problems
   */
  public static void assertPathExists(FileContext fileContext, String message,
      Path path) throws IOException {
    if (!fileContext.util().exists(path)) {
      //failure, report it
      throw new FileNotFoundException(
          message + ": not found " + path + " in " + path.getParent());
    }
  }

  /**
   * Assert that a path does not exist.
   *
   * @param fileSystem filesystem to examine
   * @param message message to include in the assertion failure message
   * @param path path in the filesystem
   * @throws IOException IO problems
   */
  public static void assertPathDoesNotExist(FileSystem fileSystem,
                                            String message,
                                            Path path) throws IOException {
    try {
      FileStatus status = fileSystem.getFileStatus(path);
      fail(message + ": unexpectedly found " + path + " as  " + status);
    } catch (FileNotFoundException expected) {
      //this is expected

    }
  }

  /**
   * Assert that a path does not exist.
   *
   * @param fileContext fileContext to examine
   * @param message     message to include in the assertion failure message
   * @param path        path in the filesystem
   * @throws IOException IO problems
   */
  public static void assertPathDoesNotExist(FileContext fileContext,
      String message, Path path) throws IOException {
    try {
      FileStatus status = fileContext.getFileStatus(path);
      fail(message + ": unexpectedly found " + path + " as  " + status);
    } catch (FileNotFoundException expected) {
      //this is expected

    }
  }

  /**
   * Assert that a FileSystem.listStatus on a dir finds the subdir/child entry.
   * @param fs filesystem
   * @param dir directory to scan
   * @param subdir full path to look for
   * @throws IOException IO probles
   */
  public static void assertListStatusFinds(FileSystem fs,
                                           Path dir,
                                           Path subdir) throws IOException {
    FileStatus[] stats = fs.listStatus(dir);
    boolean found = false;
    StringBuilder builder = new StringBuilder();
    for (FileStatus stat : stats) {
      builder.append(stat.toString()).append(System.lineSeparator());
      if (stat.getPath().equals(subdir)) {
        found = true;
      }
    }
    assertTrue("Path " + subdir
                      + " not found in directory " + dir + ":" + builder,
                      found);
  }

  /**
   * Execute {@link FileSystem#mkdirs(Path)}; expect {@code true} back.
   * (Note: does not work for localFS if the directory already exists)
   * Does not perform any validation of the created directory.
   * @param fs filesystem
   * @param dir directory to create
   * @throws IOException IO Problem
   */
  public static void assertMkdirs(FileSystem fs, Path dir) throws IOException {
    assertTrue("mkdirs(" + dir + ") returned false", fs.mkdirs(dir));
  }

  /**
   * Test for the host being an OSX machine.
   * @return true if the JVM thinks that is running on OSX
   */
  public static boolean isOSX() {
    return System.getProperty("os.name").contains("OS X");
  }

  /**
   * compare content of file operations using a double byte array.
   * @param concat concatenated files
   * @param bytes bytes
   */
  public static void validateFileContent(byte[] concat, byte[][] bytes) {
    int idx = 0;
    boolean mismatch = false;

    for (byte[] bb : bytes) {
      for (byte b : bb) {
        if (b != concat[idx++]) {
          mismatch = true;
          break;
        }
      }
      if (mismatch) {
        break;
      }
    }
    assertFalse("File content of file is not as expected at offset " + idx,
                mismatch);
  }

  /**
   * Receives test data from the given input file and checks the size of the
   * data as well as the pattern inside the received data.
   *
   * @param fs FileSystem
   * @param path Input file to be checked
   * @param expectedSize the expected size of the data to be read from the
   *        input file in bytes
   * @param bufferLen Pattern length
   * @param modulus   Pattern modulus
   * @throws IOException
   *         thrown if an error occurs while reading the data
   */
  public static void verifyReceivedData(FileSystem fs, Path path,
                                      final long expectedSize,
                                      final int bufferLen,
                                      final int modulus) throws IOException {
    final byte[] testBuffer = new byte[bufferLen];

    long totalBytesRead = 0;
    int nextExpectedNumber = 0;
    NanoTimer timer = new NanoTimer();
    try (InputStream inputStream = fs.open(path)) {
      while (true) {
        final int bytesRead = inputStream.read(testBuffer);
        if (bytesRead < 0) {
          break;
        }

        totalBytesRead += bytesRead;

        for (int i = 0; i < bytesRead; ++i) {
          if (testBuffer[i] != nextExpectedNumber) {
            throw new IOException("Read number " + testBuffer[i]
                + " but expected " + nextExpectedNumber);
          }

          ++nextExpectedNumber;

          if (nextExpectedNumber == modulus) {
            nextExpectedNumber = 0;
          }
        }
      }

      if (totalBytesRead != expectedSize) {
        throw new IOException("Expected to read " + expectedSize +
            " bytes but only received " + totalBytesRead);
      }
    }
    timer.end("Time to read %d bytes", expectedSize);
    bandwidth(timer, expectedSize);
  }

  /**
   * Generates test data of the given size according to some specific pattern
   * and writes it to the provided output file.
   *
   * @param fs FileSystem
   * @param path Test file to be generated
   * @param size The size of the test data to be generated in bytes
   * @param bufferLen Pattern length
   * @param modulus   Pattern modulus
   * @throws IOException
   *         thrown if an error occurs while writing the data
   */
  public static long generateTestFile(FileSystem fs, Path path,
                                      final long size,
                                      final int bufferLen,
                                      final int modulus) throws IOException {
    final byte[] testBuffer = new byte[bufferLen];
    for (int i = 0; i < testBuffer.length; ++i) {
      testBuffer[i] = (byte) (i % modulus);
    }

    long bytesWritten = 0;
    try (OutputStream outputStream = fs.create(path, false)) {
      while (bytesWritten < size) {
        final long diff = size - bytesWritten;
        if (diff < testBuffer.length) {
          outputStream.write(testBuffer, 0, (int) diff);
          bytesWritten += diff;
        } else {
          outputStream.write(testBuffer);
          bytesWritten += testBuffer.length;
        }
      }

      return bytesWritten;
    }
  }

  /**
   * Creates and reads a file with the given size. The test file is generated
   * according to a specific pattern so it can be easily verified even if it's
   * a multi-GB one.
   * During the read phase the incoming data stream is also checked against
   * this pattern.
   *
   * @param fs FileSystem
   * @param parent Test file parent dir path
   * @throws IOException
   *    thrown if an I/O error occurs while writing or reading the test file
   */
  public static void createAndVerifyFile(FileSystem fs,
                                         Path parent,
                                         final long fileSize)
      throws IOException {
    int testBufferSize = fs.getConf()
        .getInt(IO_CHUNK_BUFFER_SIZE, DEFAULT_IO_CHUNK_BUFFER_SIZE);
    int modulus = fs.getConf()
        .getInt(IO_CHUNK_MODULUS_SIZE, DEFAULT_IO_CHUNK_MODULUS_SIZE);

    final String objectName = UUID.randomUUID().toString();
    final Path objectPath = new Path(parent, objectName);

    // Write test file in a specific pattern
    NanoTimer timer = new NanoTimer();
    assertEquals(fileSize,
        generateTestFile(fs, objectPath, fileSize, testBufferSize, modulus));
    assertPathExists(fs, "not created successful", objectPath);
    timer.end("Time to write %d bytes", fileSize);
    bandwidth(timer, fileSize);

    // Now read the same file back and verify its content
    try {
      verifyReceivedData(fs, objectPath, fileSize, testBufferSize, modulus);
    } finally {
      // Delete test file
      fs.delete(objectPath, false);
    }
  }

  /**
   * Make times more readable, by adding a "," every three digits.
   * @param nanos nanos or other large number
   * @return a string for logging
   */
  public static String toHuman(long nanos) {
    return String.format(Locale.ENGLISH, "%,d", nanos);
  }

  /**
   * Log the bandwidth of a timer as inferred from the number of
   * bytes processed.
   * @param timer timer
   * @param bytes bytes processed in the time period
   */
  public static void bandwidth(NanoTimer timer, long bytes) {
    LOG.info("Bandwidth = {}  MB/S",
        timer.bandwidthDescription(bytes));
  }

  /**
   * Work out the bandwidth in MB/s.
   * @param bytes bytes
   * @param durationNS duration in nanos
   * @return the number of megabytes/second of the recorded operation
   */
  public static double bandwidthMBs(long bytes, long durationNS) {
    return bytes / (1024.0 * 1024) * 1.0e9 / durationNS;
  }

  /**
   * Recursively create a directory tree.
   * Return the details about the created tree. The files and directories
   * are those created under the path, not the base directory created. That
   * is retrievable via {@link TreeScanResults#getBasePath()}.
   * @param fs filesystem
   * @param current parent dir
   * @param depth depth of directory tree
   * @param width width: subdirs per entry
   * @param files number of files per entry
   * @param filesize size of files to create in bytes.
   * @return the details about the created tree.
   * @throws IOException IO Problems
   */
  public static TreeScanResults createSubdirs(FileSystem fs,
      Path current,
      int depth,
      int width,
      int files,
      int filesize) throws IOException {
    return createSubdirs(fs, current, depth, width, files,
        filesize, "dir-", "file-", "0");
  }

  /**
   * Recursively create a directory tree.
   * @param fs filesystem
   * @param current the current dir in the walk
   * @param depth depth of directory tree
   * @param width width: subdirs per entry
   * @param files number of files per entry
   * @param filesize size of files to create in bytes.
   * @param dirPrefix prefix for directory entries
   * @param filePrefix prefix for file entries
   * @param marker string which is slowly built up to uniquely name things
   * @return the details about the created tree.
   * @throws IOException IO Problems
   */
  public static TreeScanResults createSubdirs(FileSystem fs,
      Path current,
      int depth,
      int width,
      int files,
      int filesize,
      String dirPrefix,
      String filePrefix,
      String marker) throws IOException {
    fs.mkdirs(current);
    TreeScanResults results = new TreeScanResults(current);
    if (depth > 0) {
      byte[] data = dataset(filesize, 'a', 'z');
      for (int i = 0; i < files; i++) {
        String name = String.format("%s-%s-%04d.txt", filePrefix, marker, i);
        Path path = new Path(current, name);
        createFile(fs, path, true, data);
        results.add(fs, path);
      }
      for (int w = 0; w < width; w++) {
        String marker2 = String.format("%s-%04d", marker, w);
        Path child = new Path(current, dirPrefix + marker2);
        results.add(createSubdirs(fs, child, depth - 1, width, files,
            filesize, dirPrefix, filePrefix, marker2));
        results.add(fs, child);
      }
    }
    return results;
  }

  /**
   * Predicate to determine if two lists are equivalent, that is, they
   * contain the same entries.
   * @param left first collection of paths
   * @param right second collection of paths
   * @return true if all entries are in each collection of path.
   */
  public static boolean collectionsEquivalent(Collection<Path> left,
      Collection<Path> right) {
    Set<Path> leftSet = new HashSet<>(left);
    Set<Path> rightSet = new HashSet<>(right);
    return leftSet.containsAll(right) && rightSet.containsAll(left);
  }

  /**
   * Take a collection of paths and build a string from them: useful
   * for assertion messages.
   * @param paths paths to stringify
   * @return a string representation
   */
  public static String pathsToString(Collection<Path> paths) {
    StringBuilder builder = new StringBuilder(paths.size() * 100);
    String nl = System.lineSeparator();
    builder.append(nl);
    for (Path path : paths) {
      builder.append("  \"").append(path.toString())
          .append("\"").append(nl);
    }
    builder.append("]");
    return builder.toString();
  }

  /**
   * Predicate to determine if two lists are equivalent, that is, they
   * contain the same entries.
   * @param left first collection of paths
   * @param right second collection of paths
   * @return true if all entries are in each collection of path.
   */
  public static boolean collectionsEquivalentNoDuplicates(Collection<Path> left,
      Collection<Path> right) {
    return collectionsEquivalent(left, right) &&
        !containsDuplicates(left) && !containsDuplicates(right);
  }


  /**
   * Predicate to test for a collection of paths containing duplicate entries.
   * @param paths collection of paths
   * @return true if there are duplicates.
   */
  public static boolean containsDuplicates(Collection<Path> paths) {
    return new HashSet<>(paths).size() != paths.size();
  }

  /**
   * Get the status of a path eventually, even if the FS doesn't have create
   * consistency. If the path is not there by the time the timeout completes,
   * an assertion is raised.
   * @param fs FileSystem
   * @param path path to look for
   * @param timeout timeout in milliseconds
   * @return the status
   * @throws IOException if an I/O error occurs while writing or reading the
   * test file <i>other than file not found</i>
   */
  public static FileStatus getFileStatusEventually(FileSystem fs, Path path,
      int timeout) throws IOException, InterruptedException {
    long endTime = System.currentTimeMillis() + timeout;
    FileStatus stat = null;
    do {
      try {
        stat = fs.getFileStatus(path);
      } catch (FileNotFoundException e) {
        if (System.currentTimeMillis() > endTime) {
          // timeout, raise an assert with more diagnostics
          assertPathExists(fs, "Path not found after " + timeout + " mS", path);
        } else {
          Thread.sleep(50);
        }
      }
    } while (stat == null);
    return stat;
  }

  /**
   * Recursively list all entries, with a depth first traversal of the
   * directory tree.
   * @param path path
   * @return the number of entries listed
   * @throws IOException IO problems
   */
  public static TreeScanResults treeWalk(FileSystem fs, Path path)
      throws IOException {
    TreeScanResults dirsAndFiles = new TreeScanResults();

    FileStatus[] statuses = fs.listStatus(path);
    for (FileStatus status : statuses) {
      LOG.info("{}{}", status.getPath(), status.isDirectory() ? "*" : "");
    }
    for (FileStatus status : statuses) {
      dirsAndFiles.add(status);
      if (status.isDirectory()) {
        dirsAndFiles.add(treeWalk(fs, status.getPath()));
      }
    }
    return dirsAndFiles;
  }

  /**
   * Convert a remote iterator over file status results into a list.
   * The utility equivalents in commons collection and guava cannot be
   * used here, as this is a different interface, one whose operators
   * can throw IOEs.
   * @param iterator input iterator
   * @return the status entries as a list.
   * @throws IOException
   */
  public static List<LocatedFileStatus> toList(
      RemoteIterator<LocatedFileStatus> iterator) throws IOException {
    ArrayList<LocatedFileStatus> list = new ArrayList<>();
    while (iterator.hasNext()) {
      list.add(iterator.next());
    }
    return list;
  }

  /**
   * Convert a remote iterator over file status results into a list.
   * This uses {@link RemoteIterator#next()} calls only, expecting
   * a raised {@link NoSuchElementException} exception to indicate that
   * the end of the listing has been reached. This iteration strategy is
   * designed to verify that the implementation of the remote iterator
   * generates results and terminates consistently with the {@code hasNext/next}
   * iteration. More succinctly "verifies that the {@code next()} operator
   * isn't relying on {@code hasNext()} to always be called during an iteration.
   * @param iterator input iterator
   * @return the status entries as a list.
   * @throws IOException IO problems
   */
  @SuppressWarnings("InfiniteLoopStatement")
  public static List<LocatedFileStatus> toListThroughNextCallsAlone(
      RemoteIterator<LocatedFileStatus> iterator) throws IOException {
    ArrayList<LocatedFileStatus> list = new ArrayList<>();
    try {
      while (true) {
        list.add(iterator.next());
      }
    } catch (NoSuchElementException expected) {
      // ignored
    }
    return list;
  }


  /**
   * Results of recursive directory creation/scan operations.
   */
  public static final class TreeScanResults {

    private Path basePath;
    private final List<Path> files = new ArrayList<>();
    private final List<Path> directories = new ArrayList<>();
    private final List<Path> other = new ArrayList<>();


    public TreeScanResults() {
    }

    public TreeScanResults(Path basePath) {
      this.basePath = basePath;
    }

    /**
     * Build from a located file status iterator.
     * @param results results of the listFiles/listStatus call.
     * @throws IOException IO problems during the iteration.
     */
    public TreeScanResults(RemoteIterator<LocatedFileStatus> results)
        throws IOException {
      while (results.hasNext()) {
        add(results.next());
      }
    }

    /**
     * Construct results from an array of statistics.
     * @param stats statistics array. Must not be null.
     */
    public TreeScanResults(FileStatus[] stats) {
      assertNotNull("Null file status array", stats);
      for (FileStatus stat : stats) {
        add(stat);
      }
    }

    /**
     * Construct results from an iterable collection of statistics.
     * @param stats statistics source. Must not be null.
     */
    public <F extends FileStatus> TreeScanResults(Iterable<F> stats) {
      for (FileStatus stat : stats) {
        add(stat);
      }
    }

    /**
     * Add all paths in the other set of results to this instance.
     * @param that the other instance
     * @return this instance
     */
    public TreeScanResults add(TreeScanResults that) {
      files.addAll(that.files);
      directories.addAll(that.directories);
      other.addAll(that.other);
      return this;
    }

    /**
     * Increment the counters based on the file status.
     * @param status path status to count.
     */
    public void add(FileStatus status) {
      if (status.isFile()) {
        files.add(status.getPath());
      } else if (status.isDirectory()) {
        directories.add(status.getPath());
      } else {
        other.add(status.getPath());
      }
    }

    public void add(FileSystem fs, Path path) throws IOException {
      add(fs.getFileStatus(path));
    }

    @Override
    public String toString() {
      return String.format("%d director%s and %d file%s",
          getDirCount(),
          getDirCount() == 1 ? "y" : "ies",
          getFileCount(),
          getFileCount() == 1 ? "" : "s");
    }

    /**
     * Equality check compares files and directory counts.
     * As these are non-final fields, this class cannot be used in
     * hash tables.
     * @param o other object
     * @return true iff the file and dir count match.
     */
    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      TreeScanResults that = (TreeScanResults) o;
      return getFileCount() == that.getFileCount() &&
          getDirCount() == that.getDirCount();
    }

    /**
     * This is a spurious hash code subclass to keep findbugs quiet.
     * @return the base {@link Object#hashCode()}
     */
    @Override
    public int hashCode() {
      return super.hashCode();
    }

    /**
     * Assert that the state of a listing has the specific number of files,
     * directories and other entries. The error text will include
     * the {@code text} param, the field in question, and the entire object's
     * string value.
     * @param text text prefix for assertions.
     * @param f file count
     * @param d expected directory count
     * @param o expected other entries.
     */
    public void assertSizeEquals(String text, long f, long d, long o) {
      String self = toString();
      Assert.assertEquals(text + ": file count in " + self,
          f, getFileCount());
      Assert.assertEquals(text + ": directory count in " + self,
          d, getDirCount());
      Assert.assertEquals(text + ": 'other' count in " + self,
          o, getOtherCount());
    }

    /**
     * Assert that the trees are equivalent: that every list matches (and
     * that neither has any duplicates).
     * @param that the other entry
     */
    public void assertEquivalent(TreeScanResults that) {
      assertFieldsEquivalent("files", that, files, that.files);
      assertFieldsEquivalent("directories", that,
          directories, that.directories);
      assertFieldsEquivalent("other", that, other, that.other);
    }

    /**
     * Assert that a field in two instances are equivalent.
     * @param fieldname field name for error messages
     * @param that the other instance to scan
     * @param ours our field's contents
     * @param theirs the other instance's field constants
     */
    public void assertFieldsEquivalent(String fieldname,
        TreeScanResults that,
        List<Path> ours, List<Path> theirs) {
      String ourList = pathsToString(ours);
      String theirList = pathsToString(theirs);
      assertFalse("Duplicate  " + fieldname + " in " + this
          +": " + ourList,
          containsDuplicates(ours));
      assertFalse("Duplicate  " + fieldname + " in other " + that
              + ": " + theirList,
          containsDuplicates(theirs));
      assertTrue(fieldname + " mismatch: between " + ourList
          + " and " + theirList,
          collectionsEquivalent(ours, theirs));
    }

    public List<Path> getFiles() {
      return files;
    }

    public List<Path> getDirectories() {
      return directories;
    }

    public List<Path> getOther() {
      return other;
    }

    public Path getBasePath() {
      return basePath;
    }

    public long getFileCount() {
      return files.size();
    }

    public long getDirCount() {
      return directories.size();
    }

    public long getOtherCount() {
      return other.size();
    }

    /**
     * Total count of entries.
     * @return the total number of entries
     */
    public long totalCount() {
      return getFileCount() + getDirCount() + getOtherCount();
    }

  }

  /**
   * A simple class for timing operations in nanoseconds, and for
   * printing some useful results in the process.
   */
  public static final class NanoTimer {
    private long startTime;
    private long endTime;

    public NanoTimer() {
      startTime = now();
    }

    /**
     * Reset the timer.  Equivalent to the reset button of a stopwatch.
     */
    public void reset() {
      endTime = 0;
      startTime = now();
    }

    /**
     * End the operation.
     * @return the duration of the operation
     */
    public long end() {
      endTime = now();
      return duration();
    }

    /**
     * End the operation; log the duration.
     * @param format message
     * @param args any arguments
     * @return the duration of the operation
     */
    public long end(String format, Object... args) {
      long d = end();
      LOG.info("Duration of {}: {} nS",
          String.format(format, args), toHuman(d));
      return d;
    }

    public long now() {
      return System.nanoTime();
    }

    public long duration() {
      return endTime - startTime;
    }

    /**
     * Intermediate duration of the operation.
     * @return how much time has passed since the start (in nanos).
     */
    public long elapsedTime() {
      return now() - startTime;
    }

    /**
     * Elapsed time in milliseconds; no rounding.
     * @return elapsed time
     */
    public long elapsedTimeMs() {
      return elapsedTime() / 1000000;
    }

    public double bandwidth(long bytes) {
      return bandwidthMBs(bytes, duration());
    }

    /**
     * Bandwidth as bytes per second.
     * @param bytes bytes in
     * @return the number of bytes per second this operation.
     *         0 if duration == 0.
     */
    public double bandwidthBytes(long bytes) {
      double duration = duration();
      return duration > 0 ? bytes / duration : 0;
    }

    /**
     * How many nanoseconds per IOP, byte, etc.
     * @param operations operations processed in this time period
     * @return the nanoseconds it took each byte to be processed
     */
    public long nanosPerOperation(long operations) {
      return duration() / operations;
    }

    /**
     * Get a description of the bandwidth, even down to fractions of
     * a MB.
     * @param bytes bytes processed
     * @return bandwidth
     */
    public String bandwidthDescription(long bytes) {
      return String.format("%,.6f", bandwidth(bytes));
    }

    public long getStartTime() {
      return startTime;
    }

    public long getEndTime() {
      return endTime;
    }
  }

}
