/*
 * Copyright (C) 2018 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 "test/test_helper.h"

#include "perfetto/base/compiler.h"
#include "perfetto/ext/tracing/core/trace_packet.h"
#include "perfetto/ext/tracing/ipc/default_socket.h"
#include "perfetto/tracing/core/tracing_service_state.h"

#include "protos/perfetto/trace/trace_packet.pbzero.h"

namespace perfetto {

namespace {
const char* ProducerSocketForMode(TestHelper::Mode mode) {
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  base::ignore_result(mode);
  return ::perfetto::GetProducerSocket();
#else
  switch (mode) {
    case TestHelper::Mode::kStartDaemons:
      return "/data/local/tmp/traced_producer";
    case TestHelper::Mode::kUseSystemService:
      return ::perfetto::GetProducerSocket();
  }
#endif
}

const char* ConsumerSocketForMode(TestHelper::Mode mode) {
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  base::ignore_result(mode);
  return ::perfetto::GetConsumerSocket();
#else
  switch (mode) {
    case TestHelper::Mode::kStartDaemons:
      return "/data/local/tmp/traced_consumer";
    case TestHelper::Mode::kUseSystemService:
      return ::perfetto::GetConsumerSocket();
  }
#endif
}
}  // namespace

uint64_t TestHelper::next_instance_num_ = 0;
#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
TestHelper::Mode TestHelper::kDefaultMode = Mode::kStartDaemons;
#else
TestHelper::Mode TestHelper::kDefaultMode = Mode::kUseSystemService;
#endif

TestHelper::TestHelper(base::TestTaskRunner* task_runner, Mode mode)
    : instance_num_(next_instance_num_++),
      task_runner_(task_runner),
      mode_(mode),
      producer_socket_(ProducerSocketForMode(mode)),
      consumer_socket_(ConsumerSocketForMode(mode)),
      service_thread_(producer_socket_, consumer_socket_),
      fake_producer_thread_(producer_socket_,
                            WrapTask(CreateCheckpoint("producer.connect")),
                            WrapTask(CreateCheckpoint("producer.setup")),
                            WrapTask(CreateCheckpoint("producer.enabled"))) {}

void TestHelper::OnConnect() {
  std::move(on_connect_callback_)();
}

void TestHelper::OnDisconnect() {
  PERFETTO_FATAL("Consumer unexpectedly disconnected from the service");
}

void TestHelper::OnTracingDisabled(const std::string& /*error*/) {
  std::move(on_stop_tracing_callback_)();
  on_stop_tracing_callback_ = nullptr;
}

void TestHelper::ReadTraceData(std::vector<TracePacket> packets) {
  for (auto& encoded_packet : packets) {
    protos::gen::TracePacket packet;
    PERFETTO_CHECK(
        packet.ParseFromString(encoded_packet.GetRawBytesForTesting()));
    full_trace_.push_back(packet);
    if (packet.has_clock_snapshot() || packet.has_trace_config() ||
        packet.has_trace_stats() || !packet.synchronization_marker().empty() ||
        packet.has_system_info() || packet.has_service_event()) {
      continue;
    }
    PERFETTO_CHECK(packet.has_trusted_uid());
    trace_.push_back(std::move(packet));
  }
}

void TestHelper::OnTraceData(std::vector<TracePacket> packets, bool has_more) {
  ReadTraceData(std::move(packets));
  if (!has_more) {
    std::move(on_packets_finished_callback_)();
  }
}

void TestHelper::StartServiceIfRequired() {
  if (mode_ == Mode::kStartDaemons)
    service_thread_.Start();
}

FakeProducer* TestHelper::ConnectFakeProducer() {
  fake_producer_thread_.Connect();
  // This will wait until the service has seen the RegisterDataSource() call
  // (because of the Sync() in FakeProducer::OnConnect()).
  RunUntilCheckpoint("producer.connect");
  return fake_producer_thread_.producer();
}

void TestHelper::ConnectConsumer() {
  cur_consumer_num_++;
  on_connect_callback_ = CreateCheckpoint("consumer.connected." +
                                          std::to_string(cur_consumer_num_));
  endpoint_ = ConsumerIPCClient::Connect(consumer_socket_, this, task_runner_);
}

void TestHelper::DetachConsumer(const std::string& key) {
  on_detach_callback_ = CreateCheckpoint("detach." + key);
  endpoint_->Detach(key);
  RunUntilCheckpoint("detach." + key);
  endpoint_.reset();
}

bool TestHelper::AttachConsumer(const std::string& key) {
  bool success = false;
  auto checkpoint = CreateCheckpoint("attach." + key);
  on_attach_callback_ = [&success, checkpoint](bool s) {
    success = s;
    checkpoint();
  };
  endpoint_->Attach(key);
  RunUntilCheckpoint("attach." + key);
  return success;
}

bool TestHelper::SaveTraceForBugreportAndWait() {
  bool success = false;
  auto checkpoint = CreateCheckpoint("bugreport");
  auto callback = [&success, checkpoint](bool s, const std::string&) {
    success = s;
    checkpoint();
  };
  endpoint_->SaveTraceForBugreport(callback);
  RunUntilCheckpoint("bugreport");
  return success;
}

void TestHelper::CreateProducerProvidedSmb() {
  fake_producer_thread_.CreateProducerProvidedSmb();
}

