diff options
Diffstat (limited to 'src/trace_processor/export_json_unittest.cc')
-rw-r--r-- | src/trace_processor/export_json_unittest.cc | 558 |
1 files changed, 58 insertions, 500 deletions
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc index 9dadb4481..ef1583452 100644 --- a/src/trace_processor/export_json_unittest.cc +++ b/src/trace_processor/export_json_unittest.cc @@ -24,14 +24,11 @@ #include <json/reader.h> #include <json/value.h> -#include "perfetto/ext/base/string_utils.h" #include "perfetto/ext/base/temp_file.h" #include "src/trace_processor/importers/common/args_tracker.h" -#include "src/trace_processor/importers/common/event_tracker.h" #include "src/trace_processor/importers/common/process_tracker.h" #include "src/trace_processor/importers/common/track_tracker.h" #include "src/trace_processor/importers/proto/metadata_tracker.h" -#include "src/trace_processor/importers/proto/track_event_tracker.h" #include "src/trace_processor/types/trace_processor_context.h" #include "test/gtest_and_gmock.h" @@ -71,7 +68,6 @@ class ExportJsonTest : public ::testing::Test { ExportJsonTest() { context_.global_args_tracker.reset(new GlobalArgsTracker(&context_)); context_.args_tracker.reset(new ArgsTracker(&context_)); - context_.event_tracker.reset(new EventTracker(&context_)); context_.storage.reset(new TraceStorage()); context_.track_tracker.reset(new TrackTracker(&context_)); context_.metadata_tracker.reset(new MetadataTracker(&context_)); @@ -90,12 +86,9 @@ class ExportJsonTest : public ::testing::Test { } Json::Value ToJsonValue(const std::string& json) { - Json::CharReaderBuilder b; - auto reader = std::unique_ptr<Json::CharReader>(b.newCharReader()); + Json::Reader reader; Json::Value result; - EXPECT_TRUE(reader->parse(json.data(), json.data() + json.length(), &result, - nullptr)) - << json; + EXPECT_TRUE(reader.parse(json, result)) << json; return result; } @@ -130,11 +123,11 @@ TEST_F(ExportJsonTest, StorageWithOneSlice) { context_.args_tracker->Flush(); // Flush track args. StringId cat_id = context_.storage->InternString(base::StringView(kCategory)); StringId name_id = context_.storage->InternString(base::StringView(kName)); - // The thread_slice table is a sub table of slice. - context_.storage->mutable_thread_slice_table()->Insert( - {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0, SliceId(0u), 0, - kThreadTimestamp, kThreadDuration, kThreadInstructionCount, - kThreadInstructionDelta}); + context_.storage->mutable_slice_table()->Insert( + {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0}); + context_.storage->mutable_thread_slices()->AddThreadSlice( + 0, kThreadTimestamp, kThreadDuration, kThreadInstructionCount, + kThreadInstructionDelta); base::TempFile temp_file = base::TempFile::Create(); FILE* output = fopen(temp_file.path().c_str(), "w+"); @@ -176,10 +169,11 @@ TEST_F(ExportJsonTest, StorageWithOneUnfinishedSlice) { context_.args_tracker->Flush(); // Flush track args. StringId cat_id = context_.storage->InternString(base::StringView(kCategory)); StringId name_id = context_.storage->InternString(base::StringView(kName)); - context_.storage->mutable_thread_slice_table()->Insert( - {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0, SliceId(0u), 0, - kThreadTimestamp, kThreadDuration, kThreadInstructionCount, - kThreadInstructionDelta}); + context_.storage->mutable_slice_table()->Insert( + {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0}); + context_.storage->mutable_thread_slices()->AddThreadSlice( + 0, kThreadTimestamp, kThreadDuration, kThreadInstructionCount, + kThreadInstructionDelta); base::TempFile temp_file = base::TempFile::Create(); FILE* output = fopen(temp_file.path().c_str(), "w+"); @@ -230,8 +224,9 @@ TEST_F(ExportJsonTest, StorageWithThreadName) { } TEST_F(ExportJsonTest, SystemEventsIgnored) { - TrackId track = context_.track_tracker->CreateAndroidAsyncTrack( - /*name=*/kNullStringId, /*upid=*/0); + constexpr int64_t kCookie = 22; + TrackId track = context_.track_tracker->InternAndroidAsyncTrack( + /*name=*/kNullStringId, /*upid=*/0, kCookie); context_.args_tracker->Flush(); // Flush track args. // System events have no category. @@ -256,7 +251,6 @@ TEST_F(ExportJsonTest, StorageWithMetadata) { const char* kStoryName = "story name"; const char* kStoryTag1 = "tag1"; const char* kStoryTag2 = "tag2"; - const char* kDynamicKey = "dyn_key1"; const int64_t kBenchmarkStart = 1000000; const int64_t kStoryStart = 2000000; const bool kHadFailures = true; @@ -302,13 +296,6 @@ TEST_F(ExportJsonTest, StorageWithMetadata) { context_.metadata_tracker->SetMetadata(metadata::benchmark_had_failures, had_failures); - // Metadata entries with dynamic keys are not currently exported from the - // metadata table (the Chrome metadata is exported directly from the raw - // table). - StringId dynamic_key_id = - context_.storage->InternString(base::StringView(kDynamicKey)); - context_.metadata_tracker->SetDynamicMetadata(dynamic_key_id, had_failures); - base::TempFile temp_file = base::TempFile::Create(); FILE* output = fopen(temp_file.path().c_str(), "w+"); util::Status status = ExportJson(context_.storage.get(), output); @@ -343,8 +330,6 @@ TEST_F(ExportJsonTest, StorageWithMetadata) { EXPECT_EQ(telemetry_metadata["hadFailures"].size(), 1u); EXPECT_EQ(telemetry_metadata["hadFailures"][0].asBool(), kHadFailures); - - EXPECT_FALSE(result["metadata"].isMember(kDynamicKey)); } TEST_F(ExportJsonTest, StorageWithStats) { @@ -458,6 +443,10 @@ TEST_F(ExportJsonTest, StorageWithArgs) { TEST_F(ExportJsonTest, StorageWithSliceAndFlowEventArgs) { const char* kCategory = "cat"; const char* kName = "name"; + const uint64_t kBindId = 0xaa00aa00aa00aa00; + const char* kFlowDirection = "inout"; + const char* kArgName = "arg_name"; + const int kArgValue = 123; TraceStorage* storage = context_.storage.get(); @@ -466,14 +455,23 @@ TEST_F(ExportJsonTest, StorageWithSliceAndFlowEventArgs) { context_.args_tracker->Flush(); // Flush track args. StringId cat_id = storage->InternString(base::StringView(kCategory)); StringId name_id = storage->InternString(base::StringView(kName)); - SliceId id1 = storage->mutable_slice_table() - ->Insert({0, 0, track, cat_id, name_id, 0, 0, 0}) - .id; - SliceId id2 = storage->mutable_slice_table() - ->Insert({100, 0, track, cat_id, name_id, 0, 0, 0}) - .id; + SliceId id = storage->mutable_slice_table() + ->Insert({0, 0, track, cat_id, name_id, 0, 0, 0}) + .id; + auto inserter = context_.args_tracker->AddArgsTo(id); - storage->mutable_flow_table()->Insert({id1, id2, 0}); + auto add_arg = [&](const char* key, Variadic value) { + inserter.AddArg(storage->InternString(key), 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)); + + context_.args_tracker->Flush(); base::TempFile temp_file = base::TempFile::Create(); FILE* output = fopen(temp_file.path().c_str(), "w+"); @@ -482,30 +480,17 @@ TEST_F(ExportJsonTest, StorageWithSliceAndFlowEventArgs) { EXPECT_TRUE(status.ok()); Json::Value result = ToJsonValue(ReadFile(output)); - EXPECT_EQ(result["traceEvents"].size(), 4u); - - Json::Value slice_out = result["traceEvents"][0]; - Json::Value slice_in = result["traceEvents"][1]; - Json::Value flow_out = result["traceEvents"][2]; - Json::Value flow_in = result["traceEvents"][3]; - - EXPECT_EQ(flow_out["cat"].asString(), kCategory); - EXPECT_EQ(flow_out["name"].asString(), kName); - EXPECT_EQ(flow_out["ph"].asString(), "s"); - EXPECT_EQ(flow_out["tid"].asString(), slice_out["tid"].asString()); - EXPECT_EQ(flow_out["pid"].asString(), slice_out["pid"].asString()); - - EXPECT_EQ(flow_in["cat"].asString(), kCategory); - EXPECT_EQ(flow_in["name"].asString(), kName); - EXPECT_EQ(flow_in["ph"].asString(), "f"); - EXPECT_EQ(flow_in["bp"].asString(), "e"); - EXPECT_EQ(flow_in["tid"].asString(), slice_in["tid"].asString()); - EXPECT_EQ(flow_in["pid"].asString(), slice_in["pid"].asString()); - - EXPECT_LE(slice_out["ts"].asInt64(), flow_out["ts"].asInt64()); - EXPECT_GE(slice_in["ts"].asInt64(), flow_in["ts"].asInt64()); - - EXPECT_EQ(flow_out["id"].asString(), flow_in["id"].asString()); + 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); + EXPECT_FALSE(event["args"].isMember("legacy_event")); } TEST_F(ExportJsonTest, StorageWithListArgs) { @@ -749,15 +734,14 @@ TEST_F(ExportJsonTest, InstantEvent) { {kTimestamp, 0, track, cat_id, name_id, 0, 0, 0}); // Global track. - TrackEventTracker track_event_tracker(&context_); - TrackId track2 = track_event_tracker.GetOrCreateDefaultDescriptorTrack(); + TrackId track2 = context_.track_tracker->GetOrCreateDefaultDescriptorTrack(); context_.args_tracker->Flush(); // Flush track args. context_.storage->mutable_slice_table()->Insert( {kTimestamp2, 0, track2, cat_id, name_id, 0, 0, 0}); // Async event track. - track_event_tracker.ReserveDescriptorChildTrack(1234, 0, kNullStringId); - TrackId track3 = *track_event_tracker.GetDescriptorTrack(1234); + context_.track_tracker->ReserveDescriptorChildTrack(1234, 0, kNullStringId); + TrackId track3 = *context_.track_tracker->GetDescriptorTrack(1234); context_.args_tracker->Flush(); // Flush track args. context_.storage->mutable_slice_table()->Insert( {kTimestamp3, 0, track3, cat_id, name_id, 0, 0, 0}); @@ -830,7 +814,8 @@ TEST_F(ExportJsonTest, DuplicatePidAndTid) { base::nullopt, base::nullopt, 1, kNullStringId); UniqueTid utid1a = context_.process_tracker->UpdateThread(1, 1); UniqueTid utid1b = context_.process_tracker->UpdateThread(2, 1); - UniqueTid utid1c = context_.process_tracker->StartNewThread(base::nullopt, 2); + UniqueTid utid1c = + context_.process_tracker->StartNewThread(base::nullopt, 2, kNullStringId); // Associate the new thread with its process. ASSERT_EQ(utid1c, context_.process_tracker->UpdateThread(2, 1)); @@ -1063,151 +1048,6 @@ TEST_F(ExportJsonTest, AsyncEvents) { EXPECT_FALSE(end_event3.isMember("use_async_tts")); } -TEST_F(ExportJsonTest, LegacyAsyncEvents) { - using Arg = GlobalArgsTracker::Arg; - const int64_t kTimestamp = 10000000; - const int64_t kDuration = 100000; - const int64_t kTimestamp2 = 10001000; - const int64_t kDuration2 = 0; - const int64_t kTimestamp3 = 10005000; - const int64_t kDuration3 = 100000; - const uint32_t kProcessID = 100; - const char* kCategory = "cat"; - const char* kName = "name"; - const char* kName2 = "name2"; - const char* kName3 = "name3"; - - UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID); - StringId cat_id = context_.storage->InternString(base::StringView(kCategory)); - StringId name_id = context_.storage->InternString(base::StringView(kName)); - StringId name2_id = context_.storage->InternString(base::StringView(kName2)); - StringId name3_id = context_.storage->InternString(base::StringView(kName3)); - - auto arg_inserter = [this](base::StringView arg_name, - base::StringView arg_value, - std::vector<Arg>& args) { - Arg arg; - StringId arg_key_id = - context_.storage->InternString(base::StringView(arg_name)); - arg.flat_key = arg_key_id; - arg.key = arg_key_id; - StringId value_id = context_.storage->InternString(arg_value); - arg.value = Variadic::String(value_id); - args.push_back(arg); - }; - - constexpr int64_t kSourceId = 235; - TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack( - name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true, - /*source_scope=*/kNullStringId); - constexpr int64_t kSourceId2 = 236; - TrackId track2 = context_.track_tracker->InternLegacyChromeAsyncTrack( - name3_id, upid, kSourceId2, /*source_id_is_process_scoped=*/true, - /*source_scope=*/kNullStringId); - context_.args_tracker->Flush(); // Flush track args. - - context_.storage->mutable_slice_table()->Insert( - {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0}); - std::vector<Arg> args1; - arg_inserter("arg1", "value1", args1); - arg_inserter("legacy_event.phase", "S", args1); - ArgSetId arg_id1 = context_.global_args_tracker->AddArgSet(args1, 0, 2); - context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, - arg_id1); - - // Step event with first event as parent. - context_.storage->mutable_slice_table()->Insert( - {kTimestamp2, kDuration2, track, cat_id, name2_id, 0, 0, 0}); - std::vector<Arg> step_args; - arg_inserter("arg2", "value2", step_args); - arg_inserter("legacy_event.phase", "T", step_args); - arg_inserter("debug.step", "Step1", step_args); - ArgSetId arg_id2 = context_.global_args_tracker->AddArgSet(step_args, 0, 3); - context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(1, - arg_id2); - - // Another overlapping async event on a different track. - context_.storage->mutable_slice_table()->Insert( - {kTimestamp3, kDuration3, track2, cat_id, name3_id, 0, 0, 0}); - std::vector<Arg> args3; - arg_inserter("legacy_event.phase", "S", args3); - ArgSetId arg_id3 = context_.global_args_tracker->AddArgSet(args3, 0, 1); - context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(2, - arg_id3); - - base::TempFile temp_file = base::TempFile::Create(); - FILE* output = fopen(temp_file.path().c_str(), "w+"); - util::Status status = ExportJson(context_.storage.get(), output); - - EXPECT_TRUE(status.ok()); - - Json::Value result = ToJsonValue(ReadFile(output)); - EXPECT_EQ(result["traceEvents"].size(), 5u); - - // Events should be sorted by timestamp, with child slice's end before its - // parent. - - Json::Value begin_event1 = result["traceEvents"][0]; - EXPECT_EQ(begin_event1["ph"].asString(), "S"); - EXPECT_EQ(begin_event1["ts"].asInt64(), kTimestamp / 1000); - EXPECT_EQ(begin_event1["pid"].asInt(), static_cast<int>(kProcessID)); - EXPECT_EQ(begin_event1["id2"]["local"].asString(), "0xeb"); - EXPECT_EQ(begin_event1["cat"].asString(), kCategory); - EXPECT_EQ(begin_event1["name"].asString(), kName); - EXPECT_FALSE(begin_event1.isMember("tts")); - EXPECT_FALSE(begin_event1.isMember("use_async_tts")); - EXPECT_EQ(begin_event1["args"].size(), 1u); - EXPECT_EQ(begin_event1["args"]["arg1"].asString(), "value1"); - - Json::Value step_event = result["traceEvents"][1]; - EXPECT_EQ(step_event["ph"].asString(), "T"); - EXPECT_EQ(step_event["ts"].asInt64(), kTimestamp2 / 1000); - EXPECT_EQ(step_event["pid"].asInt(), static_cast<int>(kProcessID)); - EXPECT_EQ(step_event["id2"]["local"].asString(), "0xeb"); - EXPECT_EQ(step_event["cat"].asString(), kCategory); - EXPECT_EQ(step_event["name"].asString(), kName2); - EXPECT_TRUE(step_event["args"].isObject()); - EXPECT_EQ(step_event["args"].size(), 2u); - EXPECT_EQ(step_event["args"]["arg2"].asString(), "value2"); - EXPECT_EQ(step_event["args"]["step"].asString(), "Step1"); - - Json::Value begin_event2 = result["traceEvents"][2]; - EXPECT_EQ(begin_event2["ph"].asString(), "S"); - EXPECT_EQ(begin_event2["ts"].asInt64(), kTimestamp3 / 1000); - EXPECT_EQ(begin_event2["pid"].asInt(), static_cast<int>(kProcessID)); - EXPECT_EQ(begin_event2["id2"]["local"].asString(), "0xec"); - EXPECT_EQ(begin_event2["cat"].asString(), kCategory); - EXPECT_EQ(begin_event2["name"].asString(), kName3); - EXPECT_TRUE(begin_event2["args"].isObject()); - EXPECT_EQ(begin_event2["args"].size(), 0u); - EXPECT_FALSE(begin_event2.isMember("tts")); - EXPECT_FALSE(begin_event2.isMember("use_async_tts")); - - Json::Value end_event1 = result["traceEvents"][3]; - EXPECT_EQ(end_event1["ph"].asString(), "F"); - EXPECT_EQ(end_event1["ts"].asInt64(), (kTimestamp + kDuration) / 1000); - EXPECT_EQ(end_event1["pid"].asInt(), static_cast<int>(kProcessID)); - EXPECT_EQ(end_event1["id2"]["local"].asString(), "0xeb"); - EXPECT_EQ(end_event1["cat"].asString(), kCategory); - EXPECT_EQ(end_event1["name"].asString(), kName); - EXPECT_TRUE(end_event1["args"].isObject()); - EXPECT_EQ(end_event1["args"].size(), 0u); - EXPECT_FALSE(end_event1.isMember("tts")); - EXPECT_FALSE(end_event1.isMember("use_async_tts")); - - Json::Value end_event3 = result["traceEvents"][4]; - EXPECT_EQ(end_event3["ph"].asString(), "F"); - EXPECT_EQ(end_event3["ts"].asInt64(), (kTimestamp3 + kDuration3) / 1000); - EXPECT_EQ(end_event3["pid"].asInt(), static_cast<int>(kProcessID)); - EXPECT_EQ(end_event3["id2"]["local"].asString(), "0xec"); - EXPECT_EQ(end_event3["cat"].asString(), kCategory); - EXPECT_EQ(end_event3["name"].asString(), kName3); - EXPECT_TRUE(end_event3["args"].isObject()); - EXPECT_EQ(end_event3["args"].size(), 0u); - EXPECT_FALSE(end_event3.isMember("tts")); - EXPECT_FALSE(end_event3.isMember("use_async_tts")); -} - TEST_F(ExportJsonTest, AsyncEventWithThreadTimestamp) { const int64_t kTimestamp = 10000000; const int64_t kDuration = 100000; @@ -1231,7 +1071,7 @@ TEST_F(ExportJsonTest, AsyncEventWithThreadTimestamp) { auto id_and_row = slices->Insert({kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0}); context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice( - id_and_row.id, kThreadTimestamp, kThreadDuration, 0, 0); + id_and_row.id.value, kThreadTimestamp, kThreadDuration, 0, 0); base::TempFile temp_file = base::TempFile::Create(); FILE* output = fopen(temp_file.path().c_str(), "w+"); @@ -1288,7 +1128,7 @@ TEST_F(ExportJsonTest, UnfinishedAsyncEvent) { ->Insert({kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0}) .id; context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice( - slice_id, kThreadTimestamp, kThreadDuration, 0, 0); + slice_id.value, kThreadTimestamp, kThreadDuration, 0, 0); base::TempFile temp_file = base::TempFile::Create(); FILE* output = fopen(temp_file.path().c_str(), "w+"); @@ -1445,6 +1285,10 @@ TEST_F(ExportJsonTest, RawEvent) { EXPECT_EQ(event["use_async_tts"].asInt(), 1); EXPECT_EQ(event["id2"]["global"].asString(), "0xaaffaaffaaffaaff"); EXPECT_EQ(event["scope"].asString(), kIdScope); + 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); } @@ -1545,12 +1389,6 @@ TEST_F(ExportJsonTest, CpuProfileEvent) { storage->mutable_cpu_profile_stack_sample_table()->Insert( {kTimestamp, frame_callsite_2.id, utid, kProcessPriority}); - storage->mutable_cpu_profile_stack_sample_table()->Insert( - {kTimestamp + 10000, frame_callsite_1.id, utid, kProcessPriority}); - - storage->mutable_cpu_profile_stack_sample_table()->Insert( - {kTimestamp + 20000, frame_callsite_1.id, utid, kProcessPriority}); - base::TempFile temp_file = base::TempFile::Create(); FILE* output = fopen(temp_file.path().c_str(), "w+"); util::Status status = ExportJson(storage, output); @@ -1559,10 +1397,7 @@ TEST_F(ExportJsonTest, CpuProfileEvent) { Json::Value result = ToJsonValue(ReadFile(output)); - // The first sample should generate only a single instant event; - // the two following samples should also generate an additional [b, e] pair - // (the async duration event). - EXPECT_EQ(result["traceEvents"].size(), 5u); + EXPECT_EQ(result["traceEvents"].size(), 1u); Json::Value event = result["traceEvents"][0]; EXPECT_EQ(event["ph"].asString(), "n"); EXPECT_EQ(event["id"].asString(), "0x1"); @@ -1575,29 +1410,6 @@ TEST_F(ExportJsonTest, CpuProfileEvent) { "foo_func - foo_module_name [foo_module_id]\nbar_func - " "bar_module_name [bar_module_id]\n"); EXPECT_EQ(event["args"]["process_priority"].asInt(), kProcessPriority); - - event = result["traceEvents"][1]; - EXPECT_EQ(event["ph"].asString(), "n"); - EXPECT_EQ(event["id"].asString(), "0x2"); - EXPECT_EQ(event["ts"].asInt64(), (kTimestamp + 10000) / 1000); - - event = result["traceEvents"][2]; - EXPECT_EQ(event["ph"].asString(), "n"); - EXPECT_EQ(event["id"].asString(), "0x2"); - EXPECT_EQ(event["ts"].asInt64(), (kTimestamp + 20000) / 1000); - Json::String second_callstack_ = event["args"]["frames"].asString(); - EXPECT_EQ(second_callstack_, "foo_func - foo_module_name [foo_module_id]\n"); - - event = result["traceEvents"][3]; - EXPECT_EQ(event["ph"].asString(), "b"); - EXPECT_EQ(event["id"].asString(), "0x2"); - EXPECT_EQ(event["ts"].asInt64(), (kTimestamp + 10000) / 1000 - 1); - EXPECT_EQ(event["args"]["frames"].asString(), second_callstack_); - - event = result["traceEvents"][4]; - EXPECT_EQ(event["ph"].asString(), "e"); - EXPECT_EQ(event["id"].asString(), "0x2"); - EXPECT_EQ(event["ts"].asInt64(), (kTimestamp + 20000) / 1000); } TEST_F(ExportJsonTest, ArgumentFilter) { @@ -1747,260 +1559,6 @@ TEST_F(ExportJsonTest, LabelFilter) { EXPECT_EQ(result[1]["name"].asString(), kName); } -TEST_F(ExportJsonTest, MemorySnapshotOsDumpEvent) { - const int64_t kTimestamp = 10000000; - const int64_t kPeakResidentSetSize = 100000; - const int64_t kPrivateFootprintBytes = 200000; - const int64_t kProtectionFlags = 1; - const int64_t kStartAddress = 1000000000; - const int64_t kSizeKb = 1000; - const int64_t kPrivateCleanResidentKb = 2000; - const int64_t kPrivateDirtyKb = 3000; - const int64_t kProportionalResidentKb = 4000; - const int64_t kSharedCleanResidentKb = 5000; - const int64_t kSharedDirtyResidentKb = 6000; - const int64_t kSwapKb = 7000; - const int64_t kModuleTimestamp = 20000000; - const uint32_t kProcessID = 100; - const bool kIsPeakRssResettable = true; - const char* kLevelOfDetail = "detailed"; - const char* kFileName = "filename"; - const char* kModuleDebugid = "debugid"; - const char* kModuleDebugPath = "debugpath"; - - UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID); - TrackId track = context_.track_tracker->InternProcessTrack(upid); - StringId level_of_detail_id = - context_.storage->InternString(base::StringView(kLevelOfDetail)); - auto snapshot_id = context_.storage->mutable_memory_snapshot_table() - ->Insert({kTimestamp, track, level_of_detail_id}) - .id; - - StringId peak_resident_set_size_id = - context_.storage->InternString("chrome.peak_resident_set_kb"); - TrackId peak_resident_set_size_counter = - context_.track_tracker->InternProcessCounterTrack( - peak_resident_set_size_id, upid); - context_.event_tracker->PushCounter(kTimestamp, kPeakResidentSetSize, - peak_resident_set_size_counter); - - StringId private_footprint_bytes_id = - context_.storage->InternString("chrome.private_footprint_kb"); - TrackId private_footprint_bytes_counter = - context_.track_tracker->InternProcessCounterTrack( - private_footprint_bytes_id, upid); - context_.event_tracker->PushCounter(kTimestamp, kPrivateFootprintBytes, - private_footprint_bytes_counter); - - StringId is_peak_rss_resettable_id = - context_.storage->InternString("is_peak_rss_resettable"); - context_.args_tracker->AddArgsTo(upid).AddArg( - is_peak_rss_resettable_id, Variadic::Boolean(kIsPeakRssResettable)); - context_.args_tracker->Flush(); - - context_.storage->mutable_profiler_smaps_table()->Insert( - {upid, kTimestamp, kNullStringId, kSizeKb, kPrivateDirtyKb, kSwapKb, - context_.storage->InternString(kFileName), kStartAddress, - kModuleTimestamp, context_.storage->InternString(kModuleDebugid), - context_.storage->InternString(kModuleDebugPath), kProtectionFlags, - kPrivateCleanResidentKb, kSharedDirtyResidentKb, kSharedCleanResidentKb, - 0, kProportionalResidentKb}); - - base::TempFile temp_file = base::TempFile::Create(); - FILE* output = fopen(temp_file.path().c_str(), "w+"); - util::Status status = ExportJson(context_.storage.get(), output); - - EXPECT_TRUE(status.ok()); - - Json::Value result = ToJsonValue(ReadFile(output)); - EXPECT_EQ(result["traceEvents"].size(), 1u); - - Json::Value event = result["traceEvents"][0]; - EXPECT_EQ(event["ph"].asString(), "v"); - EXPECT_EQ(event["cat"].asString(), "disabled-by-default-memory-infra"); - EXPECT_EQ(event["id"].asString(), base::Uint64ToHexString(snapshot_id.value)); - EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000); - EXPECT_EQ(event["name"].asString(), "periodic_interval"); - EXPECT_EQ(event["pid"].asUInt(), kProcessID); - EXPECT_EQ(event["tid"].asInt(), -1); - - EXPECT_TRUE(event["args"].isObject()); - EXPECT_EQ(event["args"]["dumps"]["level_of_detail"].asString(), - kLevelOfDetail); - - EXPECT_EQ(event["args"]["dumps"]["process_totals"]["peak_resident_set_size"] - .asString(), - base::Uint64ToHexStringNoPrefix( - static_cast<uint64_t>(kPeakResidentSetSize))); - EXPECT_EQ(event["args"]["dumps"]["process_totals"]["private_footprint_bytes"] - .asString(), - base::Uint64ToHexStringNoPrefix( - static_cast<uint64_t>(kPrivateFootprintBytes))); - EXPECT_EQ(event["args"]["dumps"]["process_totals"]["is_peak_rss_resettable"] - .asBool(), - kIsPeakRssResettable); - - EXPECT_TRUE(event["args"]["dumps"]["process_mmaps"]["vm_regions"].isArray()); - EXPECT_EQ(event["args"]["dumps"]["process_mmaps"]["vm_regions"].size(), 1u); - Json::Value region = event["args"]["dumps"]["process_mmaps"]["vm_regions"][0]; - EXPECT_EQ(region["mf"].asString(), kFileName); - EXPECT_EQ(region["pf"].asInt64(), kProtectionFlags); - EXPECT_EQ(region["sa"].asString(), base::Uint64ToHexStringNoPrefix( - static_cast<uint64_t>(kStartAddress))); - EXPECT_EQ( - region["sz"].asString(), - base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSizeKb * 1024))); - EXPECT_EQ(region["id"].asString(), kModuleDebugid); - EXPECT_EQ(region["df"].asString(), kModuleDebugPath); - EXPECT_EQ(region["bs"]["pc"].asString(), - base::Uint64ToHexStringNoPrefix( - static_cast<uint64_t>(kPrivateCleanResidentKb * 1024))); - EXPECT_EQ(region["bs"]["pd"].asString(), - base::Uint64ToHexStringNoPrefix( - static_cast<uint64_t>(kPrivateDirtyKb * 1024))); - EXPECT_EQ(region["bs"]["pss"].asString(), - base::Uint64ToHexStringNoPrefix( - static_cast<uint64_t>(kProportionalResidentKb * 1024))); - EXPECT_EQ(region["bs"]["sc"].asString(), - base::Uint64ToHexStringNoPrefix( - static_cast<uint64_t>(kSharedCleanResidentKb * 1024))); - EXPECT_EQ(region["bs"]["sd"].asString(), - base::Uint64ToHexStringNoPrefix( - static_cast<uint64_t>(kSharedDirtyResidentKb * 1024))); - EXPECT_EQ( - region["bs"]["sw"].asString(), - base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSwapKb * 1024))); -} - -TEST_F(ExportJsonTest, MemorySnapshotChromeDumpEvent) { - const int64_t kTimestamp = 10000000; - const int64_t kSize = 1000; - const int64_t kEffectiveSize = 2000; - const int64_t kScalarAttrValue = 3000; - const uint32_t kOsProcessID = 100; - const uint32_t kChromeProcessID = 200; - const uint32_t kImportance = 1; - const char* kLevelOfDetail = "detailed"; - const char* kPath1 = "path/to_file1"; - const char* kPath2 = "path/to_file2"; - const char* kScalarAttrUnits = "scalar_units"; - const char* kStringAttrValue = "string_value"; - const std::string kScalarAttrName = "scalar_name"; - const std::string kStringAttrName = "string_name"; - - UniquePid os_upid = - context_.process_tracker->GetOrCreateProcess(kOsProcessID); - TrackId track = context_.track_tracker->InternProcessTrack(os_upid); - StringId level_of_detail_id = - context_.storage->InternString(base::StringView(kLevelOfDetail)); - auto snapshot_id = context_.storage->mutable_memory_snapshot_table() - ->Insert({kTimestamp, track, level_of_detail_id}) - .id; - - UniquePid chrome_upid = - context_.process_tracker->GetOrCreateProcess(kChromeProcessID); - auto process_id = context_.storage->mutable_process_memory_snapshot_table() - ->Insert({snapshot_id, chrome_upid}) - .id; - - StringId path1_id = context_.storage->InternString(base::StringView(kPath1)); - StringId path2_id = context_.storage->InternString(base::StringView(kPath2)); - SnapshotNodeId node1_id = - context_.storage->mutable_memory_snapshot_node_table() - ->Insert( - {process_id, SnapshotNodeId(0), path1_id, kSize, kEffectiveSize}) - .id; - SnapshotNodeId node2_id = - context_.storage->mutable_memory_snapshot_node_table() - ->Insert({process_id, SnapshotNodeId(0), path2_id, 0, 0}) - .id; - - context_.args_tracker->AddArgsTo(node1_id).AddArg( - context_.storage->InternString( - base::StringView(kScalarAttrName + ".value")), - Variadic::Integer(kScalarAttrValue)); - context_.args_tracker->AddArgsTo(node1_id).AddArg( - context_.storage->InternString( - base::StringView(kScalarAttrName + ".unit")), - Variadic::String(context_.storage->InternString(kScalarAttrUnits))); - context_.args_tracker->AddArgsTo(node1_id).AddArg( - context_.storage->InternString( - base::StringView(kStringAttrName + ".value")), - Variadic::String(context_.storage->InternString(kStringAttrValue))); - context_.args_tracker->Flush(); - - context_.storage->mutable_memory_snapshot_edge_table()->Insert( - {node1_id, node2_id, kImportance}); - - base::TempFile temp_file = base::TempFile::Create(); - FILE* output = fopen(temp_file.path().c_str(), "w+"); - util::Status status = ExportJson(context_.storage.get(), output); - - EXPECT_TRUE(status.ok()); - - Json::Value result = ToJsonValue(ReadFile(output)); - EXPECT_EQ(result["traceEvents"].size(), 1u); - - Json::Value event = result["traceEvents"][0]; - EXPECT_EQ(event["ph"].asString(), "v"); - EXPECT_EQ(event["cat"].asString(), "disabled-by-default-memory-infra"); - EXPECT_EQ(event["id"].asString(), base::Uint64ToHexString(snapshot_id.value)); - EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000); - EXPECT_EQ(event["name"].asString(), "periodic_interval"); - EXPECT_EQ(event["pid"].asUInt(), kChromeProcessID); - EXPECT_EQ(event["tid"].asInt(), -1); - - EXPECT_TRUE(event["args"].isObject()); - EXPECT_EQ(event["args"]["dumps"]["level_of_detail"].asString(), - kLevelOfDetail); - - EXPECT_EQ(event["args"]["dumps"]["allocators"].size(), 2u); - Json::Value node1 = event["args"]["dumps"]["allocators"][kPath1]; - EXPECT_TRUE(node1.isObject()); - EXPECT_EQ( - node1["guid"].asString(), - base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node1_id.value))); - EXPECT_TRUE(node1["attrs"]["size"].isObject()); - EXPECT_EQ(node1["attrs"]["size"]["value"].asString(), - base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSize))); - EXPECT_EQ(node1["attrs"]["size"]["type"].asString(), "scalar"); - EXPECT_EQ(node1["attrs"]["size"]["units"].asString(), "bytes"); - EXPECT_EQ( - node1["attrs"]["effective_size"]["value"].asString(), - base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kEffectiveSize))); - EXPECT_TRUE(node1["attrs"][kScalarAttrName].isObject()); - EXPECT_EQ( - node1["attrs"][kScalarAttrName]["value"].asString(), - base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kScalarAttrValue))); - EXPECT_EQ(node1["attrs"][kScalarAttrName]["type"].asString(), "scalar"); - EXPECT_EQ(node1["attrs"][kScalarAttrName]["units"].asString(), - kScalarAttrUnits); - EXPECT_TRUE(node1["attrs"][kStringAttrName].isObject()); - EXPECT_EQ(node1["attrs"][kStringAttrName]["value"].asString(), - kStringAttrValue); - EXPECT_EQ(node1["attrs"][kStringAttrName]["type"].asString(), "string"); - EXPECT_EQ(node1["attrs"][kStringAttrName]["units"].asString(), ""); - - Json::Value node2 = event["args"]["dumps"]["allocators"][kPath2]; - EXPECT_TRUE(node2.isObject()); - EXPECT_EQ( - node2["guid"].asString(), - base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node2_id.value))); - EXPECT_TRUE(node2["attrs"].empty()); - - Json::Value graph = event["args"]["dumps"]["allocators_graph"]; - EXPECT_TRUE(graph.isArray()); - EXPECT_EQ(graph.size(), 1u); - EXPECT_EQ( - graph[0]["source"].asString(), - base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node1_id.value))); - EXPECT_EQ( - graph[0]["target"].asString(), - base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node2_id.value))); - EXPECT_EQ(graph[0]["importance"].asUInt(), kImportance); - EXPECT_EQ(graph[0]["type"].asString(), "ownership"); -} - } // namespace } // namespace json } // namespace trace_processor |