package nxm.sys.test.junit.lib;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.junit.Assert;

import nxm.sys.inc.Units;
import nxm.sys.lib.BaseFile;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.FileName;
import nxm.sys.lib.FileUtil;
import nxm.sys.lib.FileUtil.FnFilter;
import nxm.sys.lib.Midas;
import nxm.sys.lib.MidasException;
import nxm.sys.lib.NeXtMidas;
import nxm.sys.lib.Shell;
import nxm.sys.lib.StringUtil;
import nxm.sys.lib.Table;
import nxm.sys.test.junit.NMTestCase;

/** This will test the FileUtil class.

    @author  J. Czechowski IV
 */
public final class FileUtilTest extends NMTestCase {
  /** public constructor to allow running this test case directly with JUnit. */
  public FileUtilTest (String methodName) {
    this(methodName, NeXtMidas.getGlobalInstance().getMidas()); // initialized midas context for testMakeSymLink()
  }

  /** Creates a new instance of the class.
      @param methodName The name of the method being called.
      @param midas      The midas context to use when running the tests.
   */
  public FileUtilTest(String methodName, Midas midas) {
    super(methodName, midas);
  }

  //////////////////////////////////////////////////////////////////////////////
  private static final String[] PATHS_TO_TEST = { "/home/smith/myfile.prm",
                                                  "~smith/myfile.prm",
                                                  "myfile.prm",
                                                  "file:/home/smith/myfile.prm",
                                                  "file:///home/smith/myfile.prm",
                                                  "http://localhost/",
                                                  "http://localhost:8080",
                                                  "http://alice.com/myfile.prm",
                                                  "ramd:/midas/icedisk/myfile.tmp",
                                                  "c:\\data\\myfile.prm",
                                                  "file:/c:/data/myfile.prm",
                                                  "Z:\\data\\myfile.prm" };
  private static final String[] LOCAL_PATHS   = { "/home/smith/myfile.prm",
                                                  "~smith/myfile.prm",
                                                  "myfile.prm",
                                                  "/home/smith/myfile.prm",
                                                  "/home/smith/myfile.prm",
                                                  null,
                                                  null,
                                                  null,
                                                  "/midas/icedisk/myfile.tmp",
                                                  "c:\\data\\myfile.prm",
                                                  "c:\\data\\myfile.prm",
                                                  "Z:\\data\\myfile.prm" };

  //////////////////////////////////////////////////////////////////////////////
  public void testGetCanonicalFile() {
    // Can't test without specific knowledge of the local file system.
  }

  public void testGetRelativeDir() {
    String[] srcInput  = { "/home/smith/nxm230/nxm/sys/lib/",
                           "/home/smith/nxm230/nxm/",
                           "/home/smith/nxm230/nxm/sys/lib/" };

    String[] destInput = { "/home/smith/nxm230/nxm/sys/lib/",
                           "/home/smith/nxm230/nxm/sys/lib/",
                           "/home/smith/nxm230/nxm/" };

    String[] solution  = { "",
                           "sys/lib/",
                           "../../" };

    if (Shell.isWindows()) {
      warn("No unit test for FileUtil.getRelativeDir(..) on Windows.");
      solution = destInput = srcInput  = new String[] { };
    }

    for (int i = 0; i < srcInput.length; i++) {
      assertEquals("getRelativeDir("+srcInput[i]+","+destInput[i]+")", solution[i],
                   FileUtil.getRelativeDir(new File(srcInput[i]), new File(destInput[i])));

      assertEquals("getRelativeDir("+removeLast(srcInput[i])+","+destInput[i]+")", solution[i],
                   FileUtil.getRelativeDir(new File(removeLast(srcInput[i])), new File(destInput[i])));

      assertEquals("getRelativeDir("+srcInput[i]+","+removeLast(destInput[i])+")", solution[i],
                   FileUtil.getRelativeDir(new File(srcInput[i]), new File(removeLast(destInput[i]))));
    }
  }

