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

#include "dlmalloc_space.h"
#include "rosalloc_space.h"
#include "scoped_thread_state_change-inl.h"

namespace art {
namespace gc {
namespace space {

enum MallocSpaceType {
  kMallocSpaceDlMalloc,
  kMallocSpaceRosAlloc,
};

class SpaceCreateTest : public SpaceTest<CommonRuntimeTestWithParam<MallocSpaceType>> {
 public:
  MallocSpace* CreateSpace(const std::string& name,
                           size_t initial_size,
                           size_t growth_limit,
                           size_t capacity) {
    const MallocSpaceType type = GetParam();
    if (type == kMallocSpaceDlMalloc) {
      return DlMallocSpace::Create(name,
                                   initial_size,
                                   growth_limit,
                                   capacity,
                                   /*can_move_objects=*/ false);
    }
    DCHECK_EQ(static_cast<uint32_t>(type), static_cast<uint32_t>(kMallocSpaceRosAlloc));
    return RosAllocSpace::Create(name,
                                 initial_size,
                                 growth_limit,
                                 capacity,
                                 Runtime::Current()->GetHeap()->IsLowMemoryMode(),
                                 /*can_move_objects=*/ false);
  }
};

TEST_P(SpaceCreateTest, InitTestBody) {
  // This will lead to error messages in the log.
  ScopedLogSeverity sls(LogSeverity::FATAL);

  {
    // Init < max == growth
    std::unique_ptr<Space> space(CreateSpace("test", 16 * MB, 32 * MB, 32 * MB));
    EXPECT_TRUE(space != nullptr);
    // Init == max == growth
    space.reset(CreateSpace("test", 16 * MB, 16 * MB, 16 * MB));
    EXPECT_TRUE(space != nullptr);
    // Init > max == growth
    space.reset(CreateSpace("test", 32 * MB, 16 * MB, 16 * MB));
    EXPECT_TRUE(space == nullptr);
    // Growth == init < max
    space.reset(CreateSpace("test", 16 * MB, 16 * MB, 32 * MB));
    EXPECT_TRUE(space != nullptr);
    // Growth < init < max
    space.reset(CreateSpace("test", 16 * MB, 8 * MB, 32 * MB));
    EXPECT_TRUE(space == nullptr);
    // Init < growth < max
    space.reset(CreateSpace("test", 8 * MB, 16 * MB, 32 * MB));
    EXPECT_TRUE(space != nullptr);
    // Init < max < growth
    space.reset(CreateSpace("test", 8 * MB, 32 * MB, 16 * MB));
    EXPECT_TRUE(space == nullptr);
  }
}

// TODO: This test is not very good, we should improve it.
// The test should do more allocations before the creation of the ZygoteSpace, and then do
// allocations after the ZygoteSpace is created. The test should also do some GCs to ensure that
// the GC works with the ZygoteSpace.
TEST_P(SpaceCreateTest, ZygoteSpaceTestBody) {
  size_t dummy;
  MallocSpace* space(CreateSpace("test", 4 * MB, 16 * MB, 16 * MB));
  ASSERT_TRUE(space != nullptr);

  // Make space findable to the heap, will also delete space when runtime is cleaned up
  AddSpace(space);
  Thread* self = Thread::Current();
  ScopedObjectAccess soa(self);

  // Succeeds, fits without adjusting the footprint limit.
  size_t ptr1_bytes_allocated, ptr1_usable_size, ptr1_bytes_tl_bulk_allocated;
  StackHandleScope<3> hs(soa.Self());
  MutableHandle<mirror::Object> ptr1(hs.NewHandle(Alloc(space,
                                                        self,
                                                        1 * MB,
                                                        &ptr1_bytes_allocated,
                                                        &ptr1_usable_size,
                                                        &ptr1_bytes_tl_bulk_allocated)));
  EXPECT_TRUE(ptr1 != nullptr);
  EXPECT_LE(1U * MB, ptr1_bytes_allocated);
  EXPECT_LE(1U * MB, ptr1_usable_size);
  EXPECT_LE(ptr1_usable_size, ptr1_bytes_allocated);
  EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);

