/*
 * 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 "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/trace_processor/read_trace.h"

#include "src/base/test/utils.h"
#include "test/gtest_and_gmock.h"

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

namespace perfetto {
namespace trace_processor {
namespace {

base::ScopedFstream OpenTestTrace(const std::string& path) {
  std::string full_path = base::GetTestDataPath(path);
  EXPECT_TRUE(base::FileExists(full_path)) << full_path;
  return base::ScopedFstream(fopen(full_path.c_str(), "rb"));
}

std::vector<uint8_t> ReadAllData(const base::ScopedFstream& f) {
  std::vector<uint8_t> raw_trace;
  while (!feof(*f)) {
    uint8_t buf[4096];
    auto rsize =
        fread(reinterpret_cast<char*>(buf), 1, base::ArraySize(buf), *f);
    raw_trace.insert(raw_trace.end(), buf, buf + rsize);
  }
  return raw_trace;
}

TEST(ReadTraceIntegrationTest, CompressedTrace) {
  base::ScopedFstream f = OpenTestTrace("test/data/compressed.pb");
  std::vector<uint8_t> raw_trace = ReadAllData(f);

  std::vector<uint8_t> decompressed;
  decompressed.reserve(raw_trace.size());

  util::Status status = trace_processor::DecompressTrace(
      raw_trace.data(), raw_trace.size(), &decompressed);
  ASSERT_TRUE(status.ok());

  protos::pbzero::Trace::Decoder decoder(decompressed.data(),
                                         decompressed.size());
  uint32_t packet_count = 0;
  for (auto it = decoder.packet(); it; ++it) {
    protos::pbzero::TracePacket::Decoder packet(*it);
    ASSERT_FALSE(packet.has_compressed_packets());
    ++packet_count;
  }
  ASSERT_EQ(packet_count, 2412u);
}

TEST(ReadTraceIntegrationTest, NonProtobufShouldNotDecompress) {
  base::ScopedFstream f = OpenTestTrace("test/data/unsorted_trace.json");
  std::vector<uint8_t> raw_trace = ReadAllData(f);

  std::vector<uint8_t> decompressed;
  util::Status status = trace_processor::DecompressTrace(
      raw_trace.data(), raw_trace.size(), &decompressed);
  ASSERT_FALSE(status.ok());
}

TEST(ReadTraceIntegrationTest, OuterGzipDecompressTrace) {
  base::ScopedFstream f =
      OpenTestTrace("test/data/example_android_trace_30s.pb.gz");
  std::vector<uint8_t> raw_compressed_trace = ReadAllData(f);

  std::vector<uint8_t> decompressed;
  util::Status status = trace_processor::DecompressTrace(
      raw_compressed_trace.data(), raw_compressed_trace.size(), &decompressed);
  ASSERT_TRUE(status.ok());

  base::ScopedFstream u =
      OpenTestTrace("test/data/example_android_trace_30s.pb");
  std::vector<uint8_t> raw_trace = ReadAllData(u);

  ASSERT_EQ(decompressed.size(), raw_trace.size());
  ASSERT_EQ(decompressed, raw_trace);
}

TEST(ReadTraceIntegrationTest, DoubleGzipDecompressTrace) {
  base::ScopedFstream f = OpenTestTrace("test/data/compressed.pb.gz");
  std::vector<uint8_t> raw_compressed_trace = ReadAllData(f);

  std::vector<uint8_t> decompressed;
  util::Status status = trace_processor::DecompressTrace(
      raw_compressed_trace.data(), raw_compressed_trace.size(), &decompressed);
  ASSERT_TRUE(status.ok()) << status.message();

  protos::pbzero::Trace::Decoder decoder(decompressed.data(),
                                         decompressed.size());
  uint32_t packet_count = 0;
  for (auto it = decoder.packet(); it; ++it) {
    protos::pbzero::TracePacket::Decoder packet(*it);
    ASSERT_FALSE(packet.has_compressed_packets());
    ++packet_count;
  }
  ASSERT_EQ(packet_count, 2412u);
}

}  // namespace
}  // namespace trace_processor
}  // namespace perfetto