  public void testGetRelativeUrl() {
    String[] srcInput  = { "http://alice.com/nextmidas/",
                           "http://alice.com/nextmidas/snapshots/",
                           "http://alice.com/nextmidas/snapshots/",
                           "http://alice.com/nextmidas/",
                           "http://alice.com/",
                           "http://alice.com:8080/nextmidas/",
                           "http://68.167.166.136/nextmidas/",
                           "http://alice.com/nextmidas/",
                           "http://alice.com/nextmidas/" };

    String[] destInput = { "http://alice.com/nextmidas/",
                           "http://alice.com/nextmidas/",
                           "http://alice.com/",
                           "http://alice.com/nextmidas/snapshots/",
                           "http://alice.com/nextmidas/snapshots/",
                           "http://alice.com/nextmidas/",
                           "http://alice.com/nextmidas/",
                           "ftp://alice.com/nextmidas/" ,
                           "http://www.nextmidas.com/" };

    String[] solution  = { "",
                           "../",
                           "../../",
                           "snapshots/",
                           "nextmidas/snapshots/",
                           "http://alice.com/nextmidas/",
                           "http://alice.com/nextmidas/",
                           "ftp://alice.com/nextmidas/",
                           "http://www.nextmidas.com/" };
    try {
      for (int i = 0; i < srcInput.length; i++) {
        assertEquals("getRelativeUrl("+srcInput[i]+","+destInput[i]+")", solution[i],
                     FileUtil.getRelativeUrl(new URI(srcInput[i]).toURL(), new URI(destInput[i]).toURL()));

        assertEquals("getRelativeUrl("+removeLast(srcInput[i])+","+destInput[i]+")", solution[i],
                     FileUtil.getRelativeUrl(new URI(removeLast(srcInput[i])).toURL(), new URI(destInput[i]).toURL()));

        assertEquals("getRelativeUrl("+srcInput[i]+","+removeLast(destInput[i])+")", solution[i],
                     FileUtil.getRelativeUrl(new URI(srcInput[i]).toURL(), new URI(removeLast(destInput[i])).toURL()));
      }
    } catch(URISyntaxException | MalformedURLException e) {
      throw new MidasException("Problem in FileUtilTest.testGetRelativeUrl()", e);
    }
  }

  /** Removes the last character in a string. */
  private String removeLast(String str) {
    return str.substring(0,str.length()-1);
  }

  public void testChangePathSeparator() {
                      // path                      sep    solution
    String[] values = { "myfile.prm",              "/",   "myfile.prm",
                        "../home/myfile.prm",      "/",   "../home/myfile.prm",
                        "../home/myfile.prm",      "\\",  "..\\home\\myfile.prm",
                        "..\\home\\myfile.prm",    "/",   "../home/myfile.prm",
                        "..\\home\\myfile.prm",    "\\",  "..\\home\\myfile.prm",
                        "/home/smith/myfile.prm",  "/",   "/home/smith/myfile.prm",
                        "/home/smith/myfile.prm",  "\\",  "\\home\\smith\\myfile.prm",
                        "c:\\home\\myfile.prm",    "/",   "c:/home/myfile.prm" };

    for (int i = 0; i < values.length; i+=3) {
      assertEquals("changePathSeparator("+values[i]+","+values[i+1]+")", values[i+2],
                   FileUtil.changePathSeparator(values[i], values[i+1]));
    }
  }

