xref: /aosp_15_r20/external/executorch/devtools/etdump/tests/etdump_test.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #include <gtest/gtest.h>
10 #include <cstdio>
11 
12 #include <executorch/devtools/etdump/etdump_flatcc.h>
13 #include <executorch/devtools/etdump/etdump_schema_flatcc_builder.h>
14 #include <executorch/devtools/etdump/etdump_schema_flatcc_reader.h>
15 #include <executorch/runtime/core/exec_aten/testing_util/tensor_factory.h>
16 #include <executorch/runtime/core/span.h>
17 #include <executorch/runtime/platform/runtime.h>
18 #include <executorch/test/utils/DeathTest.h>
19 #include <cstdint>
20 #include <cstring>
21 #include <memory>
22 
23 using ::exec_aten::ScalarType;
24 using ::exec_aten::Tensor;
25 using ::executorch::etdump::ETDumpGen;
26 using ::executorch::etdump::ETDumpResult;
27 using ::executorch::runtime::AllocatorID;
28 using ::executorch::runtime::ArrayRef;
29 using ::executorch::runtime::BoxedEvalueList;
30 using ::executorch::runtime::DelegateDebugIdType;
31 using ::executorch::runtime::EValue;
32 using ::executorch::runtime::EventTracerEntry;
33 using ::executorch::runtime::LoggedEValueType;
34 using ::executorch::runtime::Span;
35 using ::executorch::runtime::Tag;
36 using ::executorch::runtime::testing::TensorFactory;
37 
38 class ProfilerETDumpTest : public ::testing::Test {
39  protected:
SetUp()40   void SetUp() override {
41     torch::executor::runtime_init();
42     etdump_gen[0] = new ETDumpGen();
43     const size_t buf_size = 1024 * 1024;
44     buf = (uint8_t*)malloc(buf_size * sizeof(uint8_t));
45     etdump_gen[1] = new ETDumpGen(Span<uint8_t>(buf, buf_size));
46   }
47 
TearDown()48   void TearDown() override {
49     delete etdump_gen[0];
50     delete etdump_gen[1];
51     free(buf);
52   }
53 
54   ETDumpGen* etdump_gen[2];
55   uint8_t* buf = nullptr;
56 };
57 
TEST_F(ProfilerETDumpTest,SingleProfileEvent)58 TEST_F(ProfilerETDumpTest, SingleProfileEvent) {
59   for (size_t i = 0; i < 2; i++) {
60     etdump_gen[i]->create_event_block("test_block");
61     EventTracerEntry entry = etdump_gen[i]->start_profiling("test_event", 0, 1);
62     etdump_gen[i]->end_profiling(entry);
63 
64     ETDumpResult result = etdump_gen[i]->get_etdump_data();
65     ASSERT_TRUE(result.buf != nullptr);
66     ASSERT_TRUE(result.size != 0);
67 
68     size_t size = 0;
69     void* buf = flatbuffers_read_size_prefix(result.buf, &size);
70     etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier(
71         buf, etdump_ETDump_file_identifier);
72 
73     ASSERT_NE(etdump, nullptr);
74     EXPECT_EQ(etdump_ETDump_version(etdump), ETDUMP_VERSION);
75 
76     etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump);
77     EXPECT_EQ(
78         etdump_gen[i]->get_num_blocks(), etdump_RunData_vec_len(run_data_vec));
79 
80     etdump_RunData_table_t run_data_single_prof =
81         etdump_RunData_vec_at(run_data_vec, 0);
82     EXPECT_EQ(
83         std::string(
84             etdump_RunData_name(run_data_single_prof),
85             strlen(etdump_RunData_name(run_data_single_prof))),
86         "test_block");
87 
88     if (!etdump_gen[i]->is_static_etdump()) {
89       free(result.buf);
90     }
91   }
92 }
93 
TEST_F(ProfilerETDumpTest,MultipleProfileEvent)94 TEST_F(ProfilerETDumpTest, MultipleProfileEvent) {
95   for (size_t i = 0; i < 2; i++) {
96     etdump_gen[i]->create_event_block("test_block");
97 
98     // Create the profile events and then add the actual profile events in
99     // reverse.
100     EventTracerEntry entry_1 =
101         etdump_gen[i]->start_profiling("test_event_1", 0, 1);
102     EventTracerEntry entry_2 =
103         etdump_gen[i]->start_profiling("test_event_2", 0, 2);
104 
105     etdump_gen[i]->end_profiling(entry_2);
106     etdump_gen[i]->end_profiling(entry_1);
107   }
108 }
109 
TEST_F(ProfilerETDumpTest,EmptyBlocks)110 TEST_F(ProfilerETDumpTest, EmptyBlocks) {
111   for (size_t i = 0; i < 2; i++) {
112     etdump_gen[i]->create_event_block("test_block");
113     etdump_gen[i]->create_event_block("test_block_1");
114     etdump_gen[i]->create_event_block("test_block_2");
115 
116     EventTracerEntry entry =
117         etdump_gen[i]->start_profiling("test_event_1", 0, 1);
118     etdump_gen[i]->end_profiling(entry);
119 
120     ETDumpResult result = etdump_gen[i]->get_etdump_data();
121     ASSERT_TRUE(result.buf != nullptr);
122     ASSERT_TRUE(result.size != 0);
123 
124     size_t size = 0;
125     void* buf = flatbuffers_read_size_prefix(result.buf, &size);
126     etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier(
127         buf, etdump_ETDump_file_identifier);
128 
129     etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump);
130     ASSERT_EQ(etdump_RunData_vec_len(run_data_vec), 3);
131     ASSERT_EQ(
132         etdump_Event_vec_len(
133             etdump_RunData_events(etdump_RunData_vec_at(run_data_vec, 0))),
134         0);
135 
136     if (!etdump_gen[i]->is_static_etdump()) {
137       free(result.buf);
138     }
139   }
140 }
141 
TEST_F(ProfilerETDumpTest,AddAllocators)142 TEST_F(ProfilerETDumpTest, AddAllocators) {
143   for (size_t i = 0; i < 2; i++) {
144     etdump_gen[i]->create_event_block("test_block");
145     AllocatorID allocator_id = etdump_gen[i]->track_allocator("test_allocator");
146     EXPECT_EQ(allocator_id, 1);
147     allocator_id = etdump_gen[i]->track_allocator("test_allocator_1");
148     EXPECT_EQ(allocator_id, 2);
149 
150     // Add a profiling event and then try to add an allocator which should fail.
151     EventTracerEntry entry = etdump_gen[i]->start_profiling("test_event", 0, 1);
152     etdump_gen[i]->end_profiling(entry);
153     ET_EXPECT_DEATH(etdump_gen[i]->track_allocator("test_allocator"), "");
154   }
155 }
156 
TEST_F(ProfilerETDumpTest,AllocationEvents)157 TEST_F(ProfilerETDumpTest, AllocationEvents) {
158   for (size_t i = 0; i < 2; i++) {
159     etdump_gen[i]->create_event_block("test_block");
160 
161     // Add allocation events.
162     etdump_gen[i]->track_allocation(1, 64);
163     etdump_gen[i]->track_allocation(2, 128);
164 
165     // Add a mix of performance and memory events.
166     etdump_gen[i]->track_allocation(1, 64);
167     EventTracerEntry entry = etdump_gen[i]->start_profiling("test_event", 0, 1);
168     etdump_gen[i]->end_profiling(entry);
169     etdump_gen[i]->track_allocation(2, 128);
170   }
171 }
172 
TEST_F(ProfilerETDumpTest,DebugEvent)173 TEST_F(ProfilerETDumpTest, DebugEvent) {
174   for (size_t i = 0; i < 2; i++) {
175     TensorFactory<ScalarType::Float> tf;
176     EValue evalue(tf.ones({3, 2}));
177 
178     etdump_gen[i]->create_event_block("test_block");
179 
180     void* ptr = malloc(2048);
181     Span<uint8_t> buffer((uint8_t*)ptr, 2048);
182 
183     etdump_gen[i]->set_debug_buffer(buffer);
184     etdump_gen[i]->log_evalue(evalue);
185     etdump_gen[i]->log_evalue(evalue, LoggedEValueType::kProgramOutput);
186 
187     EValue evalue_int((int64_t)5);
188     etdump_gen[i]->log_evalue(evalue_int);
189 
190     EValue evalue_double((double)1.5);
191     etdump_gen[i]->log_evalue(evalue_double);
192 
193     EValue evalue_bool(true);
194     etdump_gen[i]->log_evalue(evalue_bool);
195 
196     etdump_gen[i]->log_evalue(evalue_bool);
197 
198     free(ptr);
199   }
200 }
201 
TEST_F(ProfilerETDumpTest,DebugEventTensorList)202 TEST_F(ProfilerETDumpTest, DebugEventTensorList) {
203   for (size_t i = 0; i < 2; i++) {
204     TensorFactory<ScalarType::Int> tf;
205     exec_aten::Tensor storage[2] = {tf.ones({3, 2}), tf.ones({3, 2})};
206     EValue evalue_1(storage[0]);
207     EValue evalue_2(storage[1]);
208     EValue* values_p[2] = {&evalue_1, &evalue_2};
209 
210     BoxedEvalueList<exec_aten::Tensor> a_box(values_p, storage, 2);
211     EValue evalue(a_box);
212     evalue.tag = Tag::ListTensor;
213 
214     etdump_gen[i]->create_event_block("test_block");
215 
216     void* ptr = malloc(2048);
217     Span<uint8_t> buffer((uint8_t*)ptr, 2048);
218 
219     etdump_gen[i]->set_debug_buffer(buffer);
220     etdump_gen[i]->log_evalue(evalue);
221 
222     free(ptr);
223   }
224 }
225 
TEST_F(ProfilerETDumpTest,VerifyLogging)226 TEST_F(ProfilerETDumpTest, VerifyLogging) {
227   TensorFactory<ScalarType::Float> tf;
228   EValue evalue(tf.ones({3, 2}));
229 
230   for (size_t i = 0; i < 2; i++) {
231     etdump_gen[i]->create_event_block("test_block");
232 
233     void* ptr = malloc(2048);
234     Span<uint8_t> buffer((uint8_t*)ptr, 2048);
235 
236     etdump_gen[i]->set_debug_buffer(buffer);
237     etdump_gen[i]->log_evalue(evalue);
238     etdump_gen[i]->log_evalue(evalue, LoggedEValueType::kProgramOutput);
239 
240     ETDumpResult result = etdump_gen[i]->get_etdump_data();
241     ASSERT_TRUE(result.buf != nullptr);
242     ASSERT_TRUE(result.size != 0);
243 
244     size_t size = 0;
245     void* buf = flatbuffers_read_size_prefix(result.buf, &size);
246     etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier(
247         buf, etdump_ETDump_file_identifier);
248 
249     etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump);
250     ASSERT_EQ(etdump_RunData_vec_len(run_data_vec), 1);
251 
252     etdump_Event_vec_t events =
253         etdump_RunData_events(etdump_RunData_vec_at(run_data_vec, 0));
254     ASSERT_EQ(etdump_Event_vec_len(events), 2);
255 
256     etdump_Event_table_t event = etdump_Event_vec_at(events, 0);
257 
258     etdump_DebugEvent_table_t single_debug_event =
259         etdump_Event_debug_event(event);
260     etdump_Value_table_t value =
261         etdump_DebugEvent_debug_entry(single_debug_event);
262     ASSERT_EQ(etdump_Value_tensor_is_present(value), true);
263     ASSERT_EQ(etdump_Value_output_is_present(value), false);
264 
265     etdump_Tensor_table_t tensor = etdump_Value_tensor(value);
266     executorch_flatbuffer_ScalarType_enum_t scalar_enum =
267         etdump_Tensor_scalar_type(tensor);
268     ASSERT_EQ(scalar_enum, executorch_flatbuffer_ScalarType_FLOAT);
269     flatbuffers_int64_vec_t sizes = etdump_Tensor_sizes(tensor);
270     ASSERT_EQ(flatbuffers_int64_vec_len(sizes), 2);
271     ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 0), 3);
272     ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 1), 2);
273 
274     event = etdump_Event_vec_at(events, 1);
275     single_debug_event = etdump_Event_debug_event(event);
276     value = etdump_DebugEvent_debug_entry(single_debug_event);
277     ASSERT_EQ(etdump_Value_tensor_is_present(value), true);
278     ASSERT_EQ(etdump_Value_output_is_present(value), true);
279     etdump_Bool_table_t bool_val = etdump_Value_output_get(value);
280     bool bool_val_from_table = etdump_Bool_bool_val(bool_val);
281     ASSERT_EQ(bool_val_from_table, true);
282 
283     free(ptr);
284     if (!etdump_gen[i]->is_static_etdump()) {
285       free(result.buf);
286     }
287   }
288 }
289 
TEST_F(ProfilerETDumpTest,MultipleBlocksWithEvents)290 TEST_F(ProfilerETDumpTest, MultipleBlocksWithEvents) {
291   for (size_t i = 0; i < 2; i++) {
292     etdump_gen[i]->create_event_block("test_block");
293 
294     AllocatorID allocator_id_0 =
295         etdump_gen[i]->track_allocator("test_allocator_0");
296     AllocatorID allocator_id_1 =
297         etdump_gen[i]->track_allocator("test_allocator_1");
298     etdump_gen[i]->track_allocation(allocator_id_0, 64);
299     etdump_gen[i]->track_allocation(allocator_id_1, 128);
300 
301     EventTracerEntry entry = etdump_gen[i]->start_profiling("test_event", 0, 1);
302     etdump_gen[i]->end_profiling(entry);
303     etdump_gen[i]->create_event_block("test_block_1");
304     allocator_id_0 = etdump_gen[i]->track_allocator("test_allocator_0");
305     allocator_id_1 = etdump_gen[i]->track_allocator("test_allocator_1");
306     etdump_gen[i]->track_allocation(allocator_id_0, 64);
307     etdump_gen[i]->track_allocation(allocator_id_0, 128);
308 
309     entry = etdump_gen[i]->start_profiling("test_event", 0, 1);
310     etdump_gen[i]->end_profiling(entry);
311 
312     ETDumpResult result = etdump_gen[i]->get_etdump_data();
313     ASSERT_TRUE(result.buf != nullptr);
314     ASSERT_TRUE(result.size != 0);
315 
316     size_t size = 0;
317     void* buf = flatbuffers_read_size_prefix(result.buf, &size);
318     etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier(
319         buf, etdump_ETDump_file_identifier);
320 
321     ASSERT_NE(etdump, nullptr);
322     EXPECT_EQ(etdump_ETDump_version(etdump), ETDUMP_VERSION);
323 
324     etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump);
325     ASSERT_EQ(
326         etdump_gen[i]->get_num_blocks(), etdump_RunData_vec_len(run_data_vec));
327 
328     etdump_RunData_table_t run_data_0 = etdump_RunData_vec_at(run_data_vec, 0);
329     EXPECT_EQ(
330         std::string(
331             etdump_RunData_name(run_data_0),
332             strlen(etdump_RunData_name(run_data_0))),
333         "test_block");
334 
335     etdump_Allocator_vec_t allocator_vec_0 =
336         etdump_RunData_allocators(run_data_0);
337     ASSERT_EQ(etdump_Allocator_vec_len(allocator_vec_0), 2);
338 
339     etdump_Allocator_table_t allocator_0 =
340         etdump_Allocator_vec_at(allocator_vec_0, 0);
341     EXPECT_EQ(
342         std::string(
343             etdump_Allocator_name(allocator_0),
344             strlen(etdump_Allocator_name(allocator_0))),
345         "test_allocator_0");
346 
347     etdump_Event_vec_t event_vec = etdump_RunData_events(run_data_0);
348     ASSERT_EQ(etdump_Event_vec_len(event_vec), 3);
349 
350     etdump_Event_table_t event_0 = etdump_Event_vec_at(event_vec, 0);
351     EXPECT_EQ(
352         etdump_AllocationEvent_allocation_size(
353             etdump_Event_allocation_event(event_0)),
354         64);
355 
356     etdump_Event_table_t event_2 = etdump_Event_vec_at(event_vec, 2);
357     flatbuffers_string_t event_2_name =
358         etdump_ProfileEvent_name(etdump_Event_profile_event(event_2));
359     EXPECT_EQ(std::string(event_2_name, strlen(event_2_name)), "test_event");
360 
361     if (!etdump_gen[i]->is_static_etdump()) {
362       free(result.buf);
363     }
364   }
365 }
366 
TEST_F(ProfilerETDumpTest,VerifyData)367 TEST_F(ProfilerETDumpTest, VerifyData) {
368   for (size_t i = 0; i < 2; i++) {
369     etdump_gen[i]->create_event_block("test_block");
370 
371     etdump_gen[i]->track_allocator("single prof allocator");
372 
373     EventTracerEntry entry = etdump_gen[i]->start_profiling("test_event", 0, 1);
374     etdump_gen[i]->end_profiling(entry);
375     entry = etdump_gen[i]->start_profiling("test_event2", 0, 1);
376     etdump_gen[i]->end_profiling(entry);
377 
378     ETDumpResult result = etdump_gen[i]->get_etdump_data();
379     ASSERT_TRUE(result.buf != nullptr);
380     ASSERT_TRUE(result.size != 0);
381 
382     size_t size = 0;
383     void* buf = flatbuffers_read_size_prefix(result.buf, &size);
384     etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier(
385         buf, etdump_ETDump_file_identifier);
386 
387     ASSERT_NE(etdump, nullptr);
388     EXPECT_EQ(etdump_ETDump_version(etdump), ETDUMP_VERSION);
389 
390     etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump);
391     EXPECT_EQ(
392         etdump_gen[i]->get_num_blocks(), etdump_RunData_vec_len(run_data_vec));
393 
394     etdump_RunData_table_t run_data_single_prof =
395         etdump_RunData_vec_at(run_data_vec, 0);
396     EXPECT_EQ(
397         std::string(
398             etdump_RunData_name(run_data_single_prof),
399             strlen(etdump_RunData_name(run_data_single_prof))),
400         "test_block");
401 
402     etdump_Allocator_vec_t allocator_vec =
403         etdump_RunData_allocators(run_data_single_prof);
404 
405     etdump_Event_table_t single_event =
406         etdump_Event_vec_at(etdump_RunData_events(run_data_single_prof), 0);
407 
408     etdump_ProfileEvent_table_t single_prof_event =
409         etdump_Event_profile_event(single_event);
410 
411     EXPECT_EQ(
412         std::string(
413             etdump_ProfileEvent_name(single_prof_event),
414             strlen(etdump_ProfileEvent_name(single_prof_event))),
415         "test_event");
416     EXPECT_EQ(etdump_ProfileEvent_chain_index(single_prof_event), 0);
417 
418     flatbuffers_string_t allocator_name =
419         etdump_Allocator_name(etdump_Allocator_vec_at(allocator_vec, 0));
420     EXPECT_EQ(
421         std::string(allocator_name, strlen(allocator_name)),
422         "single prof allocator");
423 
424     if (!etdump_gen[i]->is_static_etdump()) {
425       free(result.buf);
426     }
427   }
428 }
429 
TEST_F(ProfilerETDumpTest,LogDelegateIntermediateOutput)430 TEST_F(ProfilerETDumpTest, LogDelegateIntermediateOutput) {
431   for (size_t i = 0; i < 2; i++) {
432     void* ptr = malloc(2048);
433     Span<uint8_t> buffer((uint8_t*)ptr, 2048);
434 
435     etdump_gen[i]->create_event_block("test_block");
436     TensorFactory<ScalarType::Float> tf;
437 
438     ET_EXPECT_DEATH(
439         etdump_gen[i]->log_intermediate_output_delegate(
440             "test_event_tensor",
441             static_cast<torch::executor::DebugHandle>(-1),
442             tf.ones({3, 2})),
443         "Must pre-set debug buffer with set_debug_buffer()");
444     etdump_gen[i]->set_debug_buffer(buffer);
445 
446     // Log a tensor
447     etdump_gen[i]->log_intermediate_output_delegate(
448         "test_event_tensor",
449         static_cast<torch::executor::DebugHandle>(-1),
450         tf.ones({3, 2}));
451 
452     // Log a tensor list
453     std::vector<Tensor> tensors = {tf.ones({5, 4}), tf.ones({7, 6})};
454     etdump_gen[i]->log_intermediate_output_delegate(
455         "test_event_tensorlist",
456         static_cast<torch::executor::DebugHandle>(-1),
457         ArrayRef<Tensor>(tensors.data(), tensors.size()));
458 
459     // Log an int
460     etdump_gen[i]->log_intermediate_output_delegate(
461         "test_event_tensorlist",
462         static_cast<torch::executor::DebugHandle>(-1),
463         10);
464 
465     // Log a double
466     etdump_gen[i]->log_intermediate_output_delegate(
467         "test_event_tensorlist",
468         static_cast<torch::executor::DebugHandle>(-1),
469         20.75);
470 
471     // Log a bool
472     etdump_gen[i]->log_intermediate_output_delegate(
473         "test_event_tensorlist",
474         static_cast<torch::executor::DebugHandle>(-1),
475         true);
476 
477     ETDumpResult result = etdump_gen[i]->get_etdump_data();
478     ASSERT_TRUE(result.buf != nullptr);
479     ASSERT_TRUE(result.size != 0);
480 
481     free(ptr);
482     if (!etdump_gen[i]->is_static_etdump()) {
483       free(result.buf);
484     }
485   }
486 }
487 
TEST_F(ProfilerETDumpTest,VerifyDelegateIntermediateLogging)488 TEST_F(ProfilerETDumpTest, VerifyDelegateIntermediateLogging) {
489   TensorFactory<ScalarType::Float> tf;
490   EValue evalue(tf.ones({3, 2}));
491 
492   for (size_t i = 0; i < 2; i++) {
493     etdump_gen[i]->create_event_block("test_block");
494 
495     void* ptr = malloc(2048);
496     Span<uint8_t> buffer((uint8_t*)ptr, 2048);
497 
498     etdump_gen[i]->set_debug_buffer(buffer);
499 
500     // Event 0
501     etdump_gen[i]->log_intermediate_output_delegate(
502         nullptr, 257, tf.ones({3, 4}));
503     // Event 1
504     etdump_gen[i]->log_intermediate_output_delegate(
505         nullptr, 258, tf.ones({5, 6}));
506 
507     ETDumpResult result = etdump_gen[i]->get_etdump_data();
508     ASSERT_TRUE(result.buf != nullptr);
509     ASSERT_TRUE(result.size != 0);
510 
511     size_t size = 0;
512     void* buf = flatbuffers_read_size_prefix(result.buf, &size);
513     etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier(
514         buf, etdump_ETDump_file_identifier);
515 
516     etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump);
517     ASSERT_EQ(etdump_RunData_vec_len(run_data_vec), 1);
518 
519     etdump_Event_vec_t events =
520         etdump_RunData_events(etdump_RunData_vec_at(run_data_vec, 0));
521     ASSERT_EQ(etdump_Event_vec_len(events), 2);
522 
523     // Verify Event 0
524     etdump_Event_table_t event_0 = etdump_Event_vec_at(events, 0);
525 
526     etdump_DebugEvent_table_t single_debug_event =
527         etdump_Event_debug_event(event_0);
528     etdump_Value_table_t value =
529         etdump_DebugEvent_debug_entry(single_debug_event);
530     ASSERT_EQ(etdump_Value_tensor_is_present(value), true);
531 
532     etdump_Tensor_table_t tensor = etdump_Value_tensor(value);
533     executorch_flatbuffer_ScalarType_enum_t scalar_enum =
534         etdump_Tensor_scalar_type(tensor);
535     ASSERT_EQ(scalar_enum, executorch_flatbuffer_ScalarType_FLOAT);
536     flatbuffers_int64_vec_t sizes = etdump_Tensor_sizes(tensor);
537     ASSERT_EQ(flatbuffers_int64_vec_len(sizes), 2);
538     ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 0), 3);
539     ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 1), 4);
540 
541     // Verify Event 1
542     etdump_Event_table_t event_1 = etdump_Event_vec_at(events, 1);
543 
544     single_debug_event = etdump_Event_debug_event(event_1);
545     value = etdump_DebugEvent_debug_entry(single_debug_event);
546 
547     tensor = etdump_Value_tensor(value);
548     sizes = etdump_Tensor_sizes(tensor);
549     ASSERT_EQ(flatbuffers_int64_vec_len(sizes), 2);
550     ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 0), 5);
551     ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 1), 6);
552 
553     // Event 1 should have a empty delegate_debug_id_str
554     flatbuffers_string_t delegate_debug_id_name =
555         etdump_DebugEvent_delegate_debug_id_str(
556             etdump_Event_debug_event(event_1));
557 
558     EXPECT_EQ(delegate_debug_id_name, nullptr);
559     // Check for the correct delegate_debug_id_int
560     EXPECT_EQ(
561         etdump_DebugEvent_delegate_debug_id_int(
562             etdump_Event_debug_event(event_1)),
563         258);
564 
565     free(ptr);
566     if (!etdump_gen[i]->is_static_etdump()) {
567       free(result.buf);
568     }
569   }
570 }
571 
TEST_F(ProfilerETDumpTest,LogDelegateEvents)572 TEST_F(ProfilerETDumpTest, LogDelegateEvents) {
573   for (size_t i = 0; i < 2; i++) {
574     etdump_gen[i]->create_event_block("test_block");
575 
576     // Event 0
577     etdump_gen[i]->log_profiling_delegate(nullptr, 276, 1, 2, nullptr, 0);
578     // Event 1
579     const char* metadata = "test_metadata";
580     etdump_gen[i]->log_profiling_delegate(
581         nullptr, 278, 1, 2, metadata, strlen(metadata) + 1);
582     EventTracerEntry entry = etdump_gen[i]->start_profiling_delegate(
583         "test_event", static_cast<torch::executor::DebugHandle>(-1));
584     EXPECT_NE(entry.delegate_event_id_type, DelegateDebugIdType::kNone);
585     // Event 2
586     etdump_gen[i]->end_profiling_delegate(
587         entry, metadata, strlen(metadata) + 1);
588     // Event 3
589     etdump_gen[i]->log_profiling_delegate(
590         "test_event",
591         static_cast<torch::executor::DebugHandle>(-1),
592         1,
593         2,
594         nullptr,
595         0);
596     // Event 4
597     etdump_gen[i]->log_profiling_delegate(
598         "test_event",
599         static_cast<torch::executor::DebugHandle>(-1),
600         1,
601         2,
602         metadata,
603         strlen(metadata) + 1);
604 
605     // Only a valid name or delegate debug index should be passed in. If valid
606     // entries are passed in for both then the test should assert out.
607     ET_EXPECT_DEATH(
608         etdump_gen[i]->start_profiling_delegate("test_event", 1),
609         "Only name or delegate_debug_index can be valid. Check DelegateMappingBuilder documentation for more details.");
610     ET_EXPECT_DEATH(
611         etdump_gen[i]->log_profiling_delegate(
612             "test_event", 1, 1, 2, nullptr, 0),
613         "Only name or delegate_debug_index can be valid. Check DelegateMappingBuilder documentation for more details.");
614     ET_EXPECT_DEATH(
615         etdump_gen[i]->end_profiling(entry),
616         "Delegate events must use end_profiling_delegate to mark the end of a delegate profiling event.");
617 
618     ETDumpResult result = etdump_gen[i]->get_etdump_data();
619     ASSERT_TRUE(result.buf != nullptr);
620     ASSERT_TRUE(result.size != 0);
621 
622     // Run verification tests on the data that was just serialized.
623     size_t size = 0;
624     void* buf = flatbuffers_read_size_prefix(result.buf, &size);
625     etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier(
626         buf, etdump_ETDump_file_identifier);
627     etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump);
628 
629     // Event 0
630     etdump_RunData_table_t run_data_0 = etdump_RunData_vec_at(run_data_vec, 0);
631     etdump_Event_vec_t event_vec = etdump_RunData_events(run_data_0);
632     ASSERT_EQ(etdump_Event_vec_len(event_vec), 5);
633     etdump_Event_table_t event = etdump_Event_vec_at(event_vec, 0);
634 
635     flatbuffers_string_t delegate_debug_id_name =
636         etdump_ProfileEvent_delegate_debug_id_str(
637             etdump_Event_profile_event(event));
638 
639     // Event 0 should have a empty delegate_debug_id_str
640     EXPECT_EQ(delegate_debug_id_name, nullptr);
641     // Check for the correct delegate_debug_id_int
642     EXPECT_EQ(
643         etdump_ProfileEvent_delegate_debug_id_int(
644             etdump_Event_profile_event(event)),
645         276);
646     flatbuffers_uint8_vec_t debug_metadata_name =
647         etdump_ProfileEvent_delegate_debug_metadata(
648             etdump_Event_profile_event(event));
649     // Event 0 should have an empty delegate_debug_metadata string.
650     EXPECT_EQ(flatbuffers_uint8_vec_len(debug_metadata_name), 0);
651 
652     // Event 1
653     event = etdump_Event_vec_at(event_vec, 1);
654     // Check for the correct delegate_debug_id_int
655     EXPECT_EQ(
656         etdump_ProfileEvent_delegate_debug_id_int(
657             etdump_Event_profile_event(event)),
658         278);
659     debug_metadata_name = etdump_ProfileEvent_delegate_debug_metadata(
660         etdump_Event_profile_event(event));
661     // Check for the correct delegate_debug_metadata string
662     EXPECT_EQ(
663         std::string(
664             (char*)debug_metadata_name,
665             flatbuffers_uint8_vec_len(debug_metadata_name) - 1),
666         "test_metadata");
667 
668     // Event 2
669     event = etdump_Event_vec_at(event_vec, 2);
670     delegate_debug_id_name = etdump_ProfileEvent_delegate_debug_id_str(
671         etdump_Event_profile_event(event));
672     // Check for the correct delegate_debug_id_str string.
673     EXPECT_EQ(
674         std::string(delegate_debug_id_name, strlen(delegate_debug_id_name)),
675         "test_event");
676     // Event 2 used a string delegate debug identifier, so delegate_debug_id_int
677     // should be -1.
678     EXPECT_EQ(
679         etdump_ProfileEvent_delegate_debug_id_int(
680             etdump_Event_profile_event(event)),
681         -1);
682     if (!etdump_gen[i]->is_static_etdump()) {
683       free(result.buf);
684     }
685   }
686 }
687 
TEST_F(ProfilerETDumpTest,WriteAfterGetETDumpData)688 TEST_F(ProfilerETDumpTest, WriteAfterGetETDumpData) {
689   for (size_t i = 0; i < 2; i++) {
690     for (size_t j = 0; j < 2; j++) {
691       etdump_gen[i]->create_event_block("test_block");
692       EventTracerEntry entry =
693           etdump_gen[i]->start_profiling("test_event", 0, 1);
694       etdump_gen[i]->end_profiling(entry);
695 
696       ETDumpResult result = etdump_gen[i]->get_etdump_data();
697       ASSERT_TRUE(result.buf != nullptr);
698       ASSERT_TRUE(result.size != 0);
699 
700       size_t size = 0;
701       void* buf = flatbuffers_read_size_prefix(result.buf, &size);
702       etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier(
703           buf, etdump_ETDump_file_identifier);
704 
705       ASSERT_NE(etdump, nullptr);
706       EXPECT_EQ(etdump_ETDump_version(etdump), ETDUMP_VERSION);
707 
708       etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump);
709       EXPECT_EQ(
710           etdump_gen[i]->get_num_blocks(),
711           etdump_RunData_vec_len(run_data_vec));
712 
713       etdump_RunData_table_t run_data_single_prof =
714           etdump_RunData_vec_at(run_data_vec, 0);
715       EXPECT_EQ(
716           std::string(
717               etdump_RunData_name(run_data_single_prof),
718               strlen(etdump_RunData_name(run_data_single_prof))),
719           "test_block");
720 
721       if (!etdump_gen[i]->is_static_etdump()) {
722         free(result.buf);
723       }
724     }
725   }
726 }
727