// Copyright 2013 The Flutter 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 "flutter/fml/synchronization/waitable_event.h"

#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

#include <atomic>
#include <thread>
#include <type_traits>
#include <vector>

#include "flutter/fml/macros.h"
#include "gtest/gtest.h"

namespace fml {
namespace {

constexpr TimeDelta kEpsilonTimeout = TimeDelta::FromMilliseconds(20);
constexpr TimeDelta kTinyTimeout = TimeDelta::FromMilliseconds(100);
constexpr TimeDelta kActionTimeout = TimeDelta::FromMilliseconds(10000);

// Sleeps for a "very small" amount of time.

void SleepFor(TimeDelta duration) {
  std::this_thread::sleep_for(
      std::chrono::nanoseconds(duration.ToNanoseconds()));
}

void EpsilonRandomSleep() {
  TimeDelta duration =
      TimeDelta::FromMilliseconds(static_cast<unsigned>(rand()) % 20u);
  SleepFor(duration);
}

// AutoResetWaitableEvent ------------------------------------------------------

TEST(AutoResetWaitableEventTest, Basic) {
  AutoResetWaitableEvent ev;
  EXPECT_FALSE(ev.IsSignaledForTest());
  ev.Signal();
  EXPECT_TRUE(ev.IsSignaledForTest());
  ev.Wait();
  EXPECT_FALSE(ev.IsSignaledForTest());
  ev.Reset();
  EXPECT_FALSE(ev.IsSignaledForTest());
  ev.Signal();
  EXPECT_TRUE(ev.IsSignaledForTest());
  ev.Reset();
  EXPECT_FALSE(ev.IsSignaledForTest());
  EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::Zero()));
  EXPECT_FALSE(ev.IsSignaledForTest());
  EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1)));
  EXPECT_FALSE(ev.IsSignaledForTest());
  ev.Signal();
  EXPECT_TRUE(ev.IsSignaledForTest());
  EXPECT_FALSE(ev.WaitWithTimeout(TimeDelta::Zero()));
  EXPECT_FALSE(ev.IsSignaledForTest());
  EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1)));
  EXPECT_FALSE(ev.IsSignaledForTest());
  ev.Signal();
  EXPECT_FALSE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1)));
  EXPECT_FALSE(ev.IsSignaledForTest());
}

TEST(AutoResetWaitableEventTest, MultipleWaiters) {
  AutoResetWaitableEvent ev;

  for (size_t i = 0u; i < 5u; i++) {
    std::atomic_uint wake_count(0u);
    std::vector<std::thread> threads;
    for (size_t j = 0u; j < 4u; j++) {
      threads.push_back(std::thread([&ev, &wake_count]() {
        if (rand() % 2 == 0)
          ev.Wait();
        else
          EXPECT_FALSE(ev.WaitWithTimeout(kActionTimeout));
        wake_count.fetch_add(1u);
        // Note: We can't say anything about the signaled state of |ev| here,
        // since the main thread may have already signaled it again.
      }));
    }

    // Unfortunately, we can't really wait for the threads to be waiting, so we
    // just sleep for a bit, and count on them having started and advanced to
    // waiting.
    SleepFor(kTinyTimeout + kTinyTimeout);

    for (size_t j = 0u; j < threads.size(); j++) {
      unsigned old_wake_count = wake_count.load();
      EXPECT_EQ(j, old_wake_count);

      // Each |Signal()| should wake exactly one thread.
      ev.Signal();

      // Poll for |wake_count| to change.
      while (wake_count.load() == old_wake_count)
        SleepFor(kEpsilonTimeout);

      EXPECT_FALSE(ev.IsSignaledForTest());

      // And once it's changed, wait a little longer, to see if any other
      // threads are awoken (they shouldn't be).
      SleepFor(kEpsilonTimeout);

      EXPECT_EQ(old_wake_count + 1u, wake_count.load());

      EXPECT_FALSE(ev.IsSignaledForTest());
    }

    // Having done that, if we signal |ev| now, it should stay signaled.
    ev.Signal();
    SleepFor(kEpsilonTimeout);
    EXPECT_TRUE(ev.IsSignaledForTest());

    for (auto& thread : threads)
      thread.join();

    ev.Reset();
  }
}

// ManualResetWaitableEvent ----------------------------------------------------

TEST(ManualResetWaitableEventTest, Basic) {
  ManualResetWaitableEvent ev;
  EXPECT_FALSE(ev.IsSignaledForTest());
  ev.Signal();
  EXPECT_TRUE(ev.IsSignaledForTest());
  ev.Wait();
  EXPECT_TRUE(ev.IsSignaledForTest());
  ev.Reset();
  EXPECT_FALSE(ev.IsSignaledForTest());
  EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::Zero()));
  EXPECT_FALSE(ev.IsSignaledForTest());
  EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1)));
  EXPECT_FALSE(ev.IsSignaledForTest());
  ev.Signal();
  EXPECT_TRUE(ev.IsSignaledForTest());
  EXPECT_FALSE(ev.WaitWithTimeout(TimeDelta::Zero()));
  EXPECT_TRUE(ev.IsSignaledForTest());
  EXPECT_FALSE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1)));
  EXPECT_TRUE(ev.IsSignaledForTest());
}

TEST(ManualResetWaitableEventTest, SignalMultiple) {
  ManualResetWaitableEvent ev;

  for (size_t i = 0u; i < 10u; i++) {
    for (size_t num_waiters = 1u; num_waiters < 5u; num_waiters++) {
      std::vector<std::thread> threads;
      for (size_t j = 0u; j < num_waiters; j++) {
        threads.push_back(std::thread([&ev]() {
          EpsilonRandomSleep();

          if (rand() % 2 == 0)
            ev.Wait();
          else
            EXPECT_FALSE(ev.WaitWithTimeout(kActionTimeout));
        }));
      }

      EpsilonRandomSleep();

      ev.Signal();

      // The threads will only terminate once they've successfully waited (or
      // timed out).
      for (auto& thread : threads)
        thread.join();

      ev.Reset();
    }
  }
}

}  // namespace
}  // namespace fml