  public void testToLocalFileName() {
    String localSeparator = StringUtil.textToReplacement(File.separator);

    for (int i = 0; i < PATHS_TO_TEST.length; i++) {
      String expected = LOCAL_PATHS[i];
      String actual   = FileUtil.toLocalFileName(PATHS_TO_TEST[i]);

      if (expected != null) {
        // Since it is converting the name to a local one, it is also "correcting" the slashes
        // ("file:///foo/bar" to "/foo/bar" on Unix or "\foo\bar" on Windows) we need to test
        // in a platform-independant way.
        expected = expected.replaceAll("[/\\\\]", localSeparator);
      }
      assertEquals("toLocalFileName("+PATHS_TO_TEST[i]+")", expected, actual);
    }

    // test for Bug 2474
    try {
      boolean isWindowsOS = Shell.isWindows();
      String str = "/home/smith/myfile.prm".replaceAll("[/\\\\]", localSeparator);
      URL url = (isWindowsOS) ? new URI("file://"+str.replace('\\','/')).toURL() : new URI("file://"+str).toURL();
      String localized = FileUtil.toLocalFileName(url).replaceAll("[/\\\\]", localSeparator);
      assertEquals("toLocalFileName(URL)", str, localized);
    } catch (URISyntaxException | MalformedURLException e) {
      e.printStackTrace();
      fail(e.getMessage());
    }
  }

  /** @since NeXtMidas 3.7.1
   *  @throws MalformedURLException
   */
  public void testToUrl() throws MalformedURLException {
    // Test 2 Arg FileUtil.toURL both with and without deprecated constructor
    boolean usingDeprecatedConstructor = FileUtil.getUseDeprecatedUrlAPI();
    toUrl2ArgTest(usingDeprecatedConstructor);
    FileUtil.setUseDeprecatedUrlAPI(!usingDeprecatedConstructor);
    toUrl2ArgTest(!usingDeprecatedConstructor);
    FileUtil.setUseDeprecatedUrlAPI(usingDeprecatedConstructor);

    toUrlWindowsTest();
  }

  /** since NeXtMidas 4.1.4 */
  private void toUrl2ArgTest (boolean usingDeprecatedConstructor) throws MalformedURLException {
    String[] contexts = {
        "nxm/sys/hlp/concepts.hlp",
        "jar:http://myserver/nxm/jars/nxm-sys.jar!/nxm/sys/test/test_include.mm", // to test fix for Bug 1463 under Web Start
        "/path/to/filename.ext",
        "jar:http://myserver/nxm/jars/nxm-sys.jar!/nxm/sys/test/",
        "jar:http://myserver/nxm/jars/nxm-sys.jar!/nxm/sys/test",
        "http://myfolder/"
    };
    String[] names = {
        "plot.hlp",
        "exp/ffp.exp",
        "jay/exp/foot.exp",
        "fft.exp",          // <filename> <area> of SYS
        "commands.cnf", // <filename> <area> <optionTree under $NMROOT>
        "jar:http://myserver/nxm/jars/nxm-sys.jar!/nxm/sys/test/joy.txt",
        "https://myserver/to.txt",
        "jar:file:/nxm/jars/nxm-sys.jar!/nxm/sys/test/the.txt",
        "file:world.txt"
    };

    for (String context : contexts) {
      FileName fn = new FileName(context);
      String path = fn.getPath();

      // System.out.println("testing FN="+fn + " path="+path); // DEBUG
      for (String name : names) {
        URL url = FileUtil.toURL(context,name);
        String expected = path+name; // normal case
        if (name.contains(":")) {
          expected = name;
        }

        String dep = (usingDeprecatedConstructor) ? "Deprecated " : "";
        assertTrue(dep+"toURL("+context+","+name+")  relURL="+url.toString()+" ends with "+expected.replace("\\", "/"), url.toString().endsWith(expected.replace("\\", "/")));
      } // end inner for loop
    } // end outer for loop
  }

