/**
 * 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;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.util.Shell;

import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.junit.Test;

import static org.junit.Assert.*;

/** This test LocalDirAllocator works correctly;
 * Every test case uses different buffer dirs to
 * enforce the AllocatorPerContext initialization.
 * This test does not run on Cygwin because under Cygwin
 * a directory can be created in a read-only directory
 * which breaks this test.
 */
@RunWith(Parameterized.class)
public class TestLocalDirAllocator {
  final static private Configuration conf = new Configuration();
  final static private String BUFFER_DIR_ROOT = "build/test/temp";
  final static private String ABSOLUTE_DIR_ROOT;
  final static private String QUALIFIED_DIR_ROOT;
  final static private Path BUFFER_PATH_ROOT = new Path(BUFFER_DIR_ROOT);
  final static private File BUFFER_ROOT = new File(BUFFER_DIR_ROOT);
  final static private String CONTEXT = "fs.client.buffer.dir";
  final static private String FILENAME = "block";
  final static private LocalDirAllocator dirAllocator =
    new LocalDirAllocator(CONTEXT);
  static LocalFileSystem localFs;
  final static private boolean isWindows =
    System.getProperty("os.name").startsWith("Windows");
  final static int SMALL_FILE_SIZE = 100;
  final static private String RELATIVE = "/RELATIVE";
  final static private String ABSOLUTE = "/ABSOLUTE";
  final static private String QUALIFIED = "/QUALIFIED";
  final private String ROOT;
  final private String PREFIX;

  static {
    try {
      localFs = FileSystem.getLocal(conf);
      rmBufferDirs();
    } catch(IOException e) {
      System.out.println(e.getMessage());
      e.printStackTrace();
      System.exit(-1);
    }

    ABSOLUTE_DIR_ROOT = new Path(localFs.getWorkingDirectory(),
        BUFFER_DIR_ROOT).toUri().getPath();
    QUALIFIED_DIR_ROOT = new Path(localFs.getWorkingDirectory(),
        BUFFER_DIR_ROOT).toUri().toString();
  }

  public TestLocalDirAllocator(String root, String prefix) {
    ROOT = root;
    PREFIX = prefix;
  }

  @Parameters
  public static Collection<Object[]> params() {
    Object [][] data = new Object[][] {
      { BUFFER_DIR_ROOT, RELATIVE },
      { ABSOLUTE_DIR_ROOT, ABSOLUTE },
      { QUALIFIED_DIR_ROOT, QUALIFIED }
    };

    return Arrays.asList(data);
  }

  private static void rmBufferDirs() throws IOException {
    assertTrue(!localFs.exists(BUFFER_PATH_ROOT) ||
        localFs.delete(BUFFER_PATH_ROOT, true));
  }

  private static void validateTempDirCreation(String dir) throws IOException {
    File result = createTempFile(SMALL_FILE_SIZE);
    assertTrue("Checking for " + dir + " in " + result + " - FAILED!",
        result.getPath().startsWith(new Path(dir, FILENAME).toUri().getPath()));
  }

  private static File createTempFile() throws IOException {
    return createTempFile(-1);
  }

  private static File createTempFile(long size) throws IOException {
    File result = dirAllocator.createTmpFileForWrite(FILENAME, size, conf);
    result.delete();
    return result;
  }

  private String buildBufferDir(String dir, int i) {
    return dir + PREFIX + i;
  }

  /** Two buffer dirs. The first dir does not exist & is on a read-only disk;
   * The second dir exists & is RW
   * @throws Exception
   */
  @Test
  public void test0() throws Exception {
    if (isWindows) return;
    String dir0 = buildBufferDir(ROOT, 0);
    String dir1 = buildBufferDir(ROOT, 1);
    try {
      conf.set(CONTEXT, dir0 + "," + dir1);
      assertTrue(localFs.mkdirs(new Path(dir1)));
      BUFFER_ROOT.setReadOnly();
      validateTempDirCreation(dir1);
      validateTempDirCreation(dir1);
    } finally {
      Shell.execCommand(new String[]{"chmod", "u+w", BUFFER_DIR_ROOT});
      rmBufferDirs();
    }
  }

  /** Two buffer dirs. The first dir exists & is on a read-only disk;
   * The second dir exists & is RW
   * @throws Exception
   */
  @Test
  public void test1() throws Exception {
    if (isWindows) return;
    String dir1 = buildBufferDir(ROOT, 1);
    String dir2 = buildBufferDir(ROOT, 2);
    try {
      conf.set(CONTEXT, dir1 + "," + dir2);
      assertTrue(localFs.mkdirs(new Path(dir2)));
      BUFFER_ROOT.setReadOnly();
      validateTempDirCreation(dir2);
      validateTempDirCreation(dir2);
    } finally {
      Shell.execCommand(new String[]{"chmod", "u+w", BUFFER_DIR_ROOT});
      rmBufferDirs();
    }
  }
  /** Two buffer dirs. Both do not exist but on a RW disk.
   * Check if tmp dirs are allocated in a round-robin
   */
  @Test
  public void test2() throws Exception {
    if (isWindows) return;
    String dir2 = buildBufferDir(ROOT, 2);
    String dir3 = buildBufferDir(ROOT, 3);
    try {
      conf.set(CONTEXT, dir2 + "," + dir3);

      // create the first file, and then figure the round-robin sequence
      createTempFile(SMALL_FILE_SIZE);
      int firstDirIdx = (dirAllocator.getCurrentDirectoryIndex() == 0) ? 2 : 3;
      int secondDirIdx = (firstDirIdx == 2) ? 3 : 2;

      // check if tmp dirs are allocated in a round-robin manner
      validateTempDirCreation(buildBufferDir(ROOT, firstDirIdx));
      validateTempDirCreation(buildBufferDir(ROOT, secondDirIdx));
      validateTempDirCreation(buildBufferDir(ROOT, firstDirIdx));
    } finally {
      rmBufferDirs();
    }
  }

