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

// Broadcast is Sunny Day tested in most of the other SbConditionVariable tests.

#include "starboard/nplb/thread_helpers.h"
#include "starboard/once.h"
#include "starboard/thread.h"
#include "starboard/thread_types.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace starboard {
namespace nplb {
namespace {

int s_global_value;

void IncrementGlobalValue() {
  ++s_global_value;
}

TEST(SbOnceTest, SunnyDaySingleInit) {
  SbOnceControl once_control = SB_ONCE_INITIALIZER;

  s_global_value = 0;
  EXPECT_TRUE(SbOnce(&once_control, &IncrementGlobalValue));

  EXPECT_EQ(1, s_global_value);
}

TEST(SbOnceTest, SunnyDayMultipleInit) {
  SbOnceControl once_control = SB_ONCE_INITIALIZER;

  s_global_value = 0;
  EXPECT_TRUE(SbOnce(&once_control, &IncrementGlobalValue));
  EXPECT_EQ(1, s_global_value);

  s_global_value = 0;
  EXPECT_TRUE(SbOnce(&once_control, &IncrementGlobalValue));
  EXPECT_EQ(0, s_global_value);

  s_global_value = 0;
  EXPECT_TRUE(SbOnce(&once_control, &IncrementGlobalValue));
  EXPECT_EQ(0, s_global_value);
}

struct RunSbOnceContext {
  RunSbOnceContext() : once_control(SB_ONCE_INITIALIZER) {
    SbMutexCreate(&mutex);
    SbConditionVariableCreate(&condition, &mutex);
  }
  ~RunSbOnceContext() {
    SbConditionVariableDestroy(&condition);
    SbMutexDestroy(&mutex);
  }

  Semaphore semaphore;
  SbMutex mutex;
  SbConditionVariable condition;

  SbOnceControl once_control;
};

void* RunSbOnceEntryPoint(void* context) {
  RunSbOnceContext* run_sbonce_context =
      reinterpret_cast<RunSbOnceContext*>(context);

  {
    SbMutexAcquire(&run_sbonce_context->mutex);
    run_sbonce_context->semaphore.Put();
    SbConditionVariableWait(&run_sbonce_context->condition,
                            &run_sbonce_context->mutex);
    SbMutexRelease(&run_sbonce_context->mutex);
  }

  SbThreadYield();
  static const int kIterationCount = 3;
  for (int i = 0; i < kIterationCount; ++i) {
    SbOnce(&run_sbonce_context->once_control, &IncrementGlobalValue);
  }

  return NULL;
}

// Here we spawn many threads each of which will call SbOnce multiple times
// using a shared SbOnceControl object.  We then test that the initialization
// routine got called exactly one time.
TEST(SbOnceTest, SunnyDayMultipleThreadsInit) {
  const int kMany = SB_MAX_THREADS;
  SbThread threads[kMany];

  const int kIterationCount = 10;
  for (int i = 0; i < kIterationCount; ++i) {
    SbOnceControl once_control = SB_ONCE_INITIALIZER;
    RunSbOnceContext context;

    s_global_value = 0;
    for (int j = 0; j < kMany; ++j) {
      threads[j] =
          SbThreadCreate(0, kSbThreadNoPriority, kSbThreadNoAffinity, true,
                         kThreadName, RunSbOnceEntryPoint, &context);
    }

    // Wait for all threads to finish initializing and become ready, then
    // broadcast the signal to begin.  We do this to increase the chances that
    // threads will call SbOnce() at the same time as each other.
    for (int j = 0; j < kMany; ++j) {
      context.semaphore.Take();
    }
    {
      SbMutexAcquire(&context.mutex);
      SbConditionVariableBroadcast(&context.condition);
      SbMutexRelease(&context.mutex);
    }

    // Signal threads to beginWait for all threads to complete.
    for (int i = 0; i < kMany; ++i) {
      void* result;
      SbThreadJoin(threads[i], &result);
    }

    EXPECT_EQ(1, s_global_value);
  }
}

TEST(SbOnceTest, RainyDayBadOnceControl) {
  s_global_value = 0;
  EXPECT_FALSE(SbOnce(NULL, &IncrementGlobalValue));

  EXPECT_EQ(0, s_global_value);
}

TEST(SbOnceTest, RainyDayBadInitRoutine) {
  SbOnceControl once_control = SB_ONCE_INITIALIZER;

  s_global_value = 0;
  EXPECT_FALSE(SbOnce(&once_control, NULL));

  EXPECT_EQ(0, s_global_value);
}

SB_ONCE_INITIALIZE_FUNCTION(int, GetIntSingleton);
TEST(SbOnceTest, InitializeOnceMacroFunction) {
  int* int_singelton = GetIntSingleton();
  ASSERT_TRUE(int_singelton);
  EXPECT_EQ(0, *int_singelton)
      << "Singleton Macro does not default initialize.";
}

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