/*
 * Copyright (C) 2021 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 "src/trace_processor/prelude/table_functions/experimental_flat_slice.h"

#include "test/gtest_and_gmock.h"

namespace perfetto {
namespace trace_processor {
namespace {

class TableInseter {
 public:
  void Insert(int64_t ts, int64_t dur, uint32_t depth, TrackId track_id) {
    tables::SliceTable::Row row;
    row.ts = ts;
    row.dur = dur;
    row.depth = depth;
    row.track_id = track_id;
    rows_.emplace_back(std::move(row));
  }

  void Populate(tables::SliceTable& table) {
    using R = tables::SliceTable::Row;
    std::sort(rows_.begin(), rows_.end(),
              [](const R& a, const R& b) { return a.ts < b.ts; });
    for (const auto& row : rows_) {
      table.Insert(row);
    }
    rows_.clear();
  }

 private:
  std::vector<tables::SliceTable::Row> rows_;
};

class TableAsserter {
 public:
  TableAsserter(Table table) : table_(std::move(table)) {}

  void NextSlice(int64_t ts, int64_t dur) {
    ++idx_;
    ASSERT_LT(idx_, table_.row_count());
    ASSERT_EQ(table_.GetTypedColumnByName<int64_t>("ts")[idx_], ts)
        << "where idx_ = " << idx_;
    ASSERT_EQ(table_.GetTypedColumnByName<int64_t>("dur")[idx_], dur)
        << "where idx_ = " << idx_;
  }

  bool HasMoreSlices() { return idx_ + 1 < table_.row_count(); }

 private:
  Table table_;
  uint32_t idx_ = std::numeric_limits<uint32_t>::max();
};

TEST(ExperimentalFlatSlice, Smoke) {
  StringPool pool;
  TableInseter inserter;
  tables::SliceTable table(&pool);

  // A simple stack on track 1.
  inserter.Insert(100, 10, 0, TrackId{1});
  inserter.Insert(104, 6, 1, TrackId{1});
  inserter.Insert(107, 1, 2, TrackId{1});

  // Back to back slices with a gap on track 2.
  inserter.Insert(200, 10, 0, TrackId{2});
  inserter.Insert(210, 10, 0, TrackId{2});
  inserter.Insert(230, 10, 0, TrackId{2});

  // Deep nesting on track 3.
  inserter.Insert(300, 100, 0, TrackId{3});
  inserter.Insert(301, 98, 1, TrackId{3});
  inserter.Insert(302, 96, 2, TrackId{3});
  inserter.Insert(303, 94, 3, TrackId{3});
  inserter.Insert(304, 92, 4, TrackId{3});
  inserter.Insert(305, 90, 5, TrackId{3});

  // Populate the table.
  inserter.Populate(table);

  auto out = ExperimentalFlatSlice::ComputeFlatSliceTable(table, &pool, 0, 400);
  auto sorted = out->Sort({out->track_id().ascending(), out->ts().ascending()});

  TableAsserter asserter(std::move(sorted));

  // Track 1's slices.
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 100));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(100, 4));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(104, 3));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(107, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(108, 2));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(110, 0));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(110, 290));

  // Track 2's slices.
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 200));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 10));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 0));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 10));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(220, 10));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(230, 10));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(240, 160));

  // Track 3's slices.
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 300));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(300, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(301, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(302, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(303, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(304, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(305, 90));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(395, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(396, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(397, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(398, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(399, 1));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(400, 0));

  ASSERT_FALSE(asserter.HasMoreSlices());
}

TEST(ExperimentalFlatSlice, Bounds) {
  StringPool pool;
  TableInseter inserter;
  tables::SliceTable table(&pool);

  /// Our timebounds is between 200 and 300.
  int64_t start = 200;
  int64_t end = 300;

  // Track 1 has all events inside bounds.
  inserter.Insert(200, 10, 0, TrackId{1});
  inserter.Insert(210, 10, 0, TrackId{1});
  inserter.Insert(230, 10, 0, TrackId{1});

  // Track 2 has a two stacks, first partially inside at start, second partially
  // inside at end.
  // First stack.
  inserter.Insert(190, 20, 0, TrackId{2});
  inserter.Insert(200, 9, 1, TrackId{2});
  inserter.Insert(201, 1, 2, TrackId{2});

  // Second stack.
  inserter.Insert(290, 20, 0, TrackId{2});
  inserter.Insert(299, 2, 1, TrackId{2});
  inserter.Insert(300, 1, 2, TrackId{2});

  // Track 3 has two stacks but *only* outside bounds.
  inserter.Insert(190, 9, 0, TrackId{3});
  inserter.Insert(195, 2, 1, TrackId{3});

  inserter.Insert(300, 9, 0, TrackId{3});
  inserter.Insert(301, 2, 1, TrackId{3});

  // Track 4 has one stack which is partially inside at start.
  inserter.Insert(190, 20, 0, TrackId{4});
  inserter.Insert(201, 2, 1, TrackId{4});

  // Populate the table.
  inserter.Populate(table);

  auto out =
      ExperimentalFlatSlice::ComputeFlatSliceTable(table, &pool, start, end);
  auto sorted = out->Sort({out->track_id().ascending(), out->ts().ascending()});

  TableAsserter asserter(std::move(sorted));

  // Track 1's slices.
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 0));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 10));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 0));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 10));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(220, 10));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(230, 10));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(240, 60));

  // Track 2's slices.
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 90));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(290, 9));
  ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(299, 1));

  ASSERT_FALSE(asserter.HasMoreSlices());
}

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