// Copyright 2011 Google Inc.
//
// 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.
//
// Author: morlovich@google.com (Maksim Orlovich)

#include "pagespeed/kernel/sharedmem/shared_mem_lock_manager_test_base.h"

#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/md5_hasher.h"
#include "pagespeed/kernel/base/mock_message_handler.h"
#include "pagespeed/kernel/base/mock_timer.h"
#include "pagespeed/kernel/base/named_lock_manager.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/sharedmem/shared_mem_lock_manager.h"
#include "pagespeed/kernel/sharedmem/shared_mem_test_base.h"
#include "pagespeed/kernel/thread/scheduler_based_abstract_lock.h"
#include "pagespeed/kernel/util/platform.h"

namespace net_instaweb {

namespace {

const char kPath[] = "shm_locks";
const char kLockA[] = "lock_a";
const char kLockB[] = "lock_b";

}  // namespace

SharedMemLockManagerTestBase::SharedMemLockManagerTestBase(
    SharedMemTestEnv* test_env)
    : test_env_(test_env),
      shmem_runtime_(test_env->CreateSharedMemRuntime()),
      thread_system_(Platform::CreateThreadSystem()),
      timer_(thread_system_->NewMutex(), 0),
      handler_(thread_system_->NewMutex()),
      scheduler_(thread_system_.get(), &timer_) {
}

void SharedMemLockManagerTestBase::SetUp() {
  root_lock_manager_.reset(CreateLockManager());
  EXPECT_TRUE(root_lock_manager_->Initialize());
}

void SharedMemLockManagerTestBase::TearDown() {
  SharedMemLockManager::GlobalCleanup(shmem_runtime_.get(), kPath, &handler_);
}

bool SharedMemLockManagerTestBase::CreateChild(TestMethod method) {
  Function* callback =
      new MemberFunction0<SharedMemLockManagerTestBase>(method, this);
  return test_env_->CreateChild(callback);
}

SharedMemLockManager* SharedMemLockManagerTestBase::CreateLockManager() {
  return new SharedMemLockManager(shmem_runtime_.get(), kPath, &scheduler_,
                                  &hasher_, &handler_);
}

SharedMemLockManager* SharedMemLockManagerTestBase::AttachDefault() {
  SharedMemLockManager* lock_man = CreateLockManager();
  if (!lock_man->Attach()) {
    delete lock_man;
    lock_man = NULL;
  }
  return lock_man;
}

void SharedMemLockManagerTestBase::TestBasic() {
  scoped_ptr<SharedMemLockManager> lock_manager(AttachDefault());
  ASSERT_TRUE(lock_manager.get() != NULL);
  scoped_ptr<SchedulerBasedAbstractLock> lock_a(
      lock_manager->CreateNamedLock(kLockA));
  scoped_ptr<SchedulerBasedAbstractLock> lock_b(
      lock_manager->CreateNamedLock(kLockB));

  ASSERT_TRUE(lock_a.get() != NULL);
  ASSERT_TRUE(lock_b.get() != NULL);

  EXPECT_FALSE(lock_a->Held());
  EXPECT_FALSE(lock_b->Held());

  // Can lock exactly once...
  EXPECT_TRUE(lock_a->TryLock());
  EXPECT_TRUE(lock_b->TryLock());
  EXPECT_TRUE(lock_a->Held());
  EXPECT_TRUE(lock_b->Held());
  EXPECT_FALSE(lock_a->TryLock());
  EXPECT_FALSE(lock_b->TryLock());
  EXPECT_TRUE(lock_a->Held());
  EXPECT_TRUE(lock_b->Held());

  // Unlocking lets one lock again
  lock_b->Unlock();
  EXPECT_FALSE(lock_b->Held());
  EXPECT_FALSE(lock_a->TryLock());
  EXPECT_TRUE(lock_b->TryLock());

  // Now unlock A, and let kid confirm the state
  lock_a->Unlock();
  EXPECT_FALSE(lock_a->Held());
  CreateChild(&SharedMemLockManagerTestBase::TestBasicChild);
  test_env_->WaitForChildren();

  // A should still be unlocked since child's locks should get cleaned up
  // by ~NamedLock.. but not lock b, which we were holding
  EXPECT_TRUE(lock_a->TryLock());
  EXPECT_FALSE(lock_b->TryLock());
}

void SharedMemLockManagerTestBase::TestBasicChild() {
  scoped_ptr<SharedMemLockManager> lock_manager(AttachDefault());
  scoped_ptr<SchedulerBasedAbstractLock> lock_a(
      lock_manager->CreateNamedLock(kLockA));
  scoped_ptr<SchedulerBasedAbstractLock> lock_b(
      lock_manager->CreateNamedLock(kLockB));

  if (lock_a.get() == NULL || lock_b.get() == NULL) {
    test_env_->ChildFailed();
  }

  // A should lock fine
  if (!lock_a->TryLock() || !lock_a->Held()) {
    test_env_->ChildFailed();
  }

  // B shouldn't lock fine.
  if (lock_b->TryLock() || lock_b->Held()) {
    test_env_->ChildFailed();
  }

  // Note: here we should unlock a due to destruction of A.
}

void SharedMemLockManagerTestBase::TestDestructorUnlock() {
  // Standalone test for destructors cleaning up. It is covered by the
  // above, but this does it single-threaded, without weird things.
  scoped_ptr<SharedMemLockManager> lock_manager(AttachDefault());
  ASSERT_TRUE(lock_manager.get() != NULL);

  {
    scoped_ptr<SchedulerBasedAbstractLock> lock_a(
        lock_manager->CreateNamedLock(kLockA));
    EXPECT_TRUE(lock_a->TryLock());
  }

  {
    scoped_ptr<SchedulerBasedAbstractLock> lock_a(
        lock_manager->CreateNamedLock(kLockA));
    EXPECT_TRUE(lock_a->TryLock());
  }
}

void SharedMemLockManagerTestBase::TestSteal() {
  scoped_ptr<SharedMemLockManager> lock_manager(AttachDefault());
  ASSERT_TRUE(lock_manager.get() != NULL);
  scoped_ptr<SchedulerBasedAbstractLock> lock_a(
      lock_manager->CreateNamedLock(kLockA));
  EXPECT_TRUE(lock_a->TryLock());
  EXPECT_TRUE(lock_a->Held());
  CreateChild(&SharedMemLockManagerTestBase::TestStealChild);
  test_env_->WaitForChildren();
}

void SharedMemLockManagerTestBase::TestStealChild() {
  const int kStealTimeMs = 1000;

  scoped_ptr<SharedMemLockManager> lock_manager(AttachDefault());
  ASSERT_TRUE(lock_manager.get() != NULL);
  scoped_ptr<SchedulerBasedAbstractLock> lock_a(
      lock_manager->CreateNamedLock(kLockA));

  // First, attempting to steal should fail, as 'time' hasn't moved yet.
  if (lock_a->TryLockStealOld(kStealTimeMs) || lock_a->Held()) {
    test_env_->ChildFailed();
  }

  timer_.AdvanceMs(kStealTimeMs + 1);

  // Now it should succeed.
  if (!lock_a->TryLockStealOld(kStealTimeMs) || !lock_a->Held()) {
    test_env_->ChildFailed();
  }
}

}  // namespace net_instaweb
