OLD | NEW |
---|---|
(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 | |
OLD | NEW |