/*
 * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2020, 2023 SAP SE. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "precompiled.hpp"
#include "memory/metaspace/chunkManager.hpp"
#include "memory/metaspace/metaspaceSettings.hpp"
#include "metaspaceGtestCommon.hpp"
#include "metaspaceGtestContexts.hpp"

using metaspace::Settings;

void ChunkGtestContext::checked_alloc_chunk_0(Metachunk** p_return_value, chunklevel_t preferred_level, chunklevel_t max_level,
                                                      size_t min_committed_size) {

  *p_return_value = NULL;

  Metachunk* c = cm().get_chunk(preferred_level, max_level, min_committed_size);

  if (c != NULL) {

    ASSERT_LE(c->level(), max_level);
    ASSERT_GE(c->level(), preferred_level);
    ASSERT_GE(c->committed_words(), min_committed_size);
    ASSERT_EQ(c->committed_words(), c->free_below_committed_words());
    ASSERT_EQ(c->used_words(), (size_t)0);
    ASSERT_TRUE(c->is_in_use());
    ASSERT_FALSE(c->is_free());
    ASSERT_FALSE(c->is_dead());
    ASSERT_NULL(c->next());
    ASSERT_NULL(c->prev());
    if (c->level() == HIGHEST_CHUNK_LEVEL) {
      ASSERT_TRUE(c->is_leaf_chunk());
    } else {
      ASSERT_FALSE(c->is_leaf_chunk());
    }
    if (c->level() == LOWEST_CHUNK_LEVEL) {
      ASSERT_TRUE(c->is_root_chunk());
    } else {
      ASSERT_FALSE(c->is_root_chunk());
    }
    if (_num_chunks_allocated == 0) { // First chunk? We can make more assumptions
      ASSERT_EQ(c->level(), preferred_level);
      // Needs lock EXPECT_NULL(c->next_in_vs());
      // Needs lock EXPECT_NULL(c->prev_in_vs());
      ASSERT_TRUE(c->is_root_chunk() || c->is_leader());
    }

    _num_chunks_allocated++;

  }

  *p_return_value = c;

}

// Test pattern established when allocating from the chunk with allocate_from_chunk_with_tests().
void ChunkGtestContext::test_pattern(Metachunk* c, size_t word_size) {
  check_range_for_pattern(c->base(), word_size, (uintx)c);
}

void ChunkGtestContext::return_chunk(Metachunk* c) {
  test_pattern(c);
  c->set_in_use(); // Forestall assert in cm
  cm().return_chunk(c);
}

 void ChunkGtestContext::allocate_from_chunk(MetaWord** p_return_value, Metachunk* c, size_t word_size) {

  size_t used_before = c->used_words();
  size_t free_before = c->free_words();
  size_t free_below_committed_before = c->free_below_committed_words();
  const MetaWord* top_before = c->top();

  MetaWord* p = c->allocate(word_size);
  EXPECT_NOT_NULL(p);
  EXPECT_EQ(c->used_words(), used_before + word_size);
  EXPECT_EQ(c->free_words(), free_before - word_size);
  EXPECT_EQ(c->free_below_committed_words(), free_below_committed_before - word_size);
  EXPECT_EQ(c->top(), top_before + word_size);

  // Old content should be preserved
  test_pattern(c, used_before);

  // Fill newly allocated range too
  fill_range_with_pattern(p, word_size, (uintx)c);

  *p_return_value = p;
}

void ChunkGtestContext::commit_chunk_with_test(Metachunk* c, size_t additional_size) {

  size_t used_before = c->used_words();
  size_t free_before = c->free_words();
  const MetaWord* top_before = c->top();

  c->set_in_use();
  bool b = c->ensure_committed_additional(additional_size);
  EXPECT_TRUE(b);

  // We should have enough committed size now
  EXPECT_GE(c->free_below_committed_words(), additional_size);

  // used, free, top should be unchanged.
  EXPECT_EQ(c->used_words(), used_before);
  EXPECT_EQ(c->free_words(), free_before);
  EXPECT_EQ(c->top(), top_before);

  test_pattern(c, used_before);

}

void ChunkGtestContext::commit_chunk_expect_failure(Metachunk* c, size_t additional_size) {

  size_t used_before = c->used_words();
  size_t free_before = c->free_words();
  size_t free_below_committed_before = c->free_below_committed_words();
  const MetaWord* top_before = c->top();

  c->set_in_use();
  bool b = c->ensure_committed_additional(additional_size);
  EXPECT_FALSE(b);

  // Nothing should have changed
  EXPECT_EQ(c->used_words(), used_before);
  EXPECT_EQ(c->free_words(), free_before);
  EXPECT_EQ(c->free_below_committed_words(), free_below_committed_before);
  EXPECT_EQ(c->top(), top_before);

  test_pattern(c, used_before);

}

void ChunkGtestContext::uncommit_chunk_with_test(Metachunk* c) {
  if (c->word_size() >= Settings::commit_granule_words()) {
    c->set_free();  // Forestall assert in uncommit
    c->reset_used_words();
    c->uncommit();

    EXPECT_EQ(c->free_below_committed_words(), (size_t)0);
    EXPECT_EQ(c->used_words(), (size_t)0);
    EXPECT_EQ(c->free_words(), c->word_size());
    EXPECT_EQ(c->top(), c->base());
    EXPECT_TRUE(c->is_fully_uncommitted());
  }
}

/////// SparseArray<T> ////////////////

