/*
 * FileNewerThanTargetFilterTest class.
 *
 * Copyright (C) 2007 SATOH Takayuki All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package ts.util.file;

import ts.tester.function.coverage.FunctionTester;
import ts.tester.function.*;
import ts.tester.function.print.*;
import ts.util.*;
import java.io.*;
import java.util.*;

/**
 * {@link ts.util.file.FileNewerThanTargetFilter FileNewerThanTargetFilter}クラスの機能試験クラス。
 *
 * @author  佐藤隆之.
 * @version $Revision: 1.1.1.1 $, $Date: 2010-10-16 00:03:46 $
 */
public class FileNewerThanTargetFilterTest extends FunctionTester
{
  public static void main(String[] args)
  {
    try {
      PrinterGroup group = new PrinterGroup();
      group.addPrinter(new ConsolePrinter());
      group.addPrinter(new HtmlPrinter("SATOH Takayuki"));
      setPrinter(group);

      run(FileNewerThanTargetFilterTest.class, (args.length == 0) ? null : args[0]);
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  protected void preTesting()
  {
    MSG("FileNewerThanTargetFilter クラスの機能試験を実行する。");
  }
  
  final File WORKDIR = new File("test/data/ts/util/file/FileOperation");

  protected void preInvocation(String method)
  {
    WORKDIR.mkdirs();
  }

  protected void postInvocation(String method)
  {
    try {
      FileOperation.deleteRecursive(WORKDIR);
    } catch (Exception e) {}
  }

  /* -- test case -- */

  public void constructor_basedir_destdir()
  {
    MSG("変換元と変換先の基底ディレクトリを引数にとるコンストラクタ。");

    File src = new File(WORKDIR, "aaa");
    File dst = new File(WORKDIR, "bbb");
    FileFilter filter = new FileNewerThanTargetFilter(src, dst);

    ObjectInspector oi = new ObjectInspector(this);
    oi.expect("baseDir_", src);
    oi.expect("destDir_", dst);
    oi.expect("nameReplaceLst_", new ArrayList<Trio<String,String,Boolean>>(0));
    oi.expect("dirReplaceLst_", new ArrayList<Trio<String,String,Boolean>>(0));
    oi.inspect(filter);
  }

  public void constructor_basedir_destdir_01()
  {
    MSG("引数がヌルの場合。");

    File src = new File(WORKDIR, "aaa");
    File dst = new File(WORKDIR, "bbb");
    try {
      new FileNewerThanTargetFilter(null, dst);
      NG();
    } catch (AssertionError e) {
      OK(e);
    } catch (Exception e) {
      NG(e);
    }
    try {
      new FileNewerThanTargetFilter(src, null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    } catch (Exception e) {
      NG(e);
    }
  }

  public void getRelativePaths()
  {
    MSG("基底ファイルからの相対パスを取得。");

    File b1 = new File(WORKDIR, "x/y/z");
    File b2 = new File(WORKDIR, "a/b/c");
    File src = new File(b1, "aaa/bbb/ccc/ddd.eee");

    FileNewerThanTargetFilter filter = new FileNewerThanTargetFilter(b1, b2);
    Duo<String,String> duo;
    char sep = File.separatorChar;
    try {
      duo = filter.getRelativePaths(src, b1);
      EQUAL(duo.getFirst(), "aaa/bbb/ccc".replace('/', sep));
      EQUAL(duo.getSecond(), "ddd.eee");

      duo = filter.getRelativePaths(b1, new File(WORKDIR, "x/y"));
      EQUAL(duo.getFirst(), "");
      EQUAL(duo.getSecond(), "z");

      duo = filter.getRelativePaths(b1, new File(WORKDIR, "x/y/z"));
      EQUAL(duo.getFirst(), "");
      EQUAL(duo.getSecond(), "");

      duo = filter.getRelativePaths(new File("/"), new File("/"));
      EQUAL(duo.getFirst(), "");
      EQUAL(duo.getSecond(), "");

    } catch (Exception e) {
      NG(e);
    }
  }

  public void getRelativePaths_01()
  {
    MSG("引数がヌルの場合。");

    File b1 = new File(WORKDIR, "x/y/z");
    File b2 = new File(WORKDIR, "a/b/c");
    File src = new File(b1, "aaa/bbb/ccc/ddd.eee");

    FileNewerThanTargetFilter filter = new FileNewerThanTargetFilter(b1, b2);
    try {
      filter.getRelativePaths(src, null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    } catch (Exception e) {
      NG(e);
    }

    try {
      filter.getRelativePaths(null, b1);
      NG();
    } catch (AssertionError e) {
      OK(e);
    } catch (Exception e) {
      NG(e);
    }
  }

  public void getRelativePaths_02()
  {
    MSG("相対パスを取得に失敗する場合。");

    File b1 = new File(WORKDIR, "x/y/z");
    File b2 = new File(WORKDIR, "a/b/c");

    FileNewerThanTargetFilter filter = new FileNewerThanTargetFilter(b1, b2);
    try {
      File src = new File(b1, "aaa/bbb/ccc/ddd.eee");
      filter.getRelativePaths(src, b2);
      NG();
    } catch (IllegalArgumentException e) {
      OK(e);
    } catch (Exception e) {
      NG(e);
    }
  }

  public void getTargetFile()
  {
    MSG("基底ディレクトリだけを変換。");
     
    File srcDir = new File(WORKDIR, "a/b/c"); 
    File dstDir = new File(WORKDIR, "d/e/f"); 
    File src = new File(srcDir, "ggg/hhh/iii.jjj");
    File dst = new File(dstDir, "ggg/hhh/iii.jjj");

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    try {
      File target = filter.getTargetFile(src);
      EQUAL(target, dst);
    } catch (Exception e) {
      NG(e);
    }
  }

  public void getTargetFile_01()
  {
    MSG("引数がヌルの場合。");

    File srcDir = new File(WORKDIR, "a/b/c"); 
    File dstDir = new File(WORKDIR, "d/e/f"); 
    File src = new File(srcDir, "ggg/hhh/iii.jjj");

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    try {
      File target = filter.getTargetFile(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    } catch (Exception e) {
      NG(e);
    }
  }

  public void getTargetFile_02()
  {
    MSG("ファイル名を変換。");

    File srcDir = WORKDIR;
    File dstDir = WORKDIR;
    File src = new File(srcDir, "iii/jjj/iii.jjj");

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    try {
      EQUAL(filter.getTargetFile(src), src);
    } catch (Exception e) {
      NG(e);
    }

    filter.addNameReplaceFirst("i", "I");
    try {
      EQUAL(filter.getTargetFile(src), new File(dstDir, "iii/jjj/Iii.jjj"));
    } catch (Exception e) {
      NG(e);
    }

    filter.addNameReplaceFirst("j", "J");
    try {
      EQUAL(filter.getTargetFile(src), new File(dstDir, "iii/jjj/Iii.Jjj"));
    } catch (Exception e) {
      NG(e);
    }

    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    filter.addNameReplaceAll("i", "I");
    try {
      EQUAL(filter.getTargetFile(src), new File(dstDir, "iii/jjj/III.jjj"));
    } catch (Exception e) {
      NG(e);
    }

    filter.addNameReplaceAll("j", "J");
    try {
      EQUAL(filter.getTargetFile(src), new File(dstDir, "iii/jjj/III.JJJ"));
    } catch (Exception e) {
      NG(e);
    }
  }

  public void getTargetFile_03()
  {
    MSG("ディレクトリ・パスを変換。");

    File srcDir = WORKDIR;
    File dstDir = WORKDIR;
    File src = new File(srcDir, "iii/jjj/iii.jjj");

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    try {
      EQUAL(filter.getTargetFile(src), src);
    } catch (Exception e) {
      NG(e);
    }

    filter.addDirReplaceFirst("i", "I");
    try {
      EQUAL(filter.getTargetFile(src), new File(dstDir, "Iii/jjj/iii.jjj"));
    } catch (Exception e) {
      NG(e);
    }

    filter.addDirReplaceFirst("j", "J");
    try {
      EQUAL(filter.getTargetFile(src), new File(dstDir, "Iii/Jjj/iii.Jjj"));
    } catch (Exception e) {
      NG(e);
    }

    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    filter.addDirReplaceAll("i", "I");
    try {
      EQUAL(filter.getTargetFile(src), new File(dstDir, "III/jjj/iii.jjj"));
    } catch (Exception e) {
      NG(e);
    }

    filter.addDirReplaceAll("j", "J");
    try {
      EQUAL(filter.getTargetFile(src), new File(dstDir, "III/JJJ/iii.jjj"));
    } catch (Exception e) {
      NG(e);
    }
  }

  public void getTargetFile_04()
  {
    MSG("ディレクトリ・パスが空の場合。");

    File srcDir = WORKDIR;
    File dstDir = WORKDIR;
    File src = new File(srcDir, "iii.jjj");

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    try {
      EQUAL(filter.getTargetFile(src), src);
    } catch (Exception e) {
      NG(e);
    }

    filter.addNameReplaceFirst("i", "I");
    try {
      EQUAL(filter.getTargetFile(src), new File(WORKDIR, "Iii.jjj"));
    } catch (Exception e) {
      NG(e);
    }

    filter.addNameReplaceAll("i", "I");
    try {
      EQUAL(filter.getTargetFile(src), new File(WORKDIR, "III.jjj"));
    } catch (Exception e) {
      NG(e);
    }
  }

  public void getTargetFile_05()
  {
    MSG("ディレクトリ・パスもファイル名も空の場合。");

    File srcDir = WORKDIR;
    File dstDir = WORKDIR;
    File src = WORKDIR;

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    try {
      EQUAL(filter.getTargetFile(src), WORKDIR);
    } catch (Exception e) {
      NG(e);
    }

    filter.addNameReplaceFirst("i", "I");
    try {
      EQUAL(filter.getTargetFile(src), WORKDIR);
    } catch (Exception e) {
      NG(e);
    }
  }

  public void getTargetFile_06()
  {
    MSG("ターゲット・ファイルの取得に失敗する場合。");

    File srcDir = new File(WORKDIR, "aaa");
    File dstDir = new File(WORKDIR, "bbb");
    File src = new File(WORKDIR, "ccc/ddd.eee");

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    try {
      EQUAL(filter.getTargetFile(src), WORKDIR);
    } catch (IllegalArgumentException e) {
      OK(e);
    } catch (Exception e) {
      NG(e);
    }
  }

  public void accept()
  {
    MSG("ターゲット・ファイルの方が古い場合。");

    File srcDir = new File(WORKDIR, "aaa");
    File dstDir = new File(WORKDIR, "bbb");
    File src = new File(WORKDIR, "aaa/ccc/ddd.eee");
    File dst = new File(WORKDIR, "bbb/CCC/xxx.fff");

    try {
      FileOperation.createNewFile(src);
      FileOperation.createNewFile(dst);
      src.setLastModified(2000L);
      dst.setLastModified(1000L);
    } catch (Exception e) {
      NG(e);
    }
    EQUAL(src.lastModified(), 2000L);
    EQUAL(dst.lastModified(), 1000L);

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    filter.addNameReplaceFirst("ddd", "xxx");
    filter.addNameReplaceFirst("\\.eee", ".fff");
    filter.addDirReplaceAll("c", "C");

    try {
      TRUE(filter.accept(src));
    } catch (Exception e) {
      NG(e);
    }
  }

  public void accept_01()
  {
    MSG("ターゲット・ファイルの方が新しい場合。");

    File srcDir = new File(WORKDIR, "aaa");
    File dstDir = new File(WORKDIR, "bbb");
    File src = new File(WORKDIR, "aaa/ccc/ddd.eee");
    File dst = new File(WORKDIR, "bbb/CCC/xxx.fff");

    try {
      FileOperation.createNewFile(src);
      FileOperation.createNewFile(dst);
      src.setLastModified(2000L);
      dst.setLastModified(3000L);
    } catch (Exception e) {
      NG(e);
    }
    EQUAL(src.lastModified(), 2000L);
    EQUAL(dst.lastModified(), 3000L);

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    filter.addNameReplaceFirst("ddd", "xxx");
    filter.addNameReplaceFirst("\\.eee", ".fff");
    filter.addDirReplaceAll("c", "C");

    try {
      FALSE(filter.accept(src));
    } catch (Exception e) {
      NG(e);
    }
  }

  public void accept_02()
  {
    MSG("ターゲット・ファイルが存在しない場合。");

    File srcDir = new File(WORKDIR, "aaa");
    File dstDir = new File(WORKDIR, "bbb");
    File src = new File(WORKDIR, "aaa/ccc/ddd.eee");
    File dst = new File(WORKDIR, "bbb/CCC/xxx.fff");

    try {
      FileOperation.createNewFile(src);
      src.setLastModified(2000L);
    } catch (Exception e) {
      NG(e);
    }
    EQUAL(src.lastModified(), 2000L);
    FALSE(dst.exists());

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    filter.addNameReplaceFirst("ddd", "xxx");
    filter.addNameReplaceFirst("\\.eee", ".fff");
    filter.addDirReplaceAll("c", "C");

    try {
      TRUE(filter.accept(src));
    } catch (Exception e) {
      NG(e);
    }
  }

  public void accept_03()
  {
    MSG("ターゲット・ファイルと同じ更新日時の場合。");

    File srcDir = new File(WORKDIR, "aaa");
    File dstDir = new File(WORKDIR, "bbb");
    File src = new File(WORKDIR, "aaa/ccc/ddd.eee");
    File dst = new File(WORKDIR, "bbb/CCC/xxx.fff");

    try {
      FileOperation.createNewFile(src);
      FileOperation.createNewFile(dst);
      src.setLastModified(2000L);
      dst.setLastModified(2000L);
    } catch (Exception e) {
      NG(e);
    }
    EQUAL(src.lastModified(), 2000L);
    EQUAL(dst.lastModified(), 2000L);

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    filter.addNameReplaceFirst("ddd", "xxx");
    filter.addNameReplaceFirst("\\.eee", ".fff");
    filter.addDirReplaceAll("c", "C");

    try {
      FALSE(filter.accept(src));
    } catch (Exception e) {
      NG(e);
    }
  }

  public void accept_04()
  {
    MSG("引数がヌルの場合。");

    File srcDir = new File(WORKDIR, "aaa");
    File dstDir = new File(WORKDIR, "bbb");

    try {
      srcDir.mkdirs();
      dstDir.mkdirs();
    } catch (Exception e) {
      NG(e);
    }
    TRUE(srcDir.exists());
    TRUE(dstDir.exists());

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);

    try {
      filter.accept(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    } catch (Exception e) {
      NG(e);
    }
  }

  public void accept_05()
  {
    MSG("ターゲット・ファイルの取得に失敗する場合。");

    File srcDir = new File(WORKDIR, "aaa");
    File dstDir = new File(WORKDIR, "bbb");
    File src = new File(WORKDIR, "ccc/ddd.eee");

    try {
      srcDir.mkdirs();
      dstDir.mkdirs();
      FileOperation.createNewFile(src);
    } catch (Exception e) {
      NG(e);
    }
    TRUE(srcDir.exists());
    TRUE(dstDir.exists());
    TRUE(src.exists());

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);
    try {
      FALSE(filter.accept(src));
    } catch (Exception e) {
      NG(e);
    }
  }

  public void accept_06()
  {
    MSG("引数のファイルが存在しない場合。");

    File srcDir = new File(WORKDIR, "aaa");
    File dstDir = new File(WORKDIR, "bbb");
    File src = new File(WORKDIR, "aaa/ccc/ddd.eee");
    File dst = new File(WORKDIR, "bbb/CCC/xxx.fff");

    FALSE(src.exists());
    FALSE(dst.exists());

    FileNewerThanTargetFilter filter;
    filter = new FileNewerThanTargetFilter(srcDir, dstDir);

    try {
      FALSE(filter.accept(src));
    } catch (Exception e) {
      NG(e);
    }

    try {
      FileOperation.createNewFile(dst);
    } catch (Exception e) {
      NG(e);
    }

    TRUE(dst.exists());

    try {
      FALSE(filter.accept(src));
    } catch (Exception e) {
      NG(e);
    }
  }
}
