/*
 * Copyright (C) 2015 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 <gtest/gtest.h>

#include <sys/stat.h>
#include <unistd.h>
#if defined(__BIONIC__)
#include <android-base/properties.h>
#endif

#include <atomic>
#include <chrono>
#include <thread>
#include <unordered_map>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>

#include "environment.h"
#include "event_attr.h"
#include "event_fd.h"
#include "event_type.h"
#include "utils.h"

static auto test_duration_for_long_tests = std::chrono::seconds(120);
static auto cpu_hotplug_interval = std::chrono::microseconds(1000);
static bool verbose_mode = false;

#if defined(__BIONIC__)
class ScopedMpdecisionKiller {
 public:
  ScopedMpdecisionKiller() {
    have_mpdecision_ = IsMpdecisionRunning();
    if (have_mpdecision_) {
      DisableMpdecision();
    }
  }

  ~ScopedMpdecisionKiller() {
    if (have_mpdecision_) {
      EnableMpdecision();
    }
  }

 private:
  bool IsMpdecisionRunning() {
    std::string value = android::base::GetProperty("init.svc.mpdecision", "");
    if (value.empty() || value.find("stopped") != std::string::npos) {
      return false;
    }
    return true;
  }

  void DisableMpdecision() {
    CHECK(android::base::SetProperty("ctl.stop", "mpdecision"));
    // Need to wait until mpdecision is actually stopped.
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    CHECK(!IsMpdecisionRunning());
  }

  void EnableMpdecision() {
    CHECK(android::base::SetProperty("ctl.start", "mpdecision"));
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    CHECK(IsMpdecisionRunning());
  }

  bool have_mpdecision_;
};
#else
class ScopedMpdecisionKiller {
 public:
  ScopedMpdecisionKiller() {
  }
};
#endif

static bool IsCpuOnline(int cpu, bool* has_error) {
  std::string filename = android::base::StringPrintf("/sys/devices/system/cpu/cpu%d/online", cpu);
  std::string content;
  bool ret = android::base::ReadFileToString(filename, &content);
  if (!ret) {
    PLOG(ERROR) << "failed to read file " << filename;
    *has_error = true;
    return false;
  }
  *has_error = false;
  return (content.find('1') != std::string::npos);
}

static bool SetCpuOnline(int cpu, bool online) {
  bool has_error;
  bool ret = IsCpuOnline(cpu, &has_error);
  if (has_error) {
    return false;
  }
  if (ret == online) {
    return true;
  }
  std::string filename = android::base::StringPrintf("/sys/devices/system/cpu/cpu%d/online", cpu);
  std::string content = online ? "1" : "0";
  ret = android::base::WriteStringToFile(content, filename);
  if (!ret) {
    ret = IsCpuOnline(cpu, &has_error);
    if (has_error) {
      return false;
    }
    if (online == ret) {
      return true;
    }
    PLOG(ERROR) << "failed to write " << content << " to " << filename;
    return false;
  }
  // Kernel needs time to offline/online cpus, so use a loop to wait here.
  size_t retry_count = 0;
  while (true) {
    ret = IsCpuOnline(cpu, &has_error);
    if (has_error) {
      return false;
    }
    if (ret == online) {
      break;
    }
    LOG(ERROR) << "reading cpu retry count = " << retry_count << ", requested = " << online
        << ", real = " << ret;
    if (++retry_count == 10000) {
      LOG(ERROR) << "setting cpu " << cpu << (online ? " online" : " offline") << " seems not to take effect";
      return false;
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  }
  return true;
}

static int GetCpuCount() {
  return static_cast<int>(sysconf(_SC_NPROCESSORS_CONF));
}

class CpuOnlineRestorer {
 public:
  CpuOnlineRestorer() {
    for (int cpu = 1; cpu < GetCpuCount(); ++cpu) {
      bool has_error;
      bool ret = IsCpuOnline(cpu, &has_error);
      if (has_error) {
        continue;
      }
      online_map_[cpu] = ret;
    }
  }

  ~CpuOnlineRestorer() {
    for (const auto& pair : online_map_) {
      SetCpuOnline(pair.first, pair.second);
    }
  }

 private:
  std::unordered_map<int, bool> online_map_;
};

bool FindAHotpluggableCpu(int* hotpluggable_cpu) {
  if (!IsRoot()) {
    GTEST_LOG_(INFO) << "This test needs root privilege to hotplug cpu.";
    return false;
  }
  for (int cpu = 1; cpu < GetCpuCount(); ++cpu) {
    bool has_error;
    bool online = IsCpuOnline(cpu, &has_error);
    if (has_error) {
      continue;
    }
    if (SetCpuOnline(cpu, !online)) {
      *hotpluggable_cpu = cpu;
      return true;
    }
  }
  GTEST_LOG_(INFO) << "There is no hotpluggable cpu.";
  return false;
}

struct CpuToggleThreadArg {
  int toggle_cpu;
  std::atomic<bool> end_flag;
  std::atomic<bool> cpu_hotplug_failed;

  CpuToggleThreadArg(int cpu)
      : toggle_cpu(cpu), end_flag(false), cpu_hotplug_failed(false) {
  }
};

static void CpuToggleThread(CpuToggleThreadArg* arg) {
  while (!arg->end_flag) {
    if (!SetCpuOnline(arg->toggle_cpu, true)) {
      arg->cpu_hotplug_failed = true;
      break;
    }
    std::this_thread::sleep_for(cpu_hotplug_interval);
    if (!SetCpuOnline(arg->toggle_cpu, false)) {
      arg->cpu_hotplug_failed = true;
      break;
    }
    std::this_thread::sleep_for(cpu_hotplug_interval);
  }
}

// http://b/25193162.
TEST(cpu_offline, offline_while_recording) {
  ScopedMpdecisionKiller scoped_mpdecision_killer;
  CpuOnlineRestorer cpuonline_restorer;
  if (GetCpuCount() == 1) {
    GTEST_LOG_(INFO) << "This test does nothing, because there is only one cpu in the system.";
    return;
  }
  // Start cpu hotpluger.
  int test_cpu;
  if (!FindAHotpluggableCpu(&test_cpu)) {
    return;
  }
  CpuToggleThreadArg cpu_toggle_arg(test_cpu);
  std::thread cpu_toggle_thread(CpuToggleThread, &cpu_toggle_arg);

  std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType("cpu-cycles");
  ASSERT_TRUE(event_type_modifier != nullptr);
  perf_event_attr attr = CreateDefaultPerfEventAttr(event_type_modifier->event_type);
  attr.disabled = 0;
  attr.enable_on_exec = 0;

  auto start_time = std::chrono::steady_clock::now();
  auto cur_time = start_time;
  auto end_time = std::chrono::steady_clock::now() + test_duration_for_long_tests;
  auto report_step = std::chrono::seconds(15);
  size_t iterations = 0;

  while (cur_time < end_time && !cpu_toggle_arg.cpu_hotplug_failed) {
    if (cur_time + report_step < std::chrono::steady_clock::now()) {
      // Report test time.
      auto diff = std::chrono::duration_cast<std::chrono::seconds>(
          std::chrono::steady_clock::now() - start_time);
      if (verbose_mode) {
        GTEST_LOG_(INFO) << "Have Tested " << (diff.count() / 60.0) << " minutes.";
      }
      cur_time = std::chrono::steady_clock::now();
    }

    std::unique_ptr<EventFd> event_fd = EventFd::OpenEventFile(attr, -1, test_cpu, nullptr, false);
    if (event_fd == nullptr) {
      // Failed to open because the test_cpu is offline.
      continue;
    }
    iterations++;
    if (verbose_mode) {
      GTEST_LOG_(INFO) << "Test offline while recording for " << iterations << " times.";
    }
  }
  if (cpu_toggle_arg.cpu_hotplug_failed) {
    GTEST_LOG_(INFO) << "Test ends because of cpu hotplug failure.";
  }
  cpu_toggle_arg.end_flag = true;
  cpu_toggle_thread.join();
}

// http://b/25193162.
TEST(cpu_offline, offline_while_ioctl_enable) {
  ScopedMpdecisionKiller scoped_mpdecision_killer;
  CpuOnlineRestorer cpuonline_restorer;
  if (GetCpuCount() == 1) {
    GTEST_LOG_(INFO) << "This test does nothing, because there is only one cpu in the system.";
    return;
  }
  // Start cpu hotpluger.
  int test_cpu;
  if (!FindAHotpluggableCpu(&test_cpu)) {
    return;
  }
  CpuToggleThreadArg cpu_toggle_arg(test_cpu);
  std::thread cpu_toggle_thread(CpuToggleThread, &cpu_toggle_arg);

  std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType("cpu-cycles");
  ASSERT_TRUE(event_type_modifier != nullptr);
  perf_event_attr attr = CreateDefaultPerfEventAttr(event_type_modifier->event_type);
  attr.disabled = 1;
  attr.enable_on_exec = 0;

  auto start_time = std::chrono::steady_clock::now();
  auto cur_time = start_time;
  auto end_time = std::chrono::steady_clock::now() + test_duration_for_long_tests;
  auto report_step = std::chrono::seconds(15);
  size_t iterations = 0;

  while (cur_time < end_time && !cpu_toggle_arg.cpu_hotplug_failed) {
    if (cur_time + report_step < std::chrono::steady_clock::now()) {
      // Report test time.
      auto diff = std::chrono::duration_cast<std::chrono::seconds>(
          std::chrono::steady_clock::now() - start_time);
      if (verbose_mode) {
        GTEST_LOG_(INFO) << "Have Tested " << (diff.count() / 60.0) << " minutes.";
      }
      cur_time = std::chrono::steady_clock::now();

    }
    std::unique_ptr<EventFd> event_fd = EventFd::OpenEventFile(attr, -1, test_cpu, nullptr, false);
    if (event_fd == nullptr) {
      // Failed to open because the test_cpu is offline.
      continue;
    }
    // Wait a little for the event to be installed on test_cpu's perf context.
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
    ASSERT_TRUE(event_fd->EnableEvent());
    iterations++;
    if (verbose_mode) {
      GTEST_LOG_(INFO) << "Test offline while ioctl(PERF_EVENT_IOC_ENABLE) for " << iterations << " times.";
    }
  }
  if (cpu_toggle_arg.cpu_hotplug_failed) {
    GTEST_LOG_(INFO) << "Test ends because of cpu hotplug failure.";
  }
  cpu_toggle_arg.end_flag = true;
  cpu_toggle_thread.join();
}

struct CpuSpinThreadArg {
  int spin_cpu;
  std::atomic<pid_t> tid;
  std::atomic<bool> end_flag;
};

static void CpuSpinThread(CpuSpinThreadArg* arg) {
  arg->tid = gettid();
  while (!arg->end_flag) {
    cpu_set_t mask;
    CPU_ZERO(&mask);
    CPU_SET(arg->spin_cpu, &mask);
    // If toggle_cpu is offline, setaffinity fails. So call it in a loop to
    // make sure current thread mostly runs on toggle_cpu.
    sched_setaffinity(arg->tid, sizeof(mask), &mask);
  }
}

// http://b/28086229.
TEST(cpu_offline, offline_while_user_process_profiling) {
  ScopedMpdecisionKiller scoped_mpdecision_killer;
  CpuOnlineRestorer cpuonline_restorer;
  // Start cpu hotpluger.
  int test_cpu;
  if (!FindAHotpluggableCpu(&test_cpu)) {
    return;
  }
  CpuToggleThreadArg cpu_toggle_arg(test_cpu);
  std::thread cpu_toggle_thread(CpuToggleThread, &cpu_toggle_arg);

  // Start cpu spinner.
  CpuSpinThreadArg cpu_spin_arg;
  cpu_spin_arg.spin_cpu = test_cpu;
  cpu_spin_arg.tid = 0;
  cpu_spin_arg.end_flag = false;
  std::thread cpu_spin_thread(CpuSpinThread, &cpu_spin_arg);
  while (cpu_spin_arg.tid == 0) {
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  }

  std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType("cpu-cycles");
  ASSERT_TRUE(event_type_modifier != nullptr);
  perf_event_attr attr = CreateDefaultPerfEventAttr(event_type_modifier->event_type);
  // Enable profiling in perf_event_open system call.
  attr.disabled = 0;
  attr.enable_on_exec = 0;

  auto start_time = std::chrono::steady_clock::now();
  auto cur_time = start_time;
  auto end_time = start_time + test_duration_for_long_tests;
  auto report_step = std::chrono::seconds(15);
  size_t iterations = 0;

  while (cur_time < end_time && !cpu_toggle_arg.cpu_hotplug_failed) {
    if (cur_time + report_step < std::chrono::steady_clock::now()) {
      auto diff = std::chrono::duration_cast<std::chrono::seconds>(
          std::chrono::steady_clock::now() - start_time);
      if (verbose_mode) {
        GTEST_LOG_(INFO) << "Have Tested " <<  (diff.count() / 60.0) << " minutes.";
      }
      cur_time = std::chrono::steady_clock::now();
    }
    // Test if the cpu pmu is still usable.
    ASSERT_TRUE(EventFd::OpenEventFile(attr, 0, -1, nullptr, true) != nullptr);

    std::unique_ptr<EventFd> event_fd = EventFd::OpenEventFile(attr, cpu_spin_arg.tid,
                                                               test_cpu, nullptr, false);
    if (event_fd == nullptr) {
      // Failed to open because the test_cpu is offline.
      continue;
    }
    // profile for a while.
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
    iterations++;
    if (verbose_mode) {
      GTEST_LOG_(INFO) << "Test offline while user process profiling for " << iterations << " times.";
    }
  }
  if (cpu_toggle_arg.cpu_hotplug_failed) {
    GTEST_LOG_(INFO) << "Test ends because of cpu hotplug failure.";
  }
  cpu_toggle_arg.end_flag = true;
  cpu_toggle_thread.join();
  cpu_spin_arg.end_flag = true;
  cpu_spin_thread.join();
  // Check if the cpu-cycle event is still available on test_cpu.
  if (SetCpuOnline(test_cpu, true)) {
    ASSERT_TRUE(EventFd::OpenEventFile(attr, -1, test_cpu, nullptr, true) != nullptr);
  }
}

// http://b/19863147.
TEST(cpu_offline, offline_while_recording_on_another_cpu) {
  ScopedMpdecisionKiller scoped_mpdecision_killer;
  CpuOnlineRestorer cpuonline_restorer;

  if (GetCpuCount() == 1) {
    GTEST_LOG_(INFO) << "This test does nothing, because there is only one cpu in the system.";
    return;
  }
  int test_cpu;
  if (!FindAHotpluggableCpu(&test_cpu)) {
    return;
  }
  std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType("cpu-cycles");
  perf_event_attr attr = CreateDefaultPerfEventAttr(event_type_modifier->event_type);
  attr.disabled = 0;
  attr.enable_on_exec = 0;

  const size_t TEST_ITERATION_COUNT = 10u;
  for (size_t i = 0; i < TEST_ITERATION_COUNT; ++i) {
    int record_cpu = 0;
    if (!SetCpuOnline(test_cpu, true)) {
      break;
    }
    std::unique_ptr<EventFd> event_fd = EventFd::OpenEventFile(attr, getpid(), record_cpu, nullptr);
    ASSERT_TRUE(event_fd != nullptr);
    if (!SetCpuOnline(test_cpu, false)) {
      break;
    }
    event_fd = nullptr;
    event_fd = EventFd::OpenEventFile(attr, getpid(), record_cpu, nullptr);
    ASSERT_TRUE(event_fd != nullptr);
  }
}

int main(int argc, char** argv) {
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "--help") == 0) {
      printf("--long_test_duration <second> Set test duration for long tests. Default is 120s.\n");
      printf("--cpu_hotplug_interval <microseconds> Set cpu hotplug interval. Default is 1000us.\n");
      printf("--verbose  Show verbose log.\n");
    } else if (strcmp(argv[i], "--long_test_duration") == 0) {
      if (i + 1 < argc) {
        int second_count = atoi(argv[i+1]);
        if (second_count <= 0) {
          fprintf(stderr, "Invalid arg for --long_test_duration.\n");
          return 1;
        }
        test_duration_for_long_tests = std::chrono::seconds(second_count);
        i++;
      }
    } else if (strcmp(argv[i], "--cpu_hotplug_interval") == 0) {
      if (i + 1 < argc) {
        int microsecond_count = atoi(argv[i+1]);
        if (microsecond_count <= 0) {
          fprintf(stderr, "Invalid arg for --cpu_hotplug_interval\n");
          return 1;
        }
        cpu_hotplug_interval = std::chrono::microseconds(microsecond_count);
        i++;
      }
    } else if (strcmp(argv[i], "--verbose") == 0) {
      verbose_mode = true;
    }
  }
  android::base::InitLogging(argv, android::base::StderrLogger);
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
