// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// 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 "starboard/condition_variable.h"
#include "starboard/mutex.h"
#include "starboard/nplb/thread_helpers.h"
#include "starboard/thread.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace starboard {
namespace nplb {
namespace {

void DoSunnyDay(TakeThenSignalContext* context, bool check_timeout) {
  SbThread thread =
      SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, true, NULL,
                     TakeThenSignalEntryPoint, context);

  const SbTime kDelay = kSbTimeMillisecond * 10;
  // Allow millisecond-level precision.
  const SbTime kPrecision = kSbTimeMillisecond;

  // We know the thread hasn't signaled the condition variable yet, and won't
  // unless we tell it, so it should wait at least the whole delay time.
  if (check_timeout) {
    EXPECT_TRUE(SbMutexIsSuccess(SbMutexAcquire(&context->mutex)));
    SbTimeMonotonic start = SbTimeGetMonotonicNow();
    SbConditionVariableResult result = SbConditionVariableWaitTimed(
        &context->condition, &context->mutex, kDelay);
    EXPECT_EQ(kSbConditionVariableTimedOut, result);
    SbTimeMonotonic elapsed = SbTimeGetMonotonicNow() - start;
    EXPECT_LE(kDelay, elapsed + kPrecision);
    EXPECT_GT(kDelay * 2, elapsed - kPrecision);
    EXPECT_TRUE(SbMutexRelease(&context->mutex));
  }

  {
    EXPECT_TRUE(SbMutexIsSuccess(SbMutexAcquire(&context->mutex)));

    // Tell the thread to signal the condvar, which will cause it to attempt to
    // acquire the mutex we are holding.
    context->do_signal.Put();

    SbTimeMonotonic start = SbTimeGetMonotonicNow();

    // We release the mutex when we wait, allowing the thread to actually do the
    // signaling, and ensuring we are waiting before it signals.
    SbConditionVariableResult result = SbConditionVariableWaitTimed(
        &context->condition, &context->mutex, kDelay);
    EXPECT_EQ(kSbConditionVariableSignaled, result);

    // We should have waited only a very small amount of time.
    EXPECT_GT(kDelay, SbTimeGetMonotonicNow() - start);

    EXPECT_TRUE(SbMutexRelease(&context->mutex));
  }

  // Now we wait for the thread to exit.
  EXPECT_TRUE(SbThreadJoin(thread, NULL));
  EXPECT_TRUE(SbConditionVariableDestroy(&context->condition));
  EXPECT_TRUE(SbMutexDestroy(&context->mutex));
}

TEST(SbConditionVariableWaitTimedTest, SunnyDay) {
  TakeThenSignalContext context;
  context.delay_after_signal = 0;
  EXPECT_TRUE(SbMutexCreate(&context.mutex));
  EXPECT_TRUE(SbConditionVariableCreate(&context.condition, &context.mutex));
  DoSunnyDay(&context, true);
}

TEST(SbConditionVariableWaitTimedTest, SunnyDayAutoInit) {
  {
    TakeThenSignalContext context = {TestSemaphore(0), SB_MUTEX_INITIALIZER,
                                     SB_CONDITION_VARIABLE_INITIALIZER, 0};
    DoSunnyDay(&context, true);
  }

  // Without the initial timeout test, the two threads will be racing to
  // auto-init the mutex and condition variable. So we run several trials in
  // this mode, hoping to have the auto-initting contend in various ways.
  const int kTrials = 64;
  for (int i = 0; i < kTrials; ++i) {
    TakeThenSignalContext context = {TestSemaphore(0), SB_MUTEX_INITIALIZER,
                                     SB_CONDITION_VARIABLE_INITIALIZER, 0};
    DoSunnyDay(&context, false);
  }
}

TEST(SbConditionVariableWaitTimedTest, SunnyDayNearMaxTime) {
  const SbTime kOtherDelay = kSbTimeMillisecond * 10;
  TakeThenSignalContext context = {TestSemaphore(0), SB_MUTEX_INITIALIZER,
                                   SB_CONDITION_VARIABLE_INITIALIZER,
                                   kOtherDelay};
  EXPECT_TRUE(SbMutexCreate(&context.mutex));
  EXPECT_TRUE(SbConditionVariableCreate(&context.condition, &context.mutex));
  SbThread thread =
      SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, true, NULL,
                     TakeThenSignalEntryPoint, &context);

  // Try to wait until the end of time.
  const SbTime kDelay = kSbTimeMax;

  EXPECT_TRUE(SbMutexIsSuccess(SbMutexAcquire(&context.mutex)));

  // Tell the thread to signal the condvar, which will cause it to attempt to
  // acquire the mutex we are holding, after it waits for delay_after_signal.
  context.do_signal.Put();

  SbTimeMonotonic start = SbTimeGetMonotonicNow();

  // We release the mutex when we wait, allowing the thread to actually do the
  // signaling, and ensuring we are waiting before it signals.
  SbConditionVariableResult result =
      SbConditionVariableWaitTimed(&context.condition, &context.mutex, kDelay);
  EXPECT_EQ(kSbConditionVariableSignaled, result);

  // We should have waited at least the delay_after_signal amount, but not the
  // full delay.
  // Add some padding to tolerate slightly imprecise sleeps.
  EXPECT_LT(context.delay_after_signal, SbTimeGetMonotonicNow() - start +
                                            (context.delay_after_signal / 10));
  EXPECT_GT(kDelay, SbTimeGetMonotonicNow() - start);

  EXPECT_TRUE(SbMutexRelease(&context.mutex));

  // Now we wait for the thread to exit.
  EXPECT_TRUE(SbThreadJoin(thread, NULL));
  EXPECT_TRUE(SbConditionVariableDestroy(&context.condition));
  EXPECT_TRUE(SbMutexDestroy(&context.mutex));
}

TEST(SbConditionVariableWaitTimedTest, RainyDayNull) {
  SbConditionVariableResult result =
      SbConditionVariableWaitTimed(NULL, NULL, 0);
  EXPECT_EQ(kSbConditionVariableFailed, result);

  SbMutex mutex = SB_MUTEX_INITIALIZER;
  result = SbConditionVariableWaitTimed(NULL, &mutex, 0);
  EXPECT_EQ(kSbConditionVariableFailed, result);

  SbConditionVariable condition = SB_CONDITION_VARIABLE_INITIALIZER;
  result = SbConditionVariableWaitTimed(&condition, NULL, 0);
  EXPECT_EQ(kSbConditionVariableFailed, result);
}

}  // namespace
}  // namespace nplb
}  // namespace starboard