  private void toUrlWindowsTest () throws MalformedURLException {
    if (Shell.isWindows()){
      String original = "C:\\foo\\bar.txt";
      String expPrefix = "file:";
      String expSuffix = "/foo/bar.txt" ;// omit drive letter since it may be replaced by a UNC file name
      URL    act = FileUtil.toURL(original);

      // Check the prefix and suffix, but not the middle. This allows for variations in the number of slashes
      // following the "file:" and in variations for Windows UNC file names.
      assertTrue("URL"+act.toString()+" starts with "+expPrefix,act.toString().startsWith(expPrefix));
      assertTrue("URL"+act.toString()+" ends with "+expSuffix,act.toString().endsWith(expSuffix));

      // also check relative to another file
      original = "bar.txt";
      String relativeTo = "C:\\foo\\car.txt";
      act = FileUtil.toURL(relativeTo,original);

      // Check the prefix and suffix, but not the middle. This allows for variations in the number of slashes
      // following the "file:" and in variations for Windows UNC file names.
      assertTrue("relativeTo URL"+act.toString()+" starts with "+expPrefix,act.toString().startsWith(expPrefix));
      assertTrue("relativeTo URL"+act.toString()+" ends with "+expSuffix,act.toString().endsWith(expSuffix));
    }
  }

  public void testIsLocalFileName() {
    for (int i = 0; i < PATHS_TO_TEST.length; i++) {
      assertEquals("isLocalFileName("+PATHS_TO_TEST[i]+")", (LOCAL_PATHS[i] != null),
                   FileUtil.isLocalFileName(PATHS_TO_TEST[i]));
    }
  }

  public void testStartsWithRootDir() {
                      // path
    String[] values = { "/home/smith/myfile.prm",    // true for UNIX
                        "\\home\\smith\\myfile.prm", // true for WINDOWS
                        "c:\\home\\myfile.prm",      // true
    // NOTE: the below path usage is not recommended without the "\" after the drive letter
                        "c:home\\myfile.prm",        // true
                        "Z:\\home\\myfile.prm",      // true
                        "myfile.prm",
                        "home/myfile.prm",
                        "../home/myfile.prm",
                        "..\\home\\myfile.prm",
                        "http://alice.com/myfile.prm",
                        "file:/home/smith/myfile.prm",
                        "file:///home/smith/myfile.prm",
                        "dd:\\home\\myfile.prm",
                        "ramd:/midas/icedisk/,RAM,372M,128M"
                        };
    // this initializes all solutions to false, then only set the ones that should be true later
    boolean solutions[] = new boolean[values.length];

    // currently, these are true for all OS
    solutions[2] = true; // c:\
    solutions[3] = true; // c:
    solutions[4] = true; // z:\

    // update solutions array for OS specific
    if (File.separator.equals(FileName.UNIX_PATH_DELIM)) {
        solutions[0] = true; // true for UNIX
    } else if (File.separator.equals(FileName.DOS_PATH_DELIM)) {
        solutions[1] = true; // true for DOS
    }

    for (int i = 0; i < values.length; i++) {
      assertEquals("startsWithLocalPathSeparator(" + values[i] + ")", solutions[i],
                   FileUtil.startsWithRootDir(values[i]));
    }
  }

