// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/lib/util/status_builder.h"

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#ifdef HAVE_GLOG
#include <string>
#include <vector>

#include <glog/logging.h>
#endif  // HAVE_GLOG

namespace cobalt {

using testing::HasSubstr;

TEST(StatusBuilder, Ok) {
  Status status = util::StatusBuilder(StatusCode::OK).Build();
  ASSERT_EQ(StatusCode::OK, status.error_code());
}

TEST(StatusBuilder, BasicConstructor) {
  Status status = util::StatusBuilder(StatusCode::INTERNAL, "Internal error").Build();
  ASSERT_EQ(StatusCode::INTERNAL, status.error_code());
  ASSERT_EQ("Internal error", status.error_message());
}

TEST(StatusBuilder, SetCodeWorks) {
  Status status = util::StatusBuilder(StatusCode::OK).SetCode(StatusCode::INVALID_ARGUMENT).Build();
  ASSERT_EQ(StatusCode::INVALID_ARGUMENT, status.error_code());
}

TEST(StatusBuilder, WithContextWorks) {
  Status status = util::StatusBuilder(StatusCode::RESOURCE_EXHAUSTED)
                      .WithContext("number", 10)
                      .WithContext("string", "value")
                      .WithContext("bool", true)
                      .Build();
  ASSERT_EQ(StatusCode::RESOURCE_EXHAUSTED, status.error_code());
  ASSERT_THAT(status.error_details(), HasSubstr("number=10"));
  ASSERT_THAT(status.error_details(), HasSubstr("string=value"));
  ASSERT_THAT(status.error_details(), HasSubstr("bool=1"));
}

TEST(StatusBuilder, AppendMsgWorks) {
  Status status =
      util::StatusBuilder(StatusCode::UNIMPLEMENTED, "Base msg").AppendMsg(" more message").Build();
  ASSERT_EQ(StatusCode::UNIMPLEMENTED, status.error_code());
  ASSERT_EQ(status.error_message(), "Base msg more message");
}

TEST(StatusBuilder, ContextFormatterWorks) {
  ReportDefinition rd;
  rd.set_report_name("Report name");
  Status status = util::StatusBuilder(StatusCode::UNIMPLEMENTED)
                      .WithContexts(rd)
                      .WithContext("CustomName", rd)
                      .Build();
  ASSERT_EQ(StatusCode::UNIMPLEMENTED, status.error_code());
  ASSERT_THAT(status.error_details(), HasSubstr("Report=Report name"));
  ASSERT_THAT(status.error_details(), HasSubstr("CustomName=Report name"));
}

namespace {
struct TestStruct {
  int v;
  float v2;
};

}  // namespace
namespace util {
template <>
class ContextFormatter<TestStruct> {
 public:
  explicit ContextFormatter(const TestStruct &v) : v_(v) {}
  inline static std::string default_key() { return "TestStruct"; }
  inline void write_value(std::ostream &stream) const {
    stream << "V(" << v_.v << "/" << v_.v2 << ")";
  }

 private:
  const TestStruct &v_;
};

}  // namespace util

TEST(StatusBuilder, CustomContextFormatter) {
  TestStruct ts;
  ts.v = 100;
  ts.v2 = 12.10f;
  Status status = util::StatusBuilder(StatusCode::ABORTED)
                      .WithContexts(ts)
                      .WithContext("local_name", ts)
                      .Build();
  ASSERT_EQ(StatusCode::ABORTED, status.error_code());
  ASSERT_THAT(status.error_details(), HasSubstr("TestStruct=V(100/12.1)"));
  ASSERT_THAT(status.error_details(), HasSubstr("local_name=V(100/12.1)"));
}

// Testing the logging code. Currently only runs on platforms with GLOG.
#ifdef HAVE_GLOG

class LogSink : public ::google::LogSink {
 public:
  std::vector<std::string> errors;
  void send(::google::LogSeverity severity, const char *full_filename, const char *base_filename,
            int line, const struct ::tm *tm_time, const char *message,
            size_t message_len) override {
    errors.push_back(ToString(severity, base_filename, line, tm_time, message, message_len));
  }
};

void ConstructAndDrop(util::StatusBuilder builder) { std::move(builder).Build(); }

TEST(StatusBuilder, LogWorks) {
  LogSink sink;
  ::google::AddLogSink(&sink);

  ConstructAndDrop(
      util::StatusBuilder(StatusCode::NOT_FOUND, "Msg1").Log(util::StatusBuilder::LogLevel::ERROR));
  ConstructAndDrop(util::StatusBuilder(StatusCode::NOT_FOUND, "Msg2").LogError());
  ConstructAndDrop(util::StatusBuilder(StatusCode::NOT_FOUND, "Msg3").LogWarning());
  ConstructAndDrop(util::StatusBuilder(StatusCode::NOT_FOUND, "Msg4").LogInfo());

  ASSERT_EQ(size_t{4}, sink.errors.size());
  ASSERT_THAT(sink.errors[0], HasSubstr("NOT_FOUND: Msg1"));
  ASSERT_THAT(sink.errors[1], HasSubstr("NOT_FOUND: Msg2"));
  ASSERT_THAT(sink.errors[2], HasSubstr("NOT_FOUND: Msg3"));
  ASSERT_THAT(sink.errors[3], HasSubstr("NOT_FOUND: Msg4"));

  ::google::RemoveLogSink(&sink);
}

#endif  // HAVE_GLOG

}  // namespace cobalt
