// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dictionary/file/codec.h"

#include "base/file_stream.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/util.h"
#include "dictionary/file/codec_interface.h"
#include "dictionary/file/section.h"
#include "testing/base/public/googletest.h"
#include "testing/base/public/gunit.h"

DECLARE_string(test_tmpdir);

namespace mozc {
namespace dictionary {
namespace {

class CodecTest : public ::testing::Test {
 public:
  CodecTest() : test_file_(FLAGS_test_tmpdir + "testfile.txt") {}

 protected:
  virtual void SetUp() {
    DictionaryFileCodecFactory::SetCodec(NULL);
    FileUtil::Unlink(test_file_);
  }

  virtual void TearDown() {
    // Reset to default setting
    DictionaryFileCodecFactory::SetCodec(NULL);
    FileUtil::Unlink(test_file_);
  }

  void AddSection(const DictionaryFileCodecInterface *codec,
                  const string &name,
                  const char *ptr,
                  int len,
                  vector<DictionaryFileSection> *sections) const {
    CHECK(codec);
    CHECK(sections);
    sections->push_back(
        DictionaryFileSection(ptr, len, codec->GetSectionName(name)));
  }

  bool FindSection(const DictionaryFileCodecInterface *codec,
                   const vector<DictionaryFileSection> &sections,
                   const string &name,
                   int *index) const {
    CHECK(codec);
    CHECK(index);
    const string name_find = codec->GetSectionName(name);
    for (size_t i = 0; i < sections.size(); ++i) {
      if (sections[i].name == name_find) {
        *index = i;
        return true;
      }
    }
    return false;
  }

  bool CheckValue(const DictionaryFileSection &section,
                  const string &expected) const {
    const string value = string(section.ptr, section.len);
    return (expected == value);
  }

  const string test_file_;
};

class CodecMock : public DictionaryFileCodecInterface {
 public:
  virtual void WriteSections(const vector<DictionaryFileSection> &sections,
                             ostream *ofs) const {
    const string value = "dummy value";
    ofs->write(value.data(), value.size());
  }

  virtual bool ReadSections(const char *image, int length,
                            vector<DictionaryFileSection> *sections) const {
    sections->push_back(DictionaryFileSection(NULL, 0, "dummy name"));
    return true;
  }

  virtual string GetSectionName(const string &name) const {
    return "dummy section name";
  }
};

TEST_F(CodecTest, FactoryTest) {
  scoped_ptr<CodecMock> codec_mock(new CodecMock);
  DictionaryFileCodecFactory::SetCodec(codec_mock.get());
  const DictionaryFileCodecInterface *codec =
      DictionaryFileCodecFactory::GetCodec();
  EXPECT_TRUE(codec != NULL);
  vector<DictionaryFileSection> sections;
  {
    OutputFileStream ofs;
    ofs.open(test_file_.c_str(), ios_base::out | ios_base::binary);
    codec->WriteSections(sections, &ofs);
  }
  {
    EXPECT_TRUE(FileUtil::FileExists(test_file_));
    InputFileStream ifs;
    ifs.open(test_file_.c_str(), ios_base::in | ios_base::binary);
    ifs.seekg(0, ios::end);
    const int len = ifs.tellg();
    ifs.seekg(0, ios::beg);
    char buf[64];
    ifs.read(buf, len);
    EXPECT_EQ("dummy value", string(buf, len));
  }
  {
    EXPECT_EQ(0, sections.size());
    EXPECT_TRUE(codec->ReadSections(NULL, 0, &sections));
    EXPECT_EQ(1, sections.size());
    EXPECT_EQ("dummy name", sections[0].name);
  }
  {
    EXPECT_EQ("dummy section name", codec->GetSectionName("test"));
  }
}

TEST_F(CodecTest, DefaultTest) {
  const DictionaryFileCodecInterface *codec =
      DictionaryFileCodecFactory::GetCodec();
  EXPECT_TRUE(codec != NULL);
  {
    vector<DictionaryFileSection> write_sections;
    const string value0 = "Value 0 test";
    AddSection(codec, "Section 0", value0.data(), value0.size(),
               &write_sections);
    const string value1 = "Value 1 test test";
    AddSection(codec, "Section 1", value1.data(), value1.size(),
               &write_sections);
    OutputFileStream ofs;
    ofs.open(test_file_.c_str(), ios_base::out | ios_base::binary);
    codec->WriteSections(write_sections, &ofs);
  }
  char buf[1024] = {};  // sections will reference this buffer.
  vector<DictionaryFileSection> sections;
  {
    EXPECT_TRUE(FileUtil::FileExists(test_file_));
    InputFileStream ifs;
    ifs.open(test_file_.c_str(), ios_base::in | ios_base::binary);
    ifs.read(buf, 1024);
    EXPECT_TRUE(codec->ReadSections(buf, 1024, &sections));
  }
  EXPECT_EQ(2, sections.size());
  int index = -1;
  EXPECT_TRUE(FindSection(codec, sections, "Section 0", &index));
  EXPECT_TRUE(CheckValue(sections[index], "Value 0 test"));

  EXPECT_TRUE(FindSection(codec, sections, "Section 1", &index));
  EXPECT_TRUE(CheckValue(sections[index], "Value 1 test test"));
}

TEST_F(CodecTest, CodecTest) {
  scoped_ptr<DictionaryFileCodec> default_codec(
      new DictionaryFileCodec);
  DictionaryFileCodecFactory::SetCodec(default_codec.get());
  const DictionaryFileCodecInterface *codec =
      DictionaryFileCodecFactory::GetCodec();
  EXPECT_TRUE(codec != NULL);
  {
    vector<DictionaryFileSection> write_sections;
    const string value0 = "Value 0 test";
    AddSection(codec, "Section 0", value0.data(), value0.size(),
               &write_sections);
    const string value1 = "Value 1 test test";
    AddSection(codec, "Section 1", value1.data(), value1.size(),
               &write_sections);
    OutputFileStream ofs;
    ofs.open(test_file_.c_str(), ios_base::out | ios_base::binary);
    codec->WriteSections(write_sections, &ofs);
  }
  char buf[1024] = {};  // sections will reference this buffer.
  vector<DictionaryFileSection> sections;
  {
    EXPECT_TRUE(FileUtil::FileExists(test_file_));
    InputFileStream ifs;
    ifs.open(test_file_.c_str(), ios_base::in | ios_base::binary);
    ifs.read(buf, 1024);
    EXPECT_TRUE(codec->ReadSections(buf, 1024, &sections));
  }
  EXPECT_EQ(2, sections.size());
  int index = -1;
  EXPECT_TRUE(FindSection(codec, sections, "Section 0", &index));
  EXPECT_TRUE(CheckValue(sections[index], "Value 0 test"));

  EXPECT_TRUE(FindSection(codec, sections, "Section 1", &index));
  EXPECT_TRUE(CheckValue(sections[index], "Value 1 test test"));
}


}  // namespace
}  // namespace dictionary
}  // namespace mozc
