blob: d6589e442cc75f5a1910ee53cb3ef2f8df001f5e [file] [log] [blame]
// 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 "cobalt_logger.h"
#include <fbl/macros.h>
#include "lib/async-loop/default.h"
#include "lib/fidl/cpp/binding.h"
#include "lib/fidl/cpp/interface_ptr.h"
#include "lib/fidl/cpp/interface_request.h"
#include "lib/gtest/test_loop_fixture.h"
#include "src/connectivity/bluetooth/core/bt-host/common/test_helpers.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/fake_controller_test.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/test_controller.h"
namespace bt {
namespace cobalt {
namespace {
class COBALT_CobaltLoggerTest : public ::gtest::TestLoopFixture {
public:
class LoggerImpl : public ::fuchsia::cobalt::Logger {
public:
LoggerImpl() : requests_made_(0), callback_status_(::fuchsia::cobalt::Status::OK){};
~LoggerImpl() override = default;
void LogEvent(uint32_t metric_id, uint32_t event_code, LogEventCallback callback) override {
callback(callback_status_);
requests_made_++;
::fuchsia::cobalt::CobaltEvent event = {metric_id, {event_code}};
last_recorded_event_ = std::make_unique<::fuchsia::cobalt::CobaltEvent>(std::move(event));
};
void LogEventCount(uint32_t metric_id, uint32_t event_code, ::std::string component,
int64_t period_duration_micros, int64_t count,
LogEventCountCallback callback) override {
callback(callback_status_);
requests_made_++;
::fuchsia::cobalt::CobaltEvent event = {metric_id, {event_code}};
::fuchsia::cobalt::CountEvent payload = {period_duration_micros, count};
event.payload.set_event_count(std::move(payload));
last_recorded_event_ = std::make_unique<::fuchsia::cobalt::CobaltEvent>(std::move(event));
};
void LogElapsedTime(uint32_t metric_id, uint32_t event_code, ::std::string component,
int64_t elapsed_micros, LogElapsedTimeCallback callback) override {
callback(callback_status_);
requests_made_++;
::fuchsia::cobalt::CobaltEvent event = {metric_id, {event_code}};
event.payload.set_elapsed_micros(elapsed_micros);
last_recorded_event_ = std::make_unique<::fuchsia::cobalt::CobaltEvent>(std::move(event));
};
void LogFrameRate(uint32_t metric_id, uint32_t event_code, ::std::string component, float fps,
LogFrameRateCallback callback) override {
FAIL() << "Mock method unimplemented";
};
void LogMemoryUsage(uint32_t metric_id, uint32_t event_code, ::std::string component,
int64_t bytes, LogMemoryUsageCallback callback) override {
FAIL() << "Mock method unimplemented";
};
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 {
FAIL() << "Mock method unimplemented";
};
void EndTimer(::std::string timer_id, uint64_t timestamp, uint32_t timeout_s,
EndTimerCallback callback) override {
FAIL() << "Mock method unimplemented";
};
void LogIntHistogram(uint32_t metric_id, uint32_t event_code, ::std::string component,
::std::vector<::fuchsia::cobalt::HistogramBucket> histogram,
LogIntHistogramCallback callback) override {
FAIL() << "Mock method unimplemented";
};
void LogCustomEvent(uint32_t metric_id,
::std::vector<::fuchsia::cobalt::CustomEventValue> event_values,
LogCustomEventCallback callback) override {
FAIL() << "Mock method unimplemented";
};
void LogCobaltEvent(::fuchsia::cobalt::CobaltEvent event,
LogCobaltEventCallback callback) override {
callback(callback_status_);
requests_made_++;
last_recorded_event_ = std::make_unique<::fuchsia::cobalt::CobaltEvent>(std::move(event));
};
void LogCobaltEvents(::std::vector<::fuchsia::cobalt::CobaltEvent> events,
LogCobaltEventsCallback callback) override {
callback(callback_status_);
requests_made_++;
if (!events.empty()) {
last_recorded_event_ =
std::make_unique<::fuchsia::cobalt::CobaltEvent>(std::move(events[events.size() - 1]));
} else {
last_recorded_event_ = nullptr;
}
};
// Return the total number of requests made to the server
uint32_t RequestsMade() const { return requests_made_; }
// Return the last event that was sent from a client to the server.
const ::fuchsia::cobalt::CobaltEvent* LastRecordedEvent() const {
return last_recorded_event_.get();
}
// All requests to record a cobalt event contain a response with a single status value.
// Use this method to set the cobalt status that will be passed to fidl response callbacks.
void SetCallbackStatus(::fuchsia::cobalt::Status status) { callback_status_ = status; }
private:
uint32_t requests_made_;
std::unique_ptr<::fuchsia::cobalt::CobaltEvent> last_recorded_event_;
::fuchsia::cobalt::Status callback_status_;
};
public:
COBALT_CobaltLoggerTest() = default;
~COBALT_CobaltLoggerTest() override = default;
protected:
void TearDown() override {
RunLoopUntilIdle(); // Run all pending tasks.
}
private:
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(COBALT_CobaltLoggerTest);
};
// Tests that the cobalt logger without a interface handle to the cobalt service will
// silently ignore logging requests
TEST_F(COBALT_CobaltLoggerTest, NotBoundToService) {
auto logger = CobaltLogger::Create();
logger->LogEvent(1, 2);
logger->LogEventCount(1, 2, 3);
logger->LogElapsedTime(1, 2, 3);
logger->LogCobaltEvent({1, {}, EventCount{2}});
logger->LogCobaltEvents({{1, {}, EventCount{2}}, {2, {2}, ElapsedMicros{3}}});
}
TEST_F(COBALT_CobaltLoggerTest, BoundToService) {
auto logger = CobaltLogger::Create();
LoggerImpl impl;
::fidl::Binding<fuchsia::cobalt::Logger> binding(&impl);
::fidl::InterfaceHandle<::fuchsia::cobalt::Logger> handle;
binding.Bind(handle.NewRequest(), dispatcher());
EXPECT_TRUE(handle.is_valid());
EXPECT_EQ(async_get_default_dispatcher(), dispatcher());
logger->Bind(std::move(handle));
EXPECT_EQ(impl.RequestsMade(), 0u);
EXPECT_EQ(impl.LastRecordedEvent(), nullptr);
logger->LogEvent(1, 2);
RunLoopUntilIdle();
EXPECT_EQ(impl.RequestsMade(), 1u);
EXPECT_EQ(impl.LastRecordedEvent()->metric_id, 1u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes.size(), 1u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes[0], 2u);
logger->LogEventCount(3, 4, 5);
RunLoopUntilIdle();
EXPECT_EQ(impl.RequestsMade(), 2u);
EXPECT_EQ(impl.LastRecordedEvent()->metric_id, 3u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes.size(), 1u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes[0], 4u);
EXPECT_EQ(impl.LastRecordedEvent()->payload.event_count().count, 5u);
logger->LogElapsedTime(6, 7, 8);
RunLoopUntilIdle();
EXPECT_EQ(impl.RequestsMade(), 3u);
EXPECT_EQ(impl.LastRecordedEvent()->metric_id, 6u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes.size(), 1u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes[0], 7u);
EXPECT_EQ(impl.LastRecordedEvent()->payload.elapsed_micros(), 8u);
logger->LogCobaltEvent({9, {10}, EventCount{11}});
RunLoopUntilIdle();
EXPECT_EQ(impl.RequestsMade(), 4u);
EXPECT_EQ(impl.LastRecordedEvent()->metric_id, 9u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes.size(), 1u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes[0], 10u);
EXPECT_EQ(impl.LastRecordedEvent()->payload.event_count().count, 11u);
logger->LogCobaltEvents({{12, {13, 14}, EventCount{15}}});
RunLoopUntilIdle();
EXPECT_EQ(impl.RequestsMade(), 5u);
EXPECT_EQ(impl.LastRecordedEvent()->metric_id, 12u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes.size(), 2u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes[0], 13u);
EXPECT_EQ(impl.LastRecordedEvent()->event_codes[1], 14u);
EXPECT_EQ(impl.LastRecordedEvent()->payload.event_count().count, 15u);
}
TEST_F(COBALT_CobaltLoggerTest, CloseServer) {
auto logger = CobaltLogger::Create();
LoggerImpl impl;
::fidl::Binding<fuchsia::cobalt::Logger> binding(&impl);
::fidl::InterfaceHandle<::fuchsia::cobalt::Logger> handle;
binding.Bind(handle.NewRequest(), dispatcher());
EXPECT_TRUE(handle.is_valid());
EXPECT_EQ(async_get_default_dispatcher(), dispatcher());
logger->Bind(std::move(handle));
EXPECT_EQ(impl.RequestsMade(), 0u);
EXPECT_EQ(impl.LastRecordedEvent(), nullptr);
logger->LogEvent(1, 2);
// Ensure that the server is set up correctly before shuting it down.
RunLoopUntilIdle();
logger->LogEvent(3, 4);
EXPECT_TRUE(binding.is_bound());
binding.Close(ZX_ERR_PEER_CLOSED);
EXPECT_FALSE(binding.is_bound());
logger->LogEvent(5, 6);
RunLoopUntilIdle();
// Only the first event was logged.
EXPECT_EQ(impl.RequestsMade(), 1u);
EXPECT_NE(impl.LastRecordedEvent(), nullptr);
}
} // namespace
} // namespace cobalt
} // namespace bt