bool TestHelper::IsShmemProvidedByProducer() {
  return fake_producer_thread_.producer()->IsShmemProvidedByProducer();
}

void TestHelper::ProduceStartupEventBatch(
    const protos::gen::TestConfig& config) {
  auto on_data_written = CreateCheckpoint("startup_data_written");
  fake_producer_thread_.ProduceStartupEventBatch(config,
                                                 WrapTask(on_data_written));
  RunUntilCheckpoint("startup_data_written");
}

void TestHelper::StartTracing(const TraceConfig& config,
                              base::ScopedFile file) {
  PERFETTO_CHECK(!on_stop_tracing_callback_);
  trace_.clear();
  on_stop_tracing_callback_ =
      CreateCheckpoint("stop.tracing" + std::to_string(++trace_count_));
  endpoint_->EnableTracing(config, std::move(file));
}

void TestHelper::DisableTracing() {
  endpoint_->DisableTracing();
}

void TestHelper::FlushAndWait(uint32_t timeout_ms) {
  static int flush_num = 0;
  std::string checkpoint_name = "flush." + std::to_string(flush_num++);
  auto checkpoint = CreateCheckpoint(checkpoint_name);
  endpoint_->Flush(timeout_ms, [checkpoint](bool) { checkpoint(); });
  RunUntilCheckpoint(checkpoint_name, timeout_ms + 1000);
}

void TestHelper::ReadData(uint32_t read_count) {
  on_packets_finished_callback_ =
      CreateCheckpoint("readback.complete." + std::to_string(read_count));
  endpoint_->ReadBuffers();
}

void TestHelper::FreeBuffers() {
  endpoint_->FreeBuffers();
}

void TestHelper::WaitForConsumerConnect() {
  RunUntilCheckpoint("consumer.connected." + std::to_string(cur_consumer_num_));
}

void TestHelper::WaitForProducerSetup() {
  RunUntilCheckpoint("producer.setup");
}

void TestHelper::WaitForProducerEnabled() {
  RunUntilCheckpoint("producer.enabled");
}

void TestHelper::WaitForTracingDisabled(uint32_t timeout_ms) {
  RunUntilCheckpoint(std::string("stop.tracing") + std::to_string(trace_count_),
                     timeout_ms);
}

void TestHelper::WaitForReadData(uint32_t read_count, uint32_t timeout_ms) {
  RunUntilCheckpoint("readback.complete." + std::to_string(read_count),
                     timeout_ms);
}

void TestHelper::WaitFor(std::function<bool()> predicate,
                         const std::string& error_msg,
                         uint32_t timeout_ms) {
  int64_t deadline_ms = base::GetWallTimeMs().count() + timeout_ms;
  while (base::GetWallTimeMs().count() < deadline_ms) {
    if (predicate())
      return;
    base::SleepMicroseconds(500 * 1000);  // 0.5 s.
  }
  PERFETTO_FATAL("Test timed out waiting for: %s", error_msg.c_str());
}

void TestHelper::WaitForDataSourceConnected(const std::string& ds_name) {
  auto predicate = [&] {
    auto dss = QueryServiceStateAndWait().data_sources();
    return std::any_of(dss.begin(), dss.end(),
                       [&](const TracingServiceState::DataSource& ds) {
                         return ds.ds_descriptor().name() == ds_name;
                       });
  };
  WaitFor(predicate, "connection of data source " + ds_name);
}

void TestHelper::SyncAndWaitProducer() {
  static int sync_id = 0;
  std::string checkpoint_name = "producer_sync_" + std::to_string(++sync_id);
  auto checkpoint = CreateCheckpoint(checkpoint_name);
  fake_producer_thread_.producer()->Sync(
      [this, &checkpoint] { task_runner_->PostTask(checkpoint); });
  RunUntilCheckpoint(checkpoint_name);
}

TracingServiceState TestHelper::QueryServiceStateAndWait() {
  TracingServiceState res;
  static int n = 0;
  std::string checkpoint_name = "query_svc_state_" + std::to_string(n++);
  auto checkpoint = CreateCheckpoint(checkpoint_name);
  auto callback = [&checkpoint, &res](bool, const TracingServiceState& tss) {
    res = tss;
    checkpoint();
  };
  endpoint_->QueryServiceState(callback);
  RunUntilCheckpoint(checkpoint_name);
  return res;
}

std::function<void()> TestHelper::WrapTask(
    const std::function<void()>& function) {
  return [this, function] { task_runner_->PostTask(function); };
}

void TestHelper::OnDetach(bool) {
  if (on_detach_callback_)
    std::move(on_detach_callback_)();
}

void TestHelper::OnAttach(bool success, const TraceConfig&) {
  if (on_attach_callback_)
    std::move(on_attach_callback_)(success);
}

void TestHelper::OnTraceStats(bool, const TraceStats&) {}

void TestHelper::OnObservableEvents(const ObservableEvents&) {}

// static
const char* TestHelper::GetDefaultModeConsumerSocketName() {
  return ConsumerSocketForMode(TestHelper::kDefaultMode);
}

// static
const char* TestHelper::GetDefaultModeProducerSocketName() {
  return ProducerSocketForMode(TestHelper::kDefaultMode);
}

}  // namespace perfetto
