#include "tile/base/logging/splitter_sink.h"
#include "gtest/gtest.h"

namespace tile {
class SimpleSink : public LogSink {
public:
    using Ptr = std::shared_ptr<SimpleSink>;

    static Ptr Create() { return std::shared_ptr<SimpleSink>(new SimpleSink()); }

    const char *name() const override { return "SimpleSink"; }

    void Send(LogSeverity severity,
              const char *full_filename,
              const char *base_filename,
              int line,
              const LogMessageTime &logmsgtime,
              const char *message,
              size_t message_len) override
    {
        message_ = std::string(message, message_len);
    }

    void Flush() override {}

    std::string message_;
};

TEST(SplitterSink, One)
{
    auto sink     = SimpleSink::Create();
    auto splitter = SplitterSink::Create({sink});
    splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), "message", 7);
    ASSERT_EQ(sink->message_, "message");
}

TEST(SplitterSink, Two)
{
    auto sink1    = SimpleSink::Create();
    auto sink2    = SimpleSink::Create();
    auto splitter = SplitterSink::Create({sink1, sink2});
    splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), "message", 7);
    ASSERT_EQ(sink1->message_, "message");
    ASSERT_EQ(sink2->message_, "message");
}

TEST(SplitterSink, Multi)
{
    auto splitter = SplitterSink::Create();
    for (int i = 0; i < 100; i++) { splitter->AddSink(SimpleSink::Create()); }

    for (int i = 0; i < 100; i++) {
        std::stringstream ss;
        ss << "message" << i;
        auto msg = ss.str();
        splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), msg.data(), msg.size());

        for (auto &sink : splitter->sinks()) { ASSERT_EQ(std::static_pointer_cast<SimpleSink>(sink)->message_, msg); }
    }
}

}// namespace tile
