xref: /aosp_15_r20/external/cronet/base/fuchsia/test_log_listener_safe.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/fuchsia/test_log_listener_safe.h"
6 
7 #include <lib/async/default.h>
8 #include <lib/fidl/cpp/box.h>
9 #include <lib/zx/clock.h>
10 
11 #include <optional>
12 #include <string_view>
13 
14 #include "base/fuchsia/fuchsia_component_connect.h"
15 #include "base/fuchsia/fuchsia_logging.h"
16 #include "base/functional/callback_helpers.h"
17 #include "base/process/process.h"
18 #include "base/run_loop.h"
19 #include "base/test/bind.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace base {
23 
24 TestLogListenerSafe::TestLogListenerSafe() = default;
25 
26 TestLogListenerSafe::~TestLogListenerSafe() = default;
27 
set_on_log_message(base::RepeatingCallback<void (const fuchsia_logger::LogMessage &)> callback)28 void TestLogListenerSafe::set_on_log_message(
29     base::RepeatingCallback<void(const fuchsia_logger::LogMessage&)> callback) {
30   on_log_message_ = std::move(callback);
31 }
32 
Log(TestLogListenerSafe::LogRequest & request,TestLogListenerSafe::LogCompleter::Sync & completer)33 void TestLogListenerSafe::Log(
34     TestLogListenerSafe::LogRequest& request,
35     TestLogListenerSafe::LogCompleter::Sync& completer) {
36   if (on_log_message_)
37     on_log_message_.Run(request.log());
38   completer.Reply();
39 }
40 
LogMany(TestLogListenerSafe::LogManyRequest & request,TestLogListenerSafe::LogManyCompleter::Sync & completer)41 void TestLogListenerSafe::LogMany(
42     TestLogListenerSafe::LogManyRequest& request,
43     TestLogListenerSafe::LogManyCompleter::Sync& completer) {
44   for (const auto& message : request.log()) {
45     on_log_message_.Run(message);
46   }
47   completer.Reply();
48 }
49 
Done(TestLogListenerSafe::DoneCompleter::Sync & completer)50 void TestLogListenerSafe::Done(
51     TestLogListenerSafe::DoneCompleter::Sync& completer) {}
52 
53 SimpleTestLogListener::SimpleTestLogListener() = default;
54 SimpleTestLogListener::~SimpleTestLogListener() = default;
55 
ListenToLog(const fidl::Client<fuchsia_logger::Log> & log,std::unique_ptr<fuchsia_logger::LogFilterOptions> options)56 void SimpleTestLogListener::ListenToLog(
57     const fidl::Client<fuchsia_logger::Log>& log,
58     std::unique_ptr<fuchsia_logger::LogFilterOptions> options) {
59   auto listener_endpoints =
60       fidl::CreateEndpoints<fuchsia_logger::LogListenerSafe>();
61   ZX_CHECK(listener_endpoints.is_ok(), listener_endpoints.status_value())
62       << "Failed to create listener endpoints";
63   binding_.emplace(
64       async_get_default_dispatcher(), std::move(listener_endpoints->server),
65       &listener_, [](fidl::UnbindInfo info) {
66         ZX_LOG(ERROR, info.status()) << "LogListenerSafe disconnected";
67       });
68 
69   ignore_before_ = zx::clock::get_monotonic();
70   listener_.set_on_log_message(base::BindRepeating(
71       &SimpleTestLogListener::PushLoggedMessage, base::Unretained(this)));
72   auto listen_safe_result =
73       log->ListenSafe({{.log_listener = std::move(listener_endpoints->client),
74                         .options = std::move(options)}});
75   if (listen_safe_result.is_error()) {
76     ZX_DLOG(ERROR, listen_safe_result.error_value().status())
77         << "ListenSafe() failed";
78   }
79 }
80 
81 std::optional<fuchsia_logger::LogMessage>
RunUntilMessageReceived(std::string_view expected_string)82 SimpleTestLogListener::RunUntilMessageReceived(
83     std::string_view expected_string) {
84   while (!logged_messages_.empty()) {
85     fuchsia_logger::LogMessage message = logged_messages_.front();
86     logged_messages_.pop_front();
87     if (std::string_view(message.msg()).find(expected_string) !=
88         std::string::npos) {
89       return message;
90     }
91   }
92 
93   std::optional<fuchsia_logger::LogMessage> logged_message;
94   base::RunLoop loop;
95   on_log_message_ = base::BindLambdaForTesting(
96       [ignore_before = ignore_before_, &logged_message,
97        expected_string = std::string(expected_string),
98        quit_loop =
99            loop.QuitClosure()](const fuchsia_logger::LogMessage& message) {
100         if (zx::time(message.time()) < ignore_before) {
101           return;
102         }
103         if (message.msg().find(expected_string) == std::string::npos) {
104           return;
105         }
106         logged_message.emplace(message);
107         quit_loop.Run();
108       });
109 
110   loop.Run();
111 
112   on_log_message_ = NullCallback();
113 
114   return logged_message;
115 }
116 
PushLoggedMessage(const fuchsia_logger::LogMessage & message)117 void SimpleTestLogListener::PushLoggedMessage(
118     const fuchsia_logger::LogMessage& message) {
119   DVLOG(1) << "TestLogListener received: " << message.msg();
120   if (zx::time(message.time()) < ignore_before_) {
121     return;
122   }
123   if (on_log_message_) {
124     DCHECK(logged_messages_.empty());
125     on_log_message_.Run(message);
126   } else {
127     logged_messages_.push_back(std::move(message));
128   }
129 }
130 
ListenFilteredByCurrentProcessId(SimpleTestLogListener & listener)131 void ListenFilteredByCurrentProcessId(SimpleTestLogListener& listener) {
132   // Connect the test LogListenerSafe to the Log.
133   auto log_client_end = fuchsia_component::Connect<fuchsia_logger::Log>();
134   ASSERT_TRUE(log_client_end.is_ok())
135       << FidlConnectionErrorMessage(log_client_end);
136   fidl::Client log_client(std::move(log_client_end.value()),
137                           async_get_default_dispatcher());
138   listener.ListenToLog(
139       log_client,
140       std::make_unique<fuchsia_logger::LogFilterOptions>(
141           fuchsia_logger::LogFilterOptions{
142               {.filter_by_pid = true,
143                .pid = Process::Current().Pid(),
144                .min_severity = fuchsia_logger::LogLevelFilter::kInfo}}));
145 }
146 
147 }  // namespace base
148