// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.logging.test;

import com.yahoo.container.logging.LogFileHandler;
import com.yahoo.io.IOUtils;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;

import static org.junit.Assert.assertEquals;

/**
 * @author <a href="mailto:travisb@yahoo-inc.com">Bob Travis</a>
 */
// TODO: Make these tests wait until the right things happen rather than waiting for a predetermined time
// These tests take too long, and are not cleaning up properly. See how this should be done in YApacheLogTestCase
public class LogFileHandlerTestCase {

    /**
     * The scenario
     */
    @Test
    public void testIt() {
        LogFileHandler h = new LogFileHandler();
        h.setFilePattern("./logfilehandlertest.%Y%m%d%H%M%S");
        h.setFormatter(new Formatter() {
                public String format(LogRecord r) {
                    DateFormat df = new SimpleDateFormat("yyyy.MM.dd:HH:mm:ss.SSS");
                    String timeStamp = df.format(new Date(r.getMillis()));
                    return ("["+timeStamp+"]" + " " + formatMessage(r) + "\n");
                }
            } );
        long now = System.currentTimeMillis();
        long millisPerDay = 60*60*24*1000;
        long tomorrowDays = (now / millisPerDay) +1;
        long tomorrowMillis = tomorrowDays * millisPerDay;
        assertEquals (tomorrowMillis, h.getNextRotationTime(now));
        long[] rTimes = {1000, 2000, 10000};
        h.setRotationTimes(rTimes);
        assertEquals (tomorrowMillis+1000, h.getNextRotationTime(tomorrowMillis));
        assertEquals (tomorrowMillis+10000, h.getNextRotationTime(tomorrowMillis+3000));
        boolean okToWrite = false; // don't want regular unit tests to create tiles....
        if (okToWrite) {
            LogRecord lr = new LogRecord(Level.INFO, "test");
            h.publish(lr);
            h.publish(new LogRecord(Level.INFO, "another test"));
            h.rotateNow();
            h.publish(lr);
            h.flush();
        }
    }

    private boolean delete(String fileOrDir) {
      File file = new File(fileOrDir);
      return file.delete();
    }

    private void deleteOnExit(String fileOrDir) {
        new File(fileOrDir).deleteOnExit();
    }

    private static void deleteRecursive(String directory) {
       IOUtils.recursiveDeleteDir(new File(directory));
    }

    @Test
    public void testSimpleLogging() {
      String logFilePattern = "./testLogFileG1.txt";

      //create logfilehandler
      LogFileHandler h = new LogFileHandler();
      h.setFilePattern(logFilePattern);
      h.setFormatter(new SimpleFormatter());
      h.setRotationTimes("0 5 ...");

      //write log
      LogRecord lr = new LogRecord(Level.INFO, "testDeleteFileFirst1");
      h.publish(lr);
      h.flush();

      new File(logFilePattern).deleteOnExit();
    }

    @Test
    public void testDeleteFileDuringLogging() {
      String logFilePattern = "./testLogFileG2.txt";

      //create logfilehandler
      LogFileHandler h = new LogFileHandler();
      h.setFilePattern(logFilePattern);
      h.setFormatter(new SimpleFormatter());
      h.setRotationTimes("0 5 ...");

      //write log
      LogRecord lr = new LogRecord(Level.INFO, "testDeleteFileDuringLogging1");
      h.publish(lr);
      h.flush();

      //delete log file
      delete(logFilePattern);

      //write log again
      lr = new LogRecord(Level.INFO, "testDeleteFileDuringLogging2");
      h.publish(lr);
      h.flush();

      new File(logFilePattern).deleteOnExit();
    }