  public void testCreateFnFilter () {
    String[] ALL  = { "temp.tmp", "myFile.prm", "myfile.prm", "junk.xml", "junk.csv" };
    String[] NONE = new String[0];

    try {
      filtTest("*.xml|*.csv", "*.tmp|*.prm",
               new String[] { "myfile.xml", "myFile.xml", "junk.xml", "temp.csv" },
               new String[] { "temp.tmp", "myfile.prm", "crap.txt", "CVS" });

      filtTest("+*.xml", "*.tmp|*.prm",
               new String[] { "myfile.xml", "myFile.xml", "junk.xml", "temp.tmp", "myfile.prm" },
               new String[] { "crap.txt", "temp.csv", "CVS" });

      filtTest("DEF|*.xml", "*.tmp|*.prm",
               new String[] { "myfile.xml", "myFile.xml", "junk.xml", "temp.tmp", "myfile.prm" },
               new String[] { "crap.txt", "temp.csv", "CVS" });

      filtTest("DEF", "*.tmp|*.prm",
               new String[] { "temp.tmp", "myFile.prm", "myfile.prm" },
               new String[] { "myfile.xml", "junk.xml", "crap.txt", "temp.csv", "CVS" });

      filtTest("", "*.tmp|*.prm",
               new String[] { "temp.tmp", "myFile.prm", "myfile.prm" },
               new String[] { "myfile.xml", "junk.xml", "crap.txt", "temp.csv", "CVS" });

      filtTest(null, "*.tmp|*.prm",
               new String[] { "temp.tmp", "myFile.prm", "myfile.prm" },
               new String[] { "myfile.xml", "junk.xml", "crap.txt", "temp.csv", "CVS" });

      filtTest("NONE|*.xml", "*.tmp|*.prm",
               new String[] { "myfile.xml", "myFile.xml", "junk.xml" },
               new String[] { "crap.txt", "temp.csv", "CVS", "temp.tmp", "myfile.prm" });

      filtTest("-*.tmp", "*.tmp|*.prm",
               new String[] { "myFile.prm", "myfile.prm" },
               new String[] { "crap.txt", "temp.tmp", "temp.csv", "CVS", "myfile.xml", "junk.xml" });

      filtTest("-*.xml", "*.tmp|*.prm",
               new String[] { "myFile.prm", "myfile.prm", "temp.tmp" },
               new String[] { "crap.txt", "temp.csv", "CVS", "myfile.xml", "junk.xml" });

      filtTest("*|-*.xml", "*.tmp|*.prm",
               new String[] { "crap.txt", "temp.csv", "CVS", "myFile.prm", "myfile.prm", "temp.tmp" },
               new String[] { "myfile.xml", "junk.xml" });

      // This next tests added for Bug 2649 ====================================
      if (File.separatorChar == '/') {
        filtTest("/home/user/nmroot/nxm/sys/", "docs/*.txt", "",
                 new File("/home/user/nmroot/nxm/sys/docs"),    "myfile.txt", true,
                 new File("/home/user/nmroot/nxm/sys/docs"),    "myfile.csv", false,
                 new File("/home/user/nmroot/nxm/sys/exp"),     "myfile.txt", false);
      }
      else {
        filtTest("c:\\midas\\nmroot\\nxm\\sys", "docs/*.txt", "",
                 new File("c:\\midas\\nmroot\\nxm\\sys\\docs"), "myfile.txt", true,
                 new File("c:\\midas\\nmroot\\nxm\\sys\\docs"), "myfile.csv", false,
                 new File("c:\\midas\\nmroot\\nxm\\sys\\exp"),  "myfile.txt", false);
      }
      // =======================================================================

      filtTest("-*.xml",  "",            NONE, ALL);
      filtTest("",        "",            NONE, ALL);
      filtTest("-*",      "*.tmp|*.prm", NONE, ALL);
      filtTest("NONE",    "*.tmp|*.prm", NONE, ALL);

      filtTest("*",       "*.tmp|*.prm", ALL, NONE);
      filtTest("*|*.xml", "*.tmp|*.prm", ALL, NONE);
      filtTest(null,      null,          ALL, NONE);

    } catch (SecurityException se) {
      // NTN: this OK, it happens under Java Web Start where the JVM sandbox is more restricting
      info("Unable to test createFnFilter: "+se);
    }
  }

  /** Used by testCreateFnFilter() */
  private void filtTest (String filter, String def, String[] accept, String[] reject) {
    FnFilter filt = FileUtil.createFnFilter(filter, def);

    for (String name : accept) {
      assertTrue("Test createFnFilter (accept) filter='"+filter+" def='"+def+"' name='"+name+"'", filt.accept(null,name));
    }
    for (String name : reject) {
      assertFalse("Test createFnFilter (reject) filter='"+filter+" def='"+def+"' name='"+name+"'", filt.accept(null,name));
    }
  }

