/*
 * Copyright (C) 2022 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 <sys/system_properties.h>
#include <random>
#include "test/gtest_and_gmock.h"

#include "perfetto/ext/base/android_utils.h"
#include "perfetto/ext/base/uuid.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/test_helper.h"

#include "protos/perfetto/config/test_config.gen.h"
#include "protos/perfetto/trace/test_event.gen.h"
#include "protos/perfetto/trace/trace.gen.h"
#include "protos/perfetto/trace/trace_packet.gen.h"

namespace perfetto {
namespace {

TEST(PerfettoReporterTest, TestEndToEndReport) {
  base::TestTaskRunner task_runner;
  TestHelper helper(&task_runner);
  helper.ConnectFakeProducer();

  TraceConfig trace_config;
  trace_config.add_buffers()->set_size_kb(1024);
  trace_config.set_duration_ms(200);
  trace_config.set_allow_user_build_tracing(true);

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

  base::Uuid uuid = base::Uuidv4();
  trace_config.set_trace_uuid_lsb(uuid.lsb());
  trace_config.set_trace_uuid_msb(uuid.msb());

  static constexpr uint32_t kRandomSeed = 42;
  static constexpr uint32_t kEventCount = 1;
  static constexpr uint32_t kMessageSizeBytes = 2;
  ds_config->mutable_for_testing()->set_seed(kRandomSeed);
  ds_config->mutable_for_testing()->set_message_count(kEventCount);
  ds_config->mutable_for_testing()->set_message_size(kMessageSizeBytes);
  ds_config->mutable_for_testing()->set_send_batch_on_register(true);

  auto* report_config = trace_config.mutable_android_report_config();
  report_config->set_reporter_service_package("android.perfetto.cts.reporter");
  report_config->set_reporter_service_class(
      "android.perfetto.cts.reporter.PerfettoReportService");
  report_config->set_use_pipe_in_framework_for_testing(true);

  // We have to construct all the processes we want to fork before we start the
  // service with |StartServiceIfRequired()|. this is because it is unsafe
  // (could deadlock) to fork after we've spawned some threads which might
  // printf (and thus hold locks).
  auto perfetto_proc = Exec("perfetto",
                            {
                                "--upload",
                                "-c",
                                "-",
                            },
                            trace_config.SerializeAsString());

  std::string stderr_str;
  EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;

  static constexpr char kPath[] =
      "/sdcard/Android/data/android.perfetto.cts.reporter/files/";
  std::string path = kPath + uuid.ToPrettyString();
  static constexpr uint32_t kIterationSleepMs = 500;
  static constexpr uint32_t kIterationCount =
      kDefaultTestTimeoutMs / kIterationSleepMs;
  for (size_t i = 0; i < kIterationCount; ++i) {
    if (!base::FileExists(path)) {
      base::SleepMicroseconds(kIterationSleepMs * 1000);
      continue;
    }

    std::string trace_str;
    ASSERT_TRUE(base::ReadFile(path, &trace_str));

    protos::gen::Trace trace;
    ASSERT_TRUE(trace.ParseFromString(trace_str));
    int for_testing = 0;
    for (const auto& packet : trace.packet()) {
      for_testing += packet.has_for_testing();
    }
    ASSERT_EQ(for_testing, kEventCount);
    return;
  }
  FAIL() << "Timed out waiting for trace file";
}

}  // namespace
}  // namespace perfetto