    @Test
    public void testDeleteDirDuringLogging() throws IOException {
        //create logfilehandler
        LogFileHandler h = new LogFileHandler();
        h.setFilePattern("./testlogsG/delete/during/testlog");
        h.setFormatter(new SimpleFormatter());
        h.setRotationTimes("0 5 ...");

        //write log
        LogRecord lr = new LogRecord(Level.INFO, "testDeleteDirDuringLogging1");
        h.publish(lr);
        h.flush();

        //delete log file and dir
        deleteRecursive("./testlogsG");

        //write log again
        LogRecord lr2 = new LogRecord(Level.INFO, "testDeleteDirDuringLogging2");
        h.publish(lr2);
        h.flush();

        deleteOnExit("./testlogsG");
        deleteOnExit("./testlogsG/delete");
        deleteOnExit("./testlogsG/delete/first");
        deleteOnExit("./testlogsG/delete/first/testlog");
    }

    @Test
    public void testSymlink() {
        LogFileHandler h = new LogFileHandler();
        h.setFilePattern("./testlogforsymlinkchecking/logfilehandlertest.%Y%m%d%H%M%S%s");
        h.setFormatter(new Formatter() {
            public String format(LogRecord r) {
                DateFormat df = new SimpleDateFormat("yyyy.MM.dd:HH:mm:ss.SSS");
                String timeStamp = df.format(new Date(r.getMillis()));
                return ("["+timeStamp+"]" + " " + formatMessage(r) + "\n");
            }
        } );
        h.setSymlinkName("symlink");
        LogRecord lr = new LogRecord(Level.INFO, "test");
        h.publish(lr);
        String f1 = h.getFileName();
        String f2 = null;
        try {
            while (f1 == null) {
                Thread.sleep(1);
                f1 = h.getFileName();
            }
            h.rotateNow();
            Thread.sleep(1);
            f2 = h.getFileName();
            while (f1.equals(f2)) {
                Thread.sleep(1);
                f2 = h.getFileName();
            }
            lr = new LogRecord(Level.INFO, "string which is way longer than the word test");
            h.publish(lr);
            Thread.sleep(1000);
            File f = new File(f1);
            long first = f.length();
            f = new File(f2);
            long second = f.length();
            final long secondLength = 72;
            for (int n = 0; n < 20 && second != secondLength; ++n) {
                Thread.sleep(1000);
                second = f.length();
            }
            f = new File("./testlogforsymlinkchecking", "symlink");
            long link = f.length();
            assertEquals(secondLength, link);
            assertEquals(31, first);
            assertEquals(secondLength, second);
        } catch (InterruptedException e) {
            // just let the test pass
        }
        deleteOnExit("./testlogforsymlinkchecking");
        deleteOnExit("./testlogforsymlinkchecking/symlink");
        deleteOnExit(f1);
        if (f2 != null)
            deleteOnExit(f2);
    }

}

@@ -279,36 +279,8 @@
 le;%0A
-import java.io.IOException;%0A
 impo
@@ -3849,882 +3849,8 @@
  %7D%0A%0A
-    @Test%0A    public void testDeleteDirDuringLogging() throws IOException %7B%0A        //create logfilehandler%0A        LogFileHandler h = new LogFileHandler();%0A        h.setFilePattern(%22./testlogsG/delete/during/testlog%22);%0A        h.setFormatter(new SimpleFormatter());%0A        h.setRotationTimes(%220 5 ...%22);%0A%0A        //write log%0A        LogRecord lr = new LogRecord(Level.INFO, %22testDeleteDirDuringLogging1%22);%0A        h.publish(lr);%0A        h.flush();%0A%0A        //delete log file and dir%0A        deleteRecursive(%22./testlogsG%22);%0A%0A        //write log again%0A        LogRecord lr2 = new LogRecord(Level.INFO, %22testDeleteDirDuringLogging2%22);%0A        h.publish(lr2);%0A        h.flush();%0A%0A        deleteOnExit(%22./testlogsG%22);%0A        deleteOnExit(%22./testlogsG/delete%22);%0A        deleteOnExit(%22./testlogsG/delete/first%22);%0A        deleteOnExit(%22./testlogsG/delete/first/testlog%22);%0A    %7D%0A%0A
     

Remove test for invalid use case.