/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014, Regents of the University of California.
 *
 * This file is part of NDNS (Named Data Networking Domain Name Service).
 * See AUTHORS.md for complete list of NDNS authors and contributors.
 *
 * NDNS is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NDNS 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "logger.hpp"
#include "../boost-test.hpp"
#include "config.hpp"

#include <fstream>

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/filesystem.hpp>

namespace ndn {
namespace ndns {
namespace tests {

BOOST_AUTO_TEST_SUITE(Logger)

class Fixture
{
public:
  Fixture()
    : m_logConfigFilename(boost::filesystem::unique_path().native())
    , m_logFilename(boost::filesystem::unique_path().native())
  {
  }

  ~Fixture()
  {
    boost::filesystem::remove(boost::filesystem::path(getLogConfigFilename()));
    boost::filesystem::remove(boost::filesystem::path(getLogFilename()));

    log::init("unit-tests.log4cxx");
  }

  const std::string&
  getLogConfigFilename()
  {
    return m_logConfigFilename;
  }

  const std::string&
  getLogFilename()
  {
    return m_logFilename;
  }

  void
  verifyOutput(const std::string expected[], size_t nExpected)
  {
    std::ifstream is(getLogFilename().c_str());
    std::string buffer((std::istreambuf_iterator<char>(is)),
                       (std::istreambuf_iterator<char>()));

    std::vector<std::string> components;
    boost::split(components, buffer, boost::is_any_of(" ,\n"));

    // expected + number of timestamps (one per log statement) + trailing newline of last statement
    BOOST_REQUIRE_EQUAL(components.size(), nExpected);

    for (size_t i = 0; i < nExpected; ++i) {
      if (expected[i] == "")
        continue;

      BOOST_CHECK_EQUAL(components[i], expected[i]);
    }
  }

private:
  std::string m_logConfigFilename;
  std::string m_logFilename;
};

BOOST_FIXTURE_TEST_CASE(AllLevels, Fixture)
{
  {
    std::ofstream of(getLogConfigFilename().c_str());
    of << "log4j.rootLogger=TRACE, FILE\n"
       << "log4j.appender.FILE=org.apache.log4j.FileAppender\n"
       << "log4j.appender.FILE.layout=org.apache.log4j.PatternLayout\n"
       << "log4j.appender.FILE.File=" << getLogFilename() << "\n"
       << "log4j.appender.FILE.ImmediateFlush=true\n"
       << "log4j.appender.FILE.layout.ConversionPattern=%d{HH:mm:ss} %p %c{1} - %m%n\n";
  }

  log::init(getLogConfigFilename());

  NDNS_LOG_INIT("DefaultConfig");

  NDNS_LOG_TRACE("trace-message-JHGFDSR^1");
  NDNS_LOG_DEBUG("debug-message-IGg2474fdksd-fo-" << 15 << 16 << 17);
  NDNS_LOG_INFO("info-message-Jjxjshj13");
  NDNS_LOG_WARN("warning-message-XXXhdhd11" << 1 <<"x");
  NDNS_LOG_ERROR("error-message-!#$&^%$#@");
  NDNS_LOG_FATAL("fatal-message-JJSjaamcng");

  const std::string EXPECTED[] =
    {
      "", "TRACE", "DefaultConfig", "-", "trace-message-JHGFDSR^1",
      "", "DEBUG", "DefaultConfig", "-", "debug-message-IGg2474fdksd-fo-151617",
      "", "INFO",  "DefaultConfig", "-", "info-message-Jjxjshj13",
      "", "WARN",  "DefaultConfig", "-", "warning-message-XXXhdhd111x",
      "", "ERROR", "DefaultConfig", "-", "error-message-!#$&^%$#@",
      "", "FATAL", "DefaultConfig", "-", "fatal-message-JJSjaamcng",
      "",
    };

  verifyOutput(EXPECTED, sizeof(EXPECTED) / sizeof(std::string));
}

BOOST_FIXTURE_TEST_CASE(UpToInfo, Fixture)
{
  {
    std::ofstream of(getLogConfigFilename().c_str());
    of << "log4j.rootLogger=INFO, FILE\n"
       << "log4j.appender.FILE=org.apache.log4j.FileAppender\n"
       << "log4j.appender.FILE.layout=org.apache.log4j.PatternLayout\n"
       << "log4j.appender.FILE.File=" << getLogFilename() << "\n"
       << "log4j.appender.FILE.ImmediateFlush=true\n"
       << "log4j.appender.FILE.layout.ConversionPattern=%d{HH:mm:ss} %p %c{1} - %m%n\n";
  }

  log::init(getLogConfigFilename());

  NDNS_LOG_INIT("DefaultConfig");

  NDNS_LOG_TRACE("trace-message-JHGFDSR^1");
  NDNS_LOG_DEBUG("debug-message-IGg2474fdksd-fo-" << 15 << 16 << 17);
  NDNS_LOG_INFO("info-message-Jjxjshj13");
  NDNS_LOG_WARN("warning-message-XXXhdhd11" << 1 <<"x");
  NDNS_LOG_ERROR("error-message-!#$&^%$#@");
  NDNS_LOG_FATAL("fatal-message-JJSjaamcng");

  const std::string EXPECTED[] =
    {
      "", "INFO",  "DefaultConfig", "-", "info-message-Jjxjshj13",
      "", "WARN",  "DefaultConfig", "-", "warning-message-XXXhdhd111x",
      "", "ERROR", "DefaultConfig", "-", "error-message-!#$&^%$#@",
      "", "FATAL", "DefaultConfig", "-", "fatal-message-JJSjaamcng",
      "",
    };

  verifyOutput(EXPECTED, sizeof(EXPECTED) / sizeof(std::string));
}

BOOST_FIXTURE_TEST_CASE(OnlySelectedModule, Fixture)
{
  {
    std::ofstream of(getLogConfigFilename().c_str());
    of << "log4j.rootLogger=OFF, FILE\n"
       << "log4j.appender.FILE=org.apache.log4j.FileAppender\n"
       << "log4j.appender.FILE.layout=org.apache.log4j.PatternLayout\n"
       << "log4j.appender.FILE.File=" << getLogFilename() << "\n"
       << "log4j.appender.FILE.ImmediateFlush=true\n"
       << "log4j.appender.FILE.layout.ConversionPattern=%d{HH:mm:ss} %p %c - %m%n\n"
       << "log4j.logger.SelectedModule=TRACE\n"
       << "log4j.logger.SelectedModule.Submodule=FATAL\n";
  }

  log::init(getLogConfigFilename());

  {
    NDNS_LOG_INIT("DefaultConfig");

    NDNS_LOG_TRACE("trace-message-JHGFDSR^1");
    NDNS_LOG_DEBUG("debug-message-IGg2474fdksd-fo-" << 15 << 16 << 17);
    NDNS_LOG_INFO("info-message-Jjxjshj13");
    NDNS_LOG_WARN("warning-message-XXXhdhd11" << 1 <<"x");
    NDNS_LOG_ERROR("error-message-!#$&^%$#@");
    NDNS_LOG_FATAL("fatal-message-JJSjaamcng");
  }

  {
    NDNS_LOG_INIT("SelectedModule");

    NDNS_LOG_TRACE("trace-message-JHGFDSR^1");
    NDNS_LOG_DEBUG("debug-message-IGg2474fdksd-fo-" << 15 << 16 << 17);
    NDNS_LOG_INFO("info-message-Jjxjshj13");
    NDNS_LOG_WARN("warning-message-XXXhdhd11" << 1 <<"x");
    NDNS_LOG_ERROR("error-message-!#$&^%$#@");
    NDNS_LOG_FATAL("fatal-message-JJSjaamcng");
  }

  {
    NDNS_LOG_INIT("SelectedModule.Submodule");

    NDNS_LOG_TRACE("trace-message-JHGFDSR^1");
    NDNS_LOG_DEBUG("debug-message-IGg2474fdksd-fo-" << 15 << 16 << 17);
    NDNS_LOG_INFO("info-message-Jjxjshj13");
    NDNS_LOG_WARN("warning-message-XXXhdhd11" << 1 <<"x");
    NDNS_LOG_ERROR("error-message-!#$&^%$#@");
    NDNS_LOG_FATAL("fatal-message-JJSjaamcng");
  }

  const std::string EXPECTED[] =
    {
      "", "TRACE", "SelectedModule", "-", "trace-message-JHGFDSR^1",
      "", "DEBUG", "SelectedModule", "-", "debug-message-IGg2474fdksd-fo-151617",
      "", "INFO",  "SelectedModule", "-", "info-message-Jjxjshj13",
      "", "WARN",  "SelectedModule", "-", "warning-message-XXXhdhd111x",
      "", "ERROR", "SelectedModule", "-", "error-message-!#$&^%$#@",
      "", "FATAL", "SelectedModule", "-", "fatal-message-JJSjaamcng",
      "", "FATAL", "SelectedModule.Submodule", "-", "fatal-message-JJSjaamcng",
      "",
    };

  verifyOutput(EXPECTED, sizeof(EXPECTED) / sizeof(std::string));
}


BOOST_AUTO_TEST_SUITE_END()

} // namespace tests
} // namespace ndns
} // namespace ndn
