/*
 * Copyright (C) 2019 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 "src/profiling/perf/event_config.h"

#include <linux/perf_event.h>
#include <stdint.h>
#include <time.h>

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/optional.h"
#include "test/gtest_and_gmock.h"

#include "protos/perfetto/common/perf_events.gen.h"
#include "protos/perfetto/config/data_source_config.gen.h"
#include "protos/perfetto/config/profiling/perf_event_config.gen.h"

using ::testing::UnorderedElementsAreArray;

namespace perfetto {
namespace profiling {
namespace {

bool IsPowerOfTwo(size_t v) {
  return (v != 0 && ((v & (v - 1)) == 0));
}

static DataSourceConfig AsDataSourceConfig(
    const protos::gen::PerfEventConfig& perf_cfg) {
  protos::gen::DataSourceConfig ds_cfg;
  ds_cfg.set_perf_event_config_raw(perf_cfg.SerializeAsString());
  return ds_cfg;
}

TEST(EventConfigTest, AttrStructConstructed) {
  protos::gen::PerfEventConfig cfg;
  base::Optional<EventConfig> event_config =
      EventConfig::Create(AsDataSourceConfig(cfg));

  ASSERT_TRUE(event_config.has_value());
  ASSERT_TRUE(event_config->perf_attr() != nullptr);
}

TEST(EventConfigTest, RingBufferPagesValidated) {
  {  // if unset, a default is used
    protos::gen::PerfEventConfig cfg;
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    ASSERT_GT(event_config->ring_buffer_pages(), 0u);
    ASSERT_TRUE(IsPowerOfTwo(event_config->ring_buffer_pages()));
  }
  {  // power of two pages accepted
    uint32_t num_pages = 128;
    protos::gen::PerfEventConfig cfg;
    cfg.set_ring_buffer_pages(num_pages);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    ASSERT_EQ(event_config->ring_buffer_pages(), num_pages);
  }
  {  // entire config rejected if not a power of two of pages
    protos::gen::PerfEventConfig cfg;
    cfg.set_ring_buffer_pages(7);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_FALSE(event_config.has_value());
  }
}

TEST(EventConfigTest, ReadTickPeriodDefaultedIfUnset) {
  {  // if unset, a default is used
    protos::gen::PerfEventConfig cfg;
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    ASSERT_GT(event_config->read_tick_period_ms(), 0u);
  }
  {  // otherwise, given value used
    uint32_t period_ms = 250;
    protos::gen::PerfEventConfig cfg;
    cfg.set_ring_buffer_read_period_ms(period_ms);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    ASSERT_EQ(event_config->read_tick_period_ms(), period_ms);
  }
}

TEST(EventConfigTest, RemotePeriodTimeoutDefaultedIfUnset) {
  {  // if unset, a default is used
    protos::gen::PerfEventConfig cfg;
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    ASSERT_GT(event_config->remote_descriptor_timeout_ms(), 0u);
  }
  {  // otherwise, given value used
    uint32_t timeout_ms = 300;
    protos::gen::PerfEventConfig cfg;
    cfg.set_remote_descriptor_timeout_ms(timeout_ms);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    ASSERT_EQ(event_config->remote_descriptor_timeout_ms(), timeout_ms);
  }
}

TEST(EventConfigTest, EnableKernelFrames) {
  {
    protos::gen::PerfEventConfig cfg;
    cfg.mutable_callstack_sampling()->set_kernel_frames(true);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_TRUE(event_config->kernel_frames());
  }
  {  // legacy config:
    protos::gen::PerfEventConfig cfg;
    cfg.set_all_cpus(true);  // used to detect compat mode
    cfg.set_kernel_frames(true);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_TRUE(event_config->kernel_frames());
  }
  {  // default is false
    protos::gen::PerfEventConfig cfg;
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_FALSE(event_config->kernel_frames());
  }
}

TEST(EventConfigTest, SelectSamplingInterval) {
  {  // period:
    protos::gen::PerfEventConfig cfg;
    cfg.mutable_timebase()->set_period(100);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_FALSE(event_config->perf_attr()->freq);
    EXPECT_EQ(event_config->perf_attr()->sample_period, 100u);
  }
  {  // frequency:
    protos::gen::PerfEventConfig cfg;
    cfg.mutable_timebase()->set_frequency(4000);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_TRUE(event_config->perf_attr()->freq);
    EXPECT_EQ(event_config->perf_attr()->sample_freq, 4000u);
  }
  {  // legacy frequency field:
    protos::gen::PerfEventConfig cfg;
    cfg.set_sampling_frequency(5000);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_TRUE(event_config->perf_attr()->freq);
    EXPECT_EQ(event_config->perf_attr()->sample_freq, 5000u);
  }
  {  // default is 10 Hz (implementation-defined)
    protos::gen::PerfEventConfig cfg;
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_TRUE(event_config->perf_attr()->freq);
    EXPECT_EQ(event_config->perf_attr()->sample_freq, 10u);
  }
}

TEST(EventConfigTest, SelectTimebaseEvent) {
  auto id_lookup = [](const std::string& group, const std::string& name) {
    return (group == "sched" && name == "sched_switch") ? 42 : 0;
  };

  {
    protos::gen::PerfEventConfig cfg;
    protos::gen::PerfEvents::Tracepoint* mutable_tracepoint =
        cfg.mutable_timebase()->mutable_tracepoint();
    mutable_tracepoint->set_name("sched:sched_switch");

    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg), id_lookup);

    ASSERT_TRUE(event_config.has_value());
    EXPECT_EQ(event_config->perf_attr()->type, PERF_TYPE_TRACEPOINT);
    EXPECT_EQ(event_config->perf_attr()->config, 42u);
  }
  {  // default is the CPU timer:
    protos::gen::PerfEventConfig cfg;
    cfg.mutable_timebase()->set_frequency(1000);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_EQ(event_config->perf_attr()->type, PERF_TYPE_SOFTWARE);
    EXPECT_EQ(event_config->perf_attr()->config, PERF_COUNT_SW_CPU_CLOCK);
  }
}

TEST(EventConfigTest, ParseTargetfilter) {
  {
    protos::gen::PerfEventConfig cfg;
    auto* mutable_scope = cfg.mutable_callstack_sampling()->mutable_scope();
    mutable_scope->add_target_pid(42);
    mutable_scope->add_target_cmdline("traced_probes");
    mutable_scope->add_target_cmdline("traced");
    mutable_scope->set_additional_cmdline_count(3);
    mutable_scope->add_exclude_cmdline("heapprofd");

    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    const auto& filter = event_config->filter();
    EXPECT_THAT(filter.pids, UnorderedElementsAreArray({42}));
    EXPECT_THAT(filter.cmdlines,
                UnorderedElementsAreArray({"traced_probes", "traced"}));
    EXPECT_EQ(filter.additional_cmdline_count, 3u);
    EXPECT_TRUE(filter.exclude_pids.empty());
    EXPECT_THAT(filter.exclude_cmdlines,
                UnorderedElementsAreArray({"heapprofd"}));
  }
  {  // legacy:
    protos::gen::PerfEventConfig cfg;
    cfg.set_all_cpus(true);
    cfg.add_target_pid(42);
    cfg.add_target_cmdline("traced_probes");
    cfg.add_target_cmdline("traced");
    cfg.set_additional_cmdline_count(3);
    cfg.add_exclude_cmdline("heapprofd");

    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    const auto& filter = event_config->filter();
    EXPECT_THAT(filter.pids, UnorderedElementsAreArray({42}));
    EXPECT_THAT(filter.cmdlines,
                UnorderedElementsAreArray({"traced_probes", "traced"}));
    EXPECT_EQ(filter.additional_cmdline_count, 3u);
    EXPECT_TRUE(filter.exclude_pids.empty());
    EXPECT_THAT(filter.exclude_cmdlines,
                UnorderedElementsAreArray({"heapprofd"}));
  }
}

TEST(EventConfigTest, CounterOnlyModeDetection) {
  {  // hardware counter:
    protos::gen::PerfEventConfig cfg;
    auto* mutable_timebase = cfg.mutable_timebase();
    mutable_timebase->set_period(500);
    mutable_timebase->set_counter(protos::gen::PerfEvents::HW_CPU_CYCLES);

    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_EQ(event_config->perf_attr()->type, PERF_TYPE_HARDWARE);
    EXPECT_EQ(event_config->perf_attr()->config, PERF_COUNT_HW_CPU_CYCLES);
    EXPECT_EQ(event_config->perf_attr()->sample_type &
                  (PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER),
              0u);
  }
  {  // software counter:
    protos::gen::PerfEventConfig cfg;
    auto* mutable_timebase = cfg.mutable_timebase();
    mutable_timebase->set_period(500);
    mutable_timebase->set_counter(protos::gen::PerfEvents::SW_PAGE_FAULTS);

    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_EQ(event_config->perf_attr()->type, PERF_TYPE_SOFTWARE);
    EXPECT_EQ(event_config->perf_attr()->config, PERF_COUNT_SW_PAGE_FAULTS);
    EXPECT_EQ(event_config->perf_attr()->sample_type &
                  (PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER),
              0u);
  }
}

TEST(EventConfigTest, CallstackSamplingModeDetection) {
  {  // set-but-empty |callstack_sampling| field enables callstacks
    protos::gen::PerfEventConfig cfg;
    cfg.mutable_callstack_sampling();  // set field

    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_EQ(
        event_config->perf_attr()->sample_type &
            (PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER),
        static_cast<uint64_t>(PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER));

    EXPECT_NE(event_config->perf_attr()->sample_regs_user, 0u);
    EXPECT_NE(event_config->perf_attr()->sample_stack_user, 0u);
  }
}

TEST(EventConfigTest, TimestampClockId) {
  {  // if unset, a default is used
    protos::gen::PerfEventConfig cfg;
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_TRUE(event_config->perf_attr()->use_clockid);
    EXPECT_EQ(event_config->perf_attr()->clockid, CLOCK_MONOTONIC_RAW);
  }
  {  // explicit boottime
    protos::gen::PerfEventConfig cfg;
    cfg.mutable_timebase()->set_timestamp_clock(
        protos::gen::PerfEvents::PERF_CLOCK_BOOTTIME);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_TRUE(event_config->perf_attr()->use_clockid);
    EXPECT_EQ(event_config->perf_attr()->clockid, CLOCK_BOOTTIME);
  }
  {  // explicit monotonic
    protos::gen::PerfEventConfig cfg;
    cfg.mutable_timebase()->set_timestamp_clock(
        protos::gen::PerfEvents::PERF_CLOCK_MONOTONIC);
    base::Optional<EventConfig> event_config =
        EventConfig::Create(AsDataSourceConfig(cfg));

    ASSERT_TRUE(event_config.has_value());
    EXPECT_TRUE(event_config->perf_attr()->use_clockid);
    EXPECT_EQ(event_config->perf_attr()->clockid, CLOCK_MONOTONIC);
  }
}

}  // namespace
}  // namespace profiling
}  // namespace perfetto
