/*
 * 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 <stdlib.h>
#include <sys/system_properties.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "perfetto/base/logging.h"
#include "perfetto/tracing/core/data_source_config.h"
#include "src/base/test/test_task_runner.h"
#include "test/android_test_utils.h"
#include "test/gtest_and_gmock.h"
#include "test/test_helper.h"

#include "protos/perfetto/config/profiling/java_hprof_config.gen.h"
#include "protos/perfetto/trace/profiling/heap_graph.gen.h"
#include "protos/perfetto/trace/profiling/profile_common.gen.h"
#include "protos/perfetto/trace/trace_packet.gen.h"

namespace perfetto {
namespace {

std::string RandomSessionName() {
  std::random_device rd;
  std::default_random_engine generator(rd());
  std::uniform_int_distribution<> distribution('a', 'z');

  constexpr size_t kSessionNameLen = 20;
  std::string result(kSessionNameLen, '\0');
  for (size_t i = 0; i < kSessionNameLen; ++i)
    result[i] = static_cast<char>(distribution(generator));
  return result;
}

std::vector<protos::gen::TracePacket> ProfileRuntime(std::string app_name) {
  base::TestTaskRunner task_runner;

  // (re)start the target app's main activity
  if (IsAppRunning(app_name)) {
    StopApp(app_name, "old.app.stopped", &task_runner);
    task_runner.RunUntilCheckpoint("old.app.stopped", 10000 /*ms*/);
  }
  StartAppActivity(app_name, "MainActivity", "target.app.running", &task_runner,
                   /*delay_ms=*/100);
  task_runner.RunUntilCheckpoint("target.app.running", 10000 /*ms*/);
  // If we try to dump too early in app initialization, we sometimes deadlock.
  sleep(1);

  // set up tracing
  TestHelper helper(&task_runner);
  helper.ConnectConsumer();
  helper.WaitForConsumerConnect();

  TraceConfig trace_config;
  trace_config.add_buffers()->set_size_kb(40 * 1024);
  trace_config.set_duration_ms(6000);
  trace_config.set_unique_session_name(RandomSessionName().c_str());

  auto* ds_config = trace_config.add_data_sources()->mutable_config();
  ds_config->set_name("android.java_hprof");
  ds_config->set_target_buffer(0);

  protos::gen::JavaHprofConfig java_hprof_config;
  java_hprof_config.add_process_cmdline(app_name.c_str());
  ds_config->set_java_hprof_config_raw(java_hprof_config.SerializeAsString());

  // start tracing
  helper.StartTracing(trace_config);
  helper.WaitForTracingDisabled();
  helper.ReadData();
  helper.WaitForReadData();
  PERFETTO_CHECK(IsAppRunning(app_name));
  StopApp(app_name, "new.app.stopped", &task_runner);
  task_runner.RunUntilCheckpoint("new.app.stopped", 10000 /*ms*/);
  return helper.trace();
}

void AssertGraphPresent(std::vector<protos::gen::TracePacket> packets) {
  ASSERT_GT(packets.size(), 0u);

  size_t objects = 0;
  size_t roots = 0;
  for (const auto& packet : packets) {
    objects += static_cast<size_t>(packet.heap_graph().objects_size());
    roots += static_cast<size_t>(packet.heap_graph().roots_size());
  }
  ASSERT_GT(objects, 0u);
  ASSERT_GT(roots, 0u);
}

void AssertNoProfileContents(std::vector<protos::gen::TracePacket> packets) {
  // If profile packets are present, they must be empty.
  for (const auto& packet : packets) {
    ASSERT_EQ(packet.heap_graph().roots_size(), 0);
    ASSERT_EQ(packet.heap_graph().objects_size(), 0);
    ASSERT_EQ(packet.heap_graph().types_size(), 0);
    ASSERT_EQ(packet.heap_graph().field_names_size(), 0);
  }
}

TEST(HeapprofdJavaCtsTest, DebuggableAppRuntime) {
  std::string app_name = "android.perfetto.cts.app.debuggable";
  const auto& packets = ProfileRuntime(app_name);
  AssertGraphPresent(packets);
}

TEST(HeapprofdJavaCtsTest, ProfileableAppRuntime) {
  std::string app_name = "android.perfetto.cts.app.profileable";
  const auto& packets = ProfileRuntime(app_name);
  AssertGraphPresent(packets);
}

TEST(HeapprofdJavaCtsTest, ReleaseAppRuntime) {
  std::string app_name = "android.perfetto.cts.app.release";
  const auto& packets = ProfileRuntime(app_name);

  if (!IsUserBuild())
    AssertGraphPresent(packets);
  else
    AssertNoProfileContents(packets);
}

TEST(HeapprofdJavaCtsTest, DebuggableAppRuntimeByPid) {
  std::string app_name = "android.perfetto.cts.app.debuggable";

  base::TestTaskRunner task_runner;

  // (re)start the target app's main activity
  if (IsAppRunning(app_name)) {
    StopApp(app_name, "old.app.stopped", &task_runner);
    task_runner.RunUntilCheckpoint("old.app.stopped", 10000 /*ms*/);
  }
  StartAppActivity(app_name, "MainActivity", "target.app.running", &task_runner,
                   /*delay_ms=*/100);
  task_runner.RunUntilCheckpoint("target.app.running", 10000 /*ms*/);
  // If we try to dump too early in app initialization, we sometimes deadlock.
  sleep(1);

  int target_pid = PidForProcessName(app_name);
  ASSERT_NE(target_pid, -1);

  // set up tracing
  TestHelper helper(&task_runner);
  helper.ConnectConsumer();
  helper.WaitForConsumerConnect();

  TraceConfig trace_config;
  trace_config.add_buffers()->set_size_kb(40 * 1024);
  trace_config.set_duration_ms(6000);
  trace_config.set_unique_session_name(RandomSessionName().c_str());

  auto* ds_config = trace_config.add_data_sources()->mutable_config();
  ds_config->set_name("android.java_hprof");
  ds_config->set_target_buffer(0);

  protos::gen::JavaHprofConfig java_hprof_config;
  java_hprof_config.add_pid(static_cast<uint64_t>(target_pid));
  ds_config->set_java_hprof_config_raw(java_hprof_config.SerializeAsString());

  // start tracing
  helper.StartTracing(trace_config);
  helper.WaitForTracingDisabled();
  helper.ReadData();
  helper.WaitForReadData();
  PERFETTO_CHECK(IsAppRunning(app_name));
  StopApp(app_name, "new.app.stopped", &task_runner);
  task_runner.RunUntilCheckpoint("new.app.stopped", 10000 /*ms*/);

  const auto& packets = helper.trace();
  AssertGraphPresent(packets);
}

}  // namespace
}  // namespace perfetto
