/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "perfetto/ext/base/threading/spawn.h"

#include <optional>

#include "perfetto/ext/base/event_fd.h"
#include "perfetto/ext/base/thread_task_runner.h"
#include "perfetto/ext/base/threading/future.h"
#include "perfetto/ext/base/threading/poll.h"
#include "perfetto/ext/base/threading/util.h"
#include "perfetto/ext/base/unix_task_runner.h"
#include "src/base/test/test_task_runner.h"
#include "test/gtest_and_gmock.h"

namespace perfetto {
namespace base {
namespace {

using ::testing::_;
using ::testing::Return;

template <typename T>
class MockFuturePollable : public FuturePollable<T> {
 public:
  MOCK_METHOD(FuturePollResult<T>, Poll, (PollContext*), (override));
};

template <typename T>
class MockStreamPollable : public StreamPollable<T> {
 public:
  MOCK_METHOD(StreamPollResult<T>, PollNext, (PollContext*), (override));
};

TEST(SpawnUnittest, SpawnFuture) {
  base::TestTaskRunner task_runner;

  base::EventFd fd;
  auto pollable = std::make_unique<MockFuturePollable<int>>();
  EXPECT_CALL(*pollable, Poll(_))
      .WillOnce([&fd](PollContext* ctx) {
        fd.Clear();
        ctx->RegisterInterested(fd.fd());
        return PendingPollResult();
      })
      .WillOnce(Return(FuturePollResult<int>(1024)));
  auto res = SpawnResultFuture<int>(
      &task_runner,
      [pollable = std::make_shared<std::unique_ptr<MockFuturePollable<int>>>(
           std::move(pollable))]() mutable {
        return base::Future<int>(std::move(*pollable));
      });

  task_runner.RunUntilIdle();
  ASSERT_EQ(res.channel()->ReadNonBlocking().item, std::nullopt);

  task_runner.RunUntilIdle();
  ASSERT_EQ(res.channel()->ReadNonBlocking().item, std::nullopt);

  fd.Notify();
  task_runner.RunUntilIdle();

  auto read = res.channel()->ReadNonBlocking();
  ASSERT_EQ(read.item, 1024);
  ASSERT_TRUE(read.is_closed);

  read = res.channel()->ReadNonBlocking();
  ASSERT_TRUE(read.is_closed);
}

TEST(SpawnUnittest, SpawnStream) {
  base::TestTaskRunner task_runner;

  base::EventFd fd;
  auto pollable = std::make_unique<MockStreamPollable<int>>();
  EXPECT_CALL(*pollable, PollNext(_))
      .WillOnce([&fd](PollContext* ctx) {
        fd.Clear();
        ctx->RegisterInterested(fd.fd());
        return PendingPollResult();
      })
      .WillOnce(Return(StreamPollResult<int>(1024)))
      .WillOnce([&fd](PollContext* ctx) {
        fd.Clear();
        ctx->RegisterInterested(fd.fd());
        return PendingPollResult();
      })
      .WillOnce(Return(StreamPollResult<int>(2048)))
      .WillOnce(Return(DonePollResult()));
  auto res = SpawnResultStream<int>(
      &task_runner,
      [pollable = std::make_shared<std::unique_ptr<MockStreamPollable<int>>>(
           std::move(pollable))]() mutable {
        return base::Stream<int>(std::move(*pollable));
      });

  task_runner.RunUntilIdle();
  ASSERT_EQ(res.channel()->ReadNonBlocking().item, std::nullopt);

  fd.Notify();
  task_runner.RunUntilIdle();

  auto read = res.channel()->ReadNonBlocking();
  ASSERT_EQ(read.item, 1024);
  ASSERT_FALSE(read.is_closed);

  task_runner.RunUntilIdle();
  ASSERT_EQ(res.channel()->ReadNonBlocking().item, std::nullopt);

  fd.Notify();
  task_runner.RunUntilIdle();

  read = res.channel()->ReadNonBlocking();
  ASSERT_EQ(read.item, 2048);
  ASSERT_TRUE(read.is_closed);
}

}  // namespace
}  // namespace base
}  // namespace perfetto
