/*
 * 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.log4j.db;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.log4j.Hierarchy;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.apache.log4j.VectorAppender;
import org.apache.log4j.LoggerRepositoryExImpl;
import org.apache.log4j.helpers.Constants;
import org.apache.log4j.xml.DOMConfigurator;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.RootLogger;
import org.apache.log4j.spi.LoggerRepository;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import java.util.HashMap;
import java.io.InputStream;
import java.io.IOException;


/**
 * This test case writes a few events into a databases and reads them
 * back comparing the event written and read back.
 * 
 * <p>It relies heavily on the proper configuration of its environment
 * in joran config files as well system properties.
 * </p>
 * 
 * <p>See also the Ant build file in the tests/ directory.</p> 
 * 
 * @author Ceki G&uuml;lc&uuml;
 */
public class FullCycleDBTest
       extends TestCase {
  
  Vector witnessEvents;
  Hierarchy lrWrite;
  LoggerRepository lrRead;
  String appendConfigFile = null;
  String readConfigFile = null;
  
  
  /*
   * @see TestCase#setUp()
   */
  protected void setUp()
         throws Exception {
    super.setUp();
    appendConfigFile = "append-with-drivermanager1.xml";
    readConfigFile = "read-with-drivermanager1.xml";

    witnessEvents = new Vector();
    lrWrite = new Hierarchy(new RootLogger(Level.DEBUG));
    lrRead = new LoggerRepositoryExImpl(new Hierarchy(new RootLogger(Level.DEBUG)));


    //
    //   attempt to define tables in in-memory database
    //      will throw exception if already defined.
    //
        Class.forName("org.hsqldb.jdbcDriver");
        Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:testdb");
        try {
            Statement s = connection.createStatement();
            s.executeUpdate("CREATE TABLE logging_event " +
              "( sequence_number   BIGINT NOT NULL, " +
               " timestamp         BIGINT NOT NULL, " +
               " rendered_message  LONGVARCHAR NOT NULL, " +
               " logger_name       VARCHAR NOT NULL, " +
               " level_string      VARCHAR NOT NULL, " +
               " ndc               LONGVARCHAR, " +
               " thread_name       VARCHAR, " +
               " reference_flag    SMALLINT, " +
               " caller_filename   VARCHAR, " +
               " caller_class      VARCHAR, " +
               " caller_method     VARCHAR, " +
               " caller_line       CHAR(4), " +
               " event_id          INT NOT NULL IDENTITY)");
            s.executeUpdate("CREATE TABLE logging_event_property " +
              "( event_id	      INT NOT NULL, " +
               " mapped_key        VARCHAR(254) NOT NULL, " +
               " mapped_value      LONGVARCHAR, " +
               " PRIMARY KEY(event_id, mapped_key), " +
               " FOREIGN KEY (event_id) REFERENCES logging_event(event_id))");
            s.executeUpdate("CREATE TABLE logging_event_exception" +
                    "  ( event_id         INT NOT NULL, " +
                    "    i                SMALLINT NOT NULL," +
                    "    trace_line       VARCHAR NOT NULL," +
                    "    PRIMARY KEY(event_id, i)," +
                    "    FOREIGN KEY (event_id) REFERENCES logging_event(event_id))");
        } catch(SQLException ex) {
            String s = ex.toString();
        } finally {
            connection.close();
        }

  }


  /*
   * @see TestCase#tearDown()
   */
  protected void tearDown()
         throws Exception {
    super.tearDown();
    lrRead.shutdown();
    witnessEvents = null;
  }

  /**
   * Constructor for DBReeceiverTest.
   * @param arg0
   */
  public FullCycleDBTest(String arg0) {
    super(arg0);
  }

  
  /**
   * This test starts by writing a single event to a DB using DBAppender
   * and then reads it back using DBReceiver.
   * 
   * DB related information is specified within the configuration files.
   * @throws Exception
   */
  public void testSingleOutput()
         throws Exception {
    DOMConfigurator jc1 = new DOMConfigurator();
    InputStream is = FullCycleDBTest.class.getResourceAsStream(appendConfigFile);
    jc1.doConfigure(is, lrWrite);
    is.close();
  
    long startTime = System.currentTimeMillis();
    System.out.println("***startTime is  "+startTime);

    // Write out just one log message
    Logger out = lrWrite.getLogger("testSingleOutput.out");
    out.debug("some message"+startTime);

    VectorAppender witnessAppender = (VectorAppender) lrWrite.getRootLogger().getAppender("VECTOR");
    witnessEvents = witnessAppender.getVector();
    assertEquals(1, witnessEvents.size());    

    // We have to close all appenders before starting to read
    lrWrite.shutdown();

    // now read it back
    readBack(readConfigFile, startTime);

  }

  /**
   * This test starts by writing a single event to a DB using DBAppender
   * and then reads it back using DBReceiver.
   * 
   * The written event includes MDC and repository properties as well as
   * exception info.
   * 
   * DB related information is specified within the configuration files.
   * @throws Exception
   */
  public void testAllFields() throws IOException {
    DOMConfigurator jc1 = new DOMConfigurator();
    InputStream is = FullCycleDBTest.class.getResourceAsStream(appendConfigFile);
    jc1.doConfigure(is, lrWrite);
    is.close();
  
    long startTime = System.currentTimeMillis();
    
    // Write out just one log message
    MDC.put("key1", "value1-"+startTime);
    MDC.put("key2", "value2-"+startTime);
    Map mdcMap = MDC.getContext();
//    LogLog.info("**********"+mdcMap.size());
    
    // Write out just one log message
    Logger out = lrWrite.getLogger("out"+startTime);

    out.debug("some message"+startTime);
    MDC.put("key3", "value2-"+startTime);
    out.error("some error message"+startTime, new Exception("testing"));
    
    // we clear the MDC to avoid interference with the events read back from
    // the db
    MDC.remove("key1");
    MDC.remove("key2");
    MDC.remove("key3");

    VectorAppender witnessAppender = (VectorAppender) lrWrite.getRootLogger().getAppender("VECTOR");
    witnessEvents = witnessAppender.getVector();
    assertEquals(2, witnessEvents.size());    

    // We have to close all appenders just before starting to read
    lrWrite.shutdown();
    
    readBack(readConfigFile, startTime);
  }


  void readBack(String configfile, long startTime) throws IOException {
    DOMConfigurator jc2 = new DOMConfigurator();
    InputStream is = FullCycleDBTest.class.getResourceAsStream(configfile);
    jc2.doConfigure(is, lrRead);
    is.close();
    
    // wait a little to allow events to be read
    try { Thread.sleep(3100); } catch(Exception e) {}
    VectorAppender va = (VectorAppender) lrRead.getRootLogger().getAppender("VECTOR");
    Vector returnedEvents = getRelevantEventsFromVA(va, startTime);
    
    compareEvents(witnessEvents, returnedEvents);
    
  }
  
  void compareEvents(Vector l, Vector r) {
    assertNotNull("left vector of events should not be null");
    assertEquals(l.size(), r.size());
    
    for(int i = 0; i < r.size(); i++) {
      LoggingEvent le = (LoggingEvent) l.get(i);
      LoggingEvent re = (LoggingEvent) r.get(i);
      assertEquals(le.getMessage(),        re.getMessage());
      assertEquals(le.getLoggerName(),     re.getLoggerName());
      assertEquals(le.getLevel(),          re.getLevel());
      assertEquals(le.getThreadName(), re.getThreadName());
      if(re.getTimeStamp() < le.getTimeStamp()) {
        fail("Returned event cannot preceed witness timestamp");
      }

      Map sourceMap = re.getProperties();
      Map remap;
      if (sourceMap == null) {
          remap = new HashMap();
      } else {
          remap = new HashMap(sourceMap);
          if (remap.containsKey(Constants.LOG4J_ID_KEY)) {
              remap.remove(Constants.LOG4J_ID_KEY);
          }
      }
      if(le.getProperties() == null || le.getProperties().size() == 0) {
        if(remap.size() != 0) {
          System.out.println("properties are "+remap);
          fail("Returned event should have been empty");
        }
      } else {
        assertEquals(le.getProperties(), remap);
      }
      comprareStringArrays( le.getThrowableStrRep(),  re.getThrowableStrRep());
      compareLocationInfo(le, re);
    } 
  }
  
  void comprareStringArrays(String[] la, String[] ra) {
    if((la == null) && (ra == null)) {
      return;
    }
    assertEquals(la.length, ra.length);
    for(int i = 0; i < la.length; i++) {
      assertEquals(la[i], ra[i]);
    }
  }
  
  void compareLocationInfo(LoggingEvent l, LoggingEvent r) {
    if(l.locationInformationExists()) {
      assertEquals(l.getLocationInformation().fullInfo, r.getLocationInformation().fullInfo);
    } else {
      assertEquals(LocationInfo.NA_LOCATION_INFO, r.getLocationInformation());
    }
  }
  
  Vector getRelevantEventsFromVA(VectorAppender va, long startTime) {
    assertNotNull(va);
    Vector v = va.getVector();
    Vector r = new Vector();
    // remove all elements older than startTime
    for(Iterator i = v.iterator(); i.hasNext(); ) {
      LoggingEvent event = (LoggingEvent) i.next();  
      if(startTime > event.getTimeStamp()) {
        System.out.println("***Removing event with timestamp "+event.getTimeStamp());
      } else {
        System.out.println("***Keeping event with timestamo"+event.getTimeStamp());
        r.add(event);
      }
    }
    return r;
  }

  void dump(Vector v) {
    for(int i = 0; i < v.size(); i++) {
      LoggingEvent le = (LoggingEvent) v.get(i);
      System.out.println("---"+le.getLevel()+" "+le.getLoggerName()+" "+le.getMessage());
    }
  }
  
  public static Test XXsuite() {
    TestSuite suite = new TestSuite();
    suite.addTest(new FullCycleDBTest("testSingleOutput"));
    suite.addTest(new FullCycleDBTest("testAllFields"));
    return suite;
  }
}
