/*
 * Copyright (C) 2014 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 "monitor.h"

#include <memory>
#include <string>

#include "base/atomic.h"
#include "barrier.h"
#include "base/time_utils.h"
#include "class_linker-inl.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
#include "mirror/class-inl.h"
#include "mirror/string-inl.h"  // Strings are easiest to allocate
#include "object_lock.h"
#include "scoped_thread_state_change-inl.h"
#include "thread_pool.h"

namespace art {

class MonitorTest : public CommonRuntimeTest {
 protected:
  void SetUpRuntimeOptions(RuntimeOptions *options) override {
    // Use a smaller heap
    SetUpRuntimeOptionsForFillHeap(options);

    options->push_back(std::make_pair("-Xint", nullptr));
  }
 public:
  std::unique_ptr<Monitor> monitor_;
  Handle<mirror::String> object_;
  Handle<mirror::String> second_object_;
  Handle<mirror::String> watchdog_object_;
  // One exception test is for waiting on another Thread's lock. This is used to race-free &
  // loop-free pass
  Thread* thread_;
  std::unique_ptr<Barrier> barrier_;
  std::unique_ptr<Barrier> complete_barrier_;
  bool completed_;
};

// Check that an exception can be thrown correctly.
// This test is potentially racy, but the timeout is long enough that it should work.

class CreateTask : public Task {
 public:
  CreateTask(MonitorTest* monitor_test, uint64_t initial_sleep, int64_t millis, bool expected) :
      monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis),
      expected_(expected) {}

  void Run(Thread* self) override {
    {
      ScopedObjectAccess soa(self);

      monitor_test_->thread_ = self;        // Pass the Thread.
      monitor_test_->object_.Get()->MonitorEnter(self);  // Lock the object. This should transition
      LockWord lock_after = monitor_test_->object_.Get()->GetLockWord(false);  // it to thinLocked.
      LockWord::LockState new_state = lock_after.GetState();

      // Cannot use ASSERT only, as analysis thinks we'll keep holding the mutex.
      if (LockWord::LockState::kThinLocked != new_state) {
        monitor_test_->object_.Get()->MonitorExit(self);         // To appease analysis.
        ASSERT_EQ(LockWord::LockState::kThinLocked, new_state);  // To fail the test.
        return;
      }

      // Force a fat lock by running identity hashcode to fill up lock word.
      monitor_test_->object_.Get()->IdentityHashCode();
      LockWord lock_after2 = monitor_test_->object_.Get()->GetLockWord(false);
      LockWord::LockState new_state2 = lock_after2.GetState();

      // Cannot use ASSERT only, as analysis thinks we'll keep holding the mutex.
      if (LockWord::LockState::kFatLocked != new_state2) {
        monitor_test_->object_.Get()->MonitorExit(self);         // To appease analysis.
        ASSERT_EQ(LockWord::LockState::kFatLocked, new_state2);  // To fail the test.
        return;
      }
    }  // Need to drop the mutator lock to use the barrier.

    monitor_test_->barrier_->Wait(self);           // Let the other thread know we're done.

    {
      ScopedObjectAccess soa(self);

      // Give the other task a chance to do its thing.
      NanoSleep(initial_sleep_ * 1000 * 1000);

      // Now try to Wait on the Monitor.
      Monitor::Wait(self, monitor_test_->object_.Get(), millis_, 0, true,
                    ThreadState::kTimedWaiting);

      // Check the exception status against what we expect.
      EXPECT_EQ(expected_, self->IsExceptionPending());
      if (expected_) {
        self->ClearException();
      }
    }

    monitor_test_->complete_barrier_->Wait(self);  // Wait for test completion.

    {
      ScopedObjectAccess soa(self);
      monitor_test_->object_.Get()->MonitorExit(self);  // Release the object. Appeases analysis.
    }
  }

  void Finalize() override {
    delete this;
  }

 private:
  MonitorTest* monitor_test_;
  uint64_t initial_sleep_;
  int64_t millis_;
  bool expected_;
};


class UseTask : public Task {
 public:
  UseTask(MonitorTest* monitor_test, uint64_t initial_sleep, int64_t millis, bool expected) :
      monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis),
      expected_(expected) {}

  void Run(Thread* self) override {
    monitor_test_->barrier_->Wait(self);  // Wait for the other thread to set up the monitor.

    {
      ScopedObjectAccess soa(self);

      // Give the other task a chance to do its thing.
      NanoSleep(initial_sleep_ * 1000 * 1000);

      Monitor::Wait(self, monitor_test_->object_.Get(), millis_, 0, true,
                    ThreadState::kTimedWaiting);

      // Check the exception status against what we expect.
      EXPECT_EQ(expected_, self->IsExceptionPending());
      if (expected_) {
        self->ClearException();
      }
    }

    monitor_test_->complete_barrier_->Wait(self);  // Wait for test completion.
  }

  void Finalize() override {
    delete this;
  }

 private:
  MonitorTest* monitor_test_;
  uint64_t initial_sleep_;
  int64_t millis_;
  bool expected_;
};

class InterruptTask : public Task {
 public:
  InterruptTask(MonitorTest* monitor_test, uint64_t initial_sleep, uint64_t millis) :
      monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis) {}

  void Run(Thread* self) override {
    monitor_test_->barrier_->Wait(self);  // Wait for the other thread to set up the monitor.

    {
      ScopedObjectAccess soa(self);

      // Give the other task a chance to do its thing.
      NanoSleep(initial_sleep_ * 1000 * 1000);

      // Interrupt the other thread.
      monitor_test_->thread_->Interrupt(self);

      // Give it some more time to get to the exception code.
      NanoSleep(millis_ * 1000 * 1000);

      // Now try to Wait.
      Monitor::Wait(self, monitor_test_->object_.Get(), 10, 0, true,
                    ThreadState::kTimedWaiting);

      // No check here, as depending on scheduling we may or may not fail.
      if (self->IsExceptionPending()) {
        self->ClearException();
      }
    }

    monitor_test_->complete_barrier_->Wait(self);  // Wait for test completion.
  }

  void Finalize() override {
    delete this;
  }

 private:
  MonitorTest* monitor_test_;
  uint64_t initial_sleep_;
  uint64_t millis_;
};

class WatchdogTask : public Task {
 public:
  explicit WatchdogTask(MonitorTest* monitor_test) : monitor_test_(monitor_test) {}

  void Run(Thread* self) override {
    ScopedObjectAccess soa(self);

    monitor_test_->watchdog_object_.Get()->MonitorEnter(self);        // Lock the object.

    monitor_test_->watchdog_object_.Get()->Wait(self, 30 * 1000, 0);  // Wait for 30s, or being
                                                                      // woken up.

    monitor_test_->watchdog_object_.Get()->MonitorExit(self);         // Release the lock.

    if (!monitor_test_->completed_) {
      LOG(FATAL) << "Watchdog timeout!";
    }
  }

  void Finalize() override {
    delete this;
  }

 private:
  MonitorTest* monitor_test_;
};

static void CommonWaitSetup(MonitorTest* test, ClassLinker* class_linker, uint64_t create_sleep,
                            int64_t c_millis, bool c_expected, bool interrupt, uint64_t use_sleep,
                            int64_t u_millis, bool u_expected, const char* pool_name) {
  Thread* const self = Thread::Current();
  ScopedObjectAccess soa(self);
  // First create the object we lock. String is easiest.
  StackHandleScope<3> hs(soa.Self());
  test->object_ = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "hello, world!"));
  test->watchdog_object_ = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self,
                                                                              "hello, world!"));

  // Create the barrier used to synchronize.
  test->barrier_ = std::make_unique<Barrier>(2);
  test->complete_barrier_ = std::make_unique<Barrier>(3);
  test->completed_ = false;

  // Our job: Fill the heap, then try Wait.
  {
    VariableSizedHandleScope vhs(soa.Self());
    test->FillHeap(soa.Self(), class_linker, &vhs);

    // Now release everything.
  }

  // Need to drop the mutator lock to allow barriers.
  ScopedThreadSuspension sts(soa.Self(), kNative);
  ThreadPool thread_pool(pool_name, 3);
  thread_pool.AddTask(self, new CreateTask(test, create_sleep, c_millis, c_expected));
  if (interrupt) {
    thread_pool.AddTask(self, new InterruptTask(test, use_sleep, static_cast<uint64_t>(u_millis)));
  } else {
    thread_pool.AddTask(self, new UseTask(test, use_sleep, u_millis, u_expected));
  }
  thread_pool.AddTask(self, new WatchdogTask(test));
  thread_pool.StartWorkers(self);

  // Wait on completion barrier.
  test->complete_barrier_->Wait(self);
  test->completed_ = true;

  // Wake the watchdog.
  {
    ScopedObjectAccess soa2(self);
    test->watchdog_object_.Get()->MonitorEnter(self);     // Lock the object.
    test->watchdog_object_.Get()->NotifyAll(self);        // Wake up waiting parties.
    test->watchdog_object_.Get()->MonitorExit(self);      // Release the lock.
  }

  thread_pool.StopWorkers(self);
}


// First test: throwing an exception when trying to wait in Monitor with another thread.
TEST_F(MonitorTest, CheckExceptionsWait1) {
  // Make the CreateTask wait 10ms, the UseTask wait 10ms.
  // => The use task will get the lock first and get to self == owner check.
  // This will lead to OOM and monitor error messages in the log.
  ScopedLogSeverity sls(LogSeverity::FATAL);
  CommonWaitSetup(this, class_linker_, 10, 50, false, false, 2, 50, true,
                  "Monitor test thread pool 1");
}

// Second test: throwing an exception for invalid wait time.
TEST_F(MonitorTest, CheckExceptionsWait2) {
  // Make the CreateTask wait 0ms, the UseTask wait 10ms.
  // => The create task will get the lock first and get to ms >= 0
  // This will lead to OOM and monitor error messages in the log.
  ScopedLogSeverity sls(LogSeverity::FATAL);
  CommonWaitSetup(this, class_linker_, 0, -1, true, false, 10, 50, true,
                  "Monitor test thread pool 2");
}

// Third test: throwing an interrupted-exception.
TEST_F(MonitorTest, CheckExceptionsWait3) {
  // Make the CreateTask wait 0ms, then Wait for a long time. Make the InterruptTask wait 10ms,
  // after which it will interrupt the create task and then wait another 10ms.
  // => The create task will get to the interrupted-exception throw.
  // This will lead to OOM and monitor error messages in the log.
  ScopedLogSeverity sls(LogSeverity::FATAL);
  CommonWaitSetup(this, class_linker_, 0, 500, true, true, 10, 50, true,
                  "Monitor test thread pool 3");
}

class TryLockTask : public Task {
 public:
  explicit TryLockTask(Handle<mirror::Object> obj) : obj_(obj) {}

  void Run(Thread* self) override {
    ScopedObjectAccess soa(self);
    // Lock is held by other thread, try lock should fail.
    ObjectTryLock<mirror::Object> lock(self, obj_);
    EXPECT_FALSE(lock.Acquired());
  }

  void Finalize() override {
    delete this;
  }

 private:
  Handle<mirror::Object> obj_;
};

// Test trylock in deadlock scenarios.
TEST_F(MonitorTest, TestTryLock) {
  ScopedLogSeverity sls(LogSeverity::FATAL);

  Thread* const self = Thread::Current();
  ThreadPool thread_pool("the pool", 2);
  ScopedObjectAccess soa(self);
  StackHandleScope<1> hs(self);
  Handle<mirror::Object> obj1(
      hs.NewHandle<mirror::Object>(mirror::String::AllocFromModifiedUtf8(self, "hello, world!")));
  {
    ObjectLock<mirror::Object> lock1(self, obj1);
    {
      ObjectTryLock<mirror::Object> trylock(self, obj1);
      EXPECT_TRUE(trylock.Acquired());
    }
    // Test failure case.
    thread_pool.AddTask(self, new TryLockTask(obj1));
    thread_pool.StartWorkers(self);
    ScopedThreadSuspension sts(self, kSuspended);
    thread_pool.Wait(Thread::Current(), /*do_work=*/false, /*may_hold_locks=*/false);
  }
  // Test that the trylock actually locks the object.
  {
    ObjectTryLock<mirror::Object> trylock(self, obj1);
    EXPECT_TRUE(trylock.Acquired());
    obj1->Notify(self);
    // Since we hold the lock there should be no monitor state exeception.
    self->AssertNoPendingException();
  }
  thread_pool.StopWorkers(self);
}


}  // namespace art
