|  | // Copyright 2018 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_logger.h" | 
|  |  | 
|  | #include <fuchsia/sys/cpp/fidl.h> | 
|  | #include <lib/async/default.h> | 
|  | #include <lib/fidl/cpp/binding_set.h> | 
|  | #include <lib/fidl/cpp/clone.h> | 
|  | #include <lib/gtest/test_loop_fixture.h> | 
|  | #include <lib/sys/cpp/testing/service_directory_provider.h> | 
|  | #include <lib/zx/clock.h> | 
|  | #include <lib/zx/time.h> | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include "src/lib/cobalt/cpp/cobalt_logger_impl.h" | 
|  | #include "src/lib/fsl/vmo/strings.h" | 
|  | #include "src/lib/fxl/macros.h" | 
|  |  | 
|  | namespace cobalt { | 
|  | namespace { | 
|  |  | 
|  | constexpr uint32_t kProjectId = 1234; | 
|  | constexpr int32_t kFakeCobaltMetricId = 2; | 
|  |  | 
|  | bool Equals(const OccurrenceEvent* e1, const OccurrenceEvent* e2) { | 
|  | return e1->metric_id() == e2->metric_id() && e1->event_code() == e2->event_code(); | 
|  | } | 
|  |  | 
|  | bool Equals(const CountEvent* e1, const CountEvent* e2) { | 
|  | return e1->metric_id() == e2->metric_id() && e1->event_code() == e2->event_code() && | 
|  | e1->component() == e2->component() && | 
|  | e1->period_duration_micros() == e2->period_duration_micros() && e1->count() == e2->count(); | 
|  | } | 
|  |  | 
|  | bool Equals(const ElapsedTimeEvent* e1, const ElapsedTimeEvent* e2) { | 
|  | return e1->metric_id() == e2->metric_id() && e1->event_code() == e2->event_code() && | 
|  | e1->component() == e2->component() && e1->elapsed_micros() == e2->elapsed_micros(); | 
|  | } | 
|  |  | 
|  | bool Equals(const FrameRateEvent* e1, const FrameRateEvent* e2) { | 
|  | return e1->metric_id() == e2->metric_id() && e1->event_code() == e2->event_code() && | 
|  | e1->component() == e2->component() && e1->fps() == e2->fps(); | 
|  | } | 
|  |  | 
|  | bool Equals(const MemoryUsageEvent* e1, const MemoryUsageEvent* e2) { | 
|  | return e1->metric_id() == e2->metric_id() && e1->event_code() == e2->event_code() && | 
|  | e1->component() == e2->component() && e1->bytes() == e2->bytes(); | 
|  | } | 
|  |  | 
|  | bool Equals(const StartTimerEvent* e1, const StartTimerEvent* e2) { | 
|  | return e1->metric_id() == e2->metric_id() && e1->event_code() == e2->event_code() && | 
|  | e1->component() == e2->component() && e1->timer_id() == e2->timer_id() && | 
|  | e1->timestamp() == e2->timestamp() && e1->timeout_s() == e2->timeout_s(); | 
|  | } | 
|  |  | 
|  | bool Equals(const EndTimerEvent* e1, const EndTimerEvent* e2) { | 
|  | return e1->timer_id() == e2->timer_id() && e1->timestamp() == e2->timestamp() && | 
|  | e1->timeout_s() == e2->timeout_s(); | 
|  | } | 
|  |  | 
|  | bool Equals(const IntHistogramEvent* e1, const IntHistogramEvent* e2) { | 
|  | return e1->metric_id() == e2->metric_id() && e1->event_code() == e2->event_code() && | 
|  | e1->component() == e2->component() && fidl::Equals(e1->histogram(), e2->histogram()); | 
|  | } | 
|  |  | 
|  | bool Equals(const CustomEvent* e1, const CustomEvent* e2) { | 
|  | return e1->metric_id() == e2->metric_id() && fidl::Equals(e1->event_values(), e2->event_values()); | 
|  | } | 
|  |  | 
|  | enum EventType { | 
|  | EVENT_OCCURRED, | 
|  | EVENT_COUNT, | 
|  | ELAPSED_TIME, | 
|  | FRAME_RATE, | 
|  | MEMORY_USAGE, | 
|  | STRING_USED, | 
|  | START_TIMER, | 
|  | END_TIMER, | 
|  | INT_HISTOGRAM, | 
|  | CUSTOM, | 
|  | }; | 
|  |  | 
|  | class FakeLoggerImpl : public fuchsia::cobalt::Logger { | 
|  | public: | 
|  | FakeLoggerImpl() {} | 
|  |  | 
|  | void LogEvent(uint32_t metric_id, uint32_t event_code, LogEventCallback callback) override { | 
|  | RecordCall(EventType::EVENT_OCCURRED, std::make_unique<OccurrenceEvent>(metric_id, event_code)); | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } | 
|  |  | 
|  | void LogEventCount(uint32_t metric_id, uint32_t event_code, std::string component, | 
|  | int64_t period_duration_micros, int64_t count, | 
|  | LogEventCountCallback callback) override { | 
|  | RecordCall(EventType::EVENT_COUNT, | 
|  | std::make_unique<CountEvent>(metric_id, event_code, component, | 
|  | period_duration_micros, count)); | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } | 
|  |  | 
|  | void LogElapsedTime(uint32_t metric_id, uint32_t event_code, std::string component, | 
|  | int64_t elapsed_micros, LogElapsedTimeCallback callback) override { | 
|  | RecordCall(EventType::ELAPSED_TIME, std::make_unique<ElapsedTimeEvent>( | 
|  | metric_id, event_code, component, elapsed_micros)); | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } | 
|  |  | 
|  | void LogFrameRate(uint32_t metric_id, uint32_t event_code, std::string component, float fps, | 
|  | LogFrameRateCallback callback) override { | 
|  | RecordCall(EventType::FRAME_RATE, | 
|  | std::make_unique<FrameRateEvent>(metric_id, event_code, component, fps)); | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } | 
|  |  | 
|  | void LogMemoryUsage(uint32_t metric_id, uint32_t event_code, std::string component, int64_t bytes, | 
|  | LogMemoryUsageCallback callback) override { | 
|  | RecordCall(EventType::MEMORY_USAGE, | 
|  | std::make_unique<MemoryUsageEvent>(metric_id, event_code, component, bytes)); | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } | 
|  |  | 
|  | void StartTimer(uint32_t metric_id, uint32_t event_code, std::string component, | 
|  | std::string timer_id, uint64_t timestamp, uint32_t timeout_s, | 
|  | StartTimerCallback callback) override { | 
|  | RecordCall(EventType::START_TIMER, | 
|  | std::make_unique<StartTimerEvent>(metric_id, event_code, component, timer_id, | 
|  | timestamp, timeout_s)); | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } | 
|  |  | 
|  | void EndTimer(std::string timer_id, uint64_t timestamp, uint32_t timeout_s, | 
|  | EndTimerCallback callback) override { | 
|  | RecordCall(EventType::END_TIMER, | 
|  | std::make_unique<EndTimerEvent>(timer_id, timestamp, timeout_s)); | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } | 
|  |  | 
|  | void LogIntHistogram(uint32_t metric_id, uint32_t event_code, std::string component, | 
|  | std::vector<fuchsia::cobalt::HistogramBucket> histogram, | 
|  | LogIntHistogramCallback callback) override { | 
|  | RecordCall(EventType::INT_HISTOGRAM, | 
|  | std::make_unique<IntHistogramEvent>(metric_id, event_code, component, | 
|  | std::move(histogram))); | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } | 
|  |  | 
|  | void LogCustomEvent(uint32_t metric_id, | 
|  | std::vector<fuchsia::cobalt::CustomEventValue> event_values, | 
|  | LogCustomEventCallback callback) override { | 
|  | RecordCall(EventType::CUSTOM, | 
|  | std::make_unique<CustomEvent>(metric_id, std::move(event_values))); | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } | 
|  |  | 
|  | void LogCobaltEvent(fuchsia::cobalt::CobaltEvent event, | 
|  | LogCobaltEventCallback callback) override { | 
|  | if (event.payload.is_event_count()) { | 
|  | LogEventCount(event.metric_id, event.event_codes[0], event.component.value_or(""), | 
|  | event.payload.event_count().period_duration_micros, | 
|  | event.payload.event_count().count, std::move(callback)); | 
|  | } else if (event.payload.is_int_histogram()) { | 
|  | LogIntHistogram(event.metric_id, event.event_codes[0], event.component.value_or(""), | 
|  | std::move(event.payload.int_histogram()), std::move(callback)); | 
|  |  | 
|  | } else { | 
|  | callback(fuchsia::cobalt::Status::INVALID_ARGUMENTS); | 
|  | } | 
|  | } | 
|  |  | 
|  | void LogCobaltEvents(std::vector<fuchsia::cobalt::CobaltEvent> events, | 
|  | LogCobaltEventCallback callback) override { | 
|  | auto failures = 0; | 
|  |  | 
|  | auto end = std::make_move_iterator(events.end()); | 
|  |  | 
|  | for (auto it = std::make_move_iterator(events.begin()); it != end; it++) { | 
|  | LogCobaltEvent(std::move(*it), [failures](fuchsia::cobalt::Status status) mutable { | 
|  | if (status != fuchsia::cobalt::Status::OK) { | 
|  | failures += 1; | 
|  | } | 
|  | }); | 
|  | } | 
|  |  | 
|  | if (failures == 0) { | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } else { | 
|  | callback(fuchsia::cobalt::Status::INTERNAL_ERROR); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ExpectCalledOnceWith(EventType type, const BaseEvent* expected) { | 
|  | ASSERT_EQ(1U, calls_[type].size()); | 
|  | switch (type) { | 
|  | case EventType::EVENT_OCCURRED: | 
|  | EXPECT_TRUE(Equals(static_cast<const OccurrenceEvent*>(expected), | 
|  | static_cast<OccurrenceEvent*>(calls_[type][0].get()))); | 
|  | break; | 
|  | case EventType::EVENT_COUNT: | 
|  | EXPECT_TRUE(Equals(static_cast<const CountEvent*>(expected), | 
|  | static_cast<CountEvent*>(calls_[type][0].get()))); | 
|  | break; | 
|  | case EventType::ELAPSED_TIME: | 
|  | EXPECT_TRUE(Equals(static_cast<const ElapsedTimeEvent*>(expected), | 
|  | static_cast<ElapsedTimeEvent*>(calls_[type][0].get()))); | 
|  | break; | 
|  | case EventType::FRAME_RATE: | 
|  | EXPECT_TRUE(Equals(static_cast<const FrameRateEvent*>(expected), | 
|  | static_cast<FrameRateEvent*>(calls_[type][0].get()))); | 
|  | break; | 
|  | case EventType::MEMORY_USAGE: | 
|  | EXPECT_TRUE(Equals(static_cast<const MemoryUsageEvent*>(expected), | 
|  | static_cast<MemoryUsageEvent*>(calls_[type][0].get()))); | 
|  | break; | 
|  | case EventType::START_TIMER: | 
|  | EXPECT_TRUE(Equals(static_cast<const StartTimerEvent*>(expected), | 
|  | static_cast<StartTimerEvent*>(calls_[type][0].get()))); | 
|  | break; | 
|  | case EventType::END_TIMER: | 
|  | EXPECT_TRUE(Equals(static_cast<const EndTimerEvent*>(expected), | 
|  | static_cast<EndTimerEvent*>(calls_[type][0].get()))); | 
|  | break; | 
|  | case EventType::INT_HISTOGRAM: | 
|  | EXPECT_TRUE(Equals(static_cast<const IntHistogramEvent*>(expected), | 
|  | static_cast<IntHistogramEvent*>(calls_[type][0].get()))); | 
|  | break; | 
|  | case EventType::CUSTOM: | 
|  | EXPECT_TRUE(Equals(static_cast<const CustomEvent*>(expected), | 
|  | static_cast<CustomEvent*>(calls_[type][0].get()))); | 
|  | break; | 
|  | default: | 
|  | ASSERT_TRUE(false); | 
|  | } | 
|  | } | 
|  | const std::vector<std::unique_ptr<BaseEvent>>& GetEvents(EventType type) const { | 
|  | FX_CHECK(calls_.find(type) != calls_.end()); | 
|  | return calls_.at(type); | 
|  | } | 
|  |  | 
|  | private: | 
|  | void RecordCall(EventType type, std::unique_ptr<BaseEvent> event) { | 
|  | calls_[type].push_back(std::move(event)); | 
|  | } | 
|  |  | 
|  | std::map<EventType, std::vector<std::unique_ptr<BaseEvent>>> calls_; | 
|  | }; | 
|  |  | 
|  | class FakeLoggerFactoryImpl : public fuchsia::cobalt::LoggerFactory { | 
|  | public: | 
|  | FakeLoggerFactoryImpl() {} | 
|  |  | 
|  | void CreateLoggerFromProjectId(uint32_t project_id, | 
|  | fidl::InterfaceRequest<fuchsia::cobalt::Logger> request, | 
|  | CreateLoggerFromProjectIdCallback callback) override { | 
|  | received_project_id_ = project_id; | 
|  | logger_.reset(new FakeLoggerImpl()); | 
|  | logger_bindings_.AddBinding(logger_.get(), std::move(request)); | 
|  | callback(fuchsia::cobalt::Status::OK); | 
|  | } | 
|  |  | 
|  | void CreateLoggerSimpleFromProjectId( | 
|  | uint32_t project_id, fidl::InterfaceRequest<fuchsia::cobalt::LoggerSimple> request, | 
|  | CreateLoggerSimpleFromProjectIdCallback callback) override {} | 
|  |  | 
|  | void CreateLoggerFromProjectSpec(uint32_t customer_id, uint32_t project_id, | 
|  | fidl::InterfaceRequest<fuchsia::cobalt::Logger> request, | 
|  | CreateLoggerFromProjectSpecCallback callback) override {} | 
|  |  | 
|  | FakeLoggerImpl* logger() { return logger_.get(); } | 
|  | uint32_t received_project_id() { return received_project_id_; } | 
|  |  | 
|  | private: | 
|  | uint32_t received_project_id_; | 
|  | std::unique_ptr<FakeLoggerImpl> logger_; | 
|  | fidl::BindingSet<fuchsia::cobalt::Logger> logger_bindings_; | 
|  | }; | 
|  |  | 
|  | class CobaltLoggerTest : public gtest::TestLoopFixture { | 
|  | public: | 
|  | CobaltLoggerTest() {} | 
|  | ~CobaltLoggerTest() override {} | 
|  |  | 
|  | std::shared_ptr<sys::ServiceDirectory>& service_directory() { | 
|  | return service_provider_.service_directory(); | 
|  | } | 
|  |  | 
|  | FakeLoggerFactoryImpl* logger_factory() { return factory_impl_.get(); } | 
|  |  | 
|  | FakeLoggerImpl* logger() { return factory_impl_->logger(); } | 
|  |  | 
|  | CobaltLogger* cobalt_logger() { return cobalt_logger_.get(); } | 
|  |  | 
|  | private: | 
|  | virtual void SetUp() override { | 
|  | factory_impl_.reset(new FakeLoggerFactoryImpl()); | 
|  | service_provider_.AddService<fuchsia::cobalt::LoggerFactory>( | 
|  | [this](fidl::InterfaceRequest<fuchsia::cobalt::LoggerFactory> request) { | 
|  | factory_bindings_.AddBinding(factory_impl_.get(), std::move(request)); | 
|  | }); | 
|  | service_provider_.AddService<fuchsia::sys::Environment>( | 
|  | [this](fidl::InterfaceRequest<fuchsia::sys::Environment> request) { | 
|  | app_environment_request_ = std::move(request); | 
|  | }); | 
|  | service_provider_.AddService<fuchsia::sys::Launcher>( | 
|  | [this](fidl::InterfaceRequest<fuchsia::sys::Launcher> request) { | 
|  | launcher_request_ = std::move(request); | 
|  | }); | 
|  |  | 
|  | cobalt_logger_ = NewCobaltLoggerFromProjectId(async_get_default_dispatcher(), | 
|  | service_directory(), kProjectId); | 
|  | RunLoopUntilIdle(); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<FakeLoggerFactoryImpl> factory_impl_; | 
|  | std::unique_ptr<CobaltLogger> cobalt_logger_; | 
|  | fidl::BindingSet<fuchsia::cobalt::LoggerFactory> factory_bindings_; | 
|  | fidl::InterfaceRequest<fuchsia::sys::Launcher> launcher_request_; | 
|  | fidl::InterfaceRequest<fuchsia::sys::Environment> app_environment_request_; | 
|  | sys::testing::ServiceDirectoryProvider service_provider_; | 
|  |  | 
|  | FXL_DISALLOW_COPY_AND_ASSIGN(CobaltLoggerTest); | 
|  | }; | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, InitializeCobalt) { | 
|  | // Cobalt Logger was initialized in the SetUp. | 
|  | EXPECT_EQ(kProjectId, logger_factory()->received_project_id()); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogMultipleEvent_BeforeCreateLoggerCallbackExecutes) { | 
|  | constexpr size_t num_events = 5u; | 
|  |  | 
|  | CobaltLoggerImpl cobalt_logger(async_get_default_dispatcher(), service_directory(), kProjectId); | 
|  | OccurrenceEvent event(kFakeCobaltMetricId, 123); | 
|  |  | 
|  | // Send multiple events before the FakeLoggerImpl is ready. | 
|  | for (size_t i = 0; i < num_events; ++i) { | 
|  | cobalt_logger.LogEvent(event.metric_id(), event.event_code()); | 
|  | } | 
|  | RunLoopUntilIdle(); | 
|  |  | 
|  | const auto& first_events = logger()->GetEvents(EventType::EVENT_OCCURRED); | 
|  | EXPECT_EQ(first_events.size(), num_events); | 
|  | for (size_t i = 0; i < num_events; ++i) { | 
|  | EXPECT_TRUE(Equals(static_cast<const OccurrenceEvent*>(&event), | 
|  | static_cast<OccurrenceEvent*>(first_events[i].get()))); | 
|  | } | 
|  |  | 
|  | // Log an additional event to make sure the logger is in a good state. | 
|  | cobalt_logger.LogEvent(event.metric_id(), event.event_code()); | 
|  | RunLoopUntilIdle(); | 
|  |  | 
|  | const auto& all_events = logger()->GetEvents(EventType::EVENT_OCCURRED); | 
|  | EXPECT_EQ(all_events.size(), num_events + 1); | 
|  | for (size_t i = 0; i < num_events + 1; ++i) { | 
|  | EXPECT_TRUE(Equals(static_cast<const OccurrenceEvent*>(&event), | 
|  | static_cast<OccurrenceEvent*>(all_events[i].get()))); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogEvent) { | 
|  | OccurrenceEvent event(kFakeCobaltMetricId, 123); | 
|  | cobalt_logger()->LogEvent(event.metric_id(), event.event_code()); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::EVENT_OCCURRED, &event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogEventCount) { | 
|  | CountEvent event(kFakeCobaltMetricId, 123, "some_component", 2, 321); | 
|  | cobalt_logger()->LogEventCount(event.metric_id(), event.event_code(), event.component(), | 
|  | zx::duration(event.period_duration_micros() * ZX_USEC(1)), | 
|  | event.count()); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::EVENT_COUNT, &event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogCobaltEventEventCount) { | 
|  | CountEvent count_event(kFakeCobaltMetricId, 123, "some_component", 2, 322); | 
|  | fuchsia::cobalt::CobaltEvent event; | 
|  | event.metric_id = count_event.metric_id(); | 
|  | event.event_codes.push_back(count_event.event_code()); | 
|  | event.component = count_event.component(); | 
|  | fuchsia::cobalt::CountEvent fuchsia_count_event; | 
|  | fuchsia_count_event.period_duration_micros = count_event.period_duration_micros(); | 
|  | fuchsia_count_event.count = count_event.count(); | 
|  | event.payload.set_event_count(fuchsia_count_event); | 
|  | cobalt_logger()->LogCobaltEvent(std::move(event)); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::EVENT_COUNT, &count_event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogCobaltEventsEventCount) { | 
|  | CountEvent count_event(kFakeCobaltMetricId, 123, "some_component", 2, 322); | 
|  | fuchsia::cobalt::CobaltEvent event; | 
|  | event.metric_id = count_event.metric_id(); | 
|  | event.event_codes.push_back(count_event.event_code()); | 
|  | event.component = count_event.component(); | 
|  | fuchsia::cobalt::CountEvent fuchsia_count_event; | 
|  | fuchsia_count_event.period_duration_micros = count_event.period_duration_micros(); | 
|  | fuchsia_count_event.count = count_event.count(); | 
|  | event.payload.set_event_count(fuchsia_count_event); | 
|  |  | 
|  | std::vector<fuchsia::cobalt::CobaltEvent> events; | 
|  | events.push_back(std::move(event)); | 
|  |  | 
|  | cobalt_logger()->LogCobaltEvents(std::move(events)); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::EVENT_COUNT, &count_event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogElapsedTime) { | 
|  | ElapsedTimeEvent event(kFakeCobaltMetricId, 123, "some_component", 321); | 
|  | cobalt_logger()->LogElapsedTime(event.metric_id(), event.event_code(), event.component(), | 
|  | zx::duration(event.elapsed_micros() * ZX_USEC(1))); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::ELAPSED_TIME, &event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogFrameRate) { | 
|  | FrameRateEvent event(kFakeCobaltMetricId, 123, "some_component", 321.5f); | 
|  | cobalt_logger()->LogFrameRate(event.metric_id(), event.event_code(), event.component(), | 
|  | event.fps()); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::FRAME_RATE, &event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogMemoryUsage) { | 
|  | MemoryUsageEvent event(kFakeCobaltMetricId, 123, "some_component", 534582); | 
|  | cobalt_logger()->LogMemoryUsage(event.metric_id(), event.event_code(), event.component(), | 
|  | event.bytes()); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::MEMORY_USAGE, &event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, StartTimer) { | 
|  | zx::time timestamp = zx::clock::get_monotonic(); | 
|  | StartTimerEvent event(kFakeCobaltMetricId, 123, "some_component", "timer_1", | 
|  | timestamp.get() / ZX_USEC(1), 3); | 
|  | cobalt_logger()->StartTimer(event.metric_id(), event.event_code(), event.component(), | 
|  | event.timer_id(), timestamp, | 
|  | zx::duration(event.timeout_s() * ZX_SEC(1))); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::START_TIMER, &event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, EndTimer) { | 
|  | zx::time timestamp = zx::clock::get_monotonic(); | 
|  | EndTimerEvent event("timer_1", timestamp.get() / ZX_USEC(1), 3); | 
|  | cobalt_logger()->EndTimer(event.timer_id(), timestamp, | 
|  | zx::duration(event.timeout_s() * ZX_SEC(1))); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::END_TIMER, &event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogIntHistogram) { | 
|  | std::vector<fuchsia::cobalt::HistogramBucket> histogram(1); | 
|  | histogram.at(0).index = 1; | 
|  | histogram.at(0).count = 234; | 
|  |  | 
|  | std::vector<fuchsia::cobalt::HistogramBucket> histogram_clone; | 
|  | ASSERT_EQ(ZX_OK, fidl::Clone(histogram, &histogram_clone)); | 
|  |  | 
|  | IntHistogramEvent event(kFakeCobaltMetricId, 123, "some_component", std::move(histogram_clone)); | 
|  | cobalt_logger()->LogIntHistogram(event.metric_id(), event.event_code(), event.component(), | 
|  | std::move(histogram)); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::INT_HISTOGRAM, &event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogCobaltEventIntHistogram) { | 
|  | std::vector<fuchsia::cobalt::HistogramBucket> histogram(1); | 
|  | histogram.at(0).index = 1; | 
|  | histogram.at(0).count = 234; | 
|  |  | 
|  | std::vector<fuchsia::cobalt::HistogramBucket> histogram_clone; | 
|  | ASSERT_EQ(ZX_OK, fidl::Clone(histogram, &histogram_clone)); | 
|  |  | 
|  | IntHistogramEvent histogram_event(kFakeCobaltMetricId, 123, "some_component", | 
|  | std::move(histogram_clone)); | 
|  |  | 
|  | fuchsia::cobalt::CobaltEvent event; | 
|  | event.metric_id = histogram_event.metric_id(); | 
|  | event.event_codes.push_back(histogram_event.event_code()); | 
|  | event.component = histogram_event.component(); | 
|  | event.payload.set_int_histogram(std::move(histogram)); | 
|  |  | 
|  | cobalt_logger()->LogCobaltEvent(std::move(event)); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::INT_HISTOGRAM, &histogram_event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogCobaltEventsIntHistogram) { | 
|  | std::vector<fuchsia::cobalt::HistogramBucket> histogram(1); | 
|  | histogram.at(0).index = 1; | 
|  | histogram.at(0).count = 234; | 
|  |  | 
|  | std::vector<fuchsia::cobalt::HistogramBucket> histogram_clone; | 
|  | ASSERT_EQ(ZX_OK, fidl::Clone(histogram, &histogram_clone)); | 
|  |  | 
|  | IntHistogramEvent histogram_event(kFakeCobaltMetricId, 123, "some_component", | 
|  | std::move(histogram_clone)); | 
|  |  | 
|  | fuchsia::cobalt::CobaltEvent event; | 
|  | event.metric_id = histogram_event.metric_id(); | 
|  | event.event_codes.push_back(histogram_event.event_code()); | 
|  | event.component = histogram_event.component(); | 
|  | event.payload.set_int_histogram(std::move(histogram)); | 
|  |  | 
|  | std::vector<fuchsia::cobalt::CobaltEvent> events; | 
|  | events.push_back(std::move(event)); | 
|  |  | 
|  | cobalt_logger()->LogCobaltEvents(std::move(events)); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::INT_HISTOGRAM, &histogram_event); | 
|  | } | 
|  |  | 
|  | TEST_F(CobaltLoggerTest, LogCustomEvent) { | 
|  | std::vector<fuchsia::cobalt::CustomEventValue> event_values(1); | 
|  | event_values.at(0).dimension_name = "some_dimension"; | 
|  | event_values.at(0).value.set_int_value(234); | 
|  |  | 
|  | std::vector<fuchsia::cobalt::CustomEventValue> event_values_clone; | 
|  | ASSERT_EQ(ZX_OK, fidl::Clone(event_values, &event_values_clone)); | 
|  |  | 
|  | CustomEvent event(kFakeCobaltMetricId, std::move(event_values_clone)); | 
|  | cobalt_logger()->LogCustomEvent(event.metric_id(), std::move(event_values)); | 
|  | RunLoopUntilIdle(); | 
|  | logger()->ExpectCalledOnceWith(EventType::CUSTOM, &event); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  | }  // namespace cobalt |