processor: Import and export legacy flow event args for all TrackEvents
(Legacy) flow events can be attached to events of any phase, including
those that we import into native (non-raw events) tables in TP.
To preserve them for proto2json conversion, also import the flow-event
related args for slices into their args set and convert them back into
the legacy json event attributes during export_json().
Bug: 130786981, 130786269
Change-Id: I89d5b846009b5ecff350e6b26361576187eee1cd
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index 511f677..d57e856 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -104,6 +104,7 @@
EXPECT_EQ(event["name"].asString(), kName);
EXPECT_FALSE(event.isMember("args"));
}
+
TEST(ExportJsonTest, StorageWithOneUnfinishedSlice) {
const int64_t kTimestamp = 10000000;
const int64_t kDuration = -1;
@@ -381,6 +382,63 @@
EXPECT_EQ(event["args"]["src"].asString(), kSrc);
}
+TEST(ExportJsonTest, StorageWithSliceAndFlowEventArgs) {
+ const char* kCategory = "cat";
+ const char* kName = "name";
+ constexpr TrackId track = 22;
+ const uint64_t kBindId = 0xaa00aa00aa00aa00;
+ const char* kFlowDirection = "inout";
+ const char* kArgName = "arg_name";
+ const int kArgValue = 123;
+
+ TraceProcessorContext context;
+ context.storage.reset(new TraceStorage());
+ TraceStorage* storage = context.storage.get();
+
+ UniqueTid utid = storage->AddEmptyThread(0);
+ StringId cat_id = storage->InternString(base::StringView(kCategory));
+ StringId name_id = storage->InternString(base::StringView(kName));
+ RowId row_id = TraceStorage::CreateRowId(
+ kNestableSlices,
+ storage->mutable_nestable_slices()->AddSlice(
+ 0, 0, track, utid, RefType::kRefUtid, cat_id, name_id, 0, 0, 0));
+
+ ArgsTracker args(&context);
+ auto add_arg = [&](const char* key, Variadic value) {
+ StringId key_id = storage->InternString(key);
+ args.AddArg(row_id, key_id, key_id, value);
+ };
+
+ add_arg("legacy_event.bind_id", Variadic::UnsignedInteger(kBindId));
+ add_arg("legacy_event.bind_to_enclosing", Variadic::Boolean(true));
+ StringId flow_direction_id = storage->InternString(kFlowDirection);
+ add_arg("legacy_event.flow_direction", Variadic::String(flow_direction_id));
+
+ add_arg(kArgName, Variadic::Integer(kArgValue));
+
+ args.Flush();
+
+ base::TempFile temp_file = base::TempFile::Create();
+ FILE* output = fopen(temp_file.path().c_str(), "w+");
+ int code = ExportJson(storage, output);
+
+ EXPECT_EQ(code, kResultOk);
+
+ Json::Reader reader;
+ Json::Value result;
+ EXPECT_TRUE(reader.parse(ReadFile(output), result));
+ EXPECT_EQ(result["traceEvents"].size(), 1u);
+
+ Json::Value event = result["traceEvents"][0];
+ EXPECT_EQ(event["cat"].asString(), kCategory);
+ EXPECT_EQ(event["name"].asString(), kName);
+ EXPECT_EQ(event["bind_id"].asString(), "0xaa00aa00aa00aa00");
+ EXPECT_EQ(event["bp"].asString(), "e");
+ EXPECT_EQ(event["flow_in"].asBool(), true);
+ EXPECT_EQ(event["flow_out"].asBool(), true);
+ EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
+}
+
TEST(ExportJsonTest, StorageWithListArgs) {
const char* kCategory = "cat";
const char* kName = "name";