blob: 1dba4d24bf65442dd22e793b720d119013aa7786 [file] [log] [blame]
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +01001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Eric Seckler178094e2019-10-24 14:03:04 +010017#include "perfetto/ext/trace_processor/export_json.h"
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010018#include "src/trace_processor/export_json.h"
19
Eric Seckler178094e2019-10-24 14:03:04 +010020#include <string.h>
21
22#include <limits>
23
24#include <json/reader.h>
25#include <json/value.h>
26
Tomasz Konieczny6e2d3dd2020-11-04 15:54:04 +010027#include "perfetto/ext/base/string_utils.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010028#include "perfetto/ext/base/temp_file.h"
Lalit Maganti617deae2020-04-14 21:00:49 +010029#include "src/trace_processor/importers/common/args_tracker.h"
Tomasz Konieczny6e2d3dd2020-11-04 15:54:04 +010030#include "src/trace_processor/importers/common/event_tracker.h"
Lalit Maganti617deae2020-04-14 21:00:49 +010031#include "src/trace_processor/importers/common/process_tracker.h"
32#include "src/trace_processor/importers/common/track_tracker.h"
Lalit Maganti05819e22020-04-14 21:01:38 +010033#include "src/trace_processor/importers/proto/metadata_tracker.h"
Lalit Maganti62b741f2020-12-10 18:24:00 +000034#include "src/trace_processor/importers/proto/track_event_tracker.h"
Lalit Maganti0faddc42020-04-10 17:58:24 +010035#include "src/trace_processor/types/trace_processor_context.h"
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010036
Primiano Tucci919ca1e2019-08-21 20:26:58 +020037#include "test/gtest_and_gmock.h"
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010038
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010039namespace perfetto {
40namespace trace_processor {
41namespace json {
42namespace {
43
44std::string ReadFile(FILE* input) {
45 fseek(input, 0, SEEK_SET);
Eric Secklere2b4e5c2019-12-06 14:37:29 +000046 const int kBufSize = 10000;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010047 char buffer[kBufSize];
Lalit Magantid9983462019-05-09 18:10:09 +010048 size_t ret = fread(buffer, sizeof(char), kBufSize, input);
Primiano Tucci225a4e62019-06-06 11:13:57 +010049 EXPECT_GT(ret, 0u);
Lalit Magantid9983462019-05-09 18:10:09 +010050 return std::string(buffer, ret);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010051}
52
Eric Seckler178094e2019-10-24 14:03:04 +010053class StringOutputWriter : public OutputWriter {
54 public:
55 StringOutputWriter() { str_.reserve(1024); }
56 ~StringOutputWriter() override {}
57
58 util::Status AppendString(const std::string& str) override {
59 str_ += str;
60 return util::OkStatus();
61 }
62
63 std::string TakeStr() { return std::move(str_); }
64
65 private:
66 std::string str_;
67};
68
Eric Seckler4b861052019-10-23 14:50:28 +010069class ExportJsonTest : public ::testing::Test {
70 public:
71 ExportJsonTest() {
Lalit Maganti1908e262020-01-09 14:33:19 +000072 context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
Eric Seckler4b861052019-10-23 14:50:28 +010073 context_.args_tracker.reset(new ArgsTracker(&context_));
Tomasz Konieczny6e2d3dd2020-11-04 15:54:04 +010074 context_.event_tracker.reset(new EventTracker(&context_));
Eric Seckler4b861052019-10-23 14:50:28 +010075 context_.storage.reset(new TraceStorage());
76 context_.track_tracker.reset(new TrackTracker(&context_));
Lalit Magantiededb0e2020-01-08 12:50:34 +000077 context_.metadata_tracker.reset(new MetadataTracker(&context_));
Lalit Magantieac7fff2020-01-10 16:42:54 +000078 context_.process_tracker.reset(new ProcessTracker(&context_));
Eric Seckler4b861052019-10-23 14:50:28 +010079 }
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010080
Eric Seckler178094e2019-10-24 14:03:04 +010081 std::string ToJson(ArgumentFilterPredicate argument_filter = nullptr,
82 MetadataFilterPredicate metadata_filter = nullptr,
83 LabelFilterPredicate label_filter = nullptr) {
84 StringOutputWriter writer;
85 util::Status status =
86 ExportJson(context_.storage.get(), &writer, argument_filter,
87 metadata_filter, label_filter);
88 EXPECT_TRUE(status.ok());
89 return writer.TakeStr();
90 }
91
92 Json::Value ToJsonValue(const std::string& json) {
Jordan Bayles8c6a4bc2020-07-16 20:20:48 -070093 Json::CharReaderBuilder b;
94 auto reader = std::unique_ptr<Json::CharReader>(b.newCharReader());
Eric Seckler178094e2019-10-24 14:03:04 +010095 Json::Value result;
Jordan Bayles8c6a4bc2020-07-16 20:20:48 -070096 EXPECT_TRUE(reader->parse(json.data(), json.data() + json.length(), &result,
97 nullptr))
98 << json;
Eric Seckler178094e2019-10-24 14:03:04 +010099 return result;
100 }
101
Eric Seckler4b861052019-10-23 14:50:28 +0100102 protected:
103 TraceProcessorContext context_;
104};
105
106TEST_F(ExportJsonTest, EmptyStorage) {
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100107 base::TempFile temp_file = base::TempFile::Create();
108 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100109 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100110
Eric Seckler7fb1d232019-10-23 14:42:43 +0100111 EXPECT_TRUE(status.ok());
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100112
Eric Seckler178094e2019-10-24 14:03:04 +0100113 Json::Value result = ToJsonValue(ReadFile(output));
Primiano Tucci225a4e62019-06-06 11:13:57 +0100114 EXPECT_EQ(result["traceEvents"].size(), 0u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100115}
116
Eric Seckler4b861052019-10-23 14:50:28 +0100117TEST_F(ExportJsonTest, StorageWithOneSlice) {
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100118 const int64_t kTimestamp = 10000000;
119 const int64_t kDuration = 10000;
Mikhail Khokhlov7db04912019-07-18 16:11:11 +0100120 const int64_t kThreadTimestamp = 20000000;
121 const int64_t kThreadDuration = 20000;
Eric Seckler77fb1d22019-07-31 17:02:51 +0100122 const int64_t kThreadInstructionCount = 30000000;
123 const int64_t kThreadInstructionDelta = 30000;
Eric Secklerbb0e1542020-01-16 13:44:13 +0000124 const uint32_t kThreadID = 100;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100125 const char* kCategory = "cat";
126 const char* kName = "name";
127
Lalit Magantieac7fff2020-01-10 16:42:54 +0000128 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000129 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100130 context_.args_tracker->Flush(); // Flush track args.
131 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
132 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000133 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000134 {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100135 context_.storage->mutable_thread_slices()->AddThreadSlice(
Eric Seckler77fb1d22019-07-31 17:02:51 +0100136 0, kThreadTimestamp, kThreadDuration, kThreadInstructionCount,
137 kThreadInstructionDelta);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100138
139 base::TempFile temp_file = base::TempFile::Create();
140 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100141 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100142
Eric Seckler7fb1d232019-10-23 14:42:43 +0100143 EXPECT_TRUE(status.ok());
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100144
Eric Seckler178094e2019-10-24 14:03:04 +0100145 Json::Value result = ToJsonValue(ReadFile(output));
Primiano Tucci225a4e62019-06-06 11:13:57 +0100146 EXPECT_EQ(result["traceEvents"].size(), 1u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100147
148 Json::Value event = result["traceEvents"][0];
149 EXPECT_EQ(event["ph"].asString(), "X");
150 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
151 EXPECT_EQ(event["dur"].asInt64(), kDuration / 1000);
Mikhail Khokhlov7db04912019-07-18 16:11:11 +0100152 EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
153 EXPECT_EQ(event["tdur"].asInt64(), kThreadDuration / 1000);
Eric Seckler77fb1d22019-07-31 17:02:51 +0100154 EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
155 EXPECT_EQ(event["tidelta"].asInt64(), kThreadInstructionDelta);
Eric Seckler88cab6f2020-01-16 18:33:45 +0000156 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100157 EXPECT_EQ(event["cat"].asString(), kCategory);
158 EXPECT_EQ(event["name"].asString(), kName);
Eric Secklerf91236e2019-11-04 10:25:45 +0000159 EXPECT_TRUE(event["args"].isObject());
160 EXPECT_EQ(event["args"].size(), 0u);
Eric Seckler206db472019-07-25 12:05:27 +0100161}
Eric Seckler6f13e332019-10-15 12:14:04 +0100162
Eric Seckler4b861052019-10-23 14:50:28 +0100163TEST_F(ExportJsonTest, StorageWithOneUnfinishedSlice) {
Eric Seckler206db472019-07-25 12:05:27 +0100164 const int64_t kTimestamp = 10000000;
165 const int64_t kDuration = -1;
166 const int64_t kThreadTimestamp = 20000000;
167 const int64_t kThreadDuration = -1;
Eric Seckler77fb1d22019-07-31 17:02:51 +0100168 const int64_t kThreadInstructionCount = 30000000;
169 const int64_t kThreadInstructionDelta = -1;
Eric Secklerbb0e1542020-01-16 13:44:13 +0000170 const uint32_t kThreadID = 100;
Eric Seckler206db472019-07-25 12:05:27 +0100171 const char* kCategory = "cat";
172 const char* kName = "name";
173
Lalit Magantieac7fff2020-01-10 16:42:54 +0000174 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000175 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100176 context_.args_tracker->Flush(); // Flush track args.
177 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
178 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000179 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000180 {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100181 context_.storage->mutable_thread_slices()->AddThreadSlice(
Eric Seckler77fb1d22019-07-31 17:02:51 +0100182 0, kThreadTimestamp, kThreadDuration, kThreadInstructionCount,
183 kThreadInstructionDelta);
Eric Seckler206db472019-07-25 12:05:27 +0100184
185 base::TempFile temp_file = base::TempFile::Create();
186 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100187 util::Status status = ExportJson(context_.storage.get(), output);
Eric Seckler206db472019-07-25 12:05:27 +0100188
Eric Seckler7fb1d232019-10-23 14:42:43 +0100189 EXPECT_TRUE(status.ok());
Eric Seckler206db472019-07-25 12:05:27 +0100190
Eric Seckler178094e2019-10-24 14:03:04 +0100191 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler206db472019-07-25 12:05:27 +0100192 EXPECT_EQ(result["traceEvents"].size(), 1u);
193
194 Json::Value event = result["traceEvents"][0];
195 EXPECT_EQ(event["ph"].asString(), "B");
196 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
197 EXPECT_FALSE(event.isMember("dur"));
198 EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
199 EXPECT_FALSE(event.isMember("tdur"));
Eric Seckler77fb1d22019-07-31 17:02:51 +0100200 EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
201 EXPECT_FALSE(event.isMember("tidelta"));
Eric Seckler88cab6f2020-01-16 18:33:45 +0000202 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Eric Seckler206db472019-07-25 12:05:27 +0100203 EXPECT_EQ(event["cat"].asString(), kCategory);
204 EXPECT_EQ(event["name"].asString(), kName);
Eric Secklerf91236e2019-11-04 10:25:45 +0000205 EXPECT_TRUE(event["args"].isObject());
206 EXPECT_EQ(event["args"].size(), 0u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100207}
208
Eric Seckler4b861052019-10-23 14:50:28 +0100209TEST_F(ExportJsonTest, StorageWithThreadName) {
Eric Secklerbb0e1542020-01-16 13:44:13 +0000210 const uint32_t kThreadID = 100;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100211 const char* kName = "thread";
212
Lalit Magantieac7fff2020-01-10 16:42:54 +0000213 tables::ThreadTable::Row row(kThreadID);
214 row.name = context_.storage->InternString(base::StringView(kName));
215 context_.storage->mutable_thread_table()->Insert(row);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100216
217 base::TempFile temp_file = base::TempFile::Create();
218 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100219 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100220
Eric Seckler7fb1d232019-10-23 14:42:43 +0100221 EXPECT_TRUE(status.ok());
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100222
Eric Seckler178094e2019-10-24 14:03:04 +0100223 Json::Value result = ToJsonValue(ReadFile(output));
Primiano Tucci225a4e62019-06-06 11:13:57 +0100224 EXPECT_EQ(result["traceEvents"].size(), 1u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100225
226 Json::Value event = result["traceEvents"][0];
227 EXPECT_EQ(event["ph"].asString(), "M");
Eric Seckler88cab6f2020-01-16 18:33:45 +0000228 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100229 EXPECT_EQ(event["name"].asString(), "thread_name");
230 EXPECT_EQ(event["args"]["name"].asString(), kName);
231}
232
Eric Seckler3183c6d2020-01-14 15:45:20 +0000233TEST_F(ExportJsonTest, SystemEventsIgnored) {
Lalit Magantif7a1a732020-10-12 15:42:34 +0100234 TrackId track = context_.track_tracker->CreateAndroidAsyncTrack(
235 /*name=*/kNullStringId, /*upid=*/0);
Eric Seckler4b861052019-10-23 14:50:28 +0100236 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti21b21632019-09-28 16:50:23 +0100237
Eric Seckler3183c6d2020-01-14 15:45:20 +0000238 // System events have no category.
239 StringId cat_id = kNullStringId;
Eric Seckler4b861052019-10-23 14:50:28 +0100240 StringId name_id = context_.storage->InternString("name");
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000241 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000242 {0, 0, track, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100243
244 base::TempFile temp_file = base::TempFile::Create();
245 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100246 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100247
Eric Seckler4b861052019-10-23 14:50:28 +0100248 EXPECT_TRUE(status.ok());
249
Eric Seckler178094e2019-10-24 14:03:04 +0100250 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler4b861052019-10-23 14:50:28 +0100251 EXPECT_EQ(result["traceEvents"].size(), 0u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100252}
253
Eric Seckler4b861052019-10-23 14:50:28 +0100254TEST_F(ExportJsonTest, StorageWithMetadata) {
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100255 const char* kDescription = "description";
256 const char* kBenchmarkName = "benchmark name";
257 const char* kStoryName = "story name";
258 const char* kStoryTag1 = "tag1";
259 const char* kStoryTag2 = "tag2";
260 const int64_t kBenchmarkStart = 1000000;
261 const int64_t kStoryStart = 2000000;
262 const bool kHadFailures = true;
263
Eric Seckler4b861052019-10-23 14:50:28 +0100264 StringId desc_id =
265 context_.storage->InternString(base::StringView(kDescription));
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100266 Variadic description = Variadic::String(desc_id);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000267 context_.metadata_tracker->SetMetadata(metadata::benchmark_description,
268 description);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100269
270 StringId benchmark_name_id =
Eric Seckler4b861052019-10-23 14:50:28 +0100271 context_.storage->InternString(base::StringView(kBenchmarkName));
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100272 Variadic benchmark_name = Variadic::String(benchmark_name_id);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000273 context_.metadata_tracker->SetMetadata(metadata::benchmark_name,
274 benchmark_name);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100275
Eric Seckler4b861052019-10-23 14:50:28 +0100276 StringId story_name_id =
277 context_.storage->InternString(base::StringView(kStoryName));
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100278 Variadic story_name = Variadic::String(story_name_id);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000279 context_.metadata_tracker->SetMetadata(metadata::benchmark_story_name,
280 story_name);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100281
Eric Seckler4b861052019-10-23 14:50:28 +0100282 StringId tag1_id =
283 context_.storage->InternString(base::StringView(kStoryTag1));
284 StringId tag2_id =
285 context_.storage->InternString(base::StringView(kStoryTag2));
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100286 Variadic tag1 = Variadic::String(tag1_id);
287 Variadic tag2 = Variadic::String(tag2_id);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000288 context_.metadata_tracker->AppendMetadata(metadata::benchmark_story_tags,
289 tag1);
290 context_.metadata_tracker->AppendMetadata(metadata::benchmark_story_tags,
291 tag2);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100292
293 Variadic benchmark_start = Variadic::Integer(kBenchmarkStart);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000294 context_.metadata_tracker->SetMetadata(metadata::benchmark_start_time_us,
295 benchmark_start);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100296
297 Variadic story_start = Variadic::Integer(kStoryStart);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000298 context_.metadata_tracker->SetMetadata(metadata::benchmark_story_run_time_us,
299 story_start);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100300
301 Variadic had_failures = Variadic::Integer(kHadFailures);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000302 context_.metadata_tracker->SetMetadata(metadata::benchmark_had_failures,
303 had_failures);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100304
305 base::TempFile temp_file = base::TempFile::Create();
306 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100307 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100308
Eric Seckler7fb1d232019-10-23 14:42:43 +0100309 EXPECT_TRUE(status.ok());
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100310
Eric Seckler178094e2019-10-24 14:03:04 +0100311 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100312
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100313 EXPECT_TRUE(result.isMember("metadata"));
314 EXPECT_TRUE(result["metadata"].isMember("telemetry"));
315 Json::Value telemetry_metadata = result["metadata"]["telemetry"];
316
Primiano Tucci225a4e62019-06-06 11:13:57 +0100317 EXPECT_EQ(telemetry_metadata["benchmarkDescriptions"].size(), 1u);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100318 EXPECT_EQ(telemetry_metadata["benchmarkDescriptions"][0].asString(),
319 kDescription);
320
Primiano Tucci225a4e62019-06-06 11:13:57 +0100321 EXPECT_EQ(telemetry_metadata["benchmarks"].size(), 1u);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100322 EXPECT_EQ(telemetry_metadata["benchmarks"][0].asString(), kBenchmarkName);
323
Primiano Tucci225a4e62019-06-06 11:13:57 +0100324 EXPECT_EQ(telemetry_metadata["stories"].size(), 1u);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100325 EXPECT_EQ(telemetry_metadata["stories"][0].asString(), kStoryName);
326
Primiano Tucci225a4e62019-06-06 11:13:57 +0100327 EXPECT_EQ(telemetry_metadata["storyTags"].size(), 2u);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100328 EXPECT_EQ(telemetry_metadata["storyTags"][0].asString(), kStoryTag1);
329 EXPECT_EQ(telemetry_metadata["storyTags"][1].asString(), kStoryTag2);
330
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200331 EXPECT_DOUBLE_EQ(telemetry_metadata["benchmarkStart"].asInt(),
332 kBenchmarkStart / 1000.0);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100333
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200334 EXPECT_DOUBLE_EQ(telemetry_metadata["traceStart"].asInt(),
335 kStoryStart / 1000.0);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100336
Primiano Tucci225a4e62019-06-06 11:13:57 +0100337 EXPECT_EQ(telemetry_metadata["hadFailures"].size(), 1u);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100338 EXPECT_EQ(telemetry_metadata["hadFailures"][0].asBool(), kHadFailures);
339}
340
Eric Seckler4b861052019-10-23 14:50:28 +0100341TEST_F(ExportJsonTest, StorageWithStats) {
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100342 int64_t kProducers = 10;
343 int64_t kBufferSize0 = 1000;
344 int64_t kBufferSize1 = 2000;
Eric Secklere2b4e5c2019-12-06 14:37:29 +0000345 int64_t kFtraceBegin = 3000;
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100346
Eric Seckler4b861052019-10-23 14:50:28 +0100347 context_.storage->SetStats(stats::traced_producers_connected, kProducers);
348 context_.storage->SetIndexedStats(stats::traced_buf_buffer_size, 0,
349 kBufferSize0);
350 context_.storage->SetIndexedStats(stats::traced_buf_buffer_size, 1,
351 kBufferSize1);
Eric Secklere2b4e5c2019-12-06 14:37:29 +0000352 context_.storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin, 0,
353 kFtraceBegin);
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100354
355 base::TempFile temp_file = base::TempFile::Create();
356 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100357 util::Status status = ExportJson(context_.storage.get(), output);
Eric Seckler7fb1d232019-10-23 14:42:43 +0100358 EXPECT_TRUE(status.ok());
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100359
Eric Seckler178094e2019-10-24 14:03:04 +0100360 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100361
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100362 EXPECT_TRUE(result.isMember("metadata"));
Eric Secklere2b4e5c2019-12-06 14:37:29 +0000363 EXPECT_TRUE(result["metadata"].isMember("trace_processor_stats"));
364 Json::Value stats = result["metadata"]["trace_processor_stats"];
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100365
Eric Secklere2b4e5c2019-12-06 14:37:29 +0000366 EXPECT_EQ(stats["traced_producers_connected"].asInt(), kProducers);
367 EXPECT_EQ(stats["traced_buf"].size(), 2u);
368 EXPECT_EQ(stats["traced_buf"][0]["buffer_size"].asInt(), kBufferSize0);
369 EXPECT_EQ(stats["traced_buf"][1]["buffer_size"].asInt(), kBufferSize1);
370 EXPECT_EQ(stats["ftrace_cpu_bytes_read_begin"].size(), 1u);
371 EXPECT_EQ(stats["ftrace_cpu_bytes_read_begin"][0].asInt(), kFtraceBegin);
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100372}
373
Eric Seckler4b861052019-10-23 14:50:28 +0100374TEST_F(ExportJsonTest, StorageWithChromeMetadata) {
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100375 const char* kName1 = "name1";
376 const char* kName2 = "name2";
377 const char* kValue1 = "value1";
378 const int kValue2 = 222;
379
Eric Seckler4b861052019-10-23 14:50:28 +0100380 TraceStorage* storage = context_.storage.get();
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100381
Lalit Maganti8d770f72020-01-30 15:44:04 +0000382 RawId id =
383 storage->mutable_raw_table()
384 ->Insert({0, storage->InternString("chrome_event.metadata"), 0, 0})
385 .id;
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100386
387 StringId name1_id = storage->InternString(base::StringView(kName1));
388 StringId name2_id = storage->InternString(base::StringView(kName2));
389 StringId value1_id = storage->InternString(base::StringView(kValue1));
Lalit Maganti5228f362020-01-15 13:45:56 +0000390
391 context_.args_tracker->AddArgsTo(id)
392 .AddArg(name1_id, Variadic::String(value1_id))
393 .AddArg(name2_id, Variadic::Integer(kValue2));
Eric Seckler4b861052019-10-23 14:50:28 +0100394 context_.args_tracker->Flush();
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100395
396 base::TempFile temp_file = base::TempFile::Create();
397 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +0100398 util::Status status = ExportJson(storage, output);
399 EXPECT_TRUE(status.ok());
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100400
Eric Seckler178094e2019-10-24 14:03:04 +0100401 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100402
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100403 EXPECT_TRUE(result.isMember("metadata"));
404 Json::Value metadata = result["metadata"];
405
406 EXPECT_EQ(metadata[kName1].asString(), kValue1);
407 EXPECT_EQ(metadata[kName2].asInt(), kValue2);
408}
409
Eric Seckler4b861052019-10-23 14:50:28 +0100410TEST_F(ExportJsonTest, StorageWithArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100411 const char* kCategory = "cat";
412 const char* kName = "name";
413 const char* kSrc = "source_file.cc";
414
Lalit Magantieac7fff2020-01-10 16:42:54 +0000415 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000416 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100417 context_.args_tracker->Flush(); // Flush track args.
418 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
419 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000420 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000421 {0, 0, track, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100422
Eric Seckler4b861052019-10-23 14:50:28 +0100423 StringId arg_key_id = context_.storage->InternString(
424 base::StringView("task.posted_from.file_name"));
425 StringId arg_value_id =
426 context_.storage->InternString(base::StringView(kSrc));
Lalit Maganti1908e262020-01-09 14:33:19 +0000427 GlobalArgsTracker::Arg arg;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100428 arg.flat_key = arg_key_id;
429 arg.key = arg_key_id;
430 arg.value = Variadic::String(arg_value_id);
Lalit Maganti1908e262020-01-09 14:33:19 +0000431 ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000432 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100433
434 base::TempFile temp_file = base::TempFile::Create();
435 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100436 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100437
Eric Seckler7fb1d232019-10-23 14:42:43 +0100438 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100439
Eric Seckler178094e2019-10-24 14:03:04 +0100440 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100441 EXPECT_EQ(result["traceEvents"].size(), 1u);
442
443 Json::Value event = result["traceEvents"][0];
444 EXPECT_EQ(event["cat"].asString(), kCategory);
445 EXPECT_EQ(event["name"].asString(), kName);
446 EXPECT_EQ(event["args"]["src"].asString(), kSrc);
447}
448
Eric Seckler4b861052019-10-23 14:50:28 +0100449TEST_F(ExportJsonTest, StorageWithSliceAndFlowEventArgs) {
Eric Seckler6f13e332019-10-15 12:14:04 +0100450 const char* kCategory = "cat";
451 const char* kName = "name";
Eric Seckler6f13e332019-10-15 12:14:04 +0100452
Eric Seckler4b861052019-10-23 14:50:28 +0100453 TraceStorage* storage = context_.storage.get();
Eric Seckler6f13e332019-10-15 12:14:04 +0100454
Lalit Magantieac7fff2020-01-10 16:42:54 +0000455 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000456 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100457 context_.args_tracker->Flush(); // Flush track args.
Eric Seckler6f13e332019-10-15 12:14:04 +0100458 StringId cat_id = storage->InternString(base::StringView(kCategory));
459 StringId name_id = storage->InternString(base::StringView(kName));
Andriidd07cb12020-09-10 16:09:01 +0300460 SliceId id1 = storage->mutable_slice_table()
461 ->Insert({0, 0, track, cat_id, name_id, 0, 0, 0})
462 .id;
463 SliceId id2 = storage->mutable_slice_table()
464 ->Insert({100, 0, track, cat_id, name_id, 0, 0, 0})
465 .id;
Eric Seckler6f13e332019-10-15 12:14:04 +0100466
Andriidd07cb12020-09-10 16:09:01 +0300467 storage->mutable_flow_table()->Insert({id1, id2, 0});
Eric Seckler6f13e332019-10-15 12:14:04 +0100468
469 base::TempFile temp_file = base::TempFile::Create();
470 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +0100471 util::Status status = ExportJson(storage, output);
Eric Seckler6f13e332019-10-15 12:14:04 +0100472
Eric Seckler7fb1d232019-10-23 14:42:43 +0100473 EXPECT_TRUE(status.ok());
Eric Seckler6f13e332019-10-15 12:14:04 +0100474
Eric Seckler178094e2019-10-24 14:03:04 +0100475 Json::Value result = ToJsonValue(ReadFile(output));
Andriidd07cb12020-09-10 16:09:01 +0300476 EXPECT_EQ(result["traceEvents"].size(), 4u);
Eric Seckler6f13e332019-10-15 12:14:04 +0100477
Andriidd07cb12020-09-10 16:09:01 +0300478 Json::Value slice_out = result["traceEvents"][0];
479 Json::Value slice_in = result["traceEvents"][1];
480 Json::Value flow_out = result["traceEvents"][2];
481 Json::Value flow_in = result["traceEvents"][3];
482
483 EXPECT_EQ(flow_out["cat"].asString(), kCategory);
484 EXPECT_EQ(flow_out["name"].asString(), kName);
485 EXPECT_EQ(flow_out["ph"].asString(), "s");
486 EXPECT_EQ(flow_out["tid"].asString(), slice_out["tid"].asString());
487 EXPECT_EQ(flow_out["pid"].asString(), slice_out["pid"].asString());
488
489 EXPECT_EQ(flow_in["cat"].asString(), kCategory);
490 EXPECT_EQ(flow_in["name"].asString(), kName);
491 EXPECT_EQ(flow_in["ph"].asString(), "f");
492 EXPECT_EQ(flow_in["bp"].asString(), "e");
493 EXPECT_EQ(flow_in["tid"].asString(), slice_in["tid"].asString());
494 EXPECT_EQ(flow_in["pid"].asString(), slice_in["pid"].asString());
495
496 EXPECT_LE(slice_out["ts"].asInt64(), flow_out["ts"].asInt64());
497 EXPECT_GE(slice_in["ts"].asInt64(), flow_in["ts"].asInt64());
498
499 EXPECT_EQ(flow_out["id"].asString(), flow_in["id"].asString());
Eric Seckler6f13e332019-10-15 12:14:04 +0100500}
501
Eric Seckler4b861052019-10-23 14:50:28 +0100502TEST_F(ExportJsonTest, StorageWithListArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100503 const char* kCategory = "cat";
504 const char* kName = "name";
505 double kValues[] = {1.234, 2.345};
506
Lalit Magantieac7fff2020-01-10 16:42:54 +0000507 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000508 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100509 context_.args_tracker->Flush(); // Flush track args.
510 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
511 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000512 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000513 {0, 0, track, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100514
Eric Seckler4b861052019-10-23 14:50:28 +0100515 StringId arg_flat_key_id = context_.storage->InternString(
516 base::StringView("debug.draw_duration_ms"));
517 StringId arg_key0_id = context_.storage->InternString(
518 base::StringView("debug.draw_duration_ms[0]"));
519 StringId arg_key1_id = context_.storage->InternString(
520 base::StringView("debug.draw_duration_ms[1]"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000521 GlobalArgsTracker::Arg arg0;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100522 arg0.flat_key = arg_flat_key_id;
523 arg0.key = arg_key0_id;
524 arg0.value = Variadic::Real(kValues[0]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000525 GlobalArgsTracker::Arg arg1;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100526 arg1.flat_key = arg_flat_key_id;
527 arg1.key = arg_key1_id;
528 arg1.value = Variadic::Real(kValues[1]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000529 ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000530 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100531
532 base::TempFile temp_file = base::TempFile::Create();
533 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100534 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100535
Eric Seckler7fb1d232019-10-23 14:42:43 +0100536 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100537
Eric Seckler178094e2019-10-24 14:03:04 +0100538 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100539 EXPECT_EQ(result["traceEvents"].size(), 1u);
540
541 Json::Value event = result["traceEvents"][0];
542 EXPECT_EQ(event["cat"].asString(), kCategory);
543 EXPECT_EQ(event["name"].asString(), kName);
Mikhail Khokhlovc4544ea2019-07-10 14:41:25 +0100544 EXPECT_EQ(event["args"]["draw_duration_ms"].size(), 2u);
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200545 EXPECT_DOUBLE_EQ(event["args"]["draw_duration_ms"][0].asDouble(), kValues[0]);
546 EXPECT_DOUBLE_EQ(event["args"]["draw_duration_ms"][1].asDouble(), kValues[1]);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100547}
548
Eric Seckler4b861052019-10-23 14:50:28 +0100549TEST_F(ExportJsonTest, StorageWithMultiplePointerArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100550 const char* kCategory = "cat";
551 const char* kName = "name";
552 uint64_t kValue0 = 1;
553 uint64_t kValue1 = std::numeric_limits<uint64_t>::max();
554
Lalit Magantieac7fff2020-01-10 16:42:54 +0000555 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000556 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100557 context_.args_tracker->Flush(); // Flush track args.
558 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
559 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000560 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000561 {0, 0, track, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100562
Eric Seckler4b861052019-10-23 14:50:28 +0100563 StringId arg_key0_id =
564 context_.storage->InternString(base::StringView("arg0"));
565 StringId arg_key1_id =
566 context_.storage->InternString(base::StringView("arg1"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000567 GlobalArgsTracker::Arg arg0;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100568 arg0.flat_key = arg_key0_id;
569 arg0.key = arg_key0_id;
570 arg0.value = Variadic::Pointer(kValue0);
Lalit Maganti1908e262020-01-09 14:33:19 +0000571 GlobalArgsTracker::Arg arg1;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100572 arg1.flat_key = arg_key1_id;
573 arg1.key = arg_key1_id;
574 arg1.value = Variadic::Pointer(kValue1);
Lalit Maganti1908e262020-01-09 14:33:19 +0000575 ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000576 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100577
578 base::TempFile temp_file = base::TempFile::Create();
579 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100580 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100581
Eric Seckler7fb1d232019-10-23 14:42:43 +0100582 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100583
Eric Seckler178094e2019-10-24 14:03:04 +0100584 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100585 EXPECT_EQ(result["traceEvents"].size(), 1u);
586
587 Json::Value event = result["traceEvents"][0];
588 EXPECT_EQ(event["cat"].asString(), kCategory);
589 EXPECT_EQ(event["name"].asString(), kName);
590 EXPECT_EQ(event["args"]["arg0"].asString(), "0x1");
591 EXPECT_EQ(event["args"]["arg1"].asString(), "0xffffffffffffffff");
592}
593
Eric Seckler4b861052019-10-23 14:50:28 +0100594TEST_F(ExportJsonTest, StorageWithObjectListArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100595 const char* kCategory = "cat";
596 const char* kName = "name";
597 int kValues[] = {123, 234};
598
Lalit Magantieac7fff2020-01-10 16:42:54 +0000599 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000600 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100601 context_.args_tracker->Flush(); // Flush track args.
602 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
603 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000604 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000605 {0, 0, track, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100606
Eric Seckler4b861052019-10-23 14:50:28 +0100607 StringId arg_flat_key_id =
608 context_.storage->InternString(base::StringView("a.b"));
609 StringId arg_key0_id =
610 context_.storage->InternString(base::StringView("a[0].b"));
611 StringId arg_key1_id =
612 context_.storage->InternString(base::StringView("a[1].b"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000613 GlobalArgsTracker::Arg arg0;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100614 arg0.flat_key = arg_flat_key_id;
615 arg0.key = arg_key0_id;
616 arg0.value = Variadic::Integer(kValues[0]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000617 GlobalArgsTracker::Arg arg1;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100618 arg1.flat_key = arg_flat_key_id;
619 arg1.key = arg_key1_id;
620 arg1.value = Variadic::Integer(kValues[1]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000621 ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000622 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100623
624 base::TempFile temp_file = base::TempFile::Create();
625 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100626 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100627
Eric Seckler7fb1d232019-10-23 14:42:43 +0100628 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100629
Eric Seckler178094e2019-10-24 14:03:04 +0100630 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100631 EXPECT_EQ(result["traceEvents"].size(), 1u);
632
633 Json::Value event = result["traceEvents"][0];
634 EXPECT_EQ(event["cat"].asString(), kCategory);
635 EXPECT_EQ(event["name"].asString(), kName);
Mikhail Khokhlovc4544ea2019-07-10 14:41:25 +0100636 EXPECT_EQ(event["args"]["a"].size(), 2u);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100637 EXPECT_EQ(event["args"]["a"][0]["b"].asInt(), kValues[0]);
638 EXPECT_EQ(event["args"]["a"][1]["b"].asInt(), kValues[1]);
639}
640
Eric Seckler4b861052019-10-23 14:50:28 +0100641TEST_F(ExportJsonTest, StorageWithNestedListArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100642 const char* kCategory = "cat";
643 const char* kName = "name";
644 int kValues[] = {123, 234};
645
Lalit Magantieac7fff2020-01-10 16:42:54 +0000646 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000647 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100648 context_.args_tracker->Flush(); // Flush track args.
649 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
650 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000651 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000652 {0, 0, track, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100653
Eric Seckler4b861052019-10-23 14:50:28 +0100654 StringId arg_flat_key_id =
655 context_.storage->InternString(base::StringView("a"));
656 StringId arg_key0_id =
657 context_.storage->InternString(base::StringView("a[0][0]"));
658 StringId arg_key1_id =
659 context_.storage->InternString(base::StringView("a[0][1]"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000660 GlobalArgsTracker::Arg arg0;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100661 arg0.flat_key = arg_flat_key_id;
662 arg0.key = arg_key0_id;
663 arg0.value = Variadic::Integer(kValues[0]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000664 GlobalArgsTracker::Arg arg1;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100665 arg1.flat_key = arg_flat_key_id;
666 arg1.key = arg_key1_id;
667 arg1.value = Variadic::Integer(kValues[1]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000668 ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000669 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100670
671 base::TempFile temp_file = base::TempFile::Create();
672 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100673 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100674
Eric Seckler7fb1d232019-10-23 14:42:43 +0100675 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100676
Eric Seckler178094e2019-10-24 14:03:04 +0100677 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100678 EXPECT_EQ(result["traceEvents"].size(), 1u);
679
680 Json::Value event = result["traceEvents"][0];
681 EXPECT_EQ(event["cat"].asString(), kCategory);
682 EXPECT_EQ(event["name"].asString(), kName);
Mikhail Khokhlovc4544ea2019-07-10 14:41:25 +0100683 EXPECT_EQ(event["args"]["a"].size(), 1u);
684 EXPECT_EQ(event["args"]["a"][0].size(), 2u);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100685 EXPECT_EQ(event["args"]["a"][0][0].asInt(), kValues[0]);
686 EXPECT_EQ(event["args"]["a"][0][1].asInt(), kValues[1]);
687}
688
Eric Seckler4b861052019-10-23 14:50:28 +0100689TEST_F(ExportJsonTest, StorageWithLegacyJsonArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100690 const char* kCategory = "cat";
691 const char* kName = "name";
692
Lalit Magantieac7fff2020-01-10 16:42:54 +0000693 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000694 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100695 context_.args_tracker->Flush(); // Flush track args.
696 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
697 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000698 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000699 {0, 0, track, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100700
Eric Seckler4b861052019-10-23 14:50:28 +0100701 StringId arg_key_id = context_.storage->InternString(base::StringView("a"));
702 StringId arg_value_id =
703 context_.storage->InternString(base::StringView("{\"b\":123}"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000704 GlobalArgsTracker::Arg arg;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100705 arg.flat_key = arg_key_id;
706 arg.key = arg_key_id;
707 arg.value = Variadic::Json(arg_value_id);
Lalit Maganti1908e262020-01-09 14:33:19 +0000708 ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000709 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100710
711 base::TempFile temp_file = base::TempFile::Create();
712 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100713 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100714
Eric Seckler7fb1d232019-10-23 14:42:43 +0100715 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100716
Eric Seckler178094e2019-10-24 14:03:04 +0100717 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100718 EXPECT_EQ(result["traceEvents"].size(), 1u);
719
720 Json::Value event = result["traceEvents"][0];
721 EXPECT_EQ(event["cat"].asString(), kCategory);
722 EXPECT_EQ(event["name"].asString(), kName);
723 EXPECT_EQ(event["args"]["a"]["b"].asInt(), 123);
724}
725
Eric Seckler4b861052019-10-23 14:50:28 +0100726TEST_F(ExportJsonTest, InstantEvent) {
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100727 const int64_t kTimestamp = 10000000;
Eric Secklerc64e19c2020-01-28 15:47:56 +0000728 const int64_t kTimestamp2 = 10001000;
729 const int64_t kTimestamp3 = 10002000;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100730 const char* kCategory = "cat";
731 const char* kName = "name";
732
Eric Secklerc64e19c2020-01-28 15:47:56 +0000733 // Global legacy track.
Eric Seckler4b861052019-10-23 14:50:28 +0100734 TrackId track =
735 context_.track_tracker->GetOrCreateLegacyChromeGlobalInstantTrack();
736 context_.args_tracker->Flush(); // Flush track args.
737 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
738 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000739 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000740 {kTimestamp, 0, track, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100741
Eric Secklerc64e19c2020-01-28 15:47:56 +0000742 // Global track.
Lalit Maganti62b741f2020-12-10 18:24:00 +0000743 TrackEventTracker track_event_tracker(&context_);
744 TrackId track2 = track_event_tracker.GetOrCreateDefaultDescriptorTrack();
Eric Secklerc64e19c2020-01-28 15:47:56 +0000745 context_.args_tracker->Flush(); // Flush track args.
746 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000747 {kTimestamp2, 0, track2, cat_id, name_id, 0, 0, 0});
Eric Secklerc64e19c2020-01-28 15:47:56 +0000748
749 // Async event track.
Lalit Maganti62b741f2020-12-10 18:24:00 +0000750 track_event_tracker.ReserveDescriptorChildTrack(1234, 0, kNullStringId);
751 TrackId track3 = *track_event_tracker.GetDescriptorTrack(1234);
Eric Secklerc64e19c2020-01-28 15:47:56 +0000752 context_.args_tracker->Flush(); // Flush track args.
753 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000754 {kTimestamp3, 0, track3, cat_id, name_id, 0, 0, 0});
Eric Secklerc64e19c2020-01-28 15:47:56 +0000755
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100756 base::TempFile temp_file = base::TempFile::Create();
757 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100758 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100759
Eric Seckler7fb1d232019-10-23 14:42:43 +0100760 EXPECT_TRUE(status.ok());
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100761
Eric Seckler178094e2019-10-24 14:03:04 +0100762 Json::Value result = ToJsonValue(ReadFile(output));
Eric Secklerc64e19c2020-01-28 15:47:56 +0000763 EXPECT_EQ(result["traceEvents"].size(), 3u);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100764
765 Json::Value event = result["traceEvents"][0];
Eric Seckler9dc34462019-11-06 14:44:20 +0000766 EXPECT_EQ(event["ph"].asString(), "I");
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100767 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
768 EXPECT_EQ(event["s"].asString(), "g");
769 EXPECT_EQ(event["cat"].asString(), kCategory);
770 EXPECT_EQ(event["name"].asString(), kName);
Eric Secklerc64e19c2020-01-28 15:47:56 +0000771
772 Json::Value event2 = result["traceEvents"][1];
773 EXPECT_EQ(event2["ph"].asString(), "I");
774 EXPECT_EQ(event2["ts"].asInt64(), kTimestamp2 / 1000);
775 EXPECT_EQ(event2["s"].asString(), "g");
776 EXPECT_EQ(event2["cat"].asString(), kCategory);
777 EXPECT_EQ(event2["name"].asString(), kName);
778
779 Json::Value event3 = result["traceEvents"][2];
780 EXPECT_EQ(event3["ph"].asString(), "n");
781 EXPECT_EQ(event3["ts"].asInt64(), kTimestamp3 / 1000);
782 EXPECT_EQ(event3["id"].asString(), "0x2");
783 EXPECT_EQ(event3["cat"].asString(), kCategory);
784 EXPECT_EQ(event3["name"].asString(), kName);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100785}
786
Eric Seckler4b861052019-10-23 14:50:28 +0100787TEST_F(ExportJsonTest, InstantEventOnThread) {
788 const int64_t kTimestamp = 10000000;
Eric Secklerbb0e1542020-01-16 13:44:13 +0000789 const uint32_t kThreadID = 100;
Eric Seckler4b861052019-10-23 14:50:28 +0100790 const char* kCategory = "cat";
791 const char* kName = "name";
792
Lalit Magantieac7fff2020-01-10 16:42:54 +0000793 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000794 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100795 context_.args_tracker->Flush(); // Flush track args.
796 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
797 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000798 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000799 {kTimestamp, 0, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100800
801 base::TempFile temp_file = base::TempFile::Create();
802 FILE* output = fopen(temp_file.path().c_str(), "w+");
803 util::Status status = ExportJson(context_.storage.get(), output);
804
805 EXPECT_TRUE(status.ok());
806
Eric Seckler178094e2019-10-24 14:03:04 +0100807 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler4b861052019-10-23 14:50:28 +0100808 EXPECT_EQ(result["traceEvents"].size(), 1u);
809
810 Json::Value event = result["traceEvents"][0];
Eric Seckler88cab6f2020-01-16 18:33:45 +0000811 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Eric Seckler9dc34462019-11-06 14:44:20 +0000812 EXPECT_EQ(event["ph"].asString(), "I");
Eric Seckler4b861052019-10-23 14:50:28 +0100813 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
814 EXPECT_EQ(event["s"].asString(), "t");
815 EXPECT_EQ(event["cat"].asString(), kCategory);
816 EXPECT_EQ(event["name"].asString(), kName);
817}
818
Eric Secklerbb0e1542020-01-16 13:44:13 +0000819TEST_F(ExportJsonTest, DuplicatePidAndTid) {
820 UniqueTid upid1 = context_.process_tracker->StartNewProcess(
821 base::nullopt, base::nullopt, 1, kNullStringId);
822 UniqueTid utid1a = context_.process_tracker->UpdateThread(1, 1);
823 UniqueTid utid1b = context_.process_tracker->UpdateThread(2, 1);
Mikhail Khokhlov567c0042020-07-17 17:42:44 +0100824 UniqueTid utid1c = context_.process_tracker->StartNewThread(base::nullopt, 2);
Eric Secklerbb0e1542020-01-16 13:44:13 +0000825 // Associate the new thread with its process.
826 ASSERT_EQ(utid1c, context_.process_tracker->UpdateThread(2, 1));
827
828 UniqueTid upid2 = context_.process_tracker->StartNewProcess(
829 base::nullopt, base::nullopt, 1, kNullStringId);
830 UniqueTid utid2a = context_.process_tracker->UpdateThread(1, 1);
831 UniqueTid utid2b = context_.process_tracker->UpdateThread(2, 1);
832
833 ASSERT_NE(upid1, upid2);
834 ASSERT_NE(utid1b, utid1c);
835 ASSERT_NE(utid1a, utid2a);
836 ASSERT_NE(utid1b, utid2b);
837 ASSERT_NE(utid1c, utid2b);
838
839 ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1a]);
840 ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1b]);
841 ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1c]);
842 ASSERT_EQ(upid2, *context_.storage->thread_table().upid()[utid2a]);
843 ASSERT_EQ(upid2, *context_.storage->thread_table().upid()[utid2b]);
844
845 TrackId track1a = context_.track_tracker->InternThreadTrack(utid1a);
846 TrackId track1b = context_.track_tracker->InternThreadTrack(utid1b);
847 TrackId track1c = context_.track_tracker->InternThreadTrack(utid1c);
848 TrackId track2a = context_.track_tracker->InternThreadTrack(utid2a);
849 TrackId track2b = context_.track_tracker->InternThreadTrack(utid2b);
850 context_.args_tracker->Flush(); // Flush track args.
851
852 StringId cat_id = context_.storage->InternString(base::StringView("cat"));
853 StringId name1a_id =
854 context_.storage->InternString(base::StringView("name1a"));
855 StringId name1b_id =
856 context_.storage->InternString(base::StringView("name1b"));
857 StringId name1c_id =
858 context_.storage->InternString(base::StringView("name1c"));
859 StringId name2a_id =
860 context_.storage->InternString(base::StringView("name2a"));
861 StringId name2b_id =
862 context_.storage->InternString(base::StringView("name2b"));
863
864 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000865 {10000, 0, track1a, cat_id, name1a_id, 0, 0, 0});
Eric Secklerbb0e1542020-01-16 13:44:13 +0000866 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000867 {20000, 1000, track1b, cat_id, name1b_id, 0, 0, 0});
Eric Secklerbb0e1542020-01-16 13:44:13 +0000868 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000869 {30000, 0, track1c, cat_id, name1c_id, 0, 0, 0});
Eric Secklerbb0e1542020-01-16 13:44:13 +0000870 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000871 {40000, 0, track2a, cat_id, name2a_id, 0, 0, 0});
Eric Secklerbb0e1542020-01-16 13:44:13 +0000872 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000873 {50000, 1000, track2b, cat_id, name2b_id, 0, 0, 0});
Eric Secklerbb0e1542020-01-16 13:44:13 +0000874
875 base::TempFile temp_file = base::TempFile::Create();
876 FILE* output = fopen(temp_file.path().c_str(), "w+");
877 util::Status status = ExportJson(context_.storage.get(), output);
878
879 EXPECT_TRUE(status.ok());
880
881 Json::Value result = ToJsonValue(ReadFile(output));
882 EXPECT_EQ(result["traceEvents"].size(), 5u);
883
Eric Seckler88cab6f2020-01-16 18:33:45 +0000884 EXPECT_EQ(result["traceEvents"][0]["pid"].asInt(), 1);
885 EXPECT_EQ(result["traceEvents"][0]["tid"].asInt(), 1);
Eric Secklerbb0e1542020-01-16 13:44:13 +0000886 EXPECT_EQ(result["traceEvents"][0]["ph"].asString(), "I");
887 EXPECT_EQ(result["traceEvents"][0]["ts"].asInt64(), 10);
888 EXPECT_EQ(result["traceEvents"][0]["cat"].asString(), "cat");
889 EXPECT_EQ(result["traceEvents"][0]["name"].asString(), "name1a");
890
Eric Seckler88cab6f2020-01-16 18:33:45 +0000891 EXPECT_EQ(result["traceEvents"][1]["pid"].asInt(), 1);
892 EXPECT_EQ(result["traceEvents"][1]["tid"].asInt(), 2);
Eric Secklerbb0e1542020-01-16 13:44:13 +0000893 EXPECT_EQ(result["traceEvents"][1]["ph"].asString(), "X");
894 EXPECT_EQ(result["traceEvents"][1]["ts"].asInt64(), 20);
895 EXPECT_EQ(result["traceEvents"][1]["dur"].asInt64(), 1);
896 EXPECT_EQ(result["traceEvents"][1]["cat"].asString(), "cat");
897 EXPECT_EQ(result["traceEvents"][1]["name"].asString(), "name1b");
898
Eric Seckler88cab6f2020-01-16 18:33:45 +0000899 EXPECT_EQ(result["traceEvents"][2]["pid"].asInt(), 1);
900 EXPECT_EQ(result["traceEvents"][2]["tid"].asInt(),
901 static_cast<int>(std::numeric_limits<uint32_t>::max() - 1u));
Eric Secklerbb0e1542020-01-16 13:44:13 +0000902 EXPECT_EQ(result["traceEvents"][2]["ph"].asString(), "I");
903 EXPECT_EQ(result["traceEvents"][2]["ts"].asInt64(), 30);
904 EXPECT_EQ(result["traceEvents"][2]["cat"].asString(), "cat");
905 EXPECT_EQ(result["traceEvents"][2]["name"].asString(), "name1c");
906
Eric Seckler88cab6f2020-01-16 18:33:45 +0000907 EXPECT_EQ(result["traceEvents"][3]["pid"].asInt(),
908 static_cast<int>(std::numeric_limits<uint32_t>::max()));
909 EXPECT_EQ(result["traceEvents"][3]["tid"].asInt(), 1);
Eric Secklerbb0e1542020-01-16 13:44:13 +0000910 EXPECT_EQ(result["traceEvents"][3]["ph"].asString(), "I");
911 EXPECT_EQ(result["traceEvents"][3]["ts"].asInt64(), 40);
912 EXPECT_EQ(result["traceEvents"][3]["cat"].asString(), "cat");
913 EXPECT_EQ(result["traceEvents"][3]["name"].asString(), "name2a");
914
Eric Seckler88cab6f2020-01-16 18:33:45 +0000915 EXPECT_EQ(result["traceEvents"][4]["pid"].asInt(),
916 static_cast<int>(std::numeric_limits<uint32_t>::max()));
917 EXPECT_EQ(result["traceEvents"][4]["tid"].asInt(), 2);
Eric Secklerbb0e1542020-01-16 13:44:13 +0000918 EXPECT_EQ(result["traceEvents"][4]["ph"].asString(), "X");
919 EXPECT_EQ(result["traceEvents"][4]["ts"].asInt64(), 50);
920 EXPECT_EQ(result["traceEvents"][1]["dur"].asInt64(), 1);
921 EXPECT_EQ(result["traceEvents"][4]["cat"].asString(), "cat");
922 EXPECT_EQ(result["traceEvents"][4]["name"].asString(), "name2b");
923}
924
Eric Seckler5f2907d2020-01-06 14:44:05 +0000925TEST_F(ExportJsonTest, AsyncEvents) {
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100926 const int64_t kTimestamp = 10000000;
927 const int64_t kDuration = 100000;
Eric Seckler37d69c12020-01-22 13:59:54 +0000928 const int64_t kTimestamp3 = 10005000;
929 const int64_t kDuration3 = 100000;
Eric Secklerbb0e1542020-01-16 13:44:13 +0000930 const uint32_t kProcessID = 100;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100931 const char* kCategory = "cat";
932 const char* kName = "name";
Eric Seckler5f2907d2020-01-06 14:44:05 +0000933 const char* kName2 = "name2";
Eric Seckler37d69c12020-01-22 13:59:54 +0000934 const char* kName3 = "name3";
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100935 const char* kArgName = "arg_name";
936 const int kArgValue = 123;
937
Lalit Magantieac7fff2020-01-10 16:42:54 +0000938 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +0100939 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
940 StringId name_id = context_.storage->InternString(base::StringView(kName));
Eric Seckler5f2907d2020-01-06 14:44:05 +0000941 StringId name2_id = context_.storage->InternString(base::StringView(kName2));
Eric Seckler37d69c12020-01-22 13:59:54 +0000942 StringId name3_id = context_.storage->InternString(base::StringView(kName3));
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100943
Eric Seckler4b861052019-10-23 14:50:28 +0100944 constexpr int64_t kSourceId = 235;
945 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
946 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
Lalit Magantif0599a02020-01-15 15:45:20 +0000947 /*source_scope=*/kNullStringId);
Eric Seckler37d69c12020-01-22 13:59:54 +0000948 constexpr int64_t kSourceId2 = 236;
949 TrackId track2 = context_.track_tracker->InternLegacyChromeAsyncTrack(
950 name3_id, upid, kSourceId2, /*source_id_is_process_scoped=*/true,
951 /*source_scope=*/kNullStringId);
Eric Seckler4b861052019-10-23 14:50:28 +0100952 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100953
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000954 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000955 {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100956 StringId arg_key_id =
957 context_.storage->InternString(base::StringView(kArgName));
Lalit Maganti1908e262020-01-09 14:33:19 +0000958 GlobalArgsTracker::Arg arg;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100959 arg.flat_key = arg_key_id;
960 arg.key = arg_key_id;
961 arg.value = Variadic::Integer(kArgValue);
Lalit Maganti1908e262020-01-09 14:33:19 +0000962 ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000963 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100964
Eric Seckler5f2907d2020-01-06 14:44:05 +0000965 // Child event with same timestamps as first one.
966 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000967 {kTimestamp, kDuration, track, cat_id, name2_id, 0, 0, 0});
Eric Seckler5f2907d2020-01-06 14:44:05 +0000968
Eric Seckler37d69c12020-01-22 13:59:54 +0000969 // Another overlapping async event on a different track.
970 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000971 {kTimestamp3, kDuration3, track2, cat_id, name3_id, 0, 0, 0});
Eric Seckler37d69c12020-01-22 13:59:54 +0000972
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100973 base::TempFile temp_file = base::TempFile::Create();
974 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100975 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100976
Eric Seckler7fb1d232019-10-23 14:42:43 +0100977 EXPECT_TRUE(status.ok());
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100978
Eric Seckler178094e2019-10-24 14:03:04 +0100979 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler37d69c12020-01-22 13:59:54 +0000980 EXPECT_EQ(result["traceEvents"].size(), 6u);
981
982 // Events should be sorted by timestamp, with child slice's end before its
983 // parent.
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100984
Eric Seckler5f2907d2020-01-06 14:44:05 +0000985 Json::Value begin_event1 = result["traceEvents"][0];
986 EXPECT_EQ(begin_event1["ph"].asString(), "b");
987 EXPECT_EQ(begin_event1["ts"].asInt64(), kTimestamp / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +0000988 EXPECT_EQ(begin_event1["pid"].asInt(), static_cast<int>(kProcessID));
Eric Seckler5f2907d2020-01-06 14:44:05 +0000989 EXPECT_EQ(begin_event1["id2"]["local"].asString(), "0xeb");
990 EXPECT_EQ(begin_event1["cat"].asString(), kCategory);
991 EXPECT_EQ(begin_event1["name"].asString(), kName);
992 EXPECT_EQ(begin_event1["args"][kArgName].asInt(), kArgValue);
993 EXPECT_FALSE(begin_event1.isMember("tts"));
994 EXPECT_FALSE(begin_event1.isMember("use_async_tts"));
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100995
Eric Seckler5f2907d2020-01-06 14:44:05 +0000996 Json::Value begin_event2 = result["traceEvents"][1];
997 EXPECT_EQ(begin_event2["ph"].asString(), "b");
998 EXPECT_EQ(begin_event2["ts"].asInt64(), kTimestamp / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +0000999 EXPECT_EQ(begin_event2["pid"].asInt(), static_cast<int>(kProcessID));
Eric Seckler5f2907d2020-01-06 14:44:05 +00001000 EXPECT_EQ(begin_event2["id2"]["local"].asString(), "0xeb");
1001 EXPECT_EQ(begin_event2["cat"].asString(), kCategory);
1002 EXPECT_EQ(begin_event2["name"].asString(), kName2);
1003 EXPECT_TRUE(begin_event2["args"].isObject());
1004 EXPECT_EQ(begin_event2["args"].size(), 0u);
1005 EXPECT_FALSE(begin_event2.isMember("tts"));
1006 EXPECT_FALSE(begin_event2.isMember("use_async_tts"));
1007
Eric Seckler37d69c12020-01-22 13:59:54 +00001008 Json::Value begin_event3 = result["traceEvents"][2];
1009 EXPECT_EQ(begin_event3["ph"].asString(), "b");
1010 EXPECT_EQ(begin_event3["ts"].asInt64(), kTimestamp3 / 1000);
1011 EXPECT_EQ(begin_event3["pid"].asInt(), static_cast<int>(kProcessID));
1012 EXPECT_EQ(begin_event3["id2"]["local"].asString(), "0xec");
1013 EXPECT_EQ(begin_event3["cat"].asString(), kCategory);
1014 EXPECT_EQ(begin_event3["name"].asString(), kName3);
1015 EXPECT_TRUE(begin_event3["args"].isObject());
1016 EXPECT_EQ(begin_event3["args"].size(), 0u);
1017 EXPECT_FALSE(begin_event3.isMember("tts"));
1018 EXPECT_FALSE(begin_event3.isMember("use_async_tts"));
1019
Eric Seckler5f2907d2020-01-06 14:44:05 +00001020 Json::Value end_event2 = result["traceEvents"][3];
1021 EXPECT_EQ(end_event2["ph"].asString(), "e");
1022 EXPECT_EQ(end_event2["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001023 EXPECT_EQ(end_event2["pid"].asInt(), static_cast<int>(kProcessID));
Eric Seckler5f2907d2020-01-06 14:44:05 +00001024 EXPECT_EQ(end_event2["id2"]["local"].asString(), "0xeb");
1025 EXPECT_EQ(end_event2["cat"].asString(), kCategory);
Eric Seckler37d69c12020-01-22 13:59:54 +00001026 EXPECT_EQ(end_event2["name"].asString(), kName2);
Eric Seckler5f2907d2020-01-06 14:44:05 +00001027 EXPECT_TRUE(end_event2["args"].isObject());
1028 EXPECT_EQ(end_event2["args"].size(), 0u);
1029 EXPECT_FALSE(end_event2.isMember("tts"));
1030 EXPECT_FALSE(end_event2.isMember("use_async_tts"));
1031
Eric Seckler37d69c12020-01-22 13:59:54 +00001032 Json::Value end_event1 = result["traceEvents"][4];
Eric Seckler5f2907d2020-01-06 14:44:05 +00001033 EXPECT_EQ(end_event1["ph"].asString(), "e");
1034 EXPECT_EQ(end_event1["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001035 EXPECT_EQ(end_event1["pid"].asInt(), static_cast<int>(kProcessID));
Eric Seckler5f2907d2020-01-06 14:44:05 +00001036 EXPECT_EQ(end_event1["id2"]["local"].asString(), "0xeb");
1037 EXPECT_EQ(end_event1["cat"].asString(), kCategory);
1038 EXPECT_EQ(end_event1["name"].asString(), kName);
1039 EXPECT_TRUE(end_event1["args"].isObject());
1040 EXPECT_EQ(end_event1["args"].size(), 0u);
1041 EXPECT_FALSE(end_event1.isMember("tts"));
1042 EXPECT_FALSE(end_event1.isMember("use_async_tts"));
Eric Seckler37d69c12020-01-22 13:59:54 +00001043
1044 Json::Value end_event3 = result["traceEvents"][5];
1045 EXPECT_EQ(end_event3["ph"].asString(), "e");
1046 EXPECT_EQ(end_event3["ts"].asInt64(), (kTimestamp3 + kDuration3) / 1000);
1047 EXPECT_EQ(end_event3["pid"].asInt(), static_cast<int>(kProcessID));
1048 EXPECT_EQ(end_event3["id2"]["local"].asString(), "0xec");
1049 EXPECT_EQ(end_event3["cat"].asString(), kCategory);
1050 EXPECT_EQ(end_event3["name"].asString(), kName3);
1051 EXPECT_TRUE(end_event3["args"].isObject());
1052 EXPECT_EQ(end_event3["args"].size(), 0u);
1053 EXPECT_FALSE(end_event3.isMember("tts"));
1054 EXPECT_FALSE(end_event3.isMember("use_async_tts"));
Eric Secklerc63a3af2019-07-25 11:17:37 +01001055}
1056
Eric Seckler4b861052019-10-23 14:50:28 +01001057TEST_F(ExportJsonTest, AsyncEventWithThreadTimestamp) {
Eric Secklerc63a3af2019-07-25 11:17:37 +01001058 const int64_t kTimestamp = 10000000;
1059 const int64_t kDuration = 100000;
1060 const int64_t kThreadTimestamp = 10000001;
1061 const int64_t kThreadDuration = 99998;
Eric Secklerbb0e1542020-01-16 13:44:13 +00001062 const uint32_t kProcessID = 100;
Eric Secklerc63a3af2019-07-25 11:17:37 +01001063 const char* kCategory = "cat";
1064 const char* kName = "name";
1065
Lalit Magantieac7fff2020-01-10 16:42:54 +00001066 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +01001067 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
1068 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001069
Eric Seckler4b861052019-10-23 14:50:28 +01001070 constexpr int64_t kSourceId = 235;
1071 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
1072 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
Lalit Magantif0599a02020-01-15 15:45:20 +00001073 /*source_scope=*/kNullStringId);
Eric Seckler4b861052019-10-23 14:50:28 +01001074 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001075
Lalit Maganti8d770f72020-01-30 15:44:04 +00001076 auto* slices = context_.storage->mutable_slice_table();
1077 auto id_and_row =
1078 slices->Insert({kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +01001079 context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice(
Lalit Maganti8d770f72020-01-30 15:44:04 +00001080 id_and_row.id.value, kThreadTimestamp, kThreadDuration, 0, 0);
Eric Secklerc63a3af2019-07-25 11:17:37 +01001081
1082 base::TempFile temp_file = base::TempFile::Create();
1083 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +01001084 util::Status status = ExportJson(context_.storage.get(), output);
Eric Secklerc63a3af2019-07-25 11:17:37 +01001085
Eric Seckler7fb1d232019-10-23 14:42:43 +01001086 EXPECT_TRUE(status.ok());
Eric Secklerc63a3af2019-07-25 11:17:37 +01001087
Eric Seckler178094e2019-10-24 14:03:04 +01001088 Json::Value result = ToJsonValue(ReadFile(output));
Eric Secklerc63a3af2019-07-25 11:17:37 +01001089 EXPECT_EQ(result["traceEvents"].size(), 2u);
1090
1091 Json::Value begin_event = result["traceEvents"][0];
1092 EXPECT_EQ(begin_event["ph"].asString(), "b");
1093 EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
1094 EXPECT_EQ(begin_event["tts"].asInt64(), kThreadTimestamp / 1000);
1095 EXPECT_EQ(begin_event["use_async_tts"].asInt(), 1);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001096 EXPECT_EQ(begin_event["pid"].asInt(), static_cast<int>(kProcessID));
Eric Secklerf91236e2019-11-04 10:25:45 +00001097 EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
Eric Secklerc63a3af2019-07-25 11:17:37 +01001098 EXPECT_EQ(begin_event["cat"].asString(), kCategory);
1099 EXPECT_EQ(begin_event["name"].asString(), kName);
1100
1101 Json::Value end_event = result["traceEvents"][1];
1102 EXPECT_EQ(end_event["ph"].asString(), "e");
1103 EXPECT_EQ(end_event["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
1104 EXPECT_EQ(end_event["tts"].asInt64(),
1105 (kThreadTimestamp + kThreadDuration) / 1000);
1106 EXPECT_EQ(end_event["use_async_tts"].asInt(), 1);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001107 EXPECT_EQ(end_event["pid"].asInt(), static_cast<int>(kProcessID));
Eric Secklerf91236e2019-11-04 10:25:45 +00001108 EXPECT_EQ(end_event["id2"]["local"].asString(), "0xeb");
Eric Secklerc63a3af2019-07-25 11:17:37 +01001109 EXPECT_EQ(end_event["cat"].asString(), kCategory);
1110 EXPECT_EQ(end_event["name"].asString(), kName);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001111}
1112
Eric Seckler4b861052019-10-23 14:50:28 +01001113TEST_F(ExportJsonTest, UnfinishedAsyncEvent) {
Eric Seckler206db472019-07-25 12:05:27 +01001114 const int64_t kTimestamp = 10000000;
1115 const int64_t kDuration = -1;
1116 const int64_t kThreadTimestamp = 10000001;
1117 const int64_t kThreadDuration = -1;
Eric Secklerbb0e1542020-01-16 13:44:13 +00001118 const uint32_t kProcessID = 100;
Eric Seckler206db472019-07-25 12:05:27 +01001119 const char* kCategory = "cat";
1120 const char* kName = "name";
1121
Lalit Magantieac7fff2020-01-10 16:42:54 +00001122 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +01001123 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
1124 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001125
Eric Seckler4b861052019-10-23 14:50:28 +01001126 constexpr int64_t kSourceId = 235;
1127 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
1128 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
Lalit Magantif0599a02020-01-15 15:45:20 +00001129 /*source_scope=*/kNullStringId);
Eric Seckler4b861052019-10-23 14:50:28 +01001130 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001131
Lalit Maganti8d770f72020-01-30 15:44:04 +00001132 auto slice_id =
1133 context_.storage->mutable_slice_table()
1134 ->Insert({kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0})
1135 .id;
Eric Seckler4b861052019-10-23 14:50:28 +01001136 context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice(
Lalit Magantib0e11f62020-01-02 14:17:58 +00001137 slice_id.value, kThreadTimestamp, kThreadDuration, 0, 0);
Eric Seckler206db472019-07-25 12:05:27 +01001138
1139 base::TempFile temp_file = base::TempFile::Create();
1140 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +01001141 util::Status status = ExportJson(context_.storage.get(), output);
Eric Seckler206db472019-07-25 12:05:27 +01001142
Eric Seckler7fb1d232019-10-23 14:42:43 +01001143 EXPECT_TRUE(status.ok());
Eric Seckler206db472019-07-25 12:05:27 +01001144
Eric Seckler178094e2019-10-24 14:03:04 +01001145 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler206db472019-07-25 12:05:27 +01001146 EXPECT_EQ(result["traceEvents"].size(), 1u);
1147
1148 Json::Value begin_event = result["traceEvents"][0];
1149 EXPECT_EQ(begin_event["ph"].asString(), "b");
1150 EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
1151 EXPECT_EQ(begin_event["tts"].asInt64(), kThreadTimestamp / 1000);
1152 EXPECT_EQ(begin_event["use_async_tts"].asInt(), 1);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001153 EXPECT_EQ(begin_event["pid"].asInt(), static_cast<int>(kProcessID));
Eric Secklerf91236e2019-11-04 10:25:45 +00001154 EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
Eric Seckler206db472019-07-25 12:05:27 +01001155 EXPECT_EQ(begin_event["cat"].asString(), kCategory);
1156 EXPECT_EQ(begin_event["name"].asString(), kName);
1157}
1158
Eric Seckler4b861052019-10-23 14:50:28 +01001159TEST_F(ExportJsonTest, AsyncInstantEvent) {
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001160 const int64_t kTimestamp = 10000000;
Eric Secklerbb0e1542020-01-16 13:44:13 +00001161 const uint32_t kProcessID = 100;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001162 const char* kCategory = "cat";
1163 const char* kName = "name";
1164 const char* kArgName = "arg_name";
1165 const int kArgValue = 123;
1166
Lalit Magantieac7fff2020-01-10 16:42:54 +00001167 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +01001168 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
1169 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001170
Eric Seckler4b861052019-10-23 14:50:28 +01001171 constexpr int64_t kSourceId = 235;
1172 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
1173 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
Lalit Magantif0599a02020-01-15 15:45:20 +00001174 /*source_scope=*/kNullStringId);
Eric Seckler4b861052019-10-23 14:50:28 +01001175 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001176
Lalit Maganti1308e3f2019-12-09 20:24:20 +00001177 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +00001178 {kTimestamp, 0, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +01001179 StringId arg_key_id =
1180 context_.storage->InternString(base::StringView("arg_name"));
Lalit Maganti1908e262020-01-09 14:33:19 +00001181 GlobalArgsTracker::Arg arg;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001182 arg.flat_key = arg_key_id;
1183 arg.key = arg_key_id;
1184 arg.value = Variadic::Integer(kArgValue);
Lalit Maganti1908e262020-01-09 14:33:19 +00001185 ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
Lalit Maganti1308e3f2019-12-09 20:24:20 +00001186 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001187
1188 base::TempFile temp_file = base::TempFile::Create();
1189 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +01001190 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001191
Eric Seckler7fb1d232019-10-23 14:42:43 +01001192 EXPECT_TRUE(status.ok());
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001193
Eric Seckler178094e2019-10-24 14:03:04 +01001194 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001195 EXPECT_EQ(result["traceEvents"].size(), 1u);
1196
1197 Json::Value event = result["traceEvents"][0];
1198 EXPECT_EQ(event["ph"].asString(), "n");
1199 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001200 EXPECT_EQ(event["pid"].asInt(), static_cast<int>(kProcessID));
Eric Secklerf91236e2019-11-04 10:25:45 +00001201 EXPECT_EQ(event["id2"]["local"].asString(), "0xeb");
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001202 EXPECT_EQ(event["cat"].asString(), kCategory);
1203 EXPECT_EQ(event["name"].asString(), kName);
1204 EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
1205}
1206
Eric Seckler4b861052019-10-23 14:50:28 +01001207TEST_F(ExportJsonTest, RawEvent) {
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001208 const int64_t kTimestamp = 10000000;
1209 const int64_t kDuration = 10000;
1210 const int64_t kThreadTimestamp = 20000000;
1211 const int64_t kThreadDuration = 20000;
1212 const int64_t kThreadInstructionCount = 30000000;
1213 const int64_t kThreadInstructionDelta = 30000;
Eric Secklerbb0e1542020-01-16 13:44:13 +00001214 const uint32_t kProcessID = 100;
1215 const uint32_t kThreadID = 200;
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001216 const char* kCategory = "cat";
1217 const char* kName = "name";
1218 const char* kPhase = "?";
1219 const uint64_t kGlobalId = 0xaaffaaffaaffaaff;
1220 const char* kIdScope = "my_id";
1221 const uint64_t kBindId = 0xaa00aa00aa00aa00;
1222 const char* kFlowDirection = "inout";
1223 const char* kArgName = "arg_name";
1224 const int kArgValue = 123;
1225
Eric Seckler4b861052019-10-23 14:50:28 +01001226 TraceStorage* storage = context_.storage.get();
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001227
Lalit Magantieac7fff2020-01-10 16:42:54 +00001228 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
1229 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
1230 context_.storage->mutable_thread_table()->mutable_upid()->Set(utid, upid);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001231
Lalit Maganti8d770f72020-01-30 15:44:04 +00001232 auto id_and_row = storage->mutable_raw_table()->Insert(
Lalit Maganti679b29d2020-01-13 13:26:28 +00001233 {kTimestamp, storage->InternString("track_event.legacy_event"), /*cpu=*/0,
1234 utid});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001235 auto inserter = context_.args_tracker->AddArgsTo(id_and_row.id);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001236
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001237 auto add_arg = [&](const char* key, Variadic value) {
1238 StringId key_id = storage->InternString(key);
Lalit Maganti5228f362020-01-15 13:45:56 +00001239 inserter.AddArg(key_id, value);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001240 };
1241
1242 StringId cat_id = storage->InternString(base::StringView(kCategory));
1243 add_arg("legacy_event.category", Variadic::String(cat_id));
1244 StringId name_id = storage->InternString(base::StringView(kName));
1245 add_arg("legacy_event.name", Variadic::String(name_id));
1246 StringId phase_id = storage->InternString(base::StringView(kPhase));
1247 add_arg("legacy_event.phase", Variadic::String(phase_id));
1248
1249 add_arg("legacy_event.duration_ns", Variadic::Integer(kDuration));
1250 add_arg("legacy_event.thread_timestamp_ns",
1251 Variadic::Integer(kThreadTimestamp));
1252 add_arg("legacy_event.thread_duration_ns",
1253 Variadic::Integer(kThreadDuration));
1254 add_arg("legacy_event.thread_instruction_count",
1255 Variadic::Integer(kThreadInstructionCount));
1256 add_arg("legacy_event.thread_instruction_delta",
1257 Variadic::Integer(kThreadInstructionDelta));
1258 add_arg("legacy_event.use_async_tts", Variadic::Boolean(true));
1259 add_arg("legacy_event.global_id", Variadic::UnsignedInteger(kGlobalId));
1260 StringId scope_id = storage->InternString(base::StringView(kIdScope));
1261 add_arg("legacy_event.id_scope", Variadic::String(scope_id));
1262 add_arg("legacy_event.bind_id", Variadic::UnsignedInteger(kBindId));
1263 add_arg("legacy_event.bind_to_enclosing", Variadic::Boolean(true));
1264 StringId flow_direction_id = storage->InternString(kFlowDirection);
1265 add_arg("legacy_event.flow_direction", Variadic::String(flow_direction_id));
1266
1267 add_arg(kArgName, Variadic::Integer(kArgValue));
1268
Eric Seckler4b861052019-10-23 14:50:28 +01001269 context_.args_tracker->Flush();
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001270
1271 base::TempFile temp_file = base::TempFile::Create();
1272 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +01001273 util::Status status = ExportJson(storage, output);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001274
Eric Seckler7fb1d232019-10-23 14:42:43 +01001275 EXPECT_TRUE(status.ok());
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001276
Eric Seckler178094e2019-10-24 14:03:04 +01001277 Json::Value result = ToJsonValue(ReadFile(output));
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001278 EXPECT_EQ(result["traceEvents"].size(), 1u);
1279
1280 Json::Value event = result["traceEvents"][0];
1281 EXPECT_EQ(event["ph"].asString(), kPhase);
1282 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
1283 EXPECT_EQ(event["dur"].asInt64(), kDuration / 1000);
1284 EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
1285 EXPECT_EQ(event["tdur"].asInt64(), kThreadDuration / 1000);
1286 EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
1287 EXPECT_EQ(event["tidelta"].asInt64(), kThreadInstructionDelta);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001288 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001289 EXPECT_EQ(event["cat"].asString(), kCategory);
1290 EXPECT_EQ(event["name"].asString(), kName);
1291 EXPECT_EQ(event["use_async_tts"].asInt(), 1);
1292 EXPECT_EQ(event["id2"]["global"].asString(), "0xaaffaaffaaffaaff");
1293 EXPECT_EQ(event["scope"].asString(), kIdScope);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001294 EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
1295}
1296
Eric Seckler4b861052019-10-23 14:50:28 +01001297TEST_F(ExportJsonTest, LegacyRawEvents) {
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001298 const char* kLegacyFtraceData = "some \"data\"\nsome :data:";
Eric Seckler13b84b32019-10-04 12:00:38 +01001299 const char* kLegacyJsonData1 = "{\"us";
Eric Seckler178094e2019-10-24 14:03:04 +01001300 const char* kLegacyJsonData2 = "er\": 1},{\"user\": 2}";
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001301
Eric Seckler4b861052019-10-23 14:50:28 +01001302 TraceStorage* storage = context_.storage.get();
Lalit Maganti8d770f72020-01-30 15:44:04 +00001303 auto* raw = storage->mutable_raw_table();
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001304
Lalit Maganti8d770f72020-01-30 15:44:04 +00001305 auto id_and_row = raw->Insert(
Lalit Maganti679b29d2020-01-13 13:26:28 +00001306 {0, storage->InternString("chrome_event.legacy_system_trace"), 0, 0});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001307 auto inserter = context_.args_tracker->AddArgsTo(id_and_row.id);
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001308
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001309 StringId data_id = storage->InternString("data");
1310 StringId ftrace_data_id = storage->InternString(kLegacyFtraceData);
Lalit Maganti5228f362020-01-15 13:45:56 +00001311 inserter.AddArg(data_id, Variadic::String(ftrace_data_id));
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001312
Lalit Maganti8d770f72020-01-30 15:44:04 +00001313 id_and_row = raw->Insert(
Lalit Maganti679b29d2020-01-13 13:26:28 +00001314 {0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001315 inserter = context_.args_tracker->AddArgsTo(id_and_row.id);
Eric Seckler13b84b32019-10-04 12:00:38 +01001316 StringId json_data1_id = storage->InternString(kLegacyJsonData1);
Lalit Maganti5228f362020-01-15 13:45:56 +00001317 inserter.AddArg(data_id, Variadic::String(json_data1_id));
Eric Seckler13b84b32019-10-04 12:00:38 +01001318
Lalit Maganti8d770f72020-01-30 15:44:04 +00001319 id_and_row = raw->Insert(
Lalit Maganti679b29d2020-01-13 13:26:28 +00001320 {0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001321 inserter = context_.args_tracker->AddArgsTo(id_and_row.id);
Eric Seckler13b84b32019-10-04 12:00:38 +01001322 StringId json_data2_id = storage->InternString(kLegacyJsonData2);
Lalit Maganti5228f362020-01-15 13:45:56 +00001323 inserter.AddArg(data_id, Variadic::String(json_data2_id));
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001324
Eric Seckler4b861052019-10-23 14:50:28 +01001325 context_.args_tracker->Flush();
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001326
1327 base::TempFile temp_file = base::TempFile::Create();
1328 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +01001329 util::Status status = ExportJson(storage, output);
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001330
Eric Seckler7fb1d232019-10-23 14:42:43 +01001331 EXPECT_TRUE(status.ok());
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001332
Eric Seckler178094e2019-10-24 14:03:04 +01001333 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001334
Eric Seckler178094e2019-10-24 14:03:04 +01001335 EXPECT_EQ(result["traceEvents"].size(), 2u);
1336 EXPECT_EQ(result["traceEvents"][0]["user"].asInt(), 1);
1337 EXPECT_EQ(result["traceEvents"][1]["user"].asInt(), 2);
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001338 EXPECT_EQ(result["systemTraceEvents"].asString(), kLegacyFtraceData);
1339}
1340
Eric Seckler4b861052019-10-23 14:50:28 +01001341TEST_F(ExportJsonTest, CpuProfileEvent) {
Eric Secklerbb0e1542020-01-16 13:44:13 +00001342 const uint32_t kProcessID = 100;
1343 const uint32_t kThreadID = 200;
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001344 const int64_t kTimestamp = 10000000;
Oystein Eftevaag95fe09e2020-04-17 12:55:17 -07001345 const int32_t kProcessPriority = 42;
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001346
Eric Seckler4b861052019-10-23 14:50:28 +01001347 TraceStorage* storage = context_.storage.get();
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001348
Lalit Magantieac7fff2020-01-10 16:42:54 +00001349 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
1350 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
1351 context_.storage->mutable_thread_table()->mutable_upid()->Set(utid, upid);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001352
Lalit Maganti8d770f72020-01-30 15:44:04 +00001353 auto* mappings = storage->mutable_stack_profile_mapping_table();
1354 auto* frames = storage->mutable_stack_profile_frame_table();
1355 auto* callsites = storage->mutable_stack_profile_callsite_table();
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001356
Lalit Maganti8d770f72020-01-30 15:44:04 +00001357 auto module_1 =
1358 mappings->Insert({storage->InternString("foo_module_id"), 0, 0, 0, 0, 0,
1359 storage->InternString("foo_module_name")});
1360
1361 auto module_2 =
1362 mappings->Insert({storage->InternString("bar_module_id"), 0, 0, 0, 0, 0,
1363 storage->InternString("bar_module_name")});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001364
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001365 // TODO(140860736): Once we support null values for
1366 // stack_profile_frame.symbol_set_id remove this hack
Lalit Magantif0599a02020-01-15 15:45:20 +00001367 storage->mutable_symbol_table()->Insert({0, kNullStringId, kNullStringId, 0});
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001368
Lalit Maganti8d770f72020-01-30 15:44:04 +00001369 auto frame_1 = frames->Insert({/*name_id=*/kNullStringId, module_1.id, 0x42});
Lalit Maganti0a29f6f2020-01-06 12:01:14 +00001370
Lalit Maganti7e24f062019-12-17 18:10:35 +00001371 uint32_t symbol_set_id = storage->symbol_table().row_count();
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001372 storage->mutable_symbol_table()->Insert(
1373 {symbol_set_id, storage->InternString("foo_func"),
1374 storage->InternString("foo_file"), 66});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001375 frames->mutable_symbol_set_id()->Set(frame_1.row, symbol_set_id);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001376
Lalit Maganti8d770f72020-01-30 15:44:04 +00001377 auto frame_2 =
1378 frames->Insert({/*name_id=*/kNullStringId, module_2.id, 0x4242});
Lalit Maganti0a29f6f2020-01-06 12:01:14 +00001379
Lalit Maganti7e24f062019-12-17 18:10:35 +00001380 symbol_set_id = storage->symbol_table().row_count();
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001381 storage->mutable_symbol_table()->Insert(
1382 {symbol_set_id, storage->InternString("bar_func"),
1383 storage->InternString("bar_file"), 77});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001384 frames->mutable_symbol_set_id()->Set(frame_2.row, symbol_set_id);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001385
Lalit Maganti8d770f72020-01-30 15:44:04 +00001386 auto frame_callsite_1 = callsites->Insert({0, base::nullopt, frame_1.id});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001387
Lalit Maganti8d770f72020-01-30 15:44:04 +00001388 auto frame_callsite_2 =
1389 callsites->Insert({1, frame_callsite_1.id, frame_2.id});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001390
Lalit Maganti0fd14ef2019-12-18 18:18:44 +00001391 storage->mutable_cpu_profile_stack_sample_table()->Insert(
Oystein Eftevaag95fe09e2020-04-17 12:55:17 -07001392 {kTimestamp, frame_callsite_2.id, utid, kProcessPriority});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001393
1394 base::TempFile temp_file = base::TempFile::Create();
1395 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +01001396 util::Status status = ExportJson(storage, output);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001397
Eric Seckler7fb1d232019-10-23 14:42:43 +01001398 EXPECT_TRUE(status.ok());
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001399
Eric Seckler178094e2019-10-24 14:03:04 +01001400 Json::Value result = ToJsonValue(ReadFile(output));
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001401
1402 EXPECT_EQ(result["traceEvents"].size(), 1u);
1403 Json::Value event = result["traceEvents"][0];
Oystein Eftevaaga33094d2019-11-12 10:48:15 -08001404 EXPECT_EQ(event["ph"].asString(), "n");
1405 EXPECT_EQ(event["id"].asString(), "0x1");
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001406 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001407 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Oystein Eftevaagbdd9db22020-02-04 12:52:01 -08001408 EXPECT_EQ(event["cat"].asString(), "disabled-by-default-cpu_profiler");
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001409 EXPECT_EQ(event["name"].asString(), "StackCpuSampling");
Eric Seckler9dc34462019-11-06 14:44:20 +00001410 EXPECT_EQ(event["s"].asString(), "t");
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001411 EXPECT_EQ(event["args"]["frames"].asString(),
1412 "foo_func - foo_module_name [foo_module_id]\nbar_func - "
1413 "bar_module_name [bar_module_id]\n");
Oystein Eftevaag95fe09e2020-04-17 12:55:17 -07001414 EXPECT_EQ(event["args"]["process_priority"].asInt(), kProcessPriority);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001415}
1416
Eric Seckler178094e2019-10-24 14:03:04 +01001417TEST_F(ExportJsonTest, ArgumentFilter) {
Lalit Magantieac7fff2020-01-10 16:42:54 +00001418 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +00001419 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler178094e2019-10-24 14:03:04 +01001420 context_.args_tracker->Flush(); // Flush track args.
1421
1422 StringId cat_id = context_.storage->InternString(base::StringView("cat"));
1423 std::array<StringId, 3> name_ids{
1424 context_.storage->InternString(base::StringView("name1")),
1425 context_.storage->InternString(base::StringView("name2")),
1426 context_.storage->InternString(base::StringView("name3"))};
1427 StringId arg1_id = context_.storage->InternString(base::StringView("arg1"));
1428 StringId arg2_id = context_.storage->InternString(base::StringView("arg2"));
1429 StringId val_id = context_.storage->InternString(base::StringView("val"));
1430
Lalit Maganti8d770f72020-01-30 15:44:04 +00001431 auto* slices = context_.storage->mutable_slice_table();
Lalit Maganti5228f362020-01-15 13:45:56 +00001432 std::vector<ArgsTracker::BoundInserter> slice_inserters;
Eric Seckler178094e2019-10-24 14:03:04 +01001433 for (size_t i = 0; i < name_ids.size(); i++) {
Lalit Maganti8d770f72020-01-30 15:44:04 +00001434 auto id = slices->Insert({0, 0, track, cat_id, name_ids[i], 0, 0, 0}).id;
1435 slice_inserters.emplace_back(context_.args_tracker->AddArgsTo(id));
Eric Seckler178094e2019-10-24 14:03:04 +01001436 }
1437
Lalit Maganti5228f362020-01-15 13:45:56 +00001438 for (auto& inserter : slice_inserters) {
1439 inserter.AddArg(arg1_id, Variadic::Integer(5))
1440 .AddArg(arg2_id, Variadic::String(val_id));
Eric Seckler178094e2019-10-24 14:03:04 +01001441 }
1442 context_.args_tracker->Flush();
1443
1444 auto arg_filter = [](const char* category_group_name, const char* event_name,
1445 ArgumentNameFilterPredicate* arg_name_filter) {
1446 EXPECT_TRUE(strcmp(category_group_name, "cat") == 0);
1447 if (strcmp(event_name, "name1") == 0) {
1448 // Filter all args for name1.
1449 return false;
1450 } else if (strcmp(event_name, "name2") == 0) {
1451 // Filter only the second arg for name2.
1452 *arg_name_filter = [](const char* arg_name) {
1453 if (strcmp(arg_name, "arg1") == 0) {
1454 return true;
1455 }
1456 EXPECT_TRUE(strcmp(arg_name, "arg2") == 0);
1457 return false;
1458 };
1459 return true;
1460 }
1461 // Filter no args for name3.
1462 EXPECT_TRUE(strcmp(event_name, "name3") == 0);
1463 return true;
1464 };
1465
1466 Json::Value result = ToJsonValue(ToJson(arg_filter));
1467
1468 EXPECT_EQ(result["traceEvents"].size(), 3u);
1469
1470 EXPECT_EQ(result["traceEvents"][0]["cat"].asString(), "cat");
1471 EXPECT_EQ(result["traceEvents"][0]["name"].asString(), "name1");
1472 EXPECT_EQ(result["traceEvents"][0]["args"].asString(), "__stripped__");
1473
1474 EXPECT_EQ(result["traceEvents"][1]["cat"].asString(), "cat");
1475 EXPECT_EQ(result["traceEvents"][1]["name"].asString(), "name2");
1476 EXPECT_EQ(result["traceEvents"][1]["args"]["arg1"].asInt(), 5);
1477 EXPECT_EQ(result["traceEvents"][1]["args"]["arg2"].asString(),
1478 "__stripped__");
1479
1480 EXPECT_EQ(result["traceEvents"][2]["cat"].asString(), "cat");
1481 EXPECT_EQ(result["traceEvents"][2]["name"].asString(), "name3");
1482 EXPECT_EQ(result["traceEvents"][2]["args"]["arg1"].asInt(), 5);
1483 EXPECT_EQ(result["traceEvents"][2]["args"]["arg2"].asString(), "val");
1484}
1485
1486TEST_F(ExportJsonTest, MetadataFilter) {
1487 const char* kName1 = "name1";
1488 const char* kName2 = "name2";
1489 const char* kValue1 = "value1";
1490 const int kValue2 = 222;
1491
1492 TraceStorage* storage = context_.storage.get();
1493
Lalit Maganti8d770f72020-01-30 15:44:04 +00001494 auto* raw = storage->mutable_raw_table();
1495 RawId id =
1496 raw->Insert({0, storage->InternString("chrome_event.metadata"), 0, 0}).id;
Eric Seckler178094e2019-10-24 14:03:04 +01001497
1498 StringId name1_id = storage->InternString(base::StringView(kName1));
1499 StringId name2_id = storage->InternString(base::StringView(kName2));
1500 StringId value1_id = storage->InternString(base::StringView(kValue1));
Lalit Maganti5228f362020-01-15 13:45:56 +00001501
1502 context_.args_tracker->AddArgsTo(id)
1503 .AddArg(name1_id, Variadic::String(value1_id))
1504 .AddArg(name2_id, Variadic::Integer(kValue2));
Eric Seckler178094e2019-10-24 14:03:04 +01001505 context_.args_tracker->Flush();
1506
1507 auto metadata_filter = [](const char* metadata_name) {
1508 // Only allow name1.
1509 return strcmp(metadata_name, "name1") == 0;
1510 };
1511
1512 Json::Value result = ToJsonValue(ToJson(nullptr, metadata_filter));
1513
1514 EXPECT_TRUE(result.isMember("metadata"));
1515 Json::Value metadata = result["metadata"];
1516
1517 EXPECT_EQ(metadata[kName1].asString(), kValue1);
1518 EXPECT_EQ(metadata[kName2].asString(), "__stripped__");
1519}
1520
1521TEST_F(ExportJsonTest, LabelFilter) {
1522 const int64_t kTimestamp1 = 10000000;
1523 const int64_t kTimestamp2 = 20000000;
1524 const int64_t kDuration = 10000;
Eric Secklerbb0e1542020-01-16 13:44:13 +00001525 const uint32_t kThreadID = 100;
Eric Seckler178094e2019-10-24 14:03:04 +01001526 const char* kCategory = "cat";
1527 const char* kName = "name";
1528
Lalit Magantieac7fff2020-01-10 16:42:54 +00001529 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +00001530 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler178094e2019-10-24 14:03:04 +01001531 context_.args_tracker->Flush(); // Flush track args.
1532 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
1533 StringId name_id = context_.storage->InternString(base::StringView(kName));
1534
Lalit Magantic7ea02e2019-12-12 14:06:49 +00001535 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +00001536 {kTimestamp1, kDuration, track, cat_id, name_id, 0, 0, 0});
Lalit Magantic7ea02e2019-12-12 14:06:49 +00001537 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +00001538 {kTimestamp2, kDuration, track, cat_id, name_id, 0, 0, 0});
Eric Seckler178094e2019-10-24 14:03:04 +01001539
1540 auto label_filter = [](const char* label_name) {
1541 return strcmp(label_name, "traceEvents") == 0;
1542 };
1543
1544 Json::Value result =
1545 ToJsonValue("[" + ToJson(nullptr, nullptr, label_filter) + "]");
1546
1547 EXPECT_TRUE(result.isArray());
1548 EXPECT_EQ(result.size(), 2u);
1549
1550 EXPECT_EQ(result[0]["ph"].asString(), "X");
1551 EXPECT_EQ(result[0]["ts"].asInt64(), kTimestamp1 / 1000);
1552 EXPECT_EQ(result[0]["dur"].asInt64(), kDuration / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001553 EXPECT_EQ(result[0]["tid"].asInt(), static_cast<int>(kThreadID));
Eric Seckler178094e2019-10-24 14:03:04 +01001554 EXPECT_EQ(result[0]["cat"].asString(), kCategory);
1555 EXPECT_EQ(result[0]["name"].asString(), kName);
1556 EXPECT_EQ(result[1]["ph"].asString(), "X");
1557 EXPECT_EQ(result[1]["ts"].asInt64(), kTimestamp2 / 1000);
1558 EXPECT_EQ(result[1]["dur"].asInt64(), kDuration / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001559 EXPECT_EQ(result[1]["tid"].asInt(), static_cast<int>(kThreadID));
Eric Seckler178094e2019-10-24 14:03:04 +01001560 EXPECT_EQ(result[1]["cat"].asString(), kCategory);
1561 EXPECT_EQ(result[1]["name"].asString(), kName);
1562}
Eric Seckler7fb1d232019-10-23 14:42:43 +01001563
Tomasz Konieczny6e2d3dd2020-11-04 15:54:04 +01001564TEST_F(ExportJsonTest, MemorySnapshotOsDumpEvent) {
1565 const int64_t kTimestamp = 10000000;
1566 const int64_t kPeakResidentSetSize = 100000;
1567 const int64_t kPrivateFootprintBytes = 200000;
1568 const int64_t kProtectionFlags = 1;
1569 const int64_t kStartAddress = 1000000000;
1570 const int64_t kSizeKb = 1000;
1571 const int64_t kPrivateCleanResidentKb = 2000;
1572 const int64_t kPrivateDirtyKb = 3000;
1573 const int64_t kProportionalResidentKb = 4000;
1574 const int64_t kSharedCleanResidentKb = 5000;
1575 const int64_t kSharedDirtyResidentKb = 6000;
1576 const int64_t kSwapKb = 7000;
1577 const int64_t kModuleTimestamp = 20000000;
1578 const uint32_t kProcessID = 100;
1579 const bool kIsPeakRssResettable = true;
1580 const char* kLevelOfDetail = "detailed";
1581 const char* kFileName = "filename";
1582 const char* kModuleDebugid = "debugid";
1583 const char* kModuleDebugPath = "debugpath";
1584
1585 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
1586 TrackId track = context_.track_tracker->InternProcessTrack(upid);
1587 StringId level_of_detail_id =
1588 context_.storage->InternString(base::StringView(kLevelOfDetail));
1589 auto snapshot_id = context_.storage->mutable_memory_snapshot_table()
1590 ->Insert({kTimestamp, track, level_of_detail_id})
1591 .id;
1592
1593 StringId peak_resident_set_size_id =
1594 context_.storage->InternString("chrome.peak_resident_set_kb");
1595 TrackId peak_resident_set_size_counter =
1596 context_.track_tracker->InternProcessCounterTrack(
1597 peak_resident_set_size_id, upid);
1598 context_.event_tracker->PushCounter(kTimestamp, kPeakResidentSetSize,
1599 peak_resident_set_size_counter);
1600
1601 StringId private_footprint_bytes_id =
1602 context_.storage->InternString("chrome.private_footprint_kb");
1603 TrackId private_footprint_bytes_counter =
1604 context_.track_tracker->InternProcessCounterTrack(
1605 private_footprint_bytes_id, upid);
1606 context_.event_tracker->PushCounter(kTimestamp, kPrivateFootprintBytes,
1607 private_footprint_bytes_counter);
1608
1609 StringId is_peak_rss_resettable_id =
1610 context_.storage->InternString("is_peak_rss_resettable");
1611 context_.args_tracker->AddArgsTo(upid).AddArg(
1612 is_peak_rss_resettable_id, Variadic::Boolean(kIsPeakRssResettable));
1613 context_.args_tracker->Flush();
1614
1615 context_.storage->mutable_profiler_smaps_table()->Insert(
1616 {upid, kTimestamp, kNullStringId, kSizeKb, kPrivateDirtyKb, kSwapKb,
1617 context_.storage->InternString(kFileName), kStartAddress,
1618 kModuleTimestamp, context_.storage->InternString(kModuleDebugid),
1619 context_.storage->InternString(kModuleDebugPath), kProtectionFlags,
1620 kPrivateCleanResidentKb, kSharedDirtyResidentKb, kSharedCleanResidentKb,
1621 0, kProportionalResidentKb});
1622
1623 base::TempFile temp_file = base::TempFile::Create();
1624 FILE* output = fopen(temp_file.path().c_str(), "w+");
1625 util::Status status = ExportJson(context_.storage.get(), output);
1626
1627 EXPECT_TRUE(status.ok());
1628
1629 Json::Value result = ToJsonValue(ReadFile(output));
1630 EXPECT_EQ(result["traceEvents"].size(), 1u);
1631
1632 Json::Value event = result["traceEvents"][0];
1633 EXPECT_EQ(event["ph"].asString(), "v");
1634 EXPECT_EQ(event["cat"].asString(), "disabled-by-default-memory-infra");
1635 EXPECT_EQ(event["id"].asString(), base::Uint64ToHexString(snapshot_id.value));
1636 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
1637 EXPECT_EQ(event["name"].asString(), "periodic_interval");
1638 EXPECT_EQ(event["pid"].asUInt(), kProcessID);
1639 EXPECT_EQ(event["tid"].asInt(), -1);
1640
1641 EXPECT_TRUE(event["args"].isObject());
1642 EXPECT_EQ(event["args"]["dumps"]["level_of_detail"].asString(),
1643 kLevelOfDetail);
1644
1645 EXPECT_EQ(event["args"]["dumps"]["process_totals"]["peak_resident_set_size"]
1646 .asString(),
1647 base::Uint64ToHexStringNoPrefix(
1648 static_cast<uint64_t>(kPeakResidentSetSize)));
1649 EXPECT_EQ(event["args"]["dumps"]["process_totals"]["private_footprint_bytes"]
1650 .asString(),
1651 base::Uint64ToHexStringNoPrefix(
1652 static_cast<uint64_t>(kPrivateFootprintBytes)));
1653 EXPECT_EQ(event["args"]["dumps"]["process_totals"]["is_peak_rss_resettable"]
1654 .asBool(),
1655 kIsPeakRssResettable);
1656
1657 EXPECT_TRUE(event["args"]["dumps"]["process_mmaps"]["vm_regions"].isArray());
1658 EXPECT_EQ(event["args"]["dumps"]["process_mmaps"]["vm_regions"].size(), 1u);
1659 Json::Value region = event["args"]["dumps"]["process_mmaps"]["vm_regions"][0];
1660 EXPECT_EQ(region["mf"].asString(), kFileName);
1661 EXPECT_EQ(region["pf"].asInt64(), kProtectionFlags);
1662 EXPECT_EQ(region["sa"].asString(), base::Uint64ToHexStringNoPrefix(
1663 static_cast<uint64_t>(kStartAddress)));
1664 EXPECT_EQ(region["sz"].asString(),
1665 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSizeKb)));
1666 EXPECT_EQ(region["id"].asString(), kModuleDebugid);
1667 EXPECT_EQ(region["df"].asString(), kModuleDebugPath);
1668 EXPECT_EQ(region["bs"]["pc"].asString(),
1669 base::Uint64ToHexStringNoPrefix(
1670 static_cast<uint64_t>(kPrivateCleanResidentKb)));
1671 EXPECT_EQ(
1672 region["bs"]["pd"].asString(),
1673 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kPrivateDirtyKb)));
1674 EXPECT_EQ(region["bs"]["pss"].asString(),
1675 base::Uint64ToHexStringNoPrefix(
1676 static_cast<uint64_t>(kProportionalResidentKb)));
1677 EXPECT_EQ(region["bs"]["sc"].asString(),
1678 base::Uint64ToHexStringNoPrefix(
1679 static_cast<uint64_t>(kSharedCleanResidentKb)));
1680 EXPECT_EQ(region["bs"]["sd"].asString(),
1681 base::Uint64ToHexStringNoPrefix(
1682 static_cast<uint64_t>(kSharedDirtyResidentKb)));
1683 EXPECT_EQ(region["bs"]["sw"].asString(),
1684 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSwapKb)));
1685}
1686
1687TEST_F(ExportJsonTest, MemorySnapshotChromeDumpEvent) {
1688 const int64_t kTimestamp = 10000000;
1689 const int64_t kSize = 1000;
1690 const int64_t kEffectiveSize = 2000;
1691 const int64_t kScalarAttrValue = 3000;
1692 const uint32_t kOsProcessID = 100;
1693 const uint32_t kChromeProcessID = 200;
1694 const uint32_t kImportance = 1;
1695 const char* kLevelOfDetail = "detailed";
1696 const char* kPath1 = "path/to_file1";
1697 const char* kPath2 = "path/to_file2";
1698 const char* kScalarAttrUnits = "scalar_units";
1699 const char* kStringAttrValue = "string_value";
1700 const std::string kScalarAttrName = "scalar_name";
1701 const std::string kStringAttrName = "string_name";
1702
1703 UniquePid os_upid =
1704 context_.process_tracker->GetOrCreateProcess(kOsProcessID);
1705 TrackId track = context_.track_tracker->InternProcessTrack(os_upid);
1706 StringId level_of_detail_id =
1707 context_.storage->InternString(base::StringView(kLevelOfDetail));
1708 auto snapshot_id = context_.storage->mutable_memory_snapshot_table()
1709 ->Insert({kTimestamp, track, level_of_detail_id})
1710 .id;
1711
1712 UniquePid chrome_upid =
1713 context_.process_tracker->GetOrCreateProcess(kChromeProcessID);
1714 auto process_id = context_.storage->mutable_process_memory_snapshot_table()
1715 ->Insert({snapshot_id, chrome_upid})
1716 .id;
1717
1718 StringId path1_id = context_.storage->InternString(base::StringView(kPath1));
1719 StringId path2_id = context_.storage->InternString(base::StringView(kPath2));
1720 SnapshotNodeId node1_id =
1721 context_.storage->mutable_memory_snapshot_node_table()
1722 ->Insert(
1723 {process_id, SnapshotNodeId(0), path1_id, kSize, kEffectiveSize})
1724 .id;
1725 SnapshotNodeId node2_id =
1726 context_.storage->mutable_memory_snapshot_node_table()
1727 ->Insert({process_id, SnapshotNodeId(0), path2_id, 0, 0})
1728 .id;
1729
1730 context_.args_tracker->AddArgsTo(node1_id).AddArg(
1731 context_.storage->InternString(
1732 base::StringView(kScalarAttrName + ".value")),
1733 Variadic::Integer(kScalarAttrValue));
1734 context_.args_tracker->AddArgsTo(node1_id).AddArg(
1735 context_.storage->InternString(
1736 base::StringView(kScalarAttrName + ".unit")),
1737 Variadic::String(context_.storage->InternString(kScalarAttrUnits)));
1738 context_.args_tracker->AddArgsTo(node1_id).AddArg(
1739 context_.storage->InternString(
1740 base::StringView(kStringAttrName + ".value")),
1741 Variadic::String(context_.storage->InternString(kStringAttrValue)));
1742 context_.args_tracker->Flush();
1743
1744 context_.storage->mutable_memory_snapshot_edge_table()->Insert(
1745 {node1_id, node2_id, kImportance});
1746
1747 base::TempFile temp_file = base::TempFile::Create();
1748 FILE* output = fopen(temp_file.path().c_str(), "w+");
1749 util::Status status = ExportJson(context_.storage.get(), output);
1750
1751 EXPECT_TRUE(status.ok());
1752
1753 Json::Value result = ToJsonValue(ReadFile(output));
1754 EXPECT_EQ(result["traceEvents"].size(), 1u);
1755
1756 Json::Value event = result["traceEvents"][0];
1757 EXPECT_EQ(event["ph"].asString(), "v");
1758 EXPECT_EQ(event["cat"].asString(), "disabled-by-default-memory-infra");
1759 EXPECT_EQ(event["id"].asString(), base::Uint64ToHexString(snapshot_id.value));
1760 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
1761 EXPECT_EQ(event["name"].asString(), "periodic_interval");
1762 EXPECT_EQ(event["pid"].asUInt(), kChromeProcessID);
1763 EXPECT_EQ(event["tid"].asInt(), -1);
1764
1765 EXPECT_TRUE(event["args"].isObject());
1766 EXPECT_EQ(event["args"]["dumps"]["level_of_detail"].asString(),
1767 kLevelOfDetail);
1768
1769 EXPECT_EQ(event["args"]["dumps"]["allocators"].size(), 2u);
1770 Json::Value node1 = event["args"]["dumps"]["allocators"][kPath1];
1771 EXPECT_TRUE(node1.isObject());
1772 EXPECT_EQ(
1773 node1["guid"].asString(),
1774 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node1_id.value)));
1775 EXPECT_TRUE(node1["attrs"]["size"].isObject());
1776 EXPECT_EQ(node1["attrs"]["size"]["value"].asString(),
1777 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSize)));
1778 EXPECT_EQ(node1["attrs"]["size"]["type"].asString(), "scalar");
1779 EXPECT_EQ(node1["attrs"]["size"]["units"].asString(), "bytes");
1780 EXPECT_EQ(
1781 node1["attrs"]["effective_size"]["value"].asString(),
1782 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kEffectiveSize)));
1783 EXPECT_TRUE(node1["attrs"][kScalarAttrName].isObject());
1784 EXPECT_EQ(
1785 node1["attrs"][kScalarAttrName]["value"].asString(),
1786 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kScalarAttrValue)));
1787 EXPECT_EQ(node1["attrs"][kScalarAttrName]["type"].asString(), "scalar");
1788 EXPECT_EQ(node1["attrs"][kScalarAttrName]["units"].asString(),
1789 kScalarAttrUnits);
1790 EXPECT_TRUE(node1["attrs"][kStringAttrName].isObject());
1791 EXPECT_EQ(node1["attrs"][kStringAttrName]["value"].asString(),
1792 kStringAttrValue);
1793 EXPECT_EQ(node1["attrs"][kStringAttrName]["type"].asString(), "string");
1794 EXPECT_EQ(node1["attrs"][kStringAttrName]["units"].asString(), "");
1795
1796 Json::Value node2 = event["args"]["dumps"]["allocators"][kPath2];
1797 EXPECT_TRUE(node2.isObject());
1798 EXPECT_EQ(
1799 node2["guid"].asString(),
1800 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node2_id.value)));
1801 EXPECT_TRUE(node2["attrs"].empty());
1802
1803 Json::Value graph = event["args"]["dumps"]["allocators_graph"];
1804 EXPECT_TRUE(graph.isArray());
1805 EXPECT_EQ(graph.size(), 1u);
1806 EXPECT_EQ(
1807 graph[0]["source"].asString(),
1808 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node1_id.value)));
1809 EXPECT_EQ(
1810 graph[0]["target"].asString(),
1811 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node2_id.value)));
1812 EXPECT_EQ(graph[0]["importance"].asUInt(), kImportance);
1813 EXPECT_EQ(graph[0]["type"].asString(), "ownership");
1814}
1815
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +01001816} // namespace
1817} // namespace json
1818} // namespace trace_processor
1819} // namespace perfetto