/**
 * 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.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;

import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.apache.hadoop.fs.HardLink.*;

/**
 * This testing is fairly lightweight.  Assumes HardLink routines will
 * only be called when permissions etc are okay; no negative testing is
 * provided.
 * 
 * These tests all use 
 * "src" as the source directory, 
 * "tgt_one" as the target directory for single-file hardlinking, and
 * "tgt_mult" as the target directory for multi-file hardlinking.
 * 
 * Contents of them are/will be:
 * dir:src: 
 *   files: x1, x2, x3
 * dir:tgt_one:
 *   files: x1 (linked to src/x1), y (linked to src/x2), 
 *          x3 (linked to src/x3), x11 (also linked to src/x1)
 * dir:tgt_mult:
 *   files: x1, x2, x3 (all linked to same name in src/)
 *   
 * NOTICE: This test class only tests the functionality of the OS
 * upon which the test is run! (although you're pretty safe with the
 * unix-like OS's, unless a typo sneaks in.)
 * 
 * Notes about Windows testing:  
 * (a) In order to create hardlinks, the process must be run with 
 * administrative privs, in both the account AND the invocation.
 * For instance, to run within Eclipse, the Eclipse application must be 
 * launched by right-clicking on it, and selecting "Run as Administrator" 
 * (and that option will only be available if the current user id does 
 * in fact have admin privs).
 * (b) The getLinkCount() test case will fail for Windows, unless Cygwin
 * is set up properly.  In particular, ${cygwin}/bin must be in
 * the PATH environment variable, so the cygwin utilities can be found.
 */
public class TestHardLink {
  
  public static final String TEST_ROOT_DIR = 
    System.getProperty("test.build.data", "build/test/data") + "/test";
  final static private File TEST_DIR = new File(TEST_ROOT_DIR, "hl");
  private static String DIR = "dir_";
  //define source and target directories
  private static File src = new File(TEST_DIR, DIR + "src");
  private static File tgt_mult = new File(TEST_DIR, DIR + "tgt_mult");
  private static File tgt_one = new File(TEST_DIR, DIR + "tgt_one");
  //define source files
  private static File x1 = new File(src, "x1");
  private static File x2 = new File(src, "x2");
  private static File x3 = new File(src, "x3");
  //define File objects for the target hardlinks
  private static File x1_one = new File(tgt_one, "x1");
  private static File y_one = new File(tgt_one, "y");
  private static File x3_one = new File(tgt_one, "x3");
  private static File x11_one = new File(tgt_one, "x11");
  private static File x1_mult = new File(tgt_mult, "x1");
  private static File x2_mult = new File(tgt_mult, "x2");
  private static File x3_mult = new File(tgt_mult, "x3");
  //content strings for file content testing
  private static String str1 = "11111";
  private static String str2 = "22222";
  private static String str3 = "33333";

  /**
   * Assure clean environment for start of testing
   * @throws IOException
   */
  @BeforeClass
  public static void setupClean() {
    //delete source and target directories if they exist
    FileUtil.fullyDelete(src);
    FileUtil.fullyDelete(tgt_one);
    FileUtil.fullyDelete(tgt_mult);
    //check that they are gone
    assertFalse(src.exists());
    assertFalse(tgt_one.exists());
    assertFalse(tgt_mult.exists());
  }
  
  /**
   * Initialize clean environment for start of each test
   */
  @Before
  public void setupDirs() throws IOException {
    //check that we start out with empty top-level test data directory
    assertFalse(src.exists());
    assertFalse(tgt_one.exists());
    assertFalse(tgt_mult.exists());
    //make the source and target directories
    src.mkdirs();
    tgt_one.mkdirs();
    tgt_mult.mkdirs();
    
    //create the source files in src, with unique contents per file
    makeNonEmptyFile(x1, str1);
    makeNonEmptyFile(x2, str2);
    makeNonEmptyFile(x3, str3);
    //validate
    validateSetup();
  }
  
  /**
   * validate that {@link setupDirs()} produced the expected result
   */
  private void validateSetup() throws IOException {
    //check existence of source directory and files
    assertTrue(src.exists());
    assertEquals(3, src.list().length);
    assertTrue(x1.exists());
    assertTrue(x2.exists());
    assertTrue(x3.exists());
    //check contents of source files
    assertTrue(fetchFileContents(x1).equals(str1));
    assertTrue(fetchFileContents(x2).equals(str2));
    assertTrue(fetchFileContents(x3).equals(str3));
    //check target directories exist and are empty
    assertTrue(tgt_one.exists());
    assertTrue(tgt_mult.exists());
    assertEquals(0, tgt_one.list().length);
    assertEquals(0, tgt_mult.list().length);    
  }
  
