/*
 *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "logging/rtc_event_log/output/rtc_event_log_output_file.h"

#include <fstream>
#include <memory>
#include <string>

#include "rtc_base/checks.h"
#include "rtc_base/ptr_util.h"
#include "test/gtest.h"
#include "test/testsupport/fileutils.h"

namespace webrtc {

class RtcEventLogOutputFileTest : public ::testing::Test {
 public:
  RtcEventLogOutputFileTest() : output_file_name_(GetOutputFilePath()) {
    // Ensure no leftovers from previous runs, which might not have terminated
    // in an orderly fashion.
    remove(output_file_name_.c_str());
  }

  ~RtcEventLogOutputFileTest() override { remove(output_file_name_.c_str()); }

 protected:
  std::string GetOutputFilePath() const {
    auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
    return test::OutputPath() + test_info->test_case_name() + test_info->name();
  }

  std::string GetOutputFileContents() const {
    std::ifstream file(output_file_name_,
                       std::ios_base::in | std::ios_base::binary);
    RTC_CHECK(file.is_open());
    RTC_CHECK(file.good());
    std::string file_str((std::istreambuf_iterator<char>(file)),
                         std::istreambuf_iterator<char>());
    return file_str;
  }

  const std::string output_file_name_;
};

TEST_F(RtcEventLogOutputFileTest, NonDefectiveOutputsStartOutActive) {
  auto output_file = rtc::MakeUnique<RtcEventLogOutputFile>(output_file_name_);
  EXPECT_TRUE(output_file->IsActive());
}

TEST_F(RtcEventLogOutputFileTest, DefectiveOutputsStartOutInactive) {
  const std::string illegal_filename = "/////////";
  auto output_file = rtc::MakeUnique<RtcEventLogOutputFile>(illegal_filename);
  EXPECT_FALSE(output_file->IsActive());
}

// Sanity over opening a file (by filename) with an unlimited size.
TEST_F(RtcEventLogOutputFileTest, UnlimitedOutputFile) {
  const std::string output_str = "one two three";

  auto output_file = rtc::MakeUnique<RtcEventLogOutputFile>(output_file_name_);
  output_file->Write(output_str);
  output_file.reset();  // Closing the file flushes the buffer to disk.

  EXPECT_EQ(GetOutputFileContents(), output_str);
}

// Do not allow writing more bytes to the file than
TEST_F(RtcEventLogOutputFileTest, LimitedOutputFileCappedToCapacity) {
  // Fit two bytes, then the third should be rejected.
  auto output_file =
      rtc::MakeUnique<RtcEventLogOutputFile>(output_file_name_, 2);

  output_file->Write("1");
  output_file->Write("2");
  output_file->Write("3");
  // Unsuccessful writes close the file; no need to delete the output to flush.

  EXPECT_EQ(GetOutputFileContents(), "12");
}

// Make sure that calls to Write() either write everything to the file, or
// nothing (short of underlying issues in the module that handles the file,
// which would be beyond our control).
TEST_F(RtcEventLogOutputFileTest, DoNotWritePartialLines) {
  const std::string output_str_1 = "0123456789";
  const std::string output_str_2 = "abcdefghij";

  // Set a file size limit just shy of fitting the entire second line.
  const size_t size_limit = output_str_1.length() + output_str_2.length() - 1;
  auto output_file =
      rtc::MakeUnique<RtcEventLogOutputFile>(output_file_name_, size_limit);

  output_file->Write(output_str_1);
  output_file->Write(output_str_2);
  // Unsuccessful writes close the file; no need to delete the output to flush.

  EXPECT_EQ(GetOutputFileContents(), output_str_1);
}

TEST_F(RtcEventLogOutputFileTest, UnsuccessfulWriteReturnsFalse) {
  auto output_file =
      rtc::MakeUnique<RtcEventLogOutputFile>(output_file_name_, 2);
  EXPECT_FALSE(output_file->Write("abc"));
}

TEST_F(RtcEventLogOutputFileTest, SuccessfulWriteReturnsTrue) {
  auto output_file =
      rtc::MakeUnique<RtcEventLogOutputFile>(output_file_name_, 3);
  EXPECT_TRUE(output_file->Write("abc"));
}

// Even if capacity is reached, a successful write leaves the output active.
TEST_F(RtcEventLogOutputFileTest, FileStillActiveAfterSuccessfulWrite) {
  auto output_file =
      rtc::MakeUnique<RtcEventLogOutputFile>(output_file_name_, 3);
  ASSERT_TRUE(output_file->Write("abc"));
  EXPECT_TRUE(output_file->IsActive());
}

// Unsuccessful writes switch the output to inactive, even if capacity has
// not yet been reached.
TEST_F(RtcEventLogOutputFileTest, FileInactiveAfterUnsuccessfulWrite) {
  auto output_file =
      rtc::MakeUnique<RtcEventLogOutputFile>(output_file_name_, 2);
  ASSERT_FALSE(output_file->Write("abc"));
  EXPECT_FALSE(output_file->IsActive());
}

TEST_F(RtcEventLogOutputFileTest, AllowReasonableFileSizeLimits) {
  auto output_file = rtc::MakeUnique<RtcEventLogOutputFile>(
      output_file_name_, RtcEventLogOutputFile::kMaxReasonableFileSize);
  EXPECT_TRUE(output_file->IsActive());
}

#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
#if !defined(WEBRTC_USE_MEMCHECK)  // Crashing expected to leak memory.
TEST_F(RtcEventLogOutputFileTest, WritingToInactiveFileForbidden) {
  RtcEventLogOutputFile output_file(output_file_name_, 2);
  ASSERT_FALSE(output_file.Write("abc"));
  ASSERT_FALSE(output_file.IsActive());
  EXPECT_DEATH(output_file.Write("abc"), "");
}

TEST_F(RtcEventLogOutputFileTest, DisallowUnreasonableFileSizeLimits) {
  // Keeping in a temporary unique_ptr to make it clearer that the death is
  // triggered by construction, not destruction.
  std::unique_ptr<RtcEventLogOutputFile> output_file;
  auto create_output_file = [&] {
    const size_t unreasonable_size =
        RtcEventLogOutputFile::kMaxReasonableFileSize + 1;
    output_file = rtc::MakeUnique<RtcEventLogOutputFile>(output_file_name_,
                                                         unreasonable_size);
  };
  EXPECT_DEATH(create_output_file(), "");
}
#endif  // !WEBRTC_USE_MEMCHECK
#endif

}  // namespace webrtc
