// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include "arch/x86/system_topology.h"

#include <lib/acpi_tables_test_data.h>
#include <lib/system-topology.h>
#include <lib/unittest/unittest.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <initializer_list>

#include <arch/x86/cpuid_test_data.h>

using system_topology::Graph;

namespace {

// Uses test data from a HP z840, dual socket Xeon E2690v4.
bool test_cpus_z840() {
  BEGIN_TEST;

  fbl::Vector<zbi_topology_node_t> flat_topology;
  auto status = x86::GenerateFlatTopology(
      cpu_id::kCpuIdXeon2690v4, AcpiTables(&acpi_test_data::kZ840TableProvider), &flat_topology);
  ASSERT_EQ(ZX_OK, status);

  int numa_count = 0;
  int die_count = 0;
  int cache_count = 0;
  int core_count = 0;
  int thread_count = 0;
  int last_numa = -1;
  int last_die = -1;
  int last_cache = -1;
  for (int i = 0; i < (int)flat_topology.size(); i++) {
    const auto& node = flat_topology[i];
    switch (node.entity_type) {
      case ZBI_TOPOLOGY_ENTITY_NUMA_REGION:
        last_numa = i;
        numa_count++;
        break;
      case ZBI_TOPOLOGY_ENTITY_DIE:
        EXPECT_EQ(last_numa, node.parent_index);
        last_die = i;
        die_count++;
        break;
      case ZBI_TOPOLOGY_ENTITY_CACHE:
        EXPECT_EQ(last_die, node.parent_index);
        last_cache = i;
        cache_count++;
        break;
      case ZBI_TOPOLOGY_ENTITY_PROCESSOR:
        EXPECT_EQ(last_cache, node.parent_index);
        core_count++;
        thread_count += node.entity.processor.logical_id_count;
        break;
    }
  }

  // We expect two numa regions, two dies, two caches, and 28 cores.
  EXPECT_EQ(2u + 2u + 2u + 28u, flat_topology.size());
  EXPECT_EQ(2, numa_count);
  EXPECT_EQ(2, die_count);
  EXPECT_EQ(2, cache_count);
  EXPECT_EQ(28, core_count);
  EXPECT_EQ(56, thread_count);

  // Ensure the format can be parsed and validated by the system topology library.
  Graph graph;
  EXPECT_EQ(ZX_OK, Graph::Initialize(&graph, flat_topology.data(), flat_topology.size()));

  END_TEST;
}

// Uses test data from a Threadripper 2970wx system with x399 chipset.
bool test_cpus_2970wx_x399() {
  BEGIN_TEST;

  fbl::Vector<zbi_topology_node_t> flat_topology;
  auto status =
      x86::GenerateFlatTopology(cpu_id::kCpuIdThreadRipper2970wx,
                                AcpiTables(&acpi_test_data::k2970wxTableProvider), &flat_topology);
  ASSERT_EQ(ZX_OK, status);

  int numa_count = 0;
  int die_count = 0;
  int core_count = 0;
  int cache_count = 0;
  int thread_count = 0;
  int last_numa = -1;
  int last_die = -1;
  int last_cache = -1;
  for (int i = 0; i < (int)flat_topology.size(); i++) {
    const auto& node = flat_topology[i];
    switch (node.entity_type) {
      case ZBI_TOPOLOGY_ENTITY_NUMA_REGION:
        last_numa = i;
        numa_count++;
        break;
      case ZBI_TOPOLOGY_ENTITY_DIE:
        EXPECT_EQ(last_numa, node.parent_index);
        last_die = i;
        die_count++;
        break;
      case ZBI_TOPOLOGY_ENTITY_CACHE:
        EXPECT_EQ(last_die, node.parent_index);
        last_cache = i;
        cache_count++;
        break;
      case ZBI_TOPOLOGY_ENTITY_PROCESSOR:
        EXPECT_EQ(last_cache, node.parent_index);
        core_count++;
        thread_count += node.entity.processor.logical_id_count;
        break;
    }
  }

  EXPECT_EQ(4, numa_count);
  EXPECT_EQ(4, die_count);
  EXPECT_EQ(8, cache_count);
  EXPECT_EQ(24, core_count);
  EXPECT_EQ(48, thread_count);

  // Ensure the format can be parsed and validated by the system topology library.
  Graph graph;
  EXPECT_EQ(ZX_OK, Graph::Initialize(&graph, flat_topology.data(), flat_topology.size()));

  END_TEST;
}

// Uses bad data to trigger the fallback topology, (everything flat).
bool test_cpus_fallback() {
  BEGIN_TEST;

  // The minimal cpuid data set to fallthrough our level parsing.
  // The number of processors is pulled from acpi so combining these gets us a
  // bad-cpuid but good acpi condition we are seeing on some hypervisors.
  const cpu_id::TestDataSet fallback_cpuid_data = {
    .features = {},
    .missing_features = {},
    .leaf0 = {},
    .leaf1 = {},
    .leaf4 = {},
    .leaf6 = {},
    .leaf7 = {},
    .leafB = {},
    .leaf8_0 = {.reg = {0x80000008, 0x0, 0x0}},
    .leaf8_1 = {},
    .leaf8_7 = {},
    .leaf8_8 = {},
    .leaf8_1D = {},
    .leaf8_1E = {},
  };

  fbl::Vector<zbi_topology_node_t> flat_topology;
  auto status =
      x86::GenerateFlatTopology(cpu_id::FakeCpuId(fallback_cpuid_data),
                                AcpiTables(&acpi_test_data::kEveTableProvider), &flat_topology);
  ASSERT_EQ(ZX_OK, status);

  int numa_count = 0;
  int die_count = 0;
  int core_count = 0;
  int cache_count = 0;
  int thread_count = 0;
  for (int i = 0; i < (int)flat_topology.size(); i++) {
    const auto& node = flat_topology[i];
    switch (node.entity_type) {
      case ZBI_TOPOLOGY_ENTITY_NUMA_REGION:
        numa_count++;
        break;
      case ZBI_TOPOLOGY_ENTITY_DIE:
        die_count++;
        break;
      case ZBI_TOPOLOGY_ENTITY_CACHE:
        cache_count++;
        break;
      case ZBI_TOPOLOGY_ENTITY_PROCESSOR:
        core_count++;
        thread_count += node.entity.processor.logical_id_count;
        break;
    }
  }

  EXPECT_EQ(0, numa_count);
  EXPECT_EQ(1, die_count);
  EXPECT_EQ(0, cache_count);
  EXPECT_EQ(4, core_count);
  EXPECT_EQ(4, thread_count);

  // Ensure the format can be parsed and validated by the system topology library.
  Graph graph;
  EXPECT_EQ(ZX_OK, Graph::Initialize(&graph, flat_topology.data(), flat_topology.size()));

  END_TEST;
}

}  // namespace

UNITTEST_START_TESTCASE(x86_topology_tests)
UNITTEST("Enumerate cpus using data from HP z840.", test_cpus_z840)
UNITTEST("Enumerate cpus using data from ThreadRipper 2970wx/X399.", test_cpus_2970wx_x399)
UNITTEST("Enumerate cpus using data triggering fallback.", test_cpus_fallback)
UNITTEST_END_TESTCASE(x86_topology_tests, "x86_topology",
                      "Test determining x86 topology through CPUID/APIC.")