  /**
   * validate that single-file link operations produced the expected results
   */
  private void validateTgtOne() throws IOException {
    //check that target directory tgt_one ended up with expected four files
    assertTrue(tgt_one.exists());
    assertEquals(4, tgt_one.list().length);
    assertTrue(x1_one.exists());
    assertTrue(x11_one.exists());
    assertTrue(y_one.exists());
    assertTrue(x3_one.exists());
    //confirm the contents of those four files reflects the known contents
    //of the files they were hardlinked from.
    assertTrue(fetchFileContents(x1_one).equals(str1));
    assertTrue(fetchFileContents(x11_one).equals(str1));
    assertTrue(fetchFileContents(y_one).equals(str2));
    assertTrue(fetchFileContents(x3_one).equals(str3));
  }
  
  /**
   * validate that multi-file link operations produced the expected results
   */
  private void validateTgtMult() throws IOException {
    //check that target directory tgt_mult ended up with expected three files
    assertTrue(tgt_mult.exists());
    assertEquals(3, tgt_mult.list().length);
    assertTrue(x1_mult.exists());
    assertTrue(x2_mult.exists());
    assertTrue(x3_mult.exists());
    //confirm the contents of those three files reflects the known contents
    //of the files they were hardlinked from.
    assertTrue(fetchFileContents(x1_mult).equals(str1));
    assertTrue(fetchFileContents(x2_mult).equals(str2));
    assertTrue(fetchFileContents(x3_mult).equals(str3));
  }

  @After
  public void tearDown() throws IOException {
    setupClean();
  }

  private void makeNonEmptyFile(File file, String contents) 
  throws IOException {
    FileWriter fw = new FileWriter(file);
    fw.write(contents);
    fw.close();
  }
  
  private void appendToFile(File file, String contents) 
  throws IOException {
    FileWriter fw = new FileWriter(file, true);
    fw.write(contents);
    fw.close();
  }
  
  private String fetchFileContents(File file) 
  throws IOException {
    char[] buf = new char[20];
    FileReader fr = new FileReader(file);
    int cnt = fr.read(buf); 
    fr.close();
    char[] result = Arrays.copyOf(buf, cnt);
    return new String(result);
  }
  
  /**
   * Sanity check the simplest case of HardLink.getLinkCount()
   * to make sure we get back "1" for ordinary single-linked files.
   * Tests with multiply-linked files are in later test cases.
   * 
   * If this fails on Windows but passes on Unix, the most likely cause is 
   * incorrect configuration of the Cygwin installation; see above.
   */
  @Test
  public void testGetLinkCount() throws IOException {
    //at beginning of world, check that source files have link count "1"
    //since they haven't been hardlinked yet
    assertEquals(1, getLinkCount(x1));
    assertEquals(1, getLinkCount(x2));
    assertEquals(1, getLinkCount(x3));
  }

  /**
   * Test the single-file method HardLink.createHardLink().
   * Also tests getLinkCount() with values greater than one.
   */
  @Test
  public void testCreateHardLink() throws IOException {
    //hardlink a single file and confirm expected result
    createHardLink(x1, x1_one);
    assertTrue(x1_one.exists());
    assertEquals(2, getLinkCount(x1));     //x1 and x1_one are linked now 
    assertEquals(2, getLinkCount(x1_one)); //so they both have count "2"
    //confirm that x2, which we didn't change, still shows count "1"
    assertEquals(1, getLinkCount(x2));
    
    //now do a few more
    createHardLink(x2, y_one);
    createHardLink(x3, x3_one);
    assertEquals(2, getLinkCount(x2)); 
    assertEquals(2, getLinkCount(x3));

    //create another link to a file that already has count 2
    createHardLink(x1, x11_one);
    assertEquals(3, getLinkCount(x1));      //x1, x1_one, and x11_one
    assertEquals(3, getLinkCount(x1_one));  //are all linked, so they
    assertEquals(3, getLinkCount(x11_one)); //should all have count "3"
    
    //validate by contents
    validateTgtOne();
    
    //validate that change of content is reflected in the other linked files
    appendToFile(x1_one, str3);
    assertTrue(fetchFileContents(x1_one).equals(str1 + str3));
    assertTrue(fetchFileContents(x11_one).equals(str1 + str3));
    assertTrue(fetchFileContents(x1).equals(str1 + str3));
  }
  
  /*
   * Test the multi-file method HardLink.createHardLinkMult(),
   * multiple files within a directory into one target directory
   */
  @Test
  public void testCreateHardLinkMult() throws IOException {
    //hardlink a whole list of three files at once
    String[] fileNames = src.list();
    createHardLinkMult(src, fileNames, tgt_mult);
    
    //validate by link count - each file has been linked once,
    //so each count is "2"
    assertEquals(2, getLinkCount(x1));
    assertEquals(2, getLinkCount(x2));
    assertEquals(2, getLinkCount(x3));
    assertEquals(2, getLinkCount(x1_mult));
    assertEquals(2, getLinkCount(x2_mult));
    assertEquals(2, getLinkCount(x3_mult));

    //validate by contents
    validateTgtMult();
    
    //validate that change of content is reflected in the other linked files
    appendToFile(x1_mult, str3);
    assertTrue(fetchFileContents(x1_mult).equals(str1 + str3));
    assertTrue(fetchFileContents(x1).equals(str1 + str3));
  }