  // Fails, requires a higher footprint limit.
  mirror::Object* ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
  EXPECT_TRUE(ptr2 == nullptr);

  // Succeeds, adjusts the footprint.
  size_t ptr3_bytes_allocated, ptr3_usable_size, ptr3_bytes_tl_bulk_allocated;
  MutableHandle<mirror::Object> ptr3(hs.NewHandle(AllocWithGrowth(space,
                                                                  self,
                                                                  8 * MB,
                                                                  &ptr3_bytes_allocated,
                                                                  &ptr3_usable_size,
                                                                  &ptr3_bytes_tl_bulk_allocated)));
  EXPECT_TRUE(ptr3 != nullptr);
  EXPECT_LE(8U * MB, ptr3_bytes_allocated);
  EXPECT_LE(8U * MB, ptr3_usable_size);
  EXPECT_LE(ptr3_usable_size, ptr3_bytes_allocated);
  EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);

  // Fails, requires a higher footprint limit.
  mirror::Object* ptr4 = space->Alloc(self, 8 * MB, &dummy, nullptr, &dummy);
  EXPECT_TRUE(ptr4 == nullptr);

  // Also fails, requires a higher allowed footprint.
  mirror::Object* ptr5 = space->AllocWithGrowth(self, 8 * MB, &dummy, nullptr, &dummy);
  EXPECT_TRUE(ptr5 == nullptr);

  // Release some memory.
  size_t free3 = space->AllocationSize(ptr3.Get(), nullptr);
  EXPECT_EQ(free3, ptr3_bytes_allocated);
  EXPECT_EQ(free3, space->Free(self, ptr3.Assign(nullptr)));
  EXPECT_LE(8U * MB, free3);

  // Succeeds, now that memory has been freed.
  size_t ptr6_bytes_allocated, ptr6_usable_size, ptr6_bytes_tl_bulk_allocated;
  Handle<mirror::Object> ptr6(hs.NewHandle(AllocWithGrowth(space,
                                                           self,
                                                           9 * MB,
                                                           &ptr6_bytes_allocated,
                                                           &ptr6_usable_size,
                                                           &ptr6_bytes_tl_bulk_allocated)));
  EXPECT_TRUE(ptr6 != nullptr);
  EXPECT_LE(9U * MB, ptr6_bytes_allocated);
  EXPECT_LE(9U * MB, ptr6_usable_size);
  EXPECT_LE(ptr6_usable_size, ptr6_bytes_allocated);
  EXPECT_EQ(ptr6_bytes_tl_bulk_allocated, ptr6_bytes_allocated);

  // Final clean up.
  size_t free1 = space->AllocationSize(ptr1.Get(), nullptr);
  space->Free(self, ptr1.Assign(nullptr));
  EXPECT_LE(1U * MB, free1);

  // Make sure that the zygote space isn't directly at the start of the space.
  EXPECT_TRUE(space->Alloc(self, 1U * MB, &dummy, nullptr, &dummy) != nullptr);

  gc::Heap* heap = Runtime::Current()->GetHeap();
  space::Space* old_space = space;
  {
    ScopedThreadSuspension sts(self, kSuspended);
    ScopedSuspendAll ssa("Add image space");
    heap->RemoveSpace(old_space);
  }
  heap->RevokeAllThreadLocalBuffers();
  space::ZygoteSpace* zygote_space = space->CreateZygoteSpace("alloc space",
                                                              heap->IsLowMemoryMode(),
                                                              &space);
  delete old_space;
  // Add the zygote space.
  AddSpace(zygote_space, false);

  // Make space findable to the heap, will also delete space when runtime is cleaned up
  AddSpace(space, false);

