// Copyright 2016 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 "peridot/lib/firebase/event_stream.h"

#include <memory>
#include <string>
#include <utility>

#include <lib/async/cpp/task.h>
#include <lib/fsl/socket/strings.h>
#include <src/lib/fxl/macros.h>
#include <lib/gtest/test_loop_fixture.h>

#include "peridot/lib/socket/socket_pair.h"

namespace firebase {

class EventStreamTest : public ::gtest::TestLoopFixture {
 public:
  EventStreamTest() {}
  ~EventStreamTest() override {}

 protected:
  // ApplicationTestBase:
  void SetUp() override {
    ::testing::Test::SetUp();
    socket::SocketPair socket;
    producer_socket_ = std::move(socket.socket1);
    event_stream_ = std::make_unique<EventStream>();
    event_stream_->Start(
        std::move(socket.socket2),
        [this](Status status, const std::string& event,
               const std::string& data) {
          status_.push_back(status);
          events_.push_back(event);
          data_.push_back(data);
          if (delete_on_event_) {
            event_stream_.reset();
          }
        },
        []() {});
  }

  void TearDown() override {
    producer_socket_.reset();
    ::testing::Test::TearDown();
  }

  void Feed(const std::string& data) {
    event_stream_->OnDataAvailable(data.data(), data.size());
  }

  void Done() { event_stream_->OnDataComplete(); }

  zx::socket producer_socket_;
  std::unique_ptr<EventStream> event_stream_;
  std::vector<Status> status_;
  std::vector<std::string> events_;
  std::vector<std::string> data_;
  bool delete_on_event_ = false;

 private:
  FXL_DISALLOW_COPY_AND_ASSIGN(EventStreamTest);
};

namespace {

TEST_F(EventStreamTest, OneEvent) {
  Feed("event: abc\ndata: bazinga\n\n");
  Done();

  EXPECT_EQ(1u, status_.size());
  EXPECT_EQ(Status::OK, status_[0]);
  EXPECT_EQ("abc", events_[0]);
  EXPECT_EQ("bazinga", data_[0]);
}

TEST_F(EventStreamTest, CutAtLineBreaks) {
  Feed("event: abc\n");
  Feed("data: bazinga\n");
  Feed("\n");
  Done();

  EXPECT_EQ(1u, status_.size());
  EXPECT_EQ(Status::OK, status_[0]);
  EXPECT_EQ("abc", events_[0]);
  EXPECT_EQ("bazinga", data_[0]);
}

TEST_F(EventStreamTest, CutInsideTag) {
  Feed("eve");
  Feed("nt: abc\n");
  Feed("da");
  Feed("ta: bazinga\n\n");
  Done();

  EXPECT_EQ(1u, status_.size());
  EXPECT_EQ(Status::OK, status_[0]);
  EXPECT_EQ("abc", events_[0]);
  EXPECT_EQ("bazinga", data_[0]);
}

TEST_F(EventStreamTest, CutInsideData) {
  Feed("event: abc\n");
  Feed("data: baz");
  Feed("inga\n\n");
  Done();

  EXPECT_EQ(1u, status_.size());
  EXPECT_EQ(Status::OK, status_[0]);
  EXPECT_EQ("abc", events_[0]);
  EXPECT_EQ("bazinga", data_[0]);
}

TEST_F(EventStreamTest, DataInMultipleLines) {
  Feed("event: abc\n");
  Feed("data: baz\n");
  Feed("data: in\ndata: ga\n");
  Feed("\n");
  Done();

  EXPECT_EQ(1u, status_.size());
  EXPECT_EQ(Status::OK, status_[0]);
  EXPECT_EQ("abc", events_[0]);
  EXPECT_EQ("baz\nin\nga", data_[0]);
}

TEST_F(EventStreamTest, IgnoreUnknownFieldNames) {
  Feed("event: abc\n");
  Feed("data: baz\n");
  Feed("trololo: trololo\n");  // Unknown field name.
  Feed("data: in\ndata: ga\n");
  Feed("\n");
  Done();

  EXPECT_EQ(1u, status_.size());
  EXPECT_EQ(Status::OK, status_[0]);
  EXPECT_EQ("abc", events_[0]);
  EXPECT_EQ("baz\nin\nga", data_[0]);
}

TEST_F(EventStreamTest, IgnoreLinesStartingWithColon) {
  Feed("event: abc\n");
  Feed(":ignore me, trololo\n");
  Feed("data: bazinga\n\n");
  Done();

  EXPECT_EQ(1u, status_.size());
  EXPECT_EQ(Status::OK, status_[0]);
  EXPECT_EQ("abc", events_[0]);
  EXPECT_EQ("bazinga", data_[0]);
}

TEST_F(EventStreamTest, MultipleEvents) {
  Feed("event: abc\n");
  Feed("data: bazinga\n\n");
  Feed("event: cde\n");
  Feed("data: 42\n\n");
  Feed("event: fgh\n");
  Feed("data: 50\n\n");
  Done();

  EXPECT_EQ(3u, status_.size());
  EXPECT_EQ(Status::OK, status_[0]);
  EXPECT_EQ("abc", events_[0]);
  EXPECT_EQ("bazinga", data_[0]);

  EXPECT_EQ(Status::OK, status_[1]);
  EXPECT_EQ("cde", events_[1]);
  EXPECT_EQ("42", data_[1]);

  EXPECT_EQ(Status::OK, status_[2]);
  EXPECT_EQ("fgh", events_[2]);
  EXPECT_EQ("50", data_[2]);
}

TEST_F(EventStreamTest, DeleteOnEvent) {
  delete_on_event_ = true;
  fsl::BlockingCopyFromString("event: abc\ndata: bazinga\n\n",
                              producer_socket_);

  RunLoopUntilIdle();

  EXPECT_EQ(1u, status_.size());
  EXPECT_EQ(Status::OK, status_[0]);
  EXPECT_EQ("abc", events_[0]);
  EXPECT_EQ("bazinga", data_[0]);
}

}  // namespace
}  // namespace firebase