  /**
   * Test createHardLinkMult() with empty list of files.
   * We use an extended version of the method call, that
   * returns the number of System exec calls made, which should
   * be zero in this case.
   */
  @Test
  public void testCreateHardLinkMultEmptyList() throws IOException {
    String[] emptyList = {};
    
    //test the case of empty file list
    int callCount = createHardLinkMult(src, emptyList, tgt_mult, 
        getMaxAllowedCmdArgLength());
    //check no exec calls were made
    assertEquals(0, callCount);
    //check nothing changed in the directory tree
    validateSetup();
  }
  
  /**
   * Test createHardLinkMult(), again, this time with the "too long list" 
   * case where the total size of the command line arguments exceed the 
   * allowed maximum.  In this case, the list should be automatically 
   * broken up into chunks, each chunk no larger than the max allowed.
   * 
   * We use an extended version of the method call, specifying the
   * size limit explicitly, to simulate the "too long" list with a 
   * relatively short list.
   */
  @Test
  public void testCreateHardLinkMultOversizeAndEmpty() throws IOException {
    
    // prep long filenames - each name takes 10 chars in the arg list
    // (9 actual chars plus terminal null or delimeter blank)
    String name1 = "x11111111";
    String name2 = "x22222222";
    String name3 = "x33333333";
    File x1_long = new File(src, name1);
    File x2_long = new File(src, name2);
    File x3_long = new File(src, name3);
    //set up source files with long file names
    x1.renameTo(x1_long);
    x2.renameTo(x2_long);
    x3.renameTo(x3_long);
    //validate setup
    assertTrue(x1_long.exists());
    assertTrue(x2_long.exists());
    assertTrue(x3_long.exists());
    assertFalse(x1.exists());
    assertFalse(x2.exists());
    assertFalse(x3.exists());
    
    //prep appropriate length information to construct test case for
    //oversize filename list
    int callCount;
    String[] emptyList = {};
    String[] fileNames = src.list();
    //get fixed size of arg list without any filenames
    int overhead = getLinkMultArgLength(src, emptyList, tgt_mult);
    //select a maxLength that is slightly too short to hold 3 filenames
    int maxLength = overhead + (int)(2.5 * (float)(1 + name1.length())); 
    
    //now test list of three filenames when there is room for only 2.5
    callCount = createHardLinkMult(src, fileNames, tgt_mult, maxLength);
    //check the request was completed in exactly two "chunks"
    assertEquals(2, callCount);
    //and check the results were as expected in the dir tree
    assertTrue(Arrays.deepEquals(fileNames, tgt_mult.list()));
    
    //Test the case where maxlength is too small even for one filename.
    //It should go ahead and try the single files.
    
    //Clear the test dir tree
    FileUtil.fullyDelete(tgt_mult);
    assertFalse(tgt_mult.exists());
    tgt_mult.mkdirs();
    assertTrue(tgt_mult.exists() && tgt_mult.list().length == 0);
    //set a limit size much smaller than a single filename
    maxLength = overhead + (int)(0.5 * (float)(1 + name1.length()));
    //attempt the method call
    callCount = createHardLinkMult(src, fileNames, tgt_mult, 
        maxLength);
    //should go ahead with each of the three single file names
    assertEquals(3, callCount);
    //check the results were as expected in the dir tree
    assertTrue(Arrays.deepEquals(fileNames, tgt_mult.list()));
  }
  
  /*
   * Assume that this test won't usually be run on a Windows box.
   * This test case allows testing of the correct syntax of the Windows
   * commands, even though they don't actually get executed on a non-Win box.
   * The basic idea is to have enough here that substantive changes will
   * fail and the author will fix and add to this test as appropriate.
   * 
   * Depends on the HardLinkCGWin class and member fields being accessible
   * from this test method.
   */
  @Test
  public void testWindowsSyntax() {
    class win extends HardLinkCGWin {};

    //basic checks on array lengths
    assertEquals(5, win.hardLinkCommand.length); 
    assertEquals(7, win.hardLinkMultPrefix.length);
    assertEquals(8, win.hardLinkMultSuffix.length);
    assertEquals(3, win.getLinkCountCommand.length);

    assertTrue(win.hardLinkMultPrefix[4].equals("%f"));
    //make sure "%f" was not munged
    assertEquals(2, ("%f").length()); 
    assertTrue(win.hardLinkMultDir.equals("\\%f"));
    //make sure "\\%f" was munged correctly
    assertEquals(3, ("\\%f").length()); 
    assertTrue(win.hardLinkMultSuffix[7].equals("1>NUL"));
    //make sure "1>NUL" was not munged
    assertEquals(5, ("1>NUL").length()); 
    assertTrue(win.getLinkCountCommand[1].equals("-c%h"));
    //make sure "-c%h" was not munged
    assertEquals(4, ("-c%h").length()); 
  }

}