  /** Used by testCreateFnFilter() */
  private void filtTest (String root, String filter, String def, Object ... tests) {
    String   msg  = "Test createFnFilter (accept) root='"+root+"' filter='"+filter+ " def='"+def+"'";
    FnFilter filt = FileUtil.createFnFilter(root, filter, def);

    for (int i = 0; i < tests.length; i+=3) {
      File    dir  = (File   )tests[ i ];
      String  name = (String )tests[i+1];
      boolean pass = (Boolean)tests[i+2];
      File    file = new File(FileUtil.terminatePath(dir.toString())+name);

      assertEquals(msg+" dir='"+dir+"' name='"+name+"'", pass, filt.accept(dir,name));
      assertEquals(msg+" file='"+file+"'",               pass, filt.accept(file));
    }
  }

  public void testRecDef () {
    final Object[] TESTS = {
      // NAME   FORMAT, OFFSET, TYPE,            UNITS
      "TIME",   "SD",   null,   null,            null,
      "TIME",   "SD",   0,      "UNDEFINED",     "NONE",
      "TIME",   "SD",   0,      Units.UNDEFINED, Units.NONE,
      "POS",    "VD",   null,   "CARTESIAN",     "DISTANCE_M",
      "POS",    "VD",   null,   Units.CARTESIAN, Units.DISTANCE_M,
      "VEL",    "VD",   null,   "CARTESIAN",     "SPEED_M_S",
      "VEL",    "VD",   null,   Units.CARTESIAN, Units.SPEED_M_S,
      "ACC",    "VD",   null,   "CARTESIAN",     "ACCELERATION_M_S2",
      "ACC",    "VD",   null,   Units.CARTESIAN, Units.ACCELERATION_M_S2,
    };

    for (int i = 0; i < TESTS.length; i+=5) {
      int     count5 = 1;
      String  name   = (String)TESTS[i+0];
      String  format = (String)TESTS[i+1];    if (format != null) count5++;
      Integer offset = (Integer)TESTS[i+2];   if (offset != null) count5++;
      Object  type   = TESTS[i+3];            if (type   != null) count5++;
      Object  units  = TESTS[i+4];            if (units  != null) count5++;
      int     count2 = Math.min(2, count5);

      String m2 = "FileUtil.recDef("+name+", "+format+") ";
      String m5 = "FileUtil.recDef("+name+", "+format+", "+offset+", "+type+", "+units+") ";
      Table  t2 = FileUtil.recDef(name, format);
      Table  t5 = FileUtil.recDef(name, format, offset, type, units);

      assertEquals(m2+"size",   count2,   t2.size());
      assertEquals(m5+"size",   count5,   t5.size());
      assertEquals(m2+"NAME",   name,     t2.getS("NAME"));
      assertEquals(m5+"NAME",   name,     t5.getS("NAME"));
      assertEquals(m2+"FORMAT", format,   t2.getS("FORMAT"));
      assertEquals(m5+"FORMAT", format,   t5.getS("FORMAT"));
      assertEquals(m5+"OFFSET", offset,   t5.get("OFFSET"));
      assertEquals(m5+"TYPE",   type,     t5.get("TYPE"));
      assertEquals(m5+"UNITS",  units,    t5.get("UNITS"));
    }
  }

  /**
   * Testing copyBaseFile when input file is in a tar file.
   * Using BaseFile.parseFileTestFlag() which will compare the data in each file.
   * @since NeXtMidas 3.7.1 for NXM-2918
   */
  public void testCopyBaseFile () {
    if (Shell.isWebStart() || Shell.getNmRoot().startsWith("classpath:") || Shell.isGradleBuild()) { // since 3.7.3, for NXM-3099
      warn("Skipping testCopyBaseFile test (involving copying a file within a .tar) when running as Web Start");
      return;
    }
    DataFile outFile = new DataFile(getMidasContext(), "testCopyBasefile.tmp");
    File inFile = new File("tar:"+Shell.getNmRoot()+"/nxm/sys/test/test_tar.tar!testxy3000.prm");

    FileUtil.copyBaseFile(getMidasContext(), inFile, outFile);

    // Compare original test file to new output file.
    String urlTest = urlDat;
    if (Shell.isWindows()) urlTest = urlTest.replace("file:/","");
    Path inPath = Paths.get(urlTest+"testxy3000.prm");
    Path outPath = Paths.get(FileUtil.toLocalFileName(outFile.getURL()));

    BaseFile inBF = new BaseFile(inPath.toString());
    BaseFile outBF = new BaseFile(outPath.toString());

    // This method mimics macro test file1 FEQ/D file2, testing ONLY if the DATA is equal.
    // FileUtil.copyBaseFile() adds a header to the output file.
    assertTrue("Data contents of files are equal.", inBF.equals(outBF, BaseFile.parseFileTestFlag("FEQ/D")));

    inBF.close();
    outBF.close();
  }

