/**
 * 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 <algorithm>
#include <cstddef>
#include <vector>

#include "gtest/gtest.h"

#include "query_execution/WorkOrdersContainer.hpp"
#include "relational_operators/WorkOrder.hpp"
#include "utility/PtrVector.hpp"
#include "utility/Macros.hpp"

namespace quickstep {

class MockNUMAWorkOrder : public WorkOrder {
 public:
  MockNUMAWorkOrder(const int id, const std::vector<int> &numa_nodes)
      : WorkOrder(0), id_(id) {
    for (int numa_node : numa_nodes) {
      preferred_numa_nodes_.push_back(numa_node);
    }
  }

  const int getID() const {
    return id_;
  }

  void execute() override {}

 private:
  const int id_;

  DISALLOW_COPY_AND_ASSIGN(MockNUMAWorkOrder);
};

// Note: In the tests, we create a local WorkOrder object (on stack) and use its
// address as a pointer while inserting to the container.
// The real usage of the API works as follows - we create a WorkOrder using "new"
// (on heap) and pass the pointer to the container. When a WorkOrder is
// retrieved from the container, its pointer is removed from the container and
// the caller is responsible to delete the actual WorkOrder object.

TEST(WorkOrdersContainerTest, ZeroNUMANodesTest) {
  // A container for one operator and no NUMA nodes.
  WorkOrdersContainer w(1, 0);

  EXPECT_EQ(0u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));
  EXPECT_FALSE(w.hasNormalWorkOrder(0));
  EXPECT_FALSE(w.hasRebuildWorkOrder(0));
  EXPECT_EQ(nullptr, w.getNormalWorkOrder(0));
  EXPECT_EQ(nullptr, w.getRebuildWorkOrder(0));
}

TEST(WorkOrdersContainerTest, ZeroNUMANodesAddWorkOrderTest) {
  // Add one normal and rebuild workorder each for one operator DAG. Test if
  // they get inserted and retrieved correctly.
  std::vector<int> numa_node_ids;
  // A container for one operator and no NUMA nodes.
  const std::size_t query_id = 0;
  WorkOrdersContainer w(1, 0);

  EXPECT_EQ(0u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));
  EXPECT_FALSE(w.hasNormalWorkOrder(0));
  EXPECT_FALSE(w.hasRebuildWorkOrder(0));

  // Create a NUMA agnostic normal WorkOrder.
  MockNUMAWorkOrder work_order(0, numa_node_ids);
  w.addNormalWorkOrder(&work_order, 0);

  // Expect the normal WorkOrder count to be 1.
  EXPECT_EQ(1u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));
  EXPECT_TRUE(w.hasNormalWorkOrder(0));
  EXPECT_FALSE(w.hasRebuildWorkOrder(0));

  // Create a NUMA agnostic rebuild WorkOrder.
  MockNUMAWorkOrder work_order1(1, numa_node_ids);
  w.addRebuildWorkOrder(&work_order1, 0);

  // Expect the normal WorkOrder count to be 1.
  EXPECT_EQ(1u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(1u, w.getNumRebuildWorkOrders(0));
  EXPECT_TRUE(w.hasNormalWorkOrder(0));
  EXPECT_TRUE(w.hasRebuildWorkOrder(0));

  // Check if we retrieve the same WorkOrders.
  WorkOrder *returned_work_order = w.getNormalWorkOrder(0);
  ASSERT_TRUE(returned_work_order != nullptr);
  EXPECT_EQ(work_order.getID(), static_cast<MockNUMAWorkOrder*>(returned_work_order)->getID());

  EXPECT_EQ(query_id, returned_work_order->getQueryID());

  WorkOrder *returned_rebuild_work_order = w.getRebuildWorkOrder(0);
  ASSERT_TRUE(returned_rebuild_work_order != nullptr);
  EXPECT_EQ(work_order1.getID(),
            static_cast<MockNUMAWorkOrder *>(returned_rebuild_work_order)->getID());

  EXPECT_EQ(query_id, returned_rebuild_work_order->getQueryID());

  // Container should be empty now.
  EXPECT_EQ(0u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));
  EXPECT_FALSE(w.hasNormalWorkOrder(0));
  EXPECT_FALSE(w.hasRebuildWorkOrder(0));
  EXPECT_EQ(nullptr, w.getNormalWorkOrder(0));
  EXPECT_EQ(nullptr, w.getRebuildWorkOrder(0));
}

TEST(WorkOrdersContainerTest, ZeroNUMANodesMultipleWorkOrdersTest) {
  // Add multiple normal and rebuild workorders each for one operator DAG. Test
  // if they get inserted and retrieved correctly and the order of retrieval.
  // A container for one operator and no NUMA nodes.
  std::vector<int> numa_node_ids;
  const std::size_t query_id = 0;
  WorkOrdersContainer w(1, 0);

  EXPECT_EQ(0u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));
  EXPECT_FALSE(w.hasNormalWorkOrder(0));
  EXPECT_FALSE(w.hasRebuildWorkOrder(0));

  PtrVector<MockNUMAWorkOrder> normal_workorders;
  PtrVector<MockNUMAWorkOrder> rebuild_workorders;
  const std::size_t kNumWorkOrders = 100;

  // Push the mock WorkOrders in the vectors and the container.
  for (std::size_t i = 0; i < kNumWorkOrders; ++i) {
    EXPECT_EQ(i, w.getNumNormalWorkOrders(0));
    EXPECT_EQ(i, w.getNumRebuildWorkOrders(0));

    normal_workorders.push_back(new MockNUMAWorkOrder(i, numa_node_ids));
    rebuild_workorders.push_back(
        new MockNUMAWorkOrder(kNumWorkOrders + i, numa_node_ids));

    w.addNormalWorkOrder(&(normal_workorders.back()), 0);
    w.addRebuildWorkOrder(&(rebuild_workorders.back()), 0);
  }

  // Expect the normal WorkOrder count to be kNumWorkOrders.
  EXPECT_EQ(kNumWorkOrders, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(kNumWorkOrders, w.getNumRebuildWorkOrders(0));
  EXPECT_TRUE(w.hasNormalWorkOrder(0));
  EXPECT_TRUE(w.hasRebuildWorkOrder(0));

  // Retrieve the WorkOrders and check the order of retrieval.
  for (std::size_t i = 0; i < kNumWorkOrders; ++i) {
    EXPECT_EQ(kNumWorkOrders - i, w.getNumNormalWorkOrders(0));
    EXPECT_EQ(kNumWorkOrders - i, w.getNumRebuildWorkOrders(0));
    WorkOrder *returned_work_order = w.getNormalWorkOrder(0);
    ASSERT_TRUE(returned_work_order != nullptr);
    EXPECT_EQ(static_cast<int>(i), static_cast<MockNUMAWorkOrder *>(returned_work_order)->getID());
    WorkOrder *returned_rebuild_work_order = w.getRebuildWorkOrder(0);
    ASSERT_TRUE(returned_work_order != nullptr);
    EXPECT_EQ(static_cast<int>(kNumWorkOrders + i),
              static_cast<MockNUMAWorkOrder *>(returned_rebuild_work_order)->getID());
    EXPECT_EQ(query_id, returned_work_order->getQueryID());
    EXPECT_EQ(query_id, returned_rebuild_work_order->getQueryID());
  }

  // Container should be empty now.
  EXPECT_EQ(0u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));
  EXPECT_FALSE(w.hasNormalWorkOrder(0));
  EXPECT_FALSE(w.hasRebuildWorkOrder(0));
  EXPECT_EQ(nullptr, w.getNormalWorkOrder(0));
  EXPECT_EQ(nullptr, w.getRebuildWorkOrder(0));
}

TEST(WorkOrdersContainerTest, MultipleNUMANodesTest) {
  // Create WorkOrders belonging to different NUMA nodes and test if they get
  // inserted and retrieved correctly.
  std::vector<int> numa_node_ids;
  // The sequence of NUMA nodes isn't contiguous.
  numa_node_ids.push_back(4);
  numa_node_ids.push_back(7);
  numa_node_ids.push_back(0);
  const std::size_t kNUMANodes =
      1 +
      *std::max_element(numa_node_ids.begin(), numa_node_ids.end());

  const std::size_t kNUMANodesUsed = numa_node_ids.size();

  // A container for one operator and kNUMANodes.
  const std::size_t query_id = 0;
  WorkOrdersContainer w(1, kNUMANodes);

  for (std::size_t i = 0; i < kNUMANodesUsed; ++i) {
    std::vector<int> curr_numa_node;
    curr_numa_node.push_back(numa_node_ids[i]);
  }

  PtrVector<MockNUMAWorkOrder> normal_workorders;
  PtrVector<MockNUMAWorkOrder> rebuild_workorders;

  for (std::size_t i = 0; i < kNUMANodesUsed; ++i) {
    // Create a vector consisting of the current NUMA node as its element.
    std::vector<int> curr_numa_node;
    curr_numa_node.push_back(numa_node_ids[i]);

    // Create normal and rebuild WorkOrders belonging to exactly one NUMA node.
    normal_workorders.push_back(new MockNUMAWorkOrder(i, curr_numa_node));
    rebuild_workorders.push_back(
        new MockNUMAWorkOrder(kNUMANodes + i, curr_numa_node));

    w.addNormalWorkOrder(&(normal_workorders.back()), 0);
    w.addRebuildWorkOrder(&(rebuild_workorders.back()), 0);

    // For each NUMA node, check the count of WorkOrders.
    for (std::size_t j = 0; j < i; ++j) {
      EXPECT_EQ(1u, w.getNumNormalWorkOrdersForNUMANode(0, numa_node_ids[j]));
      EXPECT_EQ(1u, w.getNumRebuildWorkOrdersForNUMANode(0, numa_node_ids[j]));
    }
  }

  // Retrieve the WorkOrders.
  for (std::size_t i = 0; i < kNUMANodesUsed; ++i) {
    // For each NUMA node, check the count of WorkOrders.
    for (std::size_t j = 0; j < kNUMANodesUsed; ++j) {
      if (j >= i) {
        // We haven't retrieved the workorders for this NUMA node yet.
        EXPECT_EQ(1u, w.getNumNormalWorkOrdersForNUMANode(0, numa_node_ids[j]));
        EXPECT_EQ(1u, w.getNumRebuildWorkOrdersForNUMANode(0, numa_node_ids[j]));
      } else {
        // We already retrieved the workorders for this NUMA node.
        EXPECT_EQ(0u, w.getNumNormalWorkOrdersForNUMANode(0, numa_node_ids[j]));
        EXPECT_EQ(0u, w.getNumRebuildWorkOrdersForNUMANode(0, numa_node_ids[j]));
      }
    }

    // Retrieve the workorders for this NUMA node.
    WorkOrder *returned_work_order = w.getNormalWorkOrderForNUMANode(0, numa_node_ids[i]);
    ASSERT_TRUE(returned_work_order != nullptr);
    EXPECT_EQ(normal_workorders[i].getID(),
              static_cast<MockNUMAWorkOrder *>(returned_work_order)->getID());

    WorkOrder *returned_rebuild_work_order =
        w.getRebuildWorkOrderForNUMANode(0, numa_node_ids[i]);
    ASSERT_TRUE(returned_rebuild_work_order != nullptr);
    EXPECT_EQ(rebuild_workorders[i].getID(),
              static_cast<MockNUMAWorkOrder *>(returned_rebuild_work_order)->getID());

    EXPECT_EQ(query_id, returned_work_order->getQueryID());
    EXPECT_EQ(query_id, returned_rebuild_work_order->getQueryID());
  }

  // No workorder should be left for this operator on any NUMA node.
  for (const int numa_node : numa_node_ids) {
    EXPECT_FALSE(w.hasNormalWorkOrderForNUMANode(0, numa_node));
    EXPECT_FALSE(w.hasRebuildWorkOrderForNUMANode(0, numa_node));
  }

  // No workorder should be left for this operator.
  EXPECT_FALSE(w.hasNormalWorkOrder(0));
  EXPECT_FALSE(w.hasRebuildWorkOrder(0));
}

TEST(WorkOrdersContainerTest, AllTypesWorkOrdersTest) {
  // For a given operator create three types of WorkOrders
  // 1. NUMA agnostic.
  // 2. WorkOrder with single NUMA node.
  // 3. WorkOrder with multiple NUMA nodes.
  std::vector<int> numa_nodes;

  // Create a WorkOrder with no NUMA node.
  MockNUMAWorkOrder no_numa_work_order(0, numa_nodes);
  EXPECT_TRUE(no_numa_work_order.getPreferredNUMANodes().empty());

  // Add one NUMA node.
  numa_nodes.push_back(0);

  // Create a WorkOrder with exactly one NUMA node.
  MockNUMAWorkOrder one_numa_work_order(1, numa_nodes);
  EXPECT_EQ(0, one_numa_work_order.getPreferredNUMANodes().front());

  // Add another NUMA node.
  numa_nodes.push_back(3);

  // Create a WorkOrder with more than one NUMA node.
  MockNUMAWorkOrder multiple_numa_work_order(2, numa_nodes);
  for (std::size_t i = 0; i < numa_nodes.size(); ++i) {
    EXPECT_EQ(numa_nodes[i], multiple_numa_work_order.getPreferredNUMANodes().at(i));
  }

  const std::size_t kNUMANodes =
      1 + *std::max_element(numa_nodes.begin(), numa_nodes.end());
  const std::size_t kNUMANodesUsed = numa_nodes.size();

  // Create the container.
  const std::size_t query_id = 0;
  WorkOrdersContainer w(1, kNUMANodes);

  w.addNormalWorkOrder(&multiple_numa_work_order, 0);

  for (std::size_t i = 0; i < kNUMANodesUsed; ++i) {
    // Check the count of per NUMA node workorders.
    EXPECT_EQ(1u, w.getNumNormalWorkOrdersForNUMANode(0, numa_nodes[i]));
  }

  // Expect 1 normal workorder in total for this operator.
  EXPECT_EQ(1u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));

  // Add the WorkOrder with no NUMA node.
  w.addNormalWorkOrder(&no_numa_work_order, 0);

  for (std::size_t i = 0; i < kNUMANodesUsed; ++i) {
    // Check the count of per NUMA node workorders.
    EXPECT_EQ(1u, w.getNumNormalWorkOrdersForNUMANode(0, numa_nodes[i]));
  }

  // Expect 2 normal workorders in total for this operator.
  EXPECT_EQ(2u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));

  // Add the WorkOrder with exactly one NUMA node.
  w.addNormalWorkOrder(&one_numa_work_order, 0);

  EXPECT_EQ(2u, w.getNumNormalWorkOrdersForNUMANode(0, numa_nodes[0]));
  EXPECT_EQ(1u, w.getNumNormalWorkOrdersForNUMANode(0, numa_nodes[1]));

  // Expect 3 normal workorders in total for this operator.
  EXPECT_EQ(3u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));

  // Retrieve the workorders for NUMA node = numa_nodes[0]
  MockNUMAWorkOrder *observed_work_order = static_cast<MockNUMAWorkOrder *>(
      w.getNormalWorkOrderForNUMANode(0, numa_nodes[0]));
  ASSERT_TRUE(observed_work_order != nullptr);

  EXPECT_EQ(query_id, observed_work_order->getQueryID());
  EXPECT_EQ(one_numa_work_order.getPreferredNUMANodes().front(),
            observed_work_order->getPreferredNUMANodes().front());
  EXPECT_EQ(one_numa_work_order.getID(), observed_work_order->getID());

  EXPECT_EQ(1u, w.getNumNormalWorkOrdersForNUMANode(0, numa_nodes[0]));
  EXPECT_EQ(1u, w.getNumNormalWorkOrdersForNUMANode(0, numa_nodes[1]));

  // Expect 2 normal workorders in total for this operator.
  EXPECT_EQ(2u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));

  // Retrieve the non NUMA workorder.
  WorkOrder *observed_non_numa_work_order = w.getNormalWorkOrder(0);
  ASSERT_TRUE(observed_non_numa_work_order != nullptr);
  EXPECT_EQ(no_numa_work_order.getID(),
            static_cast<MockNUMAWorkOrder *>(observed_non_numa_work_order)->getID());

  EXPECT_EQ(query_id, observed_non_numa_work_order->getQueryID());
  EXPECT_EQ(1u, w.getNumNormalWorkOrdersForNUMANode(0, numa_nodes[0]));
  EXPECT_EQ(1u, w.getNumNormalWorkOrdersForNUMANode(0, numa_nodes[1]));

  // Expect 1 normal workorders in total for this operator.
  EXPECT_EQ(1u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));

  // Retrieve the workorder with multiple NUMA nodes.
  MockNUMAWorkOrder *observed_work_order_multiple_numa_nodes =
      static_cast<MockNUMAWorkOrder *>(w.getNormalWorkOrder(0));
  ASSERT_TRUE(observed_work_order_multiple_numa_nodes != nullptr);
  EXPECT_EQ(multiple_numa_work_order.getID(), observed_work_order_multiple_numa_nodes->getID());

  EXPECT_EQ(query_id, observed_work_order_multiple_numa_nodes->getQueryID());
  std::vector<int> observed_numa_nodes(
      observed_work_order_multiple_numa_nodes->getPreferredNUMANodes());
  // Look up the expected numa nodes in the observed_numa_nodes vector.
  EXPECT_TRUE(std::find(observed_numa_nodes.begin(), observed_numa_nodes.end(),
                        numa_nodes[0]) != observed_numa_nodes.end());
  EXPECT_TRUE(std::find(observed_numa_nodes.begin(), observed_numa_nodes.end(),
                        numa_nodes[1]) != observed_numa_nodes.end());

  EXPECT_EQ(0u, w.getNumNormalWorkOrdersForNUMANode(0, numa_nodes[0]));
  EXPECT_EQ(0u, w.getNumNormalWorkOrdersForNUMANode(0, numa_nodes[1]));

  // Expect no normal workorders in total for this operator.
  EXPECT_EQ(0u, w.getNumNormalWorkOrders(0));
  EXPECT_EQ(0u, w.getNumRebuildWorkOrders(0));
}

TEST(WorkOrdersContainerTest, MultipleOperatorsNormalWorkOrderTest) {
  // Generate workorders for multiple operators and test their insertion and
  // retrieval. Use the IDs of the WorkOrders to verify the correctness.

  // Create the NUMA node vectors.
  std::vector<int> numa_node_ids;

  const std::size_t kNumOperators = 100;

  // For each operator create normal workorders with no NUMA node.
  PtrVector<MockNUMAWorkOrder> normal_workorders_no_numa;
  std::vector<int> normal_workorders_no_numa_ids;
  // Set of workorder IDs = {0, ... kNumOperators - 1}
  for (std::size_t i = 0; i < kNumOperators; ++i) {
    normal_workorders_no_numa_ids.push_back(i);
    normal_workorders_no_numa.push_back(new MockNUMAWorkOrder(
        normal_workorders_no_numa_ids.back(), numa_node_ids));
  }

  // Insert one NUMA node.
  numa_node_ids.push_back(0);

  // For each operator create normal workorders with one NUMA node.
  PtrVector<MockNUMAWorkOrder> normal_workorders_one_numa;
  std::vector<int> normal_workorders_one_numa_ids;
  // Set of workorder IDs = {kNumOperators, .. , 2*kNumOperators - 1}
  for (std::size_t i = 0; i < kNumOperators; ++i) {
    normal_workorders_one_numa_ids.push_back(kNumOperators + i);
    normal_workorders_one_numa.push_back(new MockNUMAWorkOrder(
        normal_workorders_one_numa_ids.back(), numa_node_ids));
  }

  // Insert another NUMA node.
  numa_node_ids.push_back(1);

  // For each operator create normal workorders with more than one NUMA node.
  PtrVector<MockNUMAWorkOrder> normal_workorders_multiple_numa;
  std::vector<int> normal_workorders_multiple_numa_ids;
  // Set of workorder IDs = {2*kNumOperators, .. , 3*kNumOperators - 1}
  for (std::size_t i = 0; i < kNumOperators; ++i) {
    normal_workorders_multiple_numa_ids.push_back(2*kNumOperators + i);
    normal_workorders_multiple_numa.push_back(new MockNUMAWorkOrder(
        normal_workorders_multiple_numa_ids.back(), numa_node_ids));
  }

  // TODO(harshad) : Design a test in which the number of NUMA nodes is
  // configurable.
  const std::size_t kNUMANodes = numa_node_ids.size();

  // Create the container.
  const std::size_t query_id = 0;
  WorkOrdersContainer w(kNumOperators, kNUMANodes);

  std::vector<std::size_t> operator_ids;
  for (std::size_t i = 0; i < kNumOperators; ++i) {
    operator_ids.push_back(i);
  }

  // Randomize the operator IDs.
  std::random_shuffle(operator_ids.begin(), operator_ids.end());

  // Insert the workorders.
  for (std::size_t outer_op = 0; outer_op < kNumOperators; ++outer_op) {
    const std::size_t curr_operator_id = operator_ids[outer_op];
    // Check the count of WorkOrders per operator.
    for (std::size_t inner_op = 0; inner_op < kNumOperators; ++inner_op) {
      if (inner_op < outer_op) {
        // WorkOrders inserted already.
        EXPECT_EQ(3u, w.getNumNormalWorkOrders(operator_ids[inner_op]));
        EXPECT_TRUE(w.hasNormalWorkOrder(operator_ids[inner_op]));
        EXPECT_EQ(0u, w.getNumRebuildWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasRebuildWorkOrder(operator_ids[inner_op]));
        // Number of WorkOrders : NUMA Node
        // 2 : 0
        // 1 : 1
        for (int numa_node_used = kNUMANodes - 1; numa_node_used >= 0;
             --numa_node_used) {
          EXPECT_EQ(kNUMANodes - numa_node_used,
                    w.getNumNormalWorkOrdersForNUMANode(
                        operator_ids[inner_op], numa_node_ids[numa_node_used]));
          EXPECT_TRUE(w.hasNormalWorkOrderForNUMANode(
              operator_ids[inner_op], numa_node_ids[numa_node_used]));
        }
      } else {
        // WorkOrders yet to be inserted.
        EXPECT_EQ(0u, w.getNumNormalWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasNormalWorkOrder(operator_ids[inner_op]));
        EXPECT_EQ(0u, w.getNumRebuildWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasRebuildWorkOrder(operator_ids[inner_op]));
        for (int numa_node_used = kNUMANodes - 1; numa_node_used >= 0;
             --numa_node_used) {
          EXPECT_EQ(
              0u, w.getNumNormalWorkOrdersForNUMANode(
                     operator_ids[inner_op], numa_node_ids[numa_node_used]));
          EXPECT_FALSE(w.hasNormalWorkOrderForNUMANode(
              operator_ids[inner_op], numa_node_ids[numa_node_used]));
        }
      }
    }
    // Insert the workorder with multiple NUMA nodes.
    w.addNormalWorkOrder(&(normal_workorders_multiple_numa[curr_operator_id]),
                        curr_operator_id);
    // Insert the workorder with no NUMA node.
    w.addNormalWorkOrder(&(normal_workorders_no_numa[curr_operator_id]),
                        curr_operator_id);
    // Insert the workorder with one NUMA node.
    w.addNormalWorkOrder(&(normal_workorders_one_numa[curr_operator_id]),
                        curr_operator_id);
  }

  // Randomize the operator IDs again and retrieve the WorkOrders.
  std::random_shuffle(operator_ids.begin(), operator_ids.end());
  for (std::size_t outer_op = 0; outer_op < kNumOperators; ++outer_op) {
    const std::size_t curr_operator_id = operator_ids[outer_op];
    // Check if the existing WorkOrder counts are correct.
    for (std::size_t inner_op = 0; inner_op < kNumOperators; ++inner_op) {
      if (inner_op >= outer_op) {
        // WorkOrders not yet retrieved.
        EXPECT_EQ(3u, w.getNumNormalWorkOrders(operator_ids[inner_op]));
        EXPECT_TRUE(w.hasNormalWorkOrder(operator_ids[inner_op]));
        EXPECT_EQ(0u, w.getNumRebuildWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasRebuildWorkOrder(operator_ids[inner_op]));
        // Number of WorkOrders : NUMA Node
        // 2 : 0
        // 1 : 1
        for (int numa_node_used = kNUMANodes - 1; numa_node_used >= 0;
             --numa_node_used) {
          EXPECT_EQ(
              kNUMANodes - numa_node_used,
              w.getNumNormalWorkOrdersForNUMANode(
                  operator_ids[inner_op], numa_node_ids[numa_node_used]));
          EXPECT_TRUE(w.hasNormalWorkOrderForNUMANode(
              operator_ids[inner_op], numa_node_ids[numa_node_used]));
        }
      } else {
        // WorkOrders already retrieved.
        EXPECT_EQ(0u, w.getNumNormalWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasNormalWorkOrder(operator_ids[inner_op]));
        EXPECT_EQ(0u, w.getNumRebuildWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasRebuildWorkOrder(operator_ids[inner_op]));
        for (int numa_node_used = kNUMANodes - 1; numa_node_used >= 0;
             --numa_node_used) {
          EXPECT_EQ(
              0u, w.getNumNormalWorkOrdersForNUMANode(
                     operator_ids[inner_op], numa_node_ids[numa_node_used]));
          EXPECT_FALSE(w.hasNormalWorkOrderForNUMANode(
              operator_ids[inner_op], numa_node_ids[numa_node_used]));
        }
      }
    }
    // There is a workorder with exactly one NUMA node, get that node id.
    const std::size_t single_numa_node_id = numa_node_ids.front();
    // There is a workorder with more than one NUMA node, get that node id
    // (which is different than the node id above).
    const std::size_t multiple_numa_node_id = numa_node_ids.back();

    // Retrieve a single NUMA node workorder.
    MockNUMAWorkOrder *observed_work_order_single_numa =
        static_cast<MockNUMAWorkOrder *>(w.getNormalWorkOrderForNUMANode(
            curr_operator_id, single_numa_node_id));
    ASSERT_TRUE(observed_work_order_single_numa != nullptr);

    EXPECT_EQ(query_id, observed_work_order_single_numa->getQueryID());
    // Verify if the workorder ID is correct.
    const int expected_workorder_id_single_numa =
        normal_workorders_one_numa_ids[curr_operator_id];
    EXPECT_EQ(expected_workorder_id_single_numa,
              observed_work_order_single_numa->getID());

    // Retrieve a multiple NUMA node workorder.
    MockNUMAWorkOrder *observed_work_order_multiple_numa =
        static_cast<MockNUMAWorkOrder *>(w.getNormalWorkOrderForNUMANode(
            curr_operator_id, multiple_numa_node_id));
    ASSERT_TRUE(observed_work_order_multiple_numa != nullptr);

    EXPECT_EQ(query_id, observed_work_order_multiple_numa->getQueryID());
    // Verify if the workorder ID is correct.
    const int expected_workorder_id_multiple_numa =
        normal_workorders_multiple_numa_ids[curr_operator_id];

    EXPECT_EQ(expected_workorder_id_multiple_numa,
              observed_work_order_multiple_numa->getID());

    // Retrieve a no NUMA node workorder.
    MockNUMAWorkOrder *observed_work_order_no_numa =
        static_cast<MockNUMAWorkOrder *>(w.getNormalWorkOrder(curr_operator_id));
    ASSERT_TRUE(observed_work_order_no_numa != nullptr);

    EXPECT_EQ(query_id, observed_work_order_no_numa->getQueryID());
    // Verify if the workorder ID is correct.
    const int expected_workorder_id_no_numa =
        normal_workorders_no_numa_ids[curr_operator_id];

    EXPECT_EQ(expected_workorder_id_no_numa, observed_work_order_no_numa->getID());
  }
}

TEST(WorkOrdersContainerTest, MultipleOperatorsRebuildWorkOrderTest) {
  // This test is exactly similar to previous one, except that this test checks
  // rebuild workorders related interface.

  // Create the NUMA node vectors.
  std::vector<int> numa_node_ids;

  const std::size_t kNumOperators = 100;

  // For each operator create rebuild workorders with no NUMA node.
  PtrVector<MockNUMAWorkOrder> rebuild_workorders_no_numa;
  std::vector<int> rebuild_workorders_no_numa_ids;
  // Set of workorder IDs = {0, ... kNumOperators - 1}
  for (std::size_t i = 0; i < kNumOperators; ++i) {
    rebuild_workorders_no_numa_ids.push_back(i);
    rebuild_workorders_no_numa.push_back(new MockNUMAWorkOrder(
        rebuild_workorders_no_numa_ids.back(), numa_node_ids));
  }

  // Insert one NUMA node.
  numa_node_ids.push_back(0);

  // For each operator create rebuild workorders with one NUMA node.
  PtrVector<MockNUMAWorkOrder> rebuild_workorders_one_numa;
  std::vector<int> rebuild_workorders_one_numa_ids;
  // Set of workorder IDs = {kNumOperators, .. , 2*kNumOperators - 1}
  for (std::size_t i = 0; i < kNumOperators; ++i) {
    rebuild_workorders_one_numa_ids.push_back(kNumOperators + i);
    rebuild_workorders_one_numa.push_back(new MockNUMAWorkOrder(
        rebuild_workorders_one_numa_ids.back(), numa_node_ids));
  }

  // Insert another NUMA node.
  numa_node_ids.push_back(1);

  // For each operator create rebuild workorders with more than one NUMA node.
  PtrVector<MockNUMAWorkOrder> rebuild_workorders_multiple_numa;
  std::vector<int> rebuild_workorders_multiple_numa_ids;
  // Set of workorder IDs = {2*kNumOperators, .. , 3*kNumOperators - 1}
  for (std::size_t i = 0; i < kNumOperators; ++i) {
    rebuild_workorders_multiple_numa_ids.push_back(2*kNumOperators + i);
    rebuild_workorders_multiple_numa.push_back(new MockNUMAWorkOrder(
        rebuild_workorders_multiple_numa_ids.back(), numa_node_ids));
  }

  // TODO(harshad) : Design a test in which the number of NUMA nodes is
  // configurable.
  const std::size_t kNUMANodes = numa_node_ids.size();

  // Create the container.
  const std::size_t query_id = 0;
  WorkOrdersContainer w(kNumOperators, kNUMANodes);

  std::vector<std::size_t> operator_ids;
  for (std::size_t i = 0; i < kNumOperators; ++i) {
    operator_ids.push_back(i);
  }

  // Randomize the operator IDs.
  std::random_shuffle(operator_ids.begin(), operator_ids.end());

  // Insert the workorders.
  for (std::size_t outer_op = 0; outer_op < kNumOperators; ++outer_op) {
    const std::size_t curr_operator_id = operator_ids[outer_op];
    // Check the count of WorkOrders per operator.
    for (std::size_t inner_op = 0; inner_op < kNumOperators; ++inner_op) {
      if (inner_op < outer_op) {
        // WorkOrders inserted already.
        EXPECT_EQ(3u, w.getNumRebuildWorkOrders(operator_ids[inner_op]));
        EXPECT_TRUE(w.hasRebuildWorkOrder(operator_ids[inner_op]));
        EXPECT_EQ(0u, w.getNumNormalWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasNormalWorkOrder(operator_ids[inner_op]));
        // Number of WorkOrders : NUMA Node
        // 2 : 0
        // 1 : 1
        for (int numa_node_used = kNUMANodes - 1; numa_node_used >= 0;
             --numa_node_used) {
          EXPECT_EQ(
              kNUMANodes - numa_node_used,
              w.getNumRebuildWorkOrdersForNUMANode(
                  operator_ids[inner_op], numa_node_ids[numa_node_used]));
          EXPECT_TRUE(w.hasRebuildWorkOrderForNUMANode(
              operator_ids[inner_op], numa_node_ids[numa_node_used]));
        }
      } else {
        // WorkOrders yet to be inserted.
        EXPECT_EQ(0u, w.getNumRebuildWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasRebuildWorkOrder(operator_ids[inner_op]));
        EXPECT_EQ(0u, w.getNumNormalWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasNormalWorkOrder(operator_ids[inner_op]));
        for (int numa_node_used = kNUMANodes - 1; numa_node_used >= 0;
             --numa_node_used) {
          EXPECT_EQ(
              0u, w.getNumRebuildWorkOrdersForNUMANode(
                     operator_ids[inner_op], numa_node_ids[numa_node_used]));
          EXPECT_FALSE(w.hasRebuildWorkOrderForNUMANode(
              operator_ids[inner_op], numa_node_ids[numa_node_used]));
        }
      }
    }
    // Insert the workorder with multiple NUMA nodes.
    w.addRebuildWorkOrder(&(rebuild_workorders_multiple_numa[curr_operator_id]),
                         curr_operator_id);
    // Insert the workorder with no NUMA node.
    w.addRebuildWorkOrder(&(rebuild_workorders_no_numa[curr_operator_id]),
                         curr_operator_id);
    // Insert the workorder with one NUMA node.
    w.addRebuildWorkOrder(&(rebuild_workorders_one_numa[curr_operator_id]),
                         curr_operator_id);
  }

  // Randomize the operator IDs again and retrieve the WorkOrders.
  std::random_shuffle(operator_ids.begin(), operator_ids.end());
  for (std::size_t outer_op = 0; outer_op < kNumOperators; ++outer_op) {
    const std::size_t curr_operator_id = operator_ids[outer_op];
    // Check if the existing WorkOrder counts are correct.
    for (std::size_t inner_op = 0; inner_op < kNumOperators; ++inner_op) {
      if (inner_op >= outer_op) {
        // WorkOrders not yet retrieved.
        EXPECT_EQ(3u, w.getNumRebuildWorkOrders(operator_ids[inner_op]));
        EXPECT_TRUE(w.hasRebuildWorkOrder(operator_ids[inner_op]));
        EXPECT_EQ(0u, w.getNumNormalWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasNormalWorkOrder(operator_ids[inner_op]));
        // Number of WorkOrders : NUMA Node
        // 2 : 0
        // 1 : 1
        for (int numa_node_used = kNUMANodes - 1; numa_node_used >= 0;
             --numa_node_used) {
          EXPECT_EQ(
              kNUMANodes - numa_node_used,
              w.getNumRebuildWorkOrdersForNUMANode(
                  operator_ids[inner_op], numa_node_ids[numa_node_used]));
          EXPECT_TRUE(w.hasRebuildWorkOrderForNUMANode(
              operator_ids[inner_op], numa_node_ids[numa_node_used]));
        }
      } else {
        // WorkOrders already retrieved.
        EXPECT_EQ(0u, w.getNumRebuildWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasRebuildWorkOrder(operator_ids[inner_op]));
        EXPECT_EQ(0u, w.getNumNormalWorkOrders(operator_ids[inner_op]));
        EXPECT_FALSE(w.hasNormalWorkOrder(operator_ids[inner_op]));
        for (int numa_node_used = kNUMANodes - 1; numa_node_used >= 0;
             --numa_node_used) {
          EXPECT_EQ(
              0u, w.getNumRebuildWorkOrdersForNUMANode(
                     operator_ids[inner_op], numa_node_ids[numa_node_used]));
          EXPECT_FALSE(w.hasRebuildWorkOrderForNUMANode(
              operator_ids[inner_op], numa_node_ids[numa_node_used]));
        }
      }
    }
    // There is a workorder with exactly one NUMA node, get that node id.
    const std::size_t single_numa_node_id = numa_node_ids.front();
    // There is a workorder with more than one NUMA node, get that node id
    // (which is different than the node id above).
    const std::size_t multiple_numa_node_id = numa_node_ids.back();

    // Retrieve a single NUMA node workorder.
    MockNUMAWorkOrder *observed_work_order_single_numa =
        static_cast<MockNUMAWorkOrder *>(w.getRebuildWorkOrderForNUMANode(
            curr_operator_id, single_numa_node_id));
    ASSERT_TRUE(observed_work_order_single_numa != nullptr);

    EXPECT_EQ(query_id, observed_work_order_single_numa->getQueryID());
    // Verify if the workorder ID is correct.
    const int expected_workorder_id_single_numa =
        rebuild_workorders_one_numa_ids[curr_operator_id];
    EXPECT_EQ(expected_workorder_id_single_numa,
              observed_work_order_single_numa->getID());

    // Retrieve a multiple NUMA node workorder.
    MockNUMAWorkOrder *observed_work_order_multiple_numa =
        static_cast<MockNUMAWorkOrder *>(w.getRebuildWorkOrderForNUMANode(
            curr_operator_id, multiple_numa_node_id));
    ASSERT_TRUE(observed_work_order_multiple_numa != nullptr);

    EXPECT_EQ(query_id, observed_work_order_multiple_numa->getQueryID());
    // Verify if the workorder ID is correct.
    const int expected_workorder_id_multiple_numa =
        rebuild_workorders_multiple_numa_ids[curr_operator_id];

    EXPECT_EQ(expected_workorder_id_multiple_numa,
              observed_work_order_multiple_numa->getID());

    // Retrieve a no NUMA node workorder.
    MockNUMAWorkOrder *observed_work_order_no_numa =
        static_cast<MockNUMAWorkOrder *>(w.getRebuildWorkOrder(curr_operator_id));

    EXPECT_EQ(query_id, observed_work_order_no_numa->getQueryID());
    // Verify if the workorder ID is correct.
    const int expected_workorder_id_no_numa =
        rebuild_workorders_no_numa_ids[curr_operator_id];

    EXPECT_EQ(expected_workorder_id_no_numa, observed_work_order_no_numa->getID());
  }
}

TEST(WorkOrdersContainerTest, RetrievalOrderTest) {
  // Create only two kinds of workorders -
  // 1. WorkOrder with exactly one NUMA node as input.
  // 2. WorkOrder with more than one NUMA node as input.
  // Vary the parameter prefer_single_NUMA_node and verify the behavior.
  std::vector<int> numa_node_ids;
  numa_node_ids.push_back(0);
  const std::size_t kNumWorkOrdersPerType = 100;

  const std::size_t query_id = 0;
  WorkOrdersContainer w(1, 2);

  std::vector<int> single_numa_node_workorder_ids;
  std::vector<int> multiple_numa_node_workorder_ids;

  PtrVector<MockNUMAWorkOrder> single_numa_node_workorders;
  PtrVector<MockNUMAWorkOrder> multiple_numa_node_workorders;

  // Insert WorkOrders with exactly one NUMA node and store the WorkOrder IDs.
  for (std::size_t work_order_num = 0;
       work_order_num < kNumWorkOrdersPerType;
       ++work_order_num) {
    w.addNormalWorkOrder(new MockNUMAWorkOrder(work_order_num, numa_node_ids), 0);
    single_numa_node_workorder_ids.push_back(work_order_num);
  }

  numa_node_ids.push_back(1);

  // Insert WorkOrders with more than one NUMA node and store the WorkOrder IDs.
  for (std::size_t work_order_num = 0;
       work_order_num < kNumWorkOrdersPerType;
       ++work_order_num) {
    w.addNormalWorkOrder(
        new MockNUMAWorkOrder(work_order_num + kNumWorkOrdersPerType, numa_node_ids),
        0);
    multiple_numa_node_workorder_ids.push_back(kNumWorkOrdersPerType + work_order_num);
  }

  // Create a vector of booleans of size kNumWorkOrdersPerType * 2
  std::vector<bool> retrieval_order;
  for (std::size_t i = 0; i < kNumWorkOrdersPerType; ++i) {
    retrieval_order.push_back(true);
    retrieval_order.push_back(false);
  }

  // Randomize the order of retrieval.
  std::random_shuffle(retrieval_order.begin(), retrieval_order.end());

  std::vector<int>::iterator single_numa_it =
      single_numa_node_workorder_ids.begin();
  std::vector<int>::iterator multiple_numa_it =
      multiple_numa_node_workorder_ids.begin();

  for (bool prefer_single_NUMA_node : retrieval_order) {
    // Retrieve the WorkOrder.
    MockNUMAWorkOrder *observed_work_order = static_cast<MockNUMAWorkOrder *>(
        w.getNormalWorkOrder(0, prefer_single_NUMA_node));
    ASSERT_TRUE(observed_work_order != nullptr);
    EXPECT_EQ(query_id, observed_work_order->getQueryID());
    if (prefer_single_NUMA_node) {
      EXPECT_EQ(*single_numa_it, observed_work_order->getID());
      EXPECT_EQ(1u, observed_work_order->getPreferredNUMANodes().size());
      ++single_numa_it;
    } else {
      EXPECT_EQ(*multiple_numa_it, observed_work_order->getID());
      EXPECT_EQ(2u, observed_work_order->getPreferredNUMANodes().size());
      ++multiple_numa_it;
    }
  }
  DEBUG_ASSERT(single_numa_it == single_numa_node_workorder_ids.end());
  DEBUG_ASSERT(multiple_numa_it == multiple_numa_node_workorder_ids.end());

  // Expect no more workorders.
  EXPECT_EQ(nullptr, w.getNormalWorkOrder(0, true));
  EXPECT_EQ(nullptr, w.getNormalWorkOrder(0, false));
}

}  // namespace quickstep
