/*
 * 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;
  }
}
