// 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_cache_data_test_base.h"

#include <cstddef>                     // for size_t
#include <set>

#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/thread_annotations.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/util/platform.h"

namespace net_instaweb {

using SharedMemCacheData::BlockNum;
using SharedMemCacheData::BlockVector;
using SharedMemCacheData::CacheEntry;
using SharedMemCacheData::EntryNum;
using SharedMemCacheData::Sector;
using SharedMemCacheData::kInvalidEntry;

namespace {

const char kSegment[] = "cache";
const size_t kExtra = 8192;  // we only allocate one segment,
                             // so we prepend these many bytes to make
                             // sure the offset is actually honored.

const int kBlocks = 20;
const int kEntries = 25;

}  // namespace

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

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

void SharedMemCacheDataTestBase::SanityCheckBlockVector(
    const SharedMemCacheData::BlockVector& blocks, int min_valid,
    int max_valid) {
  // Make sure all numbers are in range, unique.
  std::set<BlockNum> distinct_count;
  for (size_t c = 0; c < blocks.size(); ++c) {
    EXPECT_LE(min_valid, blocks[c]);
    EXPECT_LE(blocks[c], max_valid);
    distinct_count.insert(c);
  }
  EXPECT_EQ(blocks.size(), distinct_count.size());
}

void SharedMemCacheDataTestBase::ExtractAndSanityCheckLRU(
    Sector<SharedMemCacheDataTestBase::kBlockSize>* sector,
    std::vector<EntryNum>* out_lru) {

  // collect list starting form oldest.
  std::vector<EntryNum> backwards_lru;
  for (EntryNum e = sector->OldestEntryNum(); e != kInvalidEntry;
       e = sector->EntryAt(e)->lru_prev) {
    backwards_lru.push_back(e);
  }

  size_t size = backwards_lru.size();

  // Flip it to be from newest.
  out_lru->clear();
  for (size_t p = 0; p < size; ++p) {
    size_t backwards_pos = size - 1 - p;
    out_lru->push_back(backwards_lru[backwards_pos]);
  }

  // Sanity check it.
  for (size_t p = 0; p < size; ++p) {
    CacheEntry* entry = sector->EntryAt(out_lru->at(p));

    if (p == 0) {
      EXPECT_EQ(kInvalidEntry, entry->lru_prev);
    } else {
      EXPECT_EQ(out_lru->at(p - 1), entry->lru_prev);
    }

    if (p == (size - 1)) {
      EXPECT_EQ(kInvalidEntry, entry->lru_next);
    } else {
      EXPECT_EQ(out_lru->at(p + 1), entry->lru_next);
    }
  }

  EXPECT_EQ(out_lru->size(),
            static_cast<size_t>(sector->sector_stats()->used_entries));
}

void SharedMemCacheDataTestBase::TestFreeList() NO_THREAD_SAFETY_ANALYSIS {
  AbstractSharedMemSegment* seg_raw_ptr = NULL;
  Sector<kBlockSize>* sector_raw_ptr = NULL;
  ASSERT_TRUE(ParentInit(&seg_raw_ptr, &sector_raw_ptr));
  scoped_ptr<AbstractSharedMemSegment> seg(seg_raw_ptr);
  scoped_ptr<Sector<kBlockSize> > sector(sector_raw_ptr);

  // Ask for more than the sector has; get exactly as many as it has.
  EXPECT_EQ(0, sector->sector_stats()->used_blocks);
  BlockVector blocks;
  EXPECT_EQ(kBlocks, sector->AllocBlocksFromFreeList(kBlocks * 2, &blocks));
  EXPECT_EQ(static_cast<size_t>(kBlocks), blocks.size());
  SanityCheckBlockVector(blocks, 0, kBlocks - 1);
  EXPECT_EQ(kBlocks, sector->sector_stats()->used_blocks);

  // Now asking to allocate more should not return anything.
  EXPECT_EQ(0, sector->AllocBlocksFromFreeList(5, &blocks));
  // Should not damage previous blocks set, however.
  EXPECT_EQ(static_cast<size_t>(kBlocks), blocks.size());
  EXPECT_EQ(kBlocks, sector->sector_stats()->used_blocks);

  // Now free blocks 0, 1, 2
  blocks.clear();
  blocks.push_back(0);
  blocks.push_back(1);
  blocks.push_back(2);
  sector->ReturnBlocksToFreeList(blocks);
  EXPECT_EQ(kBlocks - 3, sector->sector_stats()->used_blocks);

  // Now allocate 2 blocks then 1 blocks. Should succeed, and return 3
  // blocks of valid range.
  blocks.clear();
  EXPECT_EQ(2, sector->AllocBlocksFromFreeList(2, &blocks));
  EXPECT_EQ(static_cast<size_t>(2), blocks.size());
  EXPECT_EQ(kBlocks - 1, sector->sector_stats()->used_blocks);
  SanityCheckBlockVector(blocks, 0, 2);
  EXPECT_EQ(1, sector->AllocBlocksFromFreeList(1, &blocks));
  EXPECT_EQ(static_cast<size_t>(3), blocks.size());
  SanityCheckBlockVector(blocks, 0, 2);
  EXPECT_EQ(kBlocks, sector->sector_stats()->used_blocks);

  // Run the kid, which will free things other than 0, 1, 2.
  CreateChild(&SharedMemCacheDataTestBase::TestFreeListChild);
  test_env_->WaitForChildren();
  EXPECT_EQ(3, sector->sector_stats()->used_blocks);

  // Now try allocating this rest, appending it into blocks.
  EXPECT_EQ(kBlocks - 3, sector->AllocBlocksFromFreeList(kBlocks - 3, &blocks));
  EXPECT_EQ(static_cast<size_t>(kBlocks), blocks.size());
  SanityCheckBlockVector(blocks, 0, kBlocks - 1);
  EXPECT_EQ(kBlocks, sector->sector_stats()->used_blocks);

  ParentCleanup();
}

void SharedMemCacheDataTestBase::TestFreeListChild() NO_THREAD_SAFETY_ANALYSIS {
  AbstractSharedMemSegment* seg_raw_ptr = NULL;
  Sector<kBlockSize>* sector_raw_ptr = NULL;
  if (!ChildInit(&seg_raw_ptr, &sector_raw_ptr)) {
    test_env_->ChildFailed();
  }

  scoped_ptr<AbstractSharedMemSegment> seg(seg_raw_ptr);
  scoped_ptr<Sector<kBlockSize> > sector(sector_raw_ptr);

  // Free blocks [3, kBlocks)
  BlockVector to_free;
  for (BlockNum b = 3; b < kBlocks; ++b) {
    to_free.push_back(b);
  }

  sector->ReturnBlocksToFreeList(to_free);
}

void SharedMemCacheDataTestBase::TestLRU() {
  AbstractSharedMemSegment* seg_raw_ptr = NULL;
  Sector<kBlockSize>* sector_raw_ptr = NULL;
  ASSERT_TRUE(ParentInit(&seg_raw_ptr, &sector_raw_ptr));
  scoped_ptr<AbstractSharedMemSegment> seg(seg_raw_ptr);
  scoped_ptr<Sector<kBlockSize> > sector(sector_raw_ptr);

  // Initially, nothing should be in the LRU.
  std::vector<EntryNum> lru;
  ExtractAndSanityCheckLRU(sector.get(), &lru);
  EXPECT_TRUE(lru.empty());
  EXPECT_EQ(0, sector->sector_stats()->used_entries);

  // Trying to unlink things again is fine, too.
  sector->UnlinkEntryFromLRU(0);
  EXPECT_EQ(0, sector->sector_stats()->used_entries);
  sector->UnlinkEntryFromLRU(1);
  EXPECT_EQ(0, sector->sector_stats()->used_entries);

  // Now insert 5 things into the LRU manually, with entry 0 expected
  // to be in front.
  for (EntryNum cur = 4; cur >= 0; --cur) {
    sector->InsertEntryIntoLRU(cur);
  }
  EXPECT_EQ(5, sector->sector_stats()->used_entries);

  ExtractAndSanityCheckLRU(sector.get(), &lru);
  ASSERT_EQ(5u, lru.size());
  EXPECT_EQ(0, lru[0]);
  EXPECT_EQ(1, lru[1]);
  EXPECT_EQ(2, lru[2]);
  EXPECT_EQ(3, lru[3]);
  EXPECT_EQ(4, lru[4]);

  // Unlink the middle, and two endpoints.
  sector->UnlinkEntryFromLRU(2);
  sector->UnlinkEntryFromLRU(0);
  sector->UnlinkEntryFromLRU(4);
  EXPECT_EQ(2, sector->sector_stats()->used_entries);

  ExtractAndSanityCheckLRU(sector.get(), &lru);
  ASSERT_EQ(2u, lru.size());
  EXPECT_EQ(1, lru[0]);
  EXPECT_EQ(3, lru[1]);

  ParentCleanup();
}

void SharedMemCacheDataTestBase::TestBlockLists() NO_THREAD_SAFETY_ANALYSIS {
  AbstractSharedMemSegment* seg_raw_ptr = NULL;
  Sector<kBlockSize>* sector_raw_ptr = NULL;
  ASSERT_TRUE(ParentInit(&seg_raw_ptr, &sector_raw_ptr));
  scoped_ptr<AbstractSharedMemSegment> seg(seg_raw_ptr);
  scoped_ptr<Sector<kBlockSize> > sector(sector_raw_ptr);

  // First, let's sanity-check the computation routines
  EXPECT_EQ(static_cast<size_t>(0),
            Sector<kBlockSize>::DataBlocksForSize(0));
  EXPECT_EQ(static_cast<size_t>(1),
            Sector<kBlockSize>::DataBlocksForSize(1));
  EXPECT_EQ(static_cast<size_t>(1),
            Sector<kBlockSize>::DataBlocksForSize(kBlockSize));
  EXPECT_EQ(static_cast<size_t>(2),
            Sector<kBlockSize>::DataBlocksForSize(kBlockSize + 1));
  EXPECT_EQ(static_cast<size_t>(2),
            Sector<kBlockSize>::DataBlocksForSize(kBlockSize * 2));
  EXPECT_EQ(static_cast<size_t>(3),
            Sector<kBlockSize>::DataBlocksForSize(kBlockSize * 2 + 1));

  EXPECT_EQ(static_cast<size_t>(1),
            Sector<kBlockSize>::BytesInPortion(1, 0, 1));
  EXPECT_EQ(static_cast<size_t>(kBlockSize - 1),
            Sector<kBlockSize>::BytesInPortion(kBlockSize - 1, 0, 1));
  EXPECT_EQ(static_cast<size_t>(kBlockSize),
            Sector<kBlockSize>::BytesInPortion(kBlockSize, 0, 1));

  EXPECT_EQ(static_cast<size_t>(kBlockSize),
            Sector<kBlockSize>::BytesInPortion(kBlockSize + 1, 0, 2));
  EXPECT_EQ(static_cast<size_t>(1),
            Sector<kBlockSize>::BytesInPortion(kBlockSize + 1, 1, 2));

  EXPECT_EQ(static_cast<size_t>(kBlockSize),
            Sector<kBlockSize>::BytesInPortion(2 * kBlockSize, 0, 2));
  EXPECT_EQ(static_cast<size_t>(kBlockSize),
            Sector<kBlockSize>::BytesInPortion(2 * kBlockSize, 1, 2));

  // Now, let's allocate some blocks.
  const int kTestBlocks = 10;
  BlockVector blocks;
  ASSERT_EQ(kTestBlocks,
            sector->AllocBlocksFromFreeList(kTestBlocks, &blocks));

  // Link them together, and add them to a test entry.
  sector->LinkBlockSuccessors(blocks);
  CacheEntry* entry = sector->EntryAt(0);
  entry->byte_size = kTestBlocks * kBlockSize;
  entry->first_block = blocks[0];

  // Hopefully BlockListForEntry will look things up right.
  BlockVector extracted_blocks;
  sector->BlockListForEntry(entry, &extracted_blocks);
  EXPECT_EQ(blocks, extracted_blocks);

  ParentCleanup();
}

bool SharedMemCacheDataTestBase::ParentInit(AbstractSharedMemSegment** out_seg,
                                            Sector<kBlockSize>** out_sector) {
  size_t bytes =
      Sector<kBlockSize>::RequiredSize(shmem_runtime_.get(), kEntries, kBlocks);
  AbstractSharedMemSegment* seg =
      shmem_runtime_->CreateSegment(kSegment, bytes + kExtra, &handler_);
  if (seg == NULL) {
    return false;
  }

  Sector<kBlockSize>* sector =
      new Sector<kBlockSize>(seg, kExtra, kEntries, kBlocks);
  *out_seg = seg;
  *out_sector = sector;

  return sector->Initialize(&handler_);
}

bool SharedMemCacheDataTestBase::ChildInit(AbstractSharedMemSegment** out_seg,
                                           Sector<kBlockSize>** out_sector) {
  size_t bytes =
      Sector<kBlockSize>::RequiredSize(shmem_runtime_.get(), kEntries, kBlocks);
  AbstractSharedMemSegment* seg =
      shmem_runtime_->AttachToSegment(kSegment, bytes + kExtra, &handler_);
  if (seg == NULL) {
    return false;
  }

  Sector<kBlockSize>* sector =
      new Sector<kBlockSize>(seg, kExtra, kEntries, kBlocks);
  *out_seg = seg;
  *out_sector = sector;

  return sector->Attach(&handler_);
}

void SharedMemCacheDataTestBase::ParentCleanup() {
  test_env_->WaitForChildren();
  shmem_runtime_->DestroySegment(kSegment, &handler_);
}

}  // namespace net_instaweb