  /** Two buffer dirs. Both exists and on a R/W disk.
   * Later disk1 becomes read-only.
   * @throws Exception
   */
  @Test
  public void test3() throws Exception {
    if (isWindows) return;
    String dir3 = buildBufferDir(ROOT, 3);
    String dir4 = buildBufferDir(ROOT, 4);
    try {
      conf.set(CONTEXT, dir3 + "," + dir4);
      assertTrue(localFs.mkdirs(new Path(dir3)));
      assertTrue(localFs.mkdirs(new Path(dir4)));

      // Create the first small file
      createTempFile(SMALL_FILE_SIZE);

      // Determine the round-robin sequence
      int nextDirIdx = (dirAllocator.getCurrentDirectoryIndex() == 0) ? 3 : 4;
      validateTempDirCreation(buildBufferDir(ROOT, nextDirIdx));

      // change buffer directory 2 to be read only
      new File(new Path(dir4).toUri().getPath()).setReadOnly();
      validateTempDirCreation(dir3);
      validateTempDirCreation(dir3);
    } finally {
      rmBufferDirs();
    }
  }

  /**
   * Two buffer dirs, on read-write disk.
   *
   * Try to create a whole bunch of files.
   *  Verify that they do indeed all get created where they should.
   *
   *  Would ideally check statistical properties of distribution, but
   *  we don't have the nerve to risk false-positives here.
   *
   * @throws Exception
   */
  static final int TRIALS = 100;
  @Test
  public void test4() throws Exception {
    if (isWindows) return;
    String dir5 = buildBufferDir(ROOT, 5);
    String dir6 = buildBufferDir(ROOT, 6);
    try {

      conf.set(CONTEXT, dir5 + "," + dir6);
      assertTrue(localFs.mkdirs(new Path(dir5)));
      assertTrue(localFs.mkdirs(new Path(dir6)));

      int inDir5=0, inDir6=0;
      for(int i = 0; i < TRIALS; ++i) {
        File result = createTempFile();
        if(result.getPath().startsWith(
              new Path(dir5, FILENAME).toUri().getPath())) {
          inDir5++;
        } else if(result.getPath().startsWith(
              new Path(dir6, FILENAME).toUri().getPath())) {
          inDir6++;
        }
        result.delete();
      }

      assertTrue(inDir5 + inDir6 == TRIALS);

    } finally {
      rmBufferDirs();
    }
  }

  /** Two buffer dirs. The first dir does not exist & is on a read-only disk;
   * The second dir exists & is RW
   * getLocalPathForWrite with checkAccess set to false should create a parent
   * directory. With checkAccess true, the directory should not be created.
   * @throws Exception
   */
  @Test
  public void testLocalPathForWriteDirCreation() throws IOException {
    String dir0 = buildBufferDir(ROOT, 0);
    String dir1 = buildBufferDir(ROOT, 1);
    try {
      conf.set(CONTEXT, dir0 + "," + dir1);
      assertTrue(localFs.mkdirs(new Path(dir1)));
      BUFFER_ROOT.setReadOnly();
      Path p1 =
        dirAllocator.getLocalPathForWrite("p1/x", SMALL_FILE_SIZE, conf);
      assertTrue(localFs.getFileStatus(p1.getParent()).isDirectory());

      Path p2 =
        dirAllocator.getLocalPathForWrite("p2/x", SMALL_FILE_SIZE, conf,
            false);
      try {
        localFs.getFileStatus(p2.getParent());
      } catch (Exception e) {
        assertEquals(e.getClass(), FileNotFoundException.class);
      }
    } finally {
      Shell.execCommand(new String[] { "chmod", "u+w", BUFFER_DIR_ROOT });
      rmBufferDirs();
    }
  }

  /** Test no side effect files are left over. After creating a temp
   * temp file, remove both the temp file and its parent. Verify that
   * no files or directories are left over as can happen when File objects
   * are mistakenly created from fully qualified path strings.
   * @throws IOException
   */
  @Test
  public void testNoSideEffects() throws IOException {
    if (isWindows) return;
    String dir = buildBufferDir(ROOT, 0);
    try {
      conf.set(CONTEXT, dir);
      File result = dirAllocator.createTmpFileForWrite(FILENAME, -1, conf);
      assertTrue(result.delete());
      assertTrue(result.getParentFile().delete());
      assertFalse(new File(dir).exists());
    } finally {
      Shell.execCommand(new String[]{"chmod", "u+w", BUFFER_DIR_ROOT});
      rmBufferDirs();
    }
  }
}