  // Succeeds, fits without adjusting the footprint limit.
  ptr1.Assign(Alloc(space,
                    self,
                    1 * MB,
                    &ptr1_bytes_allocated,
                    &ptr1_usable_size,
                    &ptr1_bytes_tl_bulk_allocated));
  EXPECT_TRUE(ptr1 != nullptr);
  EXPECT_LE(1U * MB, ptr1_bytes_allocated);
  EXPECT_LE(1U * MB, ptr1_usable_size);
  EXPECT_LE(ptr1_usable_size, ptr1_bytes_allocated);
  EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);

  // Fails, requires a higher footprint limit.
  ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
  EXPECT_TRUE(ptr2 == nullptr);

  // Succeeds, adjusts the footprint.
  ptr3.Assign(AllocWithGrowth(space,
                              self,
                              2 * MB,
                              &ptr3_bytes_allocated,
                              &ptr3_usable_size,
                              &ptr3_bytes_tl_bulk_allocated));
  EXPECT_TRUE(ptr3 != nullptr);
  EXPECT_LE(2U * MB, ptr3_bytes_allocated);
  EXPECT_LE(2U * MB, ptr3_usable_size);
  EXPECT_LE(ptr3_usable_size, ptr3_bytes_allocated);
  EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);
  space->Free(self, ptr3.Assign(nullptr));

  // Final clean up.
  free1 = space->AllocationSize(ptr1.Get(), nullptr);
  space->Free(self, ptr1.Assign(nullptr));
  EXPECT_LE(1U * MB, free1);
}

TEST_P(SpaceCreateTest, AllocAndFreeTestBody) {
  size_t dummy = 0;
  MallocSpace* space(CreateSpace("test", 4 * MB, 16 * MB, 16 * MB));
  ASSERT_TRUE(space != nullptr);
  Thread* self = Thread::Current();
  ScopedObjectAccess soa(self);

  // Make space findable to the heap, will also delete space when runtime is cleaned up
  AddSpace(space);

  // Succeeds, fits without adjusting the footprint limit.
  size_t ptr1_bytes_allocated, ptr1_usable_size, ptr1_bytes_tl_bulk_allocated;
  StackHandleScope<3> hs(soa.Self());
  MutableHandle<mirror::Object> ptr1(hs.NewHandle(Alloc(space,
                                                        self,
                                                        1 * MB,
                                                        &ptr1_bytes_allocated,
                                                        &ptr1_usable_size,
                                                        &ptr1_bytes_tl_bulk_allocated)));
  EXPECT_TRUE(ptr1 != nullptr);
  EXPECT_LE(1U * MB, ptr1_bytes_allocated);
  EXPECT_LE(1U * MB, ptr1_usable_size);
  EXPECT_LE(ptr1_usable_size, ptr1_bytes_allocated);
  EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);

  // Fails, requires a higher footprint limit.
  mirror::Object* ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
  EXPECT_TRUE(ptr2 == nullptr);

  // Succeeds, adjusts the footprint.
  size_t ptr3_bytes_allocated, ptr3_usable_size, ptr3_bytes_tl_bulk_allocated;
  MutableHandle<mirror::Object> ptr3(hs.NewHandle(AllocWithGrowth(space,
                                                                  self,
                                                                  8 * MB,
                                                                  &ptr3_bytes_allocated,
                                                                  &ptr3_usable_size,
                                                                  &ptr3_bytes_tl_bulk_allocated)));
  EXPECT_TRUE(ptr3 != nullptr);
  EXPECT_LE(8U * MB, ptr3_bytes_allocated);
  EXPECT_LE(8U * MB, ptr3_usable_size);
  EXPECT_LE(ptr3_usable_size, ptr3_bytes_allocated);
  EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);

  // Fails, requires a higher footprint limit.
  mirror::Object* ptr4 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
  EXPECT_TRUE(ptr4 == nullptr);

  // Also fails, requires a higher allowed footprint.
  mirror::Object* ptr5 = AllocWithGrowth(space, self, 8 * MB, &dummy, nullptr, &dummy);
  EXPECT_TRUE(ptr5 == nullptr);

  // Release some memory.
  size_t free3 = space->AllocationSize(ptr3.Get(), nullptr);
  EXPECT_EQ(free3, ptr3_bytes_allocated);
  space->Free(self, ptr3.Assign(nullptr));
  EXPECT_LE(8U * MB, free3);

  // Succeeds, now that memory has been freed.
  size_t ptr6_bytes_allocated, ptr6_usable_size, ptr6_bytes_tl_bulk_allocated;
  Handle<mirror::Object> ptr6(hs.NewHandle(AllocWithGrowth(space,
                                                           self,
                                                           9 * MB,
                                                           &ptr6_bytes_allocated,
                                                           &ptr6_usable_size,
                                                           &ptr6_bytes_tl_bulk_allocated)));
  EXPECT_TRUE(ptr6 != nullptr);
  EXPECT_LE(9U * MB, ptr6_bytes_allocated);
  EXPECT_LE(9U * MB, ptr6_usable_size);
  EXPECT_LE(ptr6_usable_size, ptr6_bytes_allocated);
  EXPECT_EQ(ptr6_bytes_tl_bulk_allocated, ptr6_bytes_allocated);

  // Final clean up.
  size_t free1 = space->AllocationSize(ptr1.Get(), nullptr);
  space->Free(self, ptr1.Assign(nullptr));
  EXPECT_LE(1U * MB, free1);
}

