// 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: fangfei@google.com (Fangfei Zhou)

#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_message_handler.h"
#include "pagespeed/kernel/base/null_message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/sharedmem/shared_circular_buffer.h"
#include "pagespeed/kernel/sharedmem/shared_circular_buffer_test_base.h"
#include "pagespeed/kernel/sharedmem/shared_mem_test_base.h"
#include "pagespeed/kernel/util/platform.h"

namespace net_instaweb {

namespace {
const int kBufferSize = 10;
const char kPrefix[] = "/prefix/";
const char kPostfix[] = "postfix";
const char kString[] = "012";
}  // namespace

SharedCircularBufferTestBase::SharedCircularBufferTestBase(
    SharedMemTestEnv* test_env)
    : test_env_(test_env),
      shmem_runtime_(test_env->CreateSharedMemRuntime()),
      thread_system_(Platform::CreateThreadSystem()),
      handler_(thread_system_->NewMutex()) {
}

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

SharedCircularBuffer* SharedCircularBufferTestBase::ChildInit() {
  SharedCircularBuffer* buff =
      new SharedCircularBuffer(shmem_runtime_.get(), kBufferSize, kPrefix,
                               kPostfix);
  buff->InitSegment(false, &handler_);
  return buff;
}

SharedCircularBuffer* SharedCircularBufferTestBase::ParentInit() {
  SharedCircularBuffer* buff =
      new SharedCircularBuffer(shmem_runtime_.get(), kBufferSize, kPrefix,
                               kPostfix);
  buff->InitSegment(true, &handler_);
  return buff;
}

// Basic initialization/writing/cleanup test
void SharedCircularBufferTestBase::TestCreate() {
  // Create buffer from root Process.
  scoped_ptr<SharedCircularBuffer> buff(ParentInit());
  buff->Write("parent", &null_handler_);
  EXPECT_EQ("parent", buff->ToString(&handler_));
  ASSERT_TRUE(CreateChild(&SharedCircularBufferTestBase::TestCreateChild));
  test_env_->WaitForChildren();
  // After the child process writes to buffer,
  // the content should be updated.
  EXPECT_EQ("parentkid", buff->ToString(&handler_));
  buff->GlobalCleanup(&handler_);
  EXPECT_EQ(0, handler_.SeriousMessages());
}

void SharedCircularBufferTestBase::TestCreateChild() {
  scoped_ptr<SharedCircularBuffer> buff(ChildInit());
  // Child writes to buffer.
  if (!buff->Write("kid", &null_handler_)) {
    test_env_->ChildFailed();
  }
}

void SharedCircularBufferTestBase::TestAdd() {
  // Every child process writes "012" to buffer.
  scoped_ptr<SharedCircularBuffer> buff(ParentInit());
  for (int i = 0; i < 2; ++i) {
    ASSERT_TRUE(CreateChild(&SharedCircularBufferTestBase::TestAddChild));
  }
  test_env_->WaitForChildren();
  EXPECT_EQ("012012", buff->ToString(&handler_));

  buff->GlobalCleanup(&handler_);
  EXPECT_EQ(0, handler_.SeriousMessages());
}

void SharedCircularBufferTestBase::TestAddChild() {
  scoped_ptr<SharedCircularBuffer> buff(ChildInit());
  buff->Write("012", &null_handler_);
}

void SharedCircularBufferTestBase::TestClear() {
  // We can clear things from the child
  scoped_ptr<SharedCircularBuffer> buff(ParentInit());
  // Write a string to buffer.
  buff->Write("012", &null_handler_);
  EXPECT_EQ("012", buff->ToString(&handler_));
  ASSERT_TRUE(CreateChild(&SharedCircularBufferTestBase::TestClearChild));
  test_env_->WaitForChildren();
  // Now the buffer should be empty as the child cleared it.
  EXPECT_EQ("", buff->ToString(&handler_));
  buff->GlobalCleanup(&handler_);
  EXPECT_EQ(0, handler_.SeriousMessages());
}

void SharedCircularBufferTestBase::TestClearChild() {
  scoped_ptr<SharedCircularBuffer> buff(ChildInit());
  buff->InitSegment(false, &handler_);
  buff->Clear();
}

void SharedCircularBufferTestBase::TestChildWrite() {
  scoped_ptr<SharedCircularBuffer> buff(ChildInit());
  buff->InitSegment(false, &handler_);
  buff->Write(message_, &null_handler_);
}

void SharedCircularBufferTestBase::TestChildBuff() {
  scoped_ptr<SharedCircularBuffer> buff(ChildInit());
  buff->InitSegment(false, &handler_);
  // Check if buffer content is correct.
  if (expected_result_ != buff->ToString(&handler_)) {
    test_env_->ChildFailed();
  }
}

// Check various operations, and wraparound, with multiple processes.
void SharedCircularBufferTestBase::TestCircular() {
  scoped_ptr<SharedCircularBuffer> parent(ParentInit());
  parent->Clear();
  // Write in parent process.
  parent->Write("012345", &null_handler_);
  EXPECT_EQ("012345", parent->ToString(&handler_));
  // Write in a child process.
  message_ = "67";
  ASSERT_TRUE(CreateChild(
      &SharedCircularBufferTestBase::TestChildWrite));
  test_env_->WaitForChildren();
  EXPECT_EQ("01234567", parent->ToString(&handler_));
  // Write in parent process.
  parent->Write("89", &null_handler_);
  // Check buffer content in a child process.
  // Buffer size is 10. It should be filled exactly so far.
  expected_result_ = "0123456789";
  ASSERT_TRUE(CreateChild(
      &SharedCircularBufferTestBase::TestChildBuff));
  test_env_->WaitForChildren();
  // Lose the first char.
  parent->Write("a", &null_handler_);
  EXPECT_EQ("123456789a", parent->ToString(&handler_));
  // Write a message with length larger than buffer.
  parent->Write("bcdefghijkl", &null_handler_);
  EXPECT_EQ("cdefghijkl", parent->ToString(&handler_));
  parent->GlobalCleanup(&handler_);
}

}  // namespace net_instaweb
