blob: 9f83b7b558afb0f32b3549bc5a55eaf72be05d7d [file] [log] [blame]
Ryan Keaneefab2ed2019-07-22 12:36:53 -07001// Copyright 2019 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
Ryan Keaneefab2ed2019-07-22 12:36:53 -07005#include <chrono>
6#include <iostream>
7#include <thread>
8
9#include "absl/types/optional.h"
10#include "gmock/gmock.h"
11#include "gtest/gtest.h"
12
Ryan Keaned5b3c342019-07-25 09:48:45 -070013#define TRACE_FORCE_ENABLE true
14
15#include "platform/api/trace_logging.h"
16
Jordan Bayles824067c2019-07-23 12:12:17 -070017// TODO(issue/52): Remove duplicate code from trace logging+internal unit tests
Ryan Keaneefab2ed2019-07-22 12:36:53 -070018namespace openscreen {
19namespace platform {
20
21using ::testing::_;
Jordan Bayles824067c2019-07-23 12:12:17 -070022using ::testing::DoAll;
Ryan Keaneefab2ed2019-07-22 12:36:53 -070023using ::testing::Invoke;
24
25class MockLoggingPlatform : public TraceLoggingPlatform {
26 public:
27 MOCK_METHOD9(LogTrace,
28 void(const char*,
29 const uint32_t,
30 const char* file,
31 Clock::time_point,
32 Clock::time_point,
33 TraceId,
34 TraceId,
35 TraceId,
36 Error::Code));
37 MOCK_METHOD7(LogAsyncStart,
38 void(const char*,
39 const uint32_t,
40 const char* file,
41 Clock::time_point,
42 TraceId,
43 TraceId,
44 TraceId));
45 MOCK_METHOD5(LogAsyncEnd,
46 void(const uint32_t,
47 const char* file,
48 Clock::time_point,
49 TraceId,
50 Error::Code));
51};
52
53// Methods to validate the results of platform-layer calls.
54template <uint64_t milliseconds>
55void ValidateTraceTimestampDiff(const char* name,
56 const uint32_t line,
57 const char* file,
58 Clock::time_point start_time,
59 Clock::time_point end_time,
60 TraceId trace_id,
61 TraceId parent_id,
62 TraceId root_id,
63 Error error) {
64 const auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
65 end_time - start_time);
Jordan Bayles824067c2019-07-23 12:12:17 -070066 EXPECT_GE(static_cast<uint64_t>(elapsed.count()), milliseconds);
Ryan Keaneefab2ed2019-07-22 12:36:53 -070067}
68
69template <Error::Code result>
70void ValidateTraceErrorCode(const char* name,
71 const uint32_t line,
72 const char* file,
73 Clock::time_point start_time,
74 Clock::time_point end_time,
75 TraceId trace_id,
76 TraceId parent_id,
77 TraceId root_id,
78 Error error) {
79 EXPECT_EQ(error.code(), result);
80}
81
82TEST(TraceLoggingTest, MacroCallScopedDoesntSegFault) {
83 MockLoggingPlatform platform;
84 TRACE_SET_DEFAULT_PLATFORM(&platform);
85 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, _, _, _, _)).Times(1);
86 { TRACE_SCOPED(TraceCategory::Value::Any, "test"); }
87}
88
89TEST(TraceLoggingTest, MacroCallUnscopedDoesntSegFault) {
90 MockLoggingPlatform platform;
91 TRACE_SET_DEFAULT_PLATFORM(&platform);
92 EXPECT_CALL(platform, LogAsyncStart(_, _, _, _, _, _, _)).Times(1);
93 { TRACE_ASYNC_START(TraceCategory::Value::Any, "test"); }
94}
95
96TEST(TraceLoggingTest, MacroVariablesUniquelyNames) {
97 MockLoggingPlatform platform;
98 TRACE_SET_DEFAULT_PLATFORM(&platform);
99 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, _, _, _, _)).Times(2);
100 EXPECT_CALL(platform, LogAsyncStart(_, _, _, _, _, _, _)).Times(2);
101
102 {
103 TRACE_SCOPED(TraceCategory::Value::Any, "test1");
104 TRACE_SCOPED(TraceCategory::Value::Any, "test2");
105 TRACE_ASYNC_START(TraceCategory::Value::Any, "test3");
106 TRACE_ASYNC_START(TraceCategory::Value::Any, "test4");
107 }
108}
109
110TEST(TraceLoggingTest, ExpectTimestampsReflectDelay) {
111 constexpr uint32_t delay_in_ms = 50;
112 MockLoggingPlatform platform;
113 TRACE_SET_DEFAULT_PLATFORM(&platform);
114 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, _, _, _, _))
115 .WillOnce(DoAll(Invoke(ValidateTraceTimestampDiff<delay_in_ms>),
116 Invoke(ValidateTraceErrorCode<Error::Code::kNone>)));
117
118 {
119 TRACE_SCOPED(TraceCategory::Value::Any, "Name");
120 std::this_thread::sleep_for(std::chrono::milliseconds(delay_in_ms));
121 }
122}
123
124TEST(TraceLoggingTest, ExpectErrorsPassedToResult) {
125 constexpr Error::Code result_code = Error::Code::kParseError;
126 MockLoggingPlatform platform;
127 TRACE_SET_DEFAULT_PLATFORM(&platform);
128 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, _, _, _, _))
129 .WillOnce(Invoke(ValidateTraceErrorCode<result_code>));
130
131 {
132 TRACE_SCOPED(TraceCategory::Value::Any, "Name");
133 TRACE_SET_RESULT(result_code);
134 }
135}
136
137TEST(TraceLoggingTest, ExpectUnsetTraceIdNotSet) {
138 MockLoggingPlatform platform;
139 TRACE_SET_DEFAULT_PLATFORM(&platform);
140 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, _, _, _, _)).Times(1);
141
142 TraceIdHierarchy h = {kUnsetTraceId, kUnsetTraceId, kUnsetTraceId};
143 {
144 TRACE_SCOPED(TraceCategory::Value::Any, "Name", h);
145
146 auto ids = TRACE_HIERARCHY;
147 EXPECT_NE(ids.current, kUnsetTraceId);
148 EXPECT_NE(ids.parent, kUnsetTraceId);
149 EXPECT_NE(ids.root, kUnsetTraceId);
150 }
151}
152
153TEST(TraceLoggingTest, ExpectCreationWithIdsToWork) {
154 constexpr TraceId current = 0x32;
155 constexpr TraceId parent = 0x47;
156 constexpr TraceId root = 0x84;
157 MockLoggingPlatform platform;
158 TRACE_SET_DEFAULT_PLATFORM(&platform);
159 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, current, parent, root, _))
160 .WillOnce(Invoke(ValidateTraceErrorCode<Error::Code::kNone>));
161
162 {
163 TraceIdHierarchy h = {current, parent, root};
164 TRACE_SCOPED(TraceCategory::Value::Any, "Name", h);
165
166 auto ids = TRACE_HIERARCHY;
167 EXPECT_EQ(ids.current, current);
168 EXPECT_EQ(ids.parent, parent);
169 EXPECT_EQ(ids.root, root);
170
171 EXPECT_EQ(TRACE_CURRENT_ID, current);
172 EXPECT_EQ(TRACE_ROOT_ID, root);
173 }
174}
175
176TEST(TraceLoggingTest, ExpectHirearchyToBeApplied) {
177 constexpr TraceId current = 0x32;
178 constexpr TraceId parent = 0x47;
179 constexpr TraceId root = 0x84;
180 MockLoggingPlatform platform;
181 TRACE_SET_DEFAULT_PLATFORM(&platform);
182 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, _, current, root, _))
183 .WillOnce(Invoke(ValidateTraceErrorCode<Error::Code::kNone>));
184 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, current, parent, root, _))
185 .WillOnce(Invoke(ValidateTraceErrorCode<Error::Code::kNone>));
186
187 {
188 TraceIdHierarchy h = {current, parent, root};
189 TRACE_SCOPED(TraceCategory::Value::Any, "Name", h);
190 auto ids = TRACE_HIERARCHY;
191 EXPECT_EQ(ids.current, current);
192 EXPECT_EQ(ids.parent, parent);
193 EXPECT_EQ(ids.root, root);
194
195 TRACE_SCOPED(TraceCategory::Value::Any, "Name");
196 ids = TRACE_HIERARCHY;
197 EXPECT_NE(ids.current, current);
198 EXPECT_EQ(ids.parent, current);
199 EXPECT_EQ(ids.root, root);
200 }
201}
202
203TEST(TraceLoggingTest, ExpectHirearchyToEndAfterScopeWhenSetWithSetter) {
204 constexpr TraceId current = 0x32;
205 constexpr TraceId parent = 0x47;
206 constexpr TraceId root = 0x84;
207 MockLoggingPlatform platform;
208 TRACE_SET_DEFAULT_PLATFORM(&platform);
209 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, _, current, root, _))
210 .WillOnce(Invoke(ValidateTraceErrorCode<Error::Code::kNone>));
211
212 {
213 TraceIdHierarchy ids = {current, parent, root};
214 TRACE_SET_HIERARCHY(ids);
215 {
216 TRACE_SCOPED(TraceCategory::Value::Any, "Name");
217 ids = TRACE_HIERARCHY;
218 EXPECT_NE(ids.current, current);
219 EXPECT_EQ(ids.parent, current);
220 EXPECT_EQ(ids.root, root);
221 }
222
223 ids = TRACE_HIERARCHY;
224 EXPECT_EQ(ids.current, current);
225 EXPECT_EQ(ids.parent, parent);
226 EXPECT_EQ(ids.root, root);
227 }
228}
229
230TEST(TraceLoggingTest, ExpectHirearchyToEndAfterScope) {
231 constexpr TraceId current = 0x32;
232 constexpr TraceId parent = 0x47;
233 constexpr TraceId root = 0x84;
234 MockLoggingPlatform platform;
235 TRACE_SET_DEFAULT_PLATFORM(&platform);
236 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, _, current, root, _))
237 .WillOnce(Invoke(ValidateTraceErrorCode<Error::Code::kNone>));
238 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, current, parent, root, _))
239 .WillOnce(Invoke(ValidateTraceErrorCode<Error::Code::kNone>));
240
241 {
242 TraceIdHierarchy ids = {current, parent, root};
243 TRACE_SCOPED(TraceCategory::Value::Any, "Name", ids);
244 {
245 TRACE_SCOPED(TraceCategory::Value::Any, "Name");
246 ids = TRACE_HIERARCHY;
247 EXPECT_NE(ids.current, current);
248 EXPECT_EQ(ids.parent, current);
249 EXPECT_EQ(ids.root, root);
250 }
251
252 ids = TRACE_HIERARCHY;
253 EXPECT_EQ(ids.current, current);
254 EXPECT_EQ(ids.parent, parent);
255 EXPECT_EQ(ids.root, root);
256 }
257}
258
259TEST(TraceLoggingTest, ExpectSetHierarchyToApply) {
260 constexpr TraceId current = 0x32;
261 constexpr TraceId parent = 0x47;
262 constexpr TraceId root = 0x84;
263 MockLoggingPlatform platform;
264 TRACE_SET_DEFAULT_PLATFORM(&platform);
265 EXPECT_CALL(platform, LogTrace(_, _, _, _, _, _, current, root, _))
266 .WillOnce(Invoke(ValidateTraceErrorCode<Error::Code::kNone>));
267
268 {
269 TraceIdHierarchy ids = {current, parent, root};
270 TRACE_SET_HIERARCHY(ids);
271 ids = TRACE_HIERARCHY;
272 EXPECT_EQ(ids.current, current);
273 EXPECT_EQ(ids.parent, parent);
274 EXPECT_EQ(ids.root, root);
275
276 TRACE_SCOPED(TraceCategory::Value::Any, "Name");
277 ids = TRACE_HIERARCHY;
278 EXPECT_NE(ids.current, current);
279 EXPECT_EQ(ids.parent, current);
280 EXPECT_EQ(ids.root, root);
281 }
282}
283
284TEST(TraceLoggingTest, CheckTraceAsyncStartLogsCorrectly) {
285 MockLoggingPlatform platform;
286 TRACE_SET_DEFAULT_PLATFORM(&platform);
287 EXPECT_CALL(platform, LogAsyncStart(_, _, _, _, _, _, _)).Times(1);
288
289 { TRACE_ASYNC_START(TraceCategory::Value::Any, "Name"); }
290}
291
292TEST(TraceLoggingTest, CheckTraceAsyncStartSetsHierarchy) {
293 constexpr TraceId current = 32;
294 constexpr TraceId parent = 47;
295 constexpr TraceId root = 84;
296 MockLoggingPlatform platform;
297 TRACE_SET_DEFAULT_PLATFORM(&platform);
298 EXPECT_CALL(platform, LogAsyncStart(_, _, _, _, _, current, root)).Times(1);
299
300 {
301 TraceIdHierarchy ids = {current, parent, root};
302 TRACE_SET_HIERARCHY(ids);
303 {
304 TRACE_ASYNC_START(TraceCategory::Value::Any, "Name");
305 ids = TRACE_HIERARCHY;
306 EXPECT_NE(ids.current, current);
307 EXPECT_EQ(ids.parent, current);
308 EXPECT_EQ(ids.root, root);
309 }
310
311 ids = TRACE_HIERARCHY;
312 EXPECT_EQ(ids.current, current);
313 EXPECT_EQ(ids.parent, parent);
314 EXPECT_EQ(ids.root, root);
315 }
316}
317
318TEST(TraceLoggingTest, CheckTraceAsyncEndLogsCorrectly) {
319 constexpr TraceId id = 12345;
320 constexpr Error::Code result = Error::Code::kAgain;
321 MockLoggingPlatform platform;
322 TRACE_SET_DEFAULT_PLATFORM(&platform);
323 EXPECT_CALL(platform, LogAsyncEnd(_, _, _, id, result)).Times(1);
324
325 TRACE_ASYNC_END(TraceCategory::Value::Any, id, result);
326}
327
328} // namespace platform
329} // namespace openscreen
Ryan Keaned5b3c342019-07-25 09:48:45 -0700330
331#undef TRACE_FORCE_ENABLE