  public void testGetInputStreamFor() {
    try(InputStream is = FileUtil.getInputStreamFor(datDirSlash+"/"+"states.json")) {

      int data=is.read();
      assertTrue("We should have a value greater than -1", data>-1);
    } catch (IOException e) {
      Assert.fail();
    }

    try(InputStream is = FileUtil.getInputStreamFor("ThisFileDoesNotExist.txt")) {
      is.read();
      Assert.fail("Should not get here, should have thrown a FileNotFound exception");
    } catch (IOException e) {
      assertEquals(e.getClass(), FileNotFoundException.class);
    }
  }


  /**
   * Testing if makeDirSymLink(linkName, targetOfLink) is able to make a directory symbolic link (symlink).
   * @since NeXtMidas 3.7.0 uses Java 7 APIs
   */
  public void testMakeDirSymLink () throws IOException {
    String nmroot = Shell.getNmRoot();
    if (!FileUtil.isLocalFileName(nmroot) || Shell.isWebStart() || Shell.isGradleBuild()) {
      info("Skipping FileUtil.makeDirSymLink test, since it is not possible to create symlink inside a jar file.");
      return;
    }

    Path   tempDir    = Files.createTempDirectory("FileUtilTestDir");
    Path   linkPath   = tempDir.resolve("make_symlink_test");
    String linkName   = linkPath.toString();

    String targetLink = FileUtil.getCanonicalPath(Shell.getNmRoot() + "/nxm/sys/test/nmopts/nxm/mytestopt1/test");

    boolean makeSymLinkResult = FileUtil.makeDirSymLink(linkName, targetLink);
    assertTrue("symlink created", makeSymLinkResult);
    boolean isSymbolicLink = Files.isSymbolicLink(linkPath);
    if (!isSymbolicLink && Shell.isWindows()) {
      assertTrue("created Windows directory junction", Files.isDirectory(linkPath));
    }
    else assertTrue("created link is a symlink", isSymbolicLink);

    // ----- test different type of failure scenarios -----
    info("!!!!! It is ok to see a 3 warnings below: Cannot make symbolic link because ... already exists there...");
    // should fail b/c of existing directory symlink -or (Windows only) directory junction point (at linkName)
    makeSymLinkResult = FileUtil.makeDirSymLink(linkName, targetLink);
    assertFalse("create symlink at existing symlink ", makeSymLinkResult);

    // should fail b/c of an existing file (at linkName)
    Path tempFile = Files.createTempFile(tempDir, "tempFile", ".tmp");
    makeSymLinkResult = FileUtil.makeDirSymLink(tempFile.toString(), targetLink);
    assertFalse("create symlink at existing file", makeSymLinkResult);

    // should fail b/c of an existing directory (at linkName)
    Path tempDir2 = Files.createTempDirectory(tempDir, "existingDir");
    makeSymLinkResult = FileUtil.makeDirSymLink(tempDir2.toString(), targetLink);
    assertFalse("create symlink at existing directory", makeSymLinkResult);

    FileUtil.recursiveDelete(tempFile.toFile());  // since 3.7.1 only delete file created and not all files under directory NXM-2858
  }
}
