// 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 <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
