Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Side by Side Diff: mojo/services/log/cpp/tests/log_client_unittest.cc

Issue 1447273002: Mojo Log service and a thread-safe client library. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: make min log level consistent with fallback logger, fix thread-safety, address trung's other commen… Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
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 <atomic>
viettrungluu 2015/12/17 18:34:39 Apparently, you don't need any atomics, according
vardhan 2015/12/17 23:35:42 Done.
6 #include <set>
7 #include <thread>
8 #include <vector>
9
10 #include "mojo/public/cpp/application/application_test_base.h"
11 #include "mojo/public/cpp/bindings/strong_binding.h"
12 #include "mojo/public/cpp/system/macros.h"
13 #include "mojo/public/cpp/utility/run_loop.h"
14 #include "mojo/services/log/cpp/log_client.h"
15 #include "mojo/services/log/interfaces/entry.mojom.h"
16 #include "mojo/services/log/interfaces/log.mojom.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 using LogClientTest = mojo::test::ApplicationTestBase;
20 using mojo::Environment;
21 using mojo::internal::ValidationError;
22
23 namespace mojo {
24 namespace {
25
26 // A Log implementation that remembers the set of all incoming messages.
27 class TestLogServiceImpl : public log::Log {
28 public:
29 explicit TestLogServiceImpl(InterfaceRequest<log::Log> log_req)
30 : binding_(this, std::move(log_req)) {
31 EXPECT_TRUE(binding_.is_bound());
32 binding_.set_connection_error_handler([this]() {
33 FAIL() << "Log service lost connection to the log client.";
34 });
35 validation_observer_.set_last_error(ValidationError::NONE);
36 }
37 void AddEntry(mojo::log::EntryPtr entry) override {
38 entry_msgs_.insert(entry->message.To<std::string>());
39 }
40 const std::set<std::string>& entries() { return entry_msgs_; }
41 mojo::internal::ValidationError previous_validation_error() {
42 return validation_observer_.last_error();
43 }
44
45 private:
46 mojo::StrongBinding<log::Log> binding_;
47 std::set<std::string> entry_msgs_;
48 mojo::internal::ValidationErrorObserverForTesting validation_observer_;
49 };
50
51 std::atomic<MojoLogLevel> g_fallback_logger_level(MOJO_LOG_LEVEL_INFO);
52 bool g_fallback_logger_invoked = false;
53 // This tests that multiple threads can use the MojoLogger that
54 // mojo::log::LogClient produces, by spawning off |kNumLogEntries| threads, each
55 // issuing one unique log message.
56 TEST_F(LogClientTest, ConcurrentAddEntry) {
57 log::LogPtr log_ptr;
58 std::unique_ptr<mojo::TestLogServiceImpl> log_impl(
59 new mojo::TestLogServiceImpl(mojo::GetProxy(&log_ptr)));
60
61 // This is our test fallback logger + state. We simply records whether it's
62 // been called.
63 MojoLogger fallback_logger = {
64 // LogMessage
65 [](MojoLogLevel log_level, const char* source_file, uint32_t source_line,
66 const char* message) { g_fallback_logger_invoked = true; },
67 // SetMinimumLogLevel
68 []() -> MojoLogLevel {
69 return g_fallback_logger_level.load(std::memory_order_relaxed);
70 },
71 // GetMinimumLogLevel
72 [](MojoLogLevel lvl) {
73 g_fallback_logger_level.store(lvl, std::memory_order_relaxed);
74 }};
75 log::InitializeLogger(std::move(log_ptr), &fallback_logger);
76 Environment::SetDefaultLogger(log::GetLogger());
77
78 // Spawn off numerous threads, each of them issuing a unique log message.
79 std::vector<std::thread> threads;
80 std::set<std::string> expected_entries;
81
82 // The number of log entries to issue.
83 const int kNumLogEntries = 1000;
84 for (int i = 0; i < kNumLogEntries; i++) {
85 std::stringstream msg;
86 msg << "Test message: " << i;
87 EXPECT_TRUE(expected_entries.insert(msg.str()).second);
88
89 std::thread t([](std::string msg) { MOJO_LOG(INFO) << msg; }, msg.str());
90
91 threads.push_back(std::move(t));
92 }
93 for (auto& t : threads) {
94 t.join();
95 }
96
97 // The log message calls should now be processed by TestLogServiceImpl.
98 mojo::RunLoop::current()->RunUntilIdle();
99
100 EXPECT_EQ(expected_entries, log_impl->entries());
101 EXPECT_EQ(ValidationError::NONE, log_impl->previous_validation_error());
102
103 // We kill our binding, closing the connection to the log client and
104 // causing the log client to revert to using its fallback logger.
105 log_impl.reset();
106
107 EXPECT_FALSE(mojo::g_fallback_logger_invoked);
108 MOJO_LOG(INFO) << "Ignore this log message.";
109 EXPECT_TRUE(mojo::g_fallback_logger_invoked);
110
111 // Check that this logger propogates get/set min level calls to the fallback
112 // logger.
113 auto* logger = log::GetLogger();
114 EXPECT_EQ(MOJO_LOG_LEVEL_INFO, logger->GetMinimumLogLevel());
115 logger->SetMinimumLogLevel(MOJO_LOG_LEVEL_FATAL);
116 EXPECT_EQ(MOJO_LOG_LEVEL_FATAL, logger->GetMinimumLogLevel());
117 EXPECT_EQ(MOJO_LOG_LEVEL_FATAL, fallback_logger.GetMinimumLogLevel());
118
119 log::DestroyLogger();
120 }
121
122 } // namespace
123 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698