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