/*
 * 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)

// Unit-test the arena

#include "pagespeed/kernel/base/arena.h"

#include <cstddef>
#include <set>

#include "pagespeed/kernel/base/gtest.h"

namespace net_instaweb {

class ArenaTest : public testing::Test {
 public:
  ArenaTest() {
    ClearStats();
  }

 protected:
  friend class KidA;
  friend class KidB;

  class Base {
   public:
    explicit Base(ArenaTest* owner) : owner_(owner) {}
    virtual ~Base() {
      // Watch out for double-delete
      EXPECT_TRUE(owner_ != NULL);
      owner_ = NULL;
    }

    // When testing creation, we invoke this method.
    virtual void Made() = 0;

    void* operator new(size_t size, Arena<Base>* arena) {
      return arena->Allocate(size);
    }

   protected:
    ArenaTest* owner_;
  };

  // We expect KidA to have size of 2 pointers: the vtable and owner,
  // (just like base). On 32-bit this will be 8-bytes, so with 8-byte
  // alignment area it will divide the block size
  class KidA : public Base {
   public:
    explicit KidA(ArenaTest* o) : Base(o) {}

    ~KidA() {
      ++owner_->destroyed_a_;
    }

    virtual void Made() {
      ++owner_->made_a_;
    }
  };

  // KidB is 3 pointers long, so on 64-bit along with the next pointer
  // we will be using 32 bytes per allocation and it will divide
  // the block size.
  //
  // The difference in size between A and B lets us test mixed combinations of
  // different sizes.
  class KidB : public Base {
   public:
    explicit KidB(ArenaTest* o) : Base(o) {}

    ~KidB() {
      ++owner_->destroyed_b_;
    }

    virtual void Made() {
      ++owner_->made_b_;
    }

   private:
    void* different_size;
  };

  // Tests a given mixture of allocations of KidA and KidB --
  // making sure we get sane pointers and delete things.
  void TestCombo(int num_a, int num_b) {
    for (int a = 0; a < num_a; ++a) {
      CheckPtr(new (&arena_) KidA(this));
    }

    for (int b = 0; b < num_b; ++b) {
      CheckPtr(new (&arena_) KidB(this));
    }

    arena_.DestroyObjects();

    EXPECT_EQ(num_a, made_a_);
    EXPECT_EQ(num_b, made_b_);
    EXPECT_EQ(num_a, destroyed_a_);
    EXPECT_EQ(num_b, destroyed_b_);
  }

  // Checks to make sure the pointer is sane, and calls Made on it.
  void CheckPtr(Base* p) {
    EXPECT_TRUE(seen_ptrs_.find(p) == seen_ptrs_.end());
    seen_ptrs_.insert(p);
    p->Made();
  }

  void ClearStats() {
    made_a_ = 0;
    made_b_ = 0;
    destroyed_a_ = 0;
    destroyed_b_ = 0;
    seen_ptrs_.clear();
  }

  int made_a_;
  int made_b_;
  int destroyed_a_;
  int destroyed_b_;
  Arena<Base> arena_;
  std::set<void*> seen_ptrs_;
};

// Empty arena should be OK without a Destroy
TEST_F(ArenaTest, TestEmpty) {
}

// calling Destroy on empty is fine.
TEST_F(ArenaTest, TestEmptyDestroy) {
  arena_.DestroyObjects();
}

TEST_F(ArenaTest, TestJustA) {
  TestCombo(10000, 0);
}

TEST_F(ArenaTest, TestJustA2) {
  // On 32-bit this should perfectly fill all the blocks it uses
  TestCombo(2048, 0);
}

TEST_F(ArenaTest, TestJustB) {
  TestCombo(0, 10000);
}

TEST_F(ArenaTest, TestJustB2) {
  // On 64-bit this should perfectly fill all the blocks it uses
  TestCombo(0, 2048);
}

TEST_F(ArenaTest, TestMix) {
  TestCombo(10000, 20000);
}

// Make sure we work again after a clear
TEST_F(ArenaTest, TestReuse) {
  TestCombo(10000, 20000);
  ClearStats();
  TestCombo(20000, 10000);
}

// Tests for alignment helper.
TEST_F(ArenaTest, TestAlign) {
  // A few that work regardless of arch, to sanity-check
  // the more through loop below
  EXPECT_EQ(8, arena_.ExpandToAlign(8));
  EXPECT_EQ(16, arena_.ExpandToAlign(15));
  EXPECT_EQ(16, arena_.ExpandToAlign(14));
  EXPECT_EQ(16, arena_.ExpandToAlign(13));

  for (size_t t = 0; t < 1000u; ++t) {
    size_t expanded = arena_.ExpandToAlign(t);
    if ((t % arena_.kAlign) == 0) {
      // Well-aligned case.
      EXPECT_EQ(t, expanded);
    } else {
      // Otherwise should be next multiple
      EXPECT_EQ(((t / arena_.kAlign) + 1) * arena_.kAlign, expanded);
    }
  }
}

}  // namespace net_instaweb
