xref: /aosp_15_r20/external/federated-compute/fcp/tracing/test/tracing_test.cc (revision 14675a029014e728ec732f129a32e299b2da0601)
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <memory>
16 #include <string>
17 #include <thread>  // NOLINT(build/c++11)
18 
19 #include "gtest/gtest.h"
20 #include "fcp/tracing/test/tracing_schema.h"
21 #include "fcp/tracing/test_tracing_recorder.h"
22 #include "fcp/tracing/tracing_severity.h"
23 #include "flatbuffers/flatbuffers.h"
24 
25 namespace fcp {
26 namespace {
27 
28 using flatbuffers::FlatBufferBuilder;
29 using flatbuffers::GetRoot;
30 using testing::_;
31 using testing::ElementsAre;
32 using testing::Eq;
33 using testing::Gt;
34 using testing::Not;
35 using testing::SizeIs;
36 using testing::UnorderedElementsAre;
37 
TEST(Tracing,TraitsTag)38 TEST(Tracing, TraitsTag) {
39   EXPECT_EQ(TracingTraits<SpanWithId>::kTag.str(), "SWID");
40   EXPECT_EQ(TracingTraits<EventBar>::kTag.str(), "EBAR");
41 }
42 
TEST(Tracing,TracingSeverity)43 TEST(Tracing, TracingSeverity) {
44   EXPECT_EQ(TracingTraits<SpanWithId>::kSeverity, fcp::TracingSeverity::kInfo);
45   EXPECT_EQ(TracingTraits<ErrorEvent>::kSeverity, fcp::TracingSeverity::kError);
46   EXPECT_EQ(TracingTraits<EventWithNoData>::kSeverity,
47             fcp::TracingSeverity::kWarning);
48 }
49 
TEST(Tracing,TraitsCreate)50 TEST(Tracing, TraitsCreate) {
51   FlatBufferBuilder fbb_foo;
52   fbb_foo.Finish(TracingTraits<EventFoo>::Create(222, 333, &fbb_foo));
53   auto foo = GetRoot<EventFoo>(fbb_foo.GetBufferPointer());
54   EXPECT_EQ(foo->first(), 222);
55   EXPECT_EQ(foo->second(), 333);
56 
57   // Creating a flat buffer involving a string field has different codegen
58   // path, testing this as well:
59   FlatBufferBuilder fbb_bar;
60   fbb_bar.Finish(
61       TracingTraits<EventBar>::Create(444, "Hello world!", &fbb_bar));
62   auto bar = GetRoot<EventBar>(fbb_bar.GetBufferPointer());
63   EXPECT_EQ(bar->first(), 444);
64   EXPECT_EQ(bar->second()->str(), "Hello world!");
65 
66   // Also make sure that a flatbuf involving a string field can be created using
67   // a std::string.
68   FlatBufferBuilder fbb_baz;
69   std::string hello_str = "Hello world!";
70   fbb_baz.Finish(TracingTraits<EventBar>::Create(444, hello_str, &fbb_baz));
71   auto baz = GetRoot<EventBar>(fbb_baz.GetBufferPointer());
72   EXPECT_EQ(baz->first(), 444);
73   EXPECT_EQ(baz->second()->str(), "Hello world!");
74 }
75 
TEST(Tracing,TraitsCreateFieldOrder)76 TEST(Tracing, TraitsCreateFieldOrder) {
77   int first_i = -333;
78   int second_i = 444;
79   FlatBufferBuilder fbb_foo;
80   fbb_foo.Finish(
81       TracingTraits<FieldOrder>::Create(first_i, second_i, "hello", &fbb_foo));
82   auto foo = GetRoot<FieldOrder>(fbb_foo.GetBufferPointer());
83   EXPECT_EQ(foo->fieldz(), first_i);
84   EXPECT_EQ(foo->fieldy(), second_i);
85   EXPECT_EQ(foo->fieldx()->str(), "hello");
86 
87   FlatBufferBuilder fbb_bar;
88   fbb_bar.Finish(TracingTraits<OrderWithIds>::Create("hello", first_i, second_i,
89                                                      &fbb_bar));
90   auto bar = GetRoot<OrderWithIds>(fbb_bar.GetBufferPointer());
91   EXPECT_EQ(bar->fieldz(), first_i);
92   EXPECT_EQ(bar->fieldy(), second_i);
93   EXPECT_EQ(bar->fieldx()->str(), "hello");
94 }
95 
TEST(Tracing,TraitsCreateAllTypes)96 TEST(Tracing, TraitsCreateAllTypes) {
97   FlatBufferBuilder fbb;
98   std::int8_t byte = -1;
99   std::uint8_t ubyte = 1;
100   std::int16_t short_i = -256;
101   std::uint16_t ushort_i = 256;
102   int i = -333;
103   unsigned int ui = 444;
104   float f = 1.1;
105   std::int64_t li = -4294967296;
106   std::uint64_t uli = 4294967296;
107   double d = 12312318.99999999;
108   fbb.Finish(TracingTraits<AllTypes>::Create(byte, ubyte, true, short_i,
109                                              ushort_i, i, ui, f, li, uli, d,
110                                              "hello", &fbb));
111   auto foo = GetRoot<AllTypes>(fbb.GetBufferPointer());
112   EXPECT_EQ(foo->fieldz(), byte);
113   EXPECT_EQ(foo->fieldy(), ubyte);
114   EXPECT_EQ(foo->fieldx(), true);
115   EXPECT_EQ(foo->fieldw(), short_i);
116   EXPECT_EQ(foo->fieldv(), ushort_i);
117   EXPECT_EQ(foo->fieldu(), i);
118   EXPECT_EQ(foo->fieldt(), ui);
119   EXPECT_EQ(foo->fields(), f);
120   EXPECT_EQ(foo->fieldr(), li);
121   EXPECT_EQ(foo->fieldq(), uli);
122   EXPECT_EQ(foo->fieldp(), d);
123   EXPECT_EQ(foo->fieldo()->str(), "hello");
124 }
125 
TEST(Tracing,TraitsCreateEnum)126 TEST(Tracing, TraitsCreateEnum) {
127   FlatBufferBuilder fbb;
128   fbb.Finish(TracingTraits<ColorEnum>::Create(Color_Blue, &fbb));
129   auto foo = GetRoot<ColorEnum>(fbb.GetBufferPointer());
130   EXPECT_EQ(foo->color(), Color_Blue);
131 }
132 
TEST(Tracing,TraitsCreateDeprecatedField)133 TEST(Tracing, TraitsCreateDeprecatedField) {
134   FlatBufferBuilder fbb_foo;
135   fbb_foo.Finish(TracingTraits<DeprecatedInt>::Create(222, &fbb_foo));
136   auto foo = GetRoot<EventFoo>(fbb_foo.GetBufferPointer());
137   EXPECT_EQ(foo->second(), 222);
138 }
139 
TEST(Tracing,LookupTraitByTag)140 TEST(Tracing, LookupTraitByTag) {
141   EXPECT_EQ(TracingTraitsBase::Lookup(TracingTag("SWID"))->Name(),
142             "SpanWithId");
143   EXPECT_EQ(TracingTraitsBase::Lookup(TracingTag("EBAR"))->Name(), "EventBar");
144 }
145 
TEST(Tracing,IntegrationTest)146 TEST(Tracing, IntegrationTest) {
147   TestTracingRecorder tracing_recorder;
148   {
149     TracingSpan<SpanWithId> inner(111);
150     Trace<EventFoo>(222, 333);
151     Trace<EventBar>(444, "Hello world!");
152     Trace<EventFoo>(555, 666);
153   }
154   {
155     TracingSpan<SpanWithNoData> inner;
156     Trace<EventWithNoData>();
157   }
158   EXPECT_THAT(
159       tracing_recorder.root(),
160       ElementsAre(AllOf(IsSpan<SpanWithId>(),
161                         ElementsAre(IsEvent<EventFoo>(222, 333),
162                                     IsEvent<EventBar>(444, "Hello world!"),
163                                     IsEvent<EventFoo>(555, 666))),
164                   AllOf(IsSpan<SpanWithNoData>(),
165                         ElementsAre(IsEvent<EventWithNoData>()))))
166       << "Tracing span/events structure and content must match";
167 }
168 
TEST(Tracing,UnscopedSpanIntegrationTest)169 TEST(Tracing, UnscopedSpanIntegrationTest) {
170   TestTracingRecorder tracing_recorder;
171   auto outer = std::make_unique<UnscopedTracingSpan<SpanWithId>>(111);
172   auto inner =
173       std::make_unique<UnscopedTracingSpan<SpanWithId>>(outer->Ref(), 222);
174   {
175     TracingSpan<SpanWithNoData> child_of_inner(inner->Ref());
176     Trace<EventFoo>(333, 444);
177   }
178   {
179     TracingSpan<SpanWithNoData> another_child_of_inner(inner->Ref());
180     Trace<EventFoo>(555, 666);
181     Trace<EventBar>(inner->Ref(), 1, "Trace in unscoped span!");
182     Trace<EventBar>(another_child_of_inner.Ref(), 1,
183                     "Trace in explicitly specified tracing span!");
184   }
185   TracingSpan<SpanWithNoData> unrelated_span;
186   Trace<EventBar>(777, "Hello world!");
187 
188   EXPECT_THAT(
189       tracing_recorder.root(),
190       ElementsAre(
191           AllOf(IsSpan<SpanWithId>(111),
192                 ElementsAre(AllOf(
193                     IsSpan<SpanWithId>(222),
194                     ElementsAre(
195                         AllOf(IsSpan<SpanWithNoData>(),
196                               ElementsAre(IsEvent<EventFoo>(333, 444))),
197                         AllOf(IsSpan<SpanWithNoData>(),
198                               ElementsAre(IsEvent<EventFoo>(555, 666),
199                                           IsEvent<EventBar>(
200                                               1,
201                                               "Trace in explicitly specified "
202                                               "tracing span!"))),
203                         IsEvent<EventBar>(1, "Trace in unscoped span!"))))),
204           AllOf(IsSpan<SpanWithNoData>(),
205                 ElementsAre(IsEvent<EventBar>(777, "Hello world!")))))
206       << "Tracing span/events structure and content must match";
207 }
208 
TEST(Tracing,ThreadingUnscopedIntegrationTest)209 TEST(Tracing, ThreadingUnscopedIntegrationTest) {
210   TestTracingRecorder tracing_recorder;
211   auto outer = std::make_unique<UnscopedTracingSpan<SpanWithId>>(111);
212   std::thread thread1([ref = outer->Ref()]() {
213     TracingSpan<SpanWithNoData> child_of_outer(ref);
214     Trace<EventFoo>(333, 444);
215   });
216   std::thread thread2([ref = outer->Ref()]() {
217     TracingSpan<SpanWithNoData> another_child_of_outer(ref);
218     Trace<EventFoo>(555, 666);
219     Trace<EventBar>(ref, 1, "Trace in unscoped span!");
220     Trace<EventBar>(another_child_of_outer.Ref(), 1, "Trace in local span!");
221   });
222   TracingSpan<SpanWithNoData> unrelated_span;
223   Trace<EventBar>(777, "Hello world!");
224   thread1.join();
225   thread2.join();
226 
227   EXPECT_THAT(
228       tracing_recorder.root(),
229       ElementsAre(AllOf(IsSpan<SpanWithId>(111),
230                         UnorderedElementsAre(
231                             AllOf(IsSpan<SpanWithNoData>(),
232                                   ElementsAre(IsEvent<EventFoo>(333, 444))),
233                             AllOf(IsSpan<SpanWithNoData>(),
234                                   ElementsAre(IsEvent<EventFoo>(555, 666),
235                                               IsEvent<EventBar>(
236                                                   1, "Trace in local span!"))),
237                             IsEvent<EventBar>(1, "Trace in unscoped span!"))),
238                   AllOf(IsSpan<SpanWithNoData>(),
239                         ElementsAre(IsEvent<EventBar>(777, "Hello world!")))))
240       << "Tracing span/events structure and content must match";
241 }
242 
TEST(Tracing,ThreadingScopedIntegrationTest)243 TEST(Tracing, ThreadingScopedIntegrationTest) {
244   TestTracingRecorder tracing_recorder;
245   TracingSpan<SpanWithId> outer(111);
246   std::thread thread1([ref = outer.Ref()]() {
247     TracingSpan<SpanWithNoData> child_of_outer(ref);
248     Trace<EventFoo>(333, 444);
249   });
250   std::thread thread2([ref = outer.Ref()]() {
251     TracingSpan<SpanWithNoData> another_child_of_outer(ref);
252     Trace<EventFoo>(555, 666);
253     Trace<EventBar>(ref, 1, "Trace in unscoped span!");
254     Trace<EventBar>(1, "Trace in local span!");
255   });
256   TracingSpan<SpanWithNoData> unrelated_span;
257   Trace<EventBar>(777, "Hello world!");
258   thread1.join();
259   thread2.join();
260 
261   EXPECT_THAT(
262       tracing_recorder.root(),
263       ElementsAre(AllOf(
264           IsSpan<SpanWithId>(111),
265           UnorderedElementsAre(
266               AllOf(IsSpan<SpanWithNoData>(),
267                     ElementsAre(IsEvent<EventFoo>(333, 444))),
268               AllOf(IsSpan<SpanWithNoData>(),
269                     ElementsAre(IsEvent<EventFoo>(555, 666),
270                                 IsEvent<EventBar>(1, "Trace in local span!"))),
271               IsEvent<EventBar>(1, "Trace in unscoped span!"),
272               AllOf(IsSpan<SpanWithNoData>(),
273                     ElementsAre(IsEvent<EventBar>(777, "Hello world!")))))))
274       << "Tracing span/events structure and content must match";
275 }
276 
TEST(Tracing,AdvancedMatching)277 TEST(Tracing, AdvancedMatching) {
278   TestTracingRecorder tracing_recorder;
279   {
280     TracingSpan<SpanWithId> span(111);
281     Trace<EventBar>(222, "Hello world!");
282   }
283 
284   auto span = tracing_recorder.root()[0];
285   auto event = span[0];
286   EXPECT_THAT(span, IsSpan<SpanWithId>());
287   EXPECT_THAT(event, IsEvent<EventBar>());
288   EXPECT_THAT(span,
289               AllOf(IsSpan<SpanWithId>(), ElementsAre(IsEvent<EventBar>())));
290   EXPECT_THAT(span, IsSpan<SpanWithId>(_));
291   EXPECT_THAT(span, IsSpan<SpanWithId>(Eq(111)));
292   EXPECT_THAT(span, IsSpan<SpanWithId>(Gt(100)));
293   EXPECT_THAT(event, IsEvent<EventBar>(Eq(222), Eq("Hello world!")));
294   EXPECT_THAT(event, IsEvent<EventBar>(_, Eq("Hello world!")));
295   EXPECT_THAT(event, IsEvent<EventBar>(_, _));
296   EXPECT_THAT(event, IsEvent<EventBar>(Eq(222), _));
297   EXPECT_THAT(event, IsEvent<EventBar>(Not(Eq(666)), _));
298   EXPECT_THAT(event, Not(IsEvent<EventBar>(Eq(666), _)));
299   EXPECT_THAT(event, Not(IsEvent<EventFoo>()));
300 }
301 
TEST(Tracing,MultipleRecorders)302 TEST(Tracing, MultipleRecorders) {
303   // NOTE: it is not a recommended scenario to have multiple instances of
304   // TestTracingRecorder per unit test, but this code path is enforced to
305   // ensure correct behavior of cleaning up global state so it is not carried
306   // over between tests.
307   {
308     TestTracingRecorder tracing_recorder;
309     Trace<EventFoo>(222, 333);
310     EXPECT_THAT(tracing_recorder.root()[0], IsEvent<EventFoo>(222, 333));
311   }
312   {
313     TestTracingRecorder tracing_recorder;
314     Trace<EventFoo>(444, 555);
315     EXPECT_THAT(tracing_recorder.root()[0], IsEvent<EventFoo>(444, 555));
316   }
317 }
318 
TEST(Tracing,TraceError)319 TEST(Tracing, TraceError) {
320   TestTracingRecorder tracing_recorder;
321   tracing_recorder.ExpectError<ErrorEvent>();
322   {
323     TracingSpan<SpanWithId> inner(111);
324     Error err = TraceError<ErrorEvent>("there was a bug");
325     (void)err;
326   }
327 }
328 
TEST(Tracing,FindOnlySpan)329 TEST(Tracing, FindOnlySpan) {
330   TestTracingRecorder tracing_recorder;
331   {
332     TracingSpan<SpanWithNoData> outer;
333     { TracingSpan<SpanWithId> inner(111); }
334     EXPECT_EQ(tracing_recorder.FindOnlySpan<SpanWithId>().data()->id(), 111);
335   }
336 }
337 
TEST(Tracing,FindAllSpans)338 TEST(Tracing, FindAllSpans) {
339   TestTracingRecorder tracing_recorder;
340   {
341     TracingSpan<SpanWithNoData> outer;
342     {
343       TracingSpan<SpanWithId> inner1(111);
344       { TracingSpan<SpanWithId> inner2(222); }
345     }
346     EXPECT_THAT(tracing_recorder.FindAllSpans<SpanWithId>(),
347                 ElementsAre(IsSpan<SpanWithId>(), IsSpan<SpanWithId>()));
348     EXPECT_THAT(tracing_recorder.FindAllSpans<SpanNeverLogged>(), SizeIs(0));
349   }
350 }
351 
TEST(Tracing,FindOnlyEvent)352 TEST(Tracing, FindOnlyEvent) {
353   TestTracingRecorder tracing_recorder;
354   {
355     TracingSpan<SpanWithNoData> outer;
356     { Trace<EventFoo>(111, 222); }
357     EXPECT_EQ(tracing_recorder.FindOnlyEvent<EventFoo>().data()->first(), 111);
358     EXPECT_EQ(tracing_recorder.FindOnlyEvent<EventFoo>().data()->second(), 222);
359   }
360 }
361 
TEST(Tracing,FindAllEvents)362 TEST(Tracing, FindAllEvents) {
363   TestTracingRecorder tracing_recorder;
364   {
365     TracingSpan<SpanWithNoData> outer;
366     {
367       Trace<EventFoo>(111, 222);
368       TracingSpan<SpanWithNoData> inner;
369       { Trace<EventFoo>(333, 444); }
370     }
371     EXPECT_THAT(tracing_recorder.FindAllEvents<EventFoo>(),
372                 ElementsAre(IsEvent<EventFoo>(), IsEvent<EventFoo>()));
373     EXPECT_THAT(tracing_recorder.FindAllEvents<EventNeverLogged>(), SizeIs(0));
374   }
375 }
TEST(Tracing,CreateJsonString)376 TEST(Tracing, CreateJsonString) {
377   FlatBufferBuilder fbb_foo;
378   fbb_foo.Finish(TracingTraits<EventFoo>::Create(222, 333, &fbb_foo));
379   auto foo_buf = fbb_foo.GetBufferPointer();
380   auto foo = GetRoot<EventFoo>(fbb_foo.GetBufferPointer());
381   EXPECT_EQ(foo->first(), 222);
382   EXPECT_EQ(foo->second(), 333);
383 
384   TracingTraits<EventFoo> tracing_traits;
385   std::string expected = "{\n  first: 222,\n  second: 333\n}\n";
386   std::string json_gen = tracing_traits.JsonStringFormat(foo_buf);
387   EXPECT_EQ(expected, json_gen);
388 }
389 
390 // TODO(team) Add Testing for when the flatbuf has a package name
391 
392 }  // namespace
393 }  // namespace fcp
394