/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <numa.h>

#include <cstddef>
#include <memory>

#include "catalog/NUMAPlacementScheme.hpp"
#include "catalog/PartitionSchemeHeader.hpp"
#include "storage/StorageBlockInfo.hpp"

#include "gtest/gtest.h"

namespace quickstep {

// Test to check if the number of NUMA nodes in the system
// is the same as the number of NUMA nodes as reported by
// the NUMAPlacementScheme.
TEST(NUMAPlacementSchemeTest, CheckNumNUMANodes) {
  // Number of partitions in the Catalog Relation.
  std::size_t num_partitions = 4;

  // Create a NUMAPlacementScheme object with the num_partitions.
  std::unique_ptr<NUMAPlacementScheme> placement_scheme(
      new NUMAPlacementScheme(num_partitions));

  // Get the number of NUMA nodes in the system.
  const std::size_t num_numa_nodes = numa_num_configured_nodes();

  // Check if the number of NUMA nodes in NUMAPlacementScheme and that returned
  // from the system are the same.
  EXPECT_EQ(num_numa_nodes, placement_scheme->getNumNUMANodes());
}

// Test to check if the partitions are assigned the available NUMA nodes in a
// round-robin manner.
TEST(NUMAPlacementSchemeTest, CheckNUMANodesAssignment) {
  // Number of partitions in the Catalog Relation.
  std::size_t num_partitions = 64;

  // Create a NUMAPlacementScheme object with the num_partitions.
  std::unique_ptr<NUMAPlacementScheme> placement_scheme(
      new NUMAPlacementScheme(num_partitions));

  // Check that the partitions are assigned to the NUMA nodes in a
  // round-robbin manner. Partition 0 should be assigned to NUMA node 0,
  // partition 1 should be assigned to NUMA node 1, and so on. Partition n
  // should be assigned to NUMA node n modulus number_of_NUMA_nodes.
  for (std::size_t part_num = 0;
       part_num < num_partitions;
       ++part_num) {
    EXPECT_EQ(static_cast<int>(part_num % placement_scheme->getNumNUMANodes()),
              placement_scheme->getNUMANodeForPartition(part_num));
  }
}

// Test the serialization and deserialization of NUMAPlacementScheme object.
TEST(NUMAPlacementSchemeTest, NUMAPlacementSchemeSerializationTest) {
  // Number of blocks in the Catalog Relation.
  constexpr int kNumBlocks = 10;

  // Number of partitions in the Catalog Relation.
  std::size_t num_partitions = 64;

  // Create a HashPartitionSchemeHeader object with 64 partitions and attribute
  //  0 as the partitioning attribute.
  std::unique_ptr<PartitionSchemeHeader> partition_scheme_header(
      new HashPartitionSchemeHeader(num_partitions, { 0 }));

  // Create a NUMAPlacementScheme object with the num_partitions.
  std::unique_ptr<NUMAPlacementScheme> placement_scheme(
      new NUMAPlacementScheme(num_partitions));

  // Add some entries into block to NUMA node map.
  for (block_id block = 0; block < kNumBlocks; ++block) {
    placement_scheme->addBlockToNUMANodeMap(
        block, block % placement_scheme->getNumNUMANodes());
  }

  // Check if the BlockToNUMANodeMap has exactly the same entries that we just
  // inserted..
  for (block_id block = 0; block < kNumBlocks; ++block) {
    EXPECT_EQ(static_cast<int>(block % placement_scheme->getNumNUMANodes()),
              placement_scheme->getNUMANodeForBlock(block));
  }

  // Create a new placement scheme object from the protobuf version of the
  // previously created placement scheme object. Note that serialization is done
  // using getProto() and deserialization is done using
  // ReconstructFromProto() methods, respectively.
  std::unique_ptr<NUMAPlacementScheme> placement_scheme_from_proto;
  placement_scheme_from_proto.reset(
      NUMAPlacementScheme::ReconstructFromProto(
          placement_scheme->getProto(), partition_scheme_header->getNumPartitions()));

  // Check if the number of NUMA nodes is the same in both the placement scheme
  // objects.
  EXPECT_EQ(placement_scheme->getNumNUMANodes(),
            placement_scheme_from_proto->getNumNUMANodes());

  // Check if the mapping between the partitions to the NUMA nodes is the same
  // in both the placement scheme objects.
  for (std::size_t part_id = 0; part_id < num_partitions; ++part_id) {
    EXPECT_EQ(placement_scheme->getNUMANodeForPartition(part_id),
              placement_scheme_from_proto->getNUMANodeForPartition(part_id));
  }

  // Check if the entries in the block to NUMA node map are the same in both the
  // placement scheme objects.
  for (block_id block = 0; block < kNumBlocks; ++block) {
    EXPECT_EQ(placement_scheme->getNUMANodeForBlock(block),
              placement_scheme_from_proto->getNUMANodeForBlock(block));
  }
}

}  // namespace quickstep