TEST_P(SpaceCreateTest, AllocAndFreeListTestBody) {
  MallocSpace* space(CreateSpace("test", 4 * MB, 16 * MB, 16 * MB));
  ASSERT_TRUE(space != nullptr);

  // Make space findable to the heap, will also delete space when runtime is cleaned up
  AddSpace(space);
  Thread* self = Thread::Current();
  ScopedObjectAccess soa(self);

  // Succeeds, fits without adjusting the max allowed footprint.
  mirror::Object* lots_of_objects[1024];
  for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
    size_t allocation_size, usable_size, bytes_tl_bulk_allocated;
    size_t size_of_zero_length_byte_array = SizeOfZeroLengthByteArray();
    lots_of_objects[i] = Alloc(space,
                               self,
                               size_of_zero_length_byte_array,
                               &allocation_size,
                               &usable_size,
                               &bytes_tl_bulk_allocated);
    EXPECT_TRUE(lots_of_objects[i] != nullptr);
    size_t computed_usable_size;
    EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i], &computed_usable_size));
    EXPECT_EQ(usable_size, computed_usable_size);
    EXPECT_TRUE(bytes_tl_bulk_allocated == 0 ||
                bytes_tl_bulk_allocated >= allocation_size);
  }

  // Release memory.
  space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);

  // Succeeds, fits by adjusting the max allowed footprint.
  for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
    size_t allocation_size, usable_size, bytes_tl_bulk_allocated;
    lots_of_objects[i] = AllocWithGrowth(space,
                                         self,
                                         1024,
                                         &allocation_size,
                                         &usable_size,
                                         &bytes_tl_bulk_allocated);
    EXPECT_TRUE(lots_of_objects[i] != nullptr);
    size_t computed_usable_size;
    EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i], &computed_usable_size));
    EXPECT_EQ(usable_size, computed_usable_size);
    EXPECT_TRUE(bytes_tl_bulk_allocated == 0 ||
                bytes_tl_bulk_allocated >= allocation_size);
  }

  // Release memory.
  space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
}

INSTANTIATE_TEST_CASE_P(CreateRosAllocSpace,
                        SpaceCreateTest,
                        testing::Values(kMallocSpaceRosAlloc));
INSTANTIATE_TEST_CASE_P(CreateDlMallocSpace,
                        SpaceCreateTest,
                        testing::Values(kMallocSpaceDlMalloc));

}  // namespace space
}  // namespace gc
}  // namespace art
