Skip to content
Snippets Groups Projects
Commit e08cbed3 authored by Henri Chataing's avatar Henri Chataing
Browse files

system: fmtlib logger implementation

- The fmtlib logger is implemented in <bluetooth/log.h>.
  The header defines the following templated logs function:

    template<typename T...>
    log::fatal(fmt::format_string<T...> fmt, T...args);
    log::error(..);
    log::warn(..);
    log::info(..);
    log::debug(..);
    log::verbose(..);

- Front-end, logs are printed out by invoking these
  macros with the macro LOG_TAG defined _before_ the
  inclusion of #include <bluetooth/log.h>

- Back-end, a single method must be implemented for all supported
  platforms (android, floss, host):

  namespace log_internal {
  void vlog(Level level, char const *tag, char const *file_name, int line,
            fmt::string_view fmt, fmt::format_args vargs);
  }

- Default implementations are provided:
  + vlog_android: outputs to <log/log.h> __android_log_write_log_message
  + vlog_syslog: outputs to <syslog.h> syslog

Bug: 305066880
Test: m libbluetooth_log
Test: atest libbluetooth_log_test
Flag: EXEMPT, logging utils
Change-Id: Ic8a80f113b25d874c372d7dce8252d5428842ee8
parent faa70d82
No related branches found
No related tags found
No related merge requests found
...@@ -25,7 +25,7 @@ sudo apt-get install repo git-core gnupg flex bison gperf build-essential \ ...@@ -25,7 +25,7 @@ sudo apt-get install repo git-core gnupg flex bison gperf build-essential \
libgl1-mesa-dev libxml2-utils xsltproc unzip liblz4-tool libssl-dev \ libgl1-mesa-dev libxml2-utils xsltproc unzip liblz4-tool libssl-dev \
libc++-dev libevent-dev \ libc++-dev libevent-dev \
flatbuffers-compiler libflatbuffers1 openssl \ flatbuffers-compiler libflatbuffers1 openssl \
libflatbuffers-dev libtinyxml2-dev \ libflatbuffers-dev libfmt-dev libtinyxml2-dev \
libglib2.0-dev libevent-dev libnss3-dev libdbus-1-dev \ libglib2.0-dev libevent-dev libnss3-dev libdbus-1-dev \
libprotobuf-dev ninja-build generate-ninja protobuf-compiler \ libprotobuf-dev ninja-build generate-ninja protobuf-compiler \
libre2-9 debmake \ libre2-9 debmake \
......
...@@ -127,6 +127,7 @@ REQUIRED_APT_PACKAGES = [ ...@@ -127,6 +127,7 @@ REQUIRED_APT_PACKAGES = [
'liblz4-tool', 'liblz4-tool',
'libncurses5', 'libncurses5',
'libnss3-dev', 'libnss3-dev',
'libfmt-dev',
'libprotobuf-dev', 'libprotobuf-dev',
'libre2-9', 'libre2-9',
'libre2-dev', 'libre2-dev',
......
...@@ -31,6 +31,7 @@ RUN apt-get update && \ ...@@ -31,6 +31,7 @@ RUN apt-get update && \
libdouble-conversion-dev \ libdouble-conversion-dev \
libevent-dev \ libevent-dev \
libflatbuffers-dev \ libflatbuffers-dev \
libfmt-dev \
libgl1-mesa-dev \ libgl1-mesa-dev \
libglib2.0-dev \ libglib2.0-dev \
libgtest-dev \ libgtest-dev \
......
...@@ -174,6 +174,10 @@ config("external_flatbuffers") { ...@@ -174,6 +174,10 @@ config("external_flatbuffers") {
libs = [ "flatbuffers" ] libs = [ "flatbuffers" ]
} }
config("external_fmtlib") {
configs = [ ":pkg_fmtlib" ]
}
# Package configurations to extract dependencies from env # Package configurations to extract dependencies from env
pkg_config("pkg_gtest") { pkg_config("pkg_gtest") {
pkg_deps = [ "gtest" ] pkg_deps = [ "gtest" ]
...@@ -203,6 +207,10 @@ pkg_config("pkg_tinyxml2") { ...@@ -203,6 +207,10 @@ pkg_config("pkg_tinyxml2") {
pkg_deps = [ "tinyxml2" ] pkg_deps = [ "tinyxml2" ]
} }
pkg_config("pkd_fmtlib") {
pkg_deps = [ "fmt" ]
}
# To include ChroemOS-specific libraries and build dependencies. # To include ChroemOS-specific libraries and build dependencies.
if (target_os == "chromeos") { if (target_os == "chromeos") {
config("external_chromeos") { config("external_chromeos") {
......
...@@ -48,7 +48,7 @@ export PATH="${PATH}:${BIN_DIR}" ...@@ -48,7 +48,7 @@ export PATH="${PATH}:${BIN_DIR}"
# Check dependencies # Check dependencies
# libchrome requires modp_b64 # libchrome requires modp_b64
APT_REQUIRED="modp-b64 libchrome flatbuffers-compiler flex g++-multilib gcc-multilib generate-ninja gnupg gperf libc++-dev libdbus-1-dev libevent-dev libevent-dev libflatbuffers-dev libflatbuffers1 libgl1-mesa-dev libglib2.0-dev liblz4-tool libncurses5 libnss3-dev libprotobuf-dev libre2-9 libssl-dev libtinyxml2-dev libx11-dev libxml2-utils ninja-build openssl protobuf-compiler unzip x11proto-core-dev xsltproc zip zlib1g-dev" APT_REQUIRED="modp-b64 libchrome flatbuffers-compiler flex g++-multilib gcc-multilib generate-ninja gnupg gperf libc++-dev libdbus-1-dev libevent-dev libevent-dev libflatbuffers-dev libflatbuffers1 libfmt-dev libgl1-mesa-dev libglib2.0-dev liblz4-tool libncurses5 libnss3-dev libprotobuf-dev libre2-9 libssl-dev libtinyxml2-dev libx11-dev libxml2-utils ninja-build openssl protobuf-compiler unzip x11proto-core-dev xsltproc zip zlib1g-dev"
# SPEED UP TEST, REMOVE ME # SPEED UP TEST, REMOVE ME
APT_REQUIRED="modp-b64 libchrome flatbuffers-compiler" APT_REQUIRED="modp-b64 libchrome flatbuffers-compiler"
......
...@@ -24,7 +24,7 @@ function ctrl_c() { ...@@ -24,7 +24,7 @@ function ctrl_c() {
# APT dependencies # APT dependencies
APT_REQUIRED="git curl wget flatbuffers-compiler flex g++-multilib gcc-multilib generate-ninja \ APT_REQUIRED="git curl wget flatbuffers-compiler flex g++-multilib gcc-multilib generate-ninja \
gnupg gperf libc++-dev libdbus-1-dev libevent-dev libflatbuffers-dev libflatbuffers1 \ gnupg gperf libc++-dev libdbus-1-dev libevent-dev libflatbuffers-dev libfmt-dev libflatbuffers1 \
libgl1-mesa-dev libglib2.0-dev liblz4-tool libncurses5 libnss3-dev libprotobuf-dev libre2-9 \ libgl1-mesa-dev libglib2.0-dev liblz4-tool libncurses5 libnss3-dev libprotobuf-dev libre2-9 \
libssl-dev libtinyxml2-dev libx11-dev libxml2-utils ninja-build openssl protobuf-compiler unzip \ libssl-dev libtinyxml2-dev libx11-dev libxml2-utils ninja-build openssl protobuf-compiler unzip \
x11proto-core-dev xsltproc zip zlib1g-dev libc++abi-dev cmake debmake ninja-build libgtest-dev \ x11proto-core-dev xsltproc zip zlib1g-dev libc++abi-dev cmake debmake ninja-build libgtest-dev \
......
...@@ -4,7 +4,7 @@ Priority: optional ...@@ -4,7 +4,7 @@ Priority: optional
Maintainer: Martin Brabham <optedoblivion@google.com> Maintainer: Martin Brabham <optedoblivion@google.com>
Version: 0.1 Version: 0.1
Homepage: https://www.google.com Homepage: https://www.google.com
Depends: debmake, ninja-build, flatbuffers-compiler, flex, g++-multilib, gcc-multilib, generate-ninja, gnupg, gperf, libc++-dev, libdbus-1-dev, libevent-dev, libevent-dev, libflatbuffers-dev, libflatbuffers1, libgl1-mesa-dev, libglib2.0-dev, liblz4-tool, libncurses5, libnss3-dev, libprotobuf-dev, libre2-9, libssl-dev, libtinyxml2-dev, libx11-dev, libxml2-utils, ninja-build, openssl, protobuf-compiler, unzip, x11proto-core-dev, xsltproc, zip, zlib1g-dev, modp-b64, libchrome Depends: debmake, ninja-build, flatbuffers-compiler, flex, g++-multilib, gcc-multilib, generate-ninja, gnupg, gperf, libc++-dev, libdbus-1-dev, libevent-dev, libevent-dev, libflatbuffers-dev, libflatbuffers1, libfmt-dev, libfmt9, libgl1-mesa-dev, libglib2.0-dev, liblz4-tool, libncurses5, libnss3-dev, libprotobuf-dev, libre2-9, libssl-dev, libtinyxml2-dev, libx11-dev, libxml2-utils, ninja-build, openssl, protobuf-compiler, unzip, x11proto-core-dev, xsltproc, zip, zlib1g-dev, modp-b64, libchrome
Architecture: all Architecture: all
Essential: no Essential: no
Installed-Size: 490MB Installed-Size: 490MB
......
cc_library {
name: "libbluetooth_log",
host_supported: true,
min_sdk_version: "33",
apex_available: [
"com.android.btservices",
],
export_include_dirs: [
"include",
],
shared_libs: [
"libbase",
"liblog",
],
srcs: [
"src/vlog_android.cc",
],
}
cc_test {
name: "libbluetooth_log_test",
host_supported: true,
srcs: [
"src/truncating_buffer_test.cc",
"src/vlog_test.cc",
],
shared_libs: [
"libbase",
"libbluetooth_log",
],
}
#
# Copyright 2024 Google, Inc.
#
# 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.
#
config("log_defaults") {
include_dirs = [
"//bt/system/log/include",
]
}
static_library("libbluetooth_log") {
cflags = [
"-fvisibility=default",
]
sources = [
"include/bluetooth/log.h",
"src/truncating_buffer.h",
"src/vlog_syslog.cc",
]
configs += [
"//bt/system:target_defaults",
":log_defaults",
]
}
/*
* Copyright 2023 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.
*/
#pragma once
#include <fmt/core.h>
#include <fmt/format.h>
#include <fmt/std.h>
#ifndef LOG_TAG
#define LOG_TAG "bluetooth"
#endif // LOG_TAG
namespace bluetooth::log_internal {
/// Android framework log priority levels.
/// They are defined in system/logging/liblog/include/android/log.h by
/// the Android Framework code.
enum Level {
kVerbose = 2,
kDebug = 3,
kInfo = 4,
kWarn = 5,
kError = 6,
kFatal = 7,
};
/// Write a single log line.
/// The implementation of this function is dependent on the backend.
void vlog(Level level, char const* tag, char const* file_name, int line,
char const* function_name, fmt::string_view fmt,
fmt::format_args vargs);
template <Level level, typename... T>
struct log {
log(fmt::format_string<T...> fmt, T&&... args,
char const* file_name = __builtin_FILE(), int line = __builtin_LINE(),
char const* function_name = __builtin_FUNCTION()) {
vlog(level, LOG_TAG, file_name, line, function_name,
static_cast<fmt::string_view>(fmt), fmt::make_format_args(args...));
}
};
#if (__cplusplus >= 202002L && defined(__GNUC__) && !defined(__clang__))
template <int level, typename... T>
log(fmt::format_string<T...>, T&&...) -> log<level, T...>;
#endif
} // namespace bluetooth::log_internal
namespace bluetooth::log {
#if (__cplusplus >= 202002L && defined(__GNUC__) && !defined(__clang__))
template <typename... T>
using fatal = log_internal::log<log_internal::kFatal, T...>;
template <typename... T>
using error = log_internal::log<log_internal::kError, T...>;
template <typename... T>
using warning = log_internal::log<log_internal::kWarning, T...>;
template <typename... T>
using info = log_internal::log<log_internal::kInfo, T...>;
template <typename... T>
using debug = log_internal::log<log_internal::kDebug, T...>;
template <typename... T>
using verbose = log_internal::log<log_internal::kVerbose, T...>;
#else
template <typename... T>
struct fatal : log_internal::log<log_internal::kFatal, T...> {
using log_internal::log<log_internal::kFatal, T...>::log;
};
template <typename... T>
struct error : log_internal::log<log_internal::kError, T...> {
using log_internal::log<log_internal::kError, T...>::log;
};
template <typename... T>
struct warn : log_internal::log<log_internal::kWarn, T...> {
using log_internal::log<log_internal::kWarn, T...>::log;
};
template <typename... T>
struct info : log_internal::log<log_internal::kInfo, T...> {
using log_internal::log<log_internal::kInfo, T...>::log;
};
template <typename... T>
struct debug : log_internal::log<log_internal::kDebug, T...> {
using log_internal::log<log_internal::kDebug, T...>::log;
};
template <typename... T>
struct verbose : log_internal::log<log_internal::kVerbose, T...> {
using log_internal::log<log_internal::kVerbose, T...>::log;
};
template <typename... T>
fatal(fmt::format_string<T...>, T&&...) -> fatal<T...>;
template <typename... T>
error(fmt::format_string<T...>, T&&...) -> error<T...>;
template <typename... T>
warn(fmt::format_string<T...>, T&&...) -> warn<T...>;
template <typename... T>
info(fmt::format_string<T...>, T&&...) -> info<T...>;
template <typename... T>
debug(fmt::format_string<T...>, T&&...) -> debug<T...>;
template <typename... T>
verbose(fmt::format_string<T...>, T&&...) -> verbose<T...>;
#endif // GCC / C++20
} // namespace bluetooth::log
namespace fmt {
/// Default formatter implementation for formatting
/// enum class values to the underlying type.
///
/// Enable this formatter in the code by declaring:
/// ```
/// template<>
/// struct fmt::formatter<EnumT> : enum_formatter<EnumT> {};
/// ```
template <typename EnumT, class CharT = char>
struct enum_formatter : fmt::formatter<std::underlying_type_t<EnumT>, CharT> {
template <class Context>
typename Context::iterator format(EnumT value, Context& ctx) const {
return fmt::formatter<std::underlying_type_t<EnumT>, CharT>::format(
static_cast<std::underlying_type_t<EnumT>>(value), ctx);
}
};
} // namespace fmt
/*
* Copyright 2023 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.
*/
#pragma once
#include <cstddef>
namespace bluetooth::log_internal {
/// Truncating write buffer.
///
/// This buffer can be used with `std::back_insert_iterator` to create
/// an output iterator. All write actions beyond the maximum length of
/// the buffer are silently ignored.
template <int buffer_size>
struct truncating_buffer {
using value_type = char;
void push_back(char c) {
if (len < buffer_size - 1) {
buffer[len++] = c;
}
}
char const* c_str() {
if (len == buffer_size - 1) {
// Inspect the last 4 bytes of the buffer to check if
// the last character was truncated. Remove the character
// entirely if that's the case.
for (size_t n = 0; n < 4; n++) {
char c = buffer[len - n - 1];
if ((c & 0b11000000) == 0b10000000) {
continue;
}
size_t char_len = (c & 0b10000000) == 0b00000000 ? 1
: (c & 0b11100000) == 0b11000000 ? 2
: (c & 0b11110000) == 0b11100000 ? 3
: (c & 0b11111000) == 0b11110000 ? 4
: 0;
if ((n + 1) < char_len) {
len -= n + 1;
}
break;
}
}
buffer[len] = '\0';
return buffer;
}
private:
char buffer[buffer_size];
size_t len{0};
};
} // namespace bluetooth::log_internal
/*
* Copyright 2023 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.
*/
#define LOG_TAG "test"
#include "truncating_buffer.h"
#include <fmt/format.h>
#include <gtest/gtest.h>
#include <log/log.h>
using namespace bluetooth::log_internal;
TEST(TruncatingBufferTest, 1byte) {
EXPECT_EQ(sizeof("ab"), 3);
truncating_buffer<2> buffer_1;
truncating_buffer<3> buffer_2;
fmt::format_to(std::back_insert_iterator(buffer_1), "ab");
fmt::format_to(std::back_insert_iterator(buffer_2), "ab");
EXPECT_STREQ(buffer_1.c_str(), "a");
EXPECT_STREQ(buffer_2.c_str(), "ab");
}
TEST(TruncatingBufferTest, 2bytes) {
EXPECT_EQ(sizeof("αβ"), 5);
truncating_buffer<3> buffer_1;
truncating_buffer<4> buffer_2;
truncating_buffer<5> buffer_3;
fmt::format_to(std::back_insert_iterator(buffer_1), "αβ");
fmt::format_to(std::back_insert_iterator(buffer_2), "αβ");
fmt::format_to(std::back_insert_iterator(buffer_3), "αβ");
EXPECT_STREQ(buffer_1.c_str(), "α");
EXPECT_STREQ(buffer_2.c_str(), "α");
EXPECT_STREQ(buffer_3.c_str(), "αβ");
}
TEST(TruncatingBufferTest, 3bytes) {
EXPECT_EQ(sizeof("ພຮ"), 7);
truncating_buffer<4> buffer_1;
truncating_buffer<5> buffer_2;
truncating_buffer<6> buffer_3;
truncating_buffer<7> buffer_4;
fmt::format_to(std::back_insert_iterator(buffer_1), "ພຮ");
fmt::format_to(std::back_insert_iterator(buffer_2), "ພຮ");
fmt::format_to(std::back_insert_iterator(buffer_3), "ພຮ");
fmt::format_to(std::back_insert_iterator(buffer_4), "ພຮ");
EXPECT_STREQ(buffer_1.c_str(), "ພ");
EXPECT_STREQ(buffer_2.c_str(), "ພ");
EXPECT_STREQ(buffer_3.c_str(), "ພ");
EXPECT_STREQ(buffer_4.c_str(), "ພຮ");
}
TEST(TruncatingBufferTest, 4bytes) {
EXPECT_EQ(sizeof("𐎡𐎪"), 9);
truncating_buffer<5> buffer_1;
truncating_buffer<6> buffer_2;
truncating_buffer<7> buffer_3;
truncating_buffer<8> buffer_4;
truncating_buffer<9> buffer_5;
fmt::format_to(std::back_insert_iterator(buffer_1), "𐎡𐎪");
fmt::format_to(std::back_insert_iterator(buffer_2), "𐎡𐎪");
fmt::format_to(std::back_insert_iterator(buffer_3), "𐎡𐎪");
fmt::format_to(std::back_insert_iterator(buffer_4), "𐎡𐎪");
fmt::format_to(std::back_insert_iterator(buffer_5), "𐎡𐎪");
EXPECT_STREQ(buffer_1.c_str(), "𐎡");
EXPECT_STREQ(buffer_2.c_str(), "𐎡");
EXPECT_STREQ(buffer_3.c_str(), "𐎡");
EXPECT_STREQ(buffer_4.c_str(), "𐎡");
EXPECT_STREQ(buffer_5.c_str(), "𐎡𐎪");
}
/*
* Copyright 2023 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 <log/log.h>
#include "bluetooth/log.h"
#include "truncating_buffer.h"
namespace bluetooth::log_internal {
static constexpr size_t kBufferSize = 1024;
void vlog(Level level, char const* tag, char const* file_name, int line,
char const* function_name, fmt::string_view fmt,
fmt::format_args vargs) {
// Check if log is enabled.
if (!__android_log_is_loggable(level, tag, ANDROID_LOG_DEFAULT) &&
!__android_log_is_loggable(level, "bluetooth", ANDROID_LOG_DEFAULT)) {
return;
}
// Format to stack buffer.
truncating_buffer<kBufferSize> buffer;
fmt::format_to(std::back_insert_iterator(buffer), "{}: ", function_name);
fmt::vformat_to(std::back_insert_iterator(buffer), fmt, vargs);
// Send message to liblog.
struct __android_log_message message = {
.struct_size = sizeof(__android_log_message),
.buffer_id = LOG_ID_MAIN,
.priority = static_cast<android_LogPriority>(level),
.tag = tag,
.file = file_name,
.line = static_cast<uint32_t>(line),
.message = buffer.c_str(),
};
__android_log_write_log_message(&message);
}
} // namespace bluetooth::log_internal
/*
* Copyright 2023 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 <syslog.h>
#include "bluetooth/log.h"
#include "truncating_buffer.h"
namespace bluetooth::log_internal {
// Default value for $MaxMessageSize for rsyslog.
static constexpr size_t kBufferSize = 8192;
void vlog(Level level, char const* tag, char const* file_name, int line,
char const* function_name, fmt::string_view fmt,
fmt::format_args vargs) {
// Convert the level to syslog severity.
int severity = LOG_DEBUG;
switch (level) {
case Level::kVerbose:
case Level::kDebug:
default:
severity = LOG_DEBUG;
break;
case Level::kInfo:
severity = LOG_INFO;
break;
case Level::kWarn:
severity = LOG_WARNING;
break;
case Level::kError:
severity = LOG_ERR;
break;
case Level::kFatal:
severity = LOG_CRIT;
break;
}
// Prepare bounded stack buffer.
truncating_buffer<kBufferSize> buffer;
// Format file, line.
fmt::format_to(std::back_insert_iterator(buffer), "{} {}:{} {}: ", tag,
file_name, line, function_name);
// Format message.
fmt::vformat_to(std::back_insert_iterator(buffer), fmt, vargs);
// Print to vsyslog.
syslog(LOG_USER | severity, "%s", buffer.c_str());
}
} // namespace bluetooth::log_internal
/*
* Copyright 2023 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.
*/
#define LOG_TAG "test"
#include <gtest/gtest.h>
#include <log/log.h>
#include "bluetooth/log.h"
#include "truncating_buffer.h"
/// Captures the latest message generated by the android vlog
/// implementation.
static std::optional<__android_log_message> androidLogMessage;
/// Mask the implementation from liblog.
int __android_log_is_loggable(int /*prio*/, const char* /*tag*/,
int /*default_prio*/) {
return true;
}
/// Mask the implementation from liblog.
void __android_log_write_log_message(
struct __android_log_message* log_message) {
if (log_message != nullptr) {
log_message->message = strdup(log_message->message);
androidLogMessage.emplace(*log_message);
}
}
using namespace bluetooth;
TEST(BluetoothLoggerTest, verbose) {
androidLogMessage.reset();
log::verbose("verbose test");
ASSERT_TRUE(androidLogMessage.has_value());
EXPECT_EQ(androidLogMessage->priority, ANDROID_LOG_VERBOSE);
EXPECT_STREQ(androidLogMessage->tag, LOG_TAG);
EXPECT_STREQ(androidLogMessage->file,
"packages/modules/Bluetooth/system/log/src/vlog_test.cc");
EXPECT_EQ(androidLogMessage->line, 49);
EXPECT_STREQ(androidLogMessage->message, "TestBody: verbose test");
}
TEST(BluetoothLoggerTest, debug) {
androidLogMessage.reset();
log::debug("debug test");
ASSERT_TRUE(androidLogMessage.has_value());
EXPECT_EQ(androidLogMessage->priority, ANDROID_LOG_DEBUG);
EXPECT_STREQ(androidLogMessage->tag, LOG_TAG);
EXPECT_STREQ(androidLogMessage->file,
"packages/modules/Bluetooth/system/log/src/vlog_test.cc");
EXPECT_EQ(androidLogMessage->line, 63);
EXPECT_STREQ(androidLogMessage->message, "TestBody: debug test");
}
TEST(BluetoothLoggerTest, info) {
androidLogMessage.reset();
log::info("info test");
ASSERT_TRUE(androidLogMessage.has_value());
EXPECT_EQ(androidLogMessage->priority, ANDROID_LOG_INFO);
EXPECT_STREQ(androidLogMessage->tag, LOG_TAG);
EXPECT_STREQ(androidLogMessage->file,
"packages/modules/Bluetooth/system/log/src/vlog_test.cc");
EXPECT_EQ(androidLogMessage->line, 77);
EXPECT_STREQ(androidLogMessage->message, "TestBody: info test");
}
TEST(BluetoothLoggerTest, warn) {
androidLogMessage.reset();
log::warn("warn test");
ASSERT_TRUE(androidLogMessage.has_value());
EXPECT_EQ(androidLogMessage->priority, ANDROID_LOG_WARN);
EXPECT_STREQ(androidLogMessage->tag, LOG_TAG);
EXPECT_STREQ(androidLogMessage->file,
"packages/modules/Bluetooth/system/log/src/vlog_test.cc");
EXPECT_EQ(androidLogMessage->line, 91);
EXPECT_STREQ(androidLogMessage->message, "TestBody: warn test");
}
TEST(BluetoothLoggerTest, error) {
androidLogMessage.reset();
log::error("error test");
ASSERT_TRUE(androidLogMessage.has_value());
EXPECT_EQ(androidLogMessage->priority, ANDROID_LOG_ERROR);
EXPECT_STREQ(androidLogMessage->tag, LOG_TAG);
EXPECT_STREQ(androidLogMessage->file,
"packages/modules/Bluetooth/system/log/src/vlog_test.cc");
EXPECT_EQ(androidLogMessage->line, 105);
EXPECT_STREQ(androidLogMessage->message, "TestBody: error test");
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment