// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/lib/cobalt/cpp/cobalt_event_builder.h"

#include "gtest/gtest.h"

namespace cobalt {

using fuchsia::cobalt::CobaltEvent;
using fuchsia::cobalt::CountEvent;
using fuchsia::cobalt::HistogramBucket;

const uint32_t kMetricId = 123;
const uint32_t kDimension1 = 456;
const uint32_t kDimension2 = 789;
const std::string kComponent = "Component1";

TEST(CobaltEventBuilder, CountEvent) {
  uint64_t duration = 10101;
  uint64_t count = 100;

  CobaltEvent event;
  event.metric_id = kMetricId;
  CountEvent payload;
  payload.period_duration_micros = duration;
  payload.count = count;
  event.payload.set_event_count(std::move(payload));

  ASSERT_EQ(event,
            CobaltEventBuilder(kMetricId).as_count_event(duration, count));
}

TEST(CobaltEventBuilder, ElapsedTimeEvent) {
  uint64_t elapsed_micros = 5678;

  CobaltEvent event;
  event.metric_id = kMetricId;
  event.event_codes.push_back(kDimension1);
  event.event_codes.push_back(kDimension2);
  event.payload.set_elapsed_micros(elapsed_micros);

  ASSERT_EQ(event, CobaltEventBuilder(kMetricId)
                       .with_event_codes({kDimension1, kDimension2})
                       .as_elapsed_time(elapsed_micros));
}

TEST(CobaltEventBuilder, FrameRateEvent) {
  float fps = 29.98;

  CobaltEvent event;
  event.metric_id = kMetricId;
  event.event_codes.push_back(kDimension1);
  event.event_codes.push_back(kDimension2);
  event.component = kComponent;
  event.payload.set_fps(fps);

  ASSERT_EQ(event, CobaltEventBuilder(kMetricId)
                       .with_event_codes({kDimension1, kDimension2})
                       .with_component(kComponent)
                       .as_frame_rate(fps));
}

TEST(CobaltEventBuilder, MemoryUsage) {
  int64_t bytes_used = 13428;

  CobaltEvent event;
  event.metric_id = kMetricId;
  event.event_codes.push_back(kDimension1);
  event.event_codes.push_back(kDimension2);
  event.component = kComponent;
  event.payload.set_memory_bytes_used(bytes_used);

  ASSERT_EQ(event, CobaltEventBuilder(kMetricId)
                       .with_event_codes({kDimension1, kDimension2})
                       .with_component(kComponent)
                       .as_memory_usage(bytes_used));
}

TEST(CobaltEventBuilder, StringEvent) {
  std::string string_event = "The string event";

  CobaltEvent event;
  event.metric_id = kMetricId;
  event.event_codes.push_back(kDimension1);
  event.event_codes.push_back(kDimension2);
  event.component = kComponent;
  event.payload.set_string_event(string_event);

  ASSERT_EQ(event, CobaltEventBuilder(kMetricId)
                       .with_event_codes({kDimension1, kDimension2})
                       .with_component(kComponent)
                       .as_string_event(string_event));
}

TEST(CobaltEventBuilder, IntHistogram) {
  std::vector<HistogramBucket> int_histogram;
  int_histogram.push_back({0, 10});
  int_histogram.push_back({1, 20});
  int_histogram.push_back({2, 30});
  int_histogram.push_back({3, 40});

  CobaltEvent event;
  event.metric_id = kMetricId;
  event.event_codes.push_back(kDimension1);
  event.event_codes.push_back(kDimension2);
  event.component = kComponent;
  event.payload.set_int_histogram(int_histogram);

  ASSERT_EQ(event, CobaltEventBuilder(kMetricId)
                       .with_event_codes({kDimension1, kDimension2})
                       .with_component(kComponent)
                       .as_int_histogram(int_histogram));
}

TEST(CobaltEventBuilder, Clone) {
  uint64_t elapsed_micros = 5678;
  auto b = std::move(CobaltEventBuilder(kMetricId)
                         .with_event_codes({kDimension1, kDimension2})
                         .with_component(kComponent));

  ASSERT_NE(b.as_elapsed_time(elapsed_micros),
            b.as_elapsed_time(elapsed_micros));

  auto b2 = std::move(CobaltEventBuilder(kMetricId)
                          .with_event_codes({kDimension1, kDimension2})
                          .with_component(kComponent));

  ASSERT_EQ(b2.Clone().as_elapsed_time(elapsed_micros),
            b2.as_elapsed_time(elapsed_micros));
}

TEST(CobaltEventBuilder, event_code_at) {
  uint64_t elapsed_micros = 5678;
  ASSERT_EQ(CobaltEventBuilder(kMetricId)
                .with_event_codes({kDimension1, kDimension2})
                .as_elapsed_time(elapsed_micros),
            CobaltEventBuilder(kMetricId)
                .with_event_code_at(1, kDimension2)
                .with_event_code_at(0, kDimension1)
                .as_elapsed_time(elapsed_micros));
}

}  // namespace cobalt
