blob: 5bce06b17010eabd1c5be04a49f6fec3079cccfa [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 Maganti0faddc42020-04-10 17:58:24 +010034#include "src/trace_processor/types/trace_processor_context.h"
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010035
Primiano Tucci919ca1e2019-08-21 20:26:58 +020036#include "test/gtest_and_gmock.h"
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010037
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010038namespace perfetto {
39namespace trace_processor {
40namespace json {
41namespace {
42
43std::string ReadFile(FILE* input) {
44 fseek(input, 0, SEEK_SET);
Eric Secklere2b4e5c2019-12-06 14:37:29 +000045 const int kBufSize = 10000;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010046 char buffer[kBufSize];
Lalit Magantid9983462019-05-09 18:10:09 +010047 size_t ret = fread(buffer, sizeof(char), kBufSize, input);
Primiano Tucci225a4e62019-06-06 11:13:57 +010048 EXPECT_GT(ret, 0u);
Lalit Magantid9983462019-05-09 18:10:09 +010049 return std::string(buffer, ret);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010050}
51
Eric Seckler178094e2019-10-24 14:03:04 +010052class StringOutputWriter : public OutputWriter {
53 public:
54 StringOutputWriter() { str_.reserve(1024); }
55 ~StringOutputWriter() override {}
56
57 util::Status AppendString(const std::string& str) override {
58 str_ += str;
59 return util::OkStatus();
60 }
61
62 std::string TakeStr() { return std::move(str_); }
63
64 private:
65 std::string str_;
66};
67
Eric Seckler4b861052019-10-23 14:50:28 +010068class ExportJsonTest : public ::testing::Test {
69 public:
70 ExportJsonTest() {
Lalit Maganti1908e262020-01-09 14:33:19 +000071 context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
Eric Seckler4b861052019-10-23 14:50:28 +010072 context_.args_tracker.reset(new ArgsTracker(&context_));
Tomasz Konieczny6e2d3dd2020-11-04 15:54:04 +010073 context_.event_tracker.reset(new EventTracker(&context_));
Eric Seckler4b861052019-10-23 14:50:28 +010074 context_.storage.reset(new TraceStorage());
75 context_.track_tracker.reset(new TrackTracker(&context_));
Lalit Magantiededb0e2020-01-08 12:50:34 +000076 context_.metadata_tracker.reset(new MetadataTracker(&context_));
Lalit Magantieac7fff2020-01-10 16:42:54 +000077 context_.process_tracker.reset(new ProcessTracker(&context_));
Eric Seckler4b861052019-10-23 14:50:28 +010078 }
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010079
Eric Seckler178094e2019-10-24 14:03:04 +010080 std::string ToJson(ArgumentFilterPredicate argument_filter = nullptr,
81 MetadataFilterPredicate metadata_filter = nullptr,
82 LabelFilterPredicate label_filter = nullptr) {
83 StringOutputWriter writer;
84 util::Status status =
85 ExportJson(context_.storage.get(), &writer, argument_filter,
86 metadata_filter, label_filter);
87 EXPECT_TRUE(status.ok());
88 return writer.TakeStr();
89 }
90
91 Json::Value ToJsonValue(const std::string& json) {
Jordan Bayles8c6a4bc2020-07-16 20:20:48 -070092 Json::CharReaderBuilder b;
93 auto reader = std::unique_ptr<Json::CharReader>(b.newCharReader());
Eric Seckler178094e2019-10-24 14:03:04 +010094 Json::Value result;
Jordan Bayles8c6a4bc2020-07-16 20:20:48 -070095 EXPECT_TRUE(reader->parse(json.data(), json.data() + json.length(), &result,
96 nullptr))
97 << json;
Eric Seckler178094e2019-10-24 14:03:04 +010098 return result;
99 }
100
Eric Seckler4b861052019-10-23 14:50:28 +0100101 protected:
102 TraceProcessorContext context_;
103};
104
105TEST_F(ExportJsonTest, EmptyStorage) {
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100106 base::TempFile temp_file = base::TempFile::Create();
107 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100108 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100109
Eric Seckler7fb1d232019-10-23 14:42:43 +0100110 EXPECT_TRUE(status.ok());
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100111
Eric Seckler178094e2019-10-24 14:03:04 +0100112 Json::Value result = ToJsonValue(ReadFile(output));
Primiano Tucci225a4e62019-06-06 11:13:57 +0100113 EXPECT_EQ(result["traceEvents"].size(), 0u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100114}
115
Eric Seckler4b861052019-10-23 14:50:28 +0100116TEST_F(ExportJsonTest, StorageWithOneSlice) {
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100117 const int64_t kTimestamp = 10000000;
118 const int64_t kDuration = 10000;
Mikhail Khokhlov7db04912019-07-18 16:11:11 +0100119 const int64_t kThreadTimestamp = 20000000;
120 const int64_t kThreadDuration = 20000;
Eric Seckler77fb1d22019-07-31 17:02:51 +0100121 const int64_t kThreadInstructionCount = 30000000;
122 const int64_t kThreadInstructionDelta = 30000;
Eric Secklerbb0e1542020-01-16 13:44:13 +0000123 const uint32_t kThreadID = 100;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100124 const char* kCategory = "cat";
125 const char* kName = "name";
126
Lalit Magantieac7fff2020-01-10 16:42:54 +0000127 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000128 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100129 context_.args_tracker->Flush(); // Flush track args.
130 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
131 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000132 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000133 {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100134 context_.storage->mutable_thread_slices()->AddThreadSlice(
Eric Seckler77fb1d22019-07-31 17:02:51 +0100135 0, kThreadTimestamp, kThreadDuration, kThreadInstructionCount,
136 kThreadInstructionDelta);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100137
138 base::TempFile temp_file = base::TempFile::Create();
139 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100140 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100141
Eric Seckler7fb1d232019-10-23 14:42:43 +0100142 EXPECT_TRUE(status.ok());
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100143
Eric Seckler178094e2019-10-24 14:03:04 +0100144 Json::Value result = ToJsonValue(ReadFile(output));
Primiano Tucci225a4e62019-06-06 11:13:57 +0100145 EXPECT_EQ(result["traceEvents"].size(), 1u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100146
147 Json::Value event = result["traceEvents"][0];
148 EXPECT_EQ(event["ph"].asString(), "X");
149 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
150 EXPECT_EQ(event["dur"].asInt64(), kDuration / 1000);
Mikhail Khokhlov7db04912019-07-18 16:11:11 +0100151 EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
152 EXPECT_EQ(event["tdur"].asInt64(), kThreadDuration / 1000);
Eric Seckler77fb1d22019-07-31 17:02:51 +0100153 EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
154 EXPECT_EQ(event["tidelta"].asInt64(), kThreadInstructionDelta);
Eric Seckler88cab6f2020-01-16 18:33:45 +0000155 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100156 EXPECT_EQ(event["cat"].asString(), kCategory);
157 EXPECT_EQ(event["name"].asString(), kName);
Eric Secklerf91236e2019-11-04 10:25:45 +0000158 EXPECT_TRUE(event["args"].isObject());
159 EXPECT_EQ(event["args"].size(), 0u);
Eric Seckler206db472019-07-25 12:05:27 +0100160}
Eric Seckler6f13e332019-10-15 12:14:04 +0100161
Eric Seckler4b861052019-10-23 14:50:28 +0100162TEST_F(ExportJsonTest, StorageWithOneUnfinishedSlice) {
Eric Seckler206db472019-07-25 12:05:27 +0100163 const int64_t kTimestamp = 10000000;
164 const int64_t kDuration = -1;
165 const int64_t kThreadTimestamp = 20000000;
166 const int64_t kThreadDuration = -1;
Eric Seckler77fb1d22019-07-31 17:02:51 +0100167 const int64_t kThreadInstructionCount = 30000000;
168 const int64_t kThreadInstructionDelta = -1;
Eric Secklerbb0e1542020-01-16 13:44:13 +0000169 const uint32_t kThreadID = 100;
Eric Seckler206db472019-07-25 12:05:27 +0100170 const char* kCategory = "cat";
171 const char* kName = "name";
172
Lalit Magantieac7fff2020-01-10 16:42:54 +0000173 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000174 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100175 context_.args_tracker->Flush(); // Flush track args.
176 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
177 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000178 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000179 {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100180 context_.storage->mutable_thread_slices()->AddThreadSlice(
Eric Seckler77fb1d22019-07-31 17:02:51 +0100181 0, kThreadTimestamp, kThreadDuration, kThreadInstructionCount,
182 kThreadInstructionDelta);
Eric Seckler206db472019-07-25 12:05:27 +0100183
184 base::TempFile temp_file = base::TempFile::Create();
185 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100186 util::Status status = ExportJson(context_.storage.get(), output);
Eric Seckler206db472019-07-25 12:05:27 +0100187
Eric Seckler7fb1d232019-10-23 14:42:43 +0100188 EXPECT_TRUE(status.ok());
Eric Seckler206db472019-07-25 12:05:27 +0100189
Eric Seckler178094e2019-10-24 14:03:04 +0100190 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler206db472019-07-25 12:05:27 +0100191 EXPECT_EQ(result["traceEvents"].size(), 1u);
192
193 Json::Value event = result["traceEvents"][0];
194 EXPECT_EQ(event["ph"].asString(), "B");
195 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
196 EXPECT_FALSE(event.isMember("dur"));
197 EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
198 EXPECT_FALSE(event.isMember("tdur"));
Eric Seckler77fb1d22019-07-31 17:02:51 +0100199 EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
200 EXPECT_FALSE(event.isMember("tidelta"));
Eric Seckler88cab6f2020-01-16 18:33:45 +0000201 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Eric Seckler206db472019-07-25 12:05:27 +0100202 EXPECT_EQ(event["cat"].asString(), kCategory);
203 EXPECT_EQ(event["name"].asString(), kName);
Eric Secklerf91236e2019-11-04 10:25:45 +0000204 EXPECT_TRUE(event["args"].isObject());
205 EXPECT_EQ(event["args"].size(), 0u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100206}
207
Eric Seckler4b861052019-10-23 14:50:28 +0100208TEST_F(ExportJsonTest, StorageWithThreadName) {
Eric Secklerbb0e1542020-01-16 13:44:13 +0000209 const uint32_t kThreadID = 100;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100210 const char* kName = "thread";
211
Lalit Magantieac7fff2020-01-10 16:42:54 +0000212 tables::ThreadTable::Row row(kThreadID);
213 row.name = context_.storage->InternString(base::StringView(kName));
214 context_.storage->mutable_thread_table()->Insert(row);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100215
216 base::TempFile temp_file = base::TempFile::Create();
217 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100218 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100219
Eric Seckler7fb1d232019-10-23 14:42:43 +0100220 EXPECT_TRUE(status.ok());
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100221
Eric Seckler178094e2019-10-24 14:03:04 +0100222 Json::Value result = ToJsonValue(ReadFile(output));
Primiano Tucci225a4e62019-06-06 11:13:57 +0100223 EXPECT_EQ(result["traceEvents"].size(), 1u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100224
225 Json::Value event = result["traceEvents"][0];
226 EXPECT_EQ(event["ph"].asString(), "M");
Eric Seckler88cab6f2020-01-16 18:33:45 +0000227 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100228 EXPECT_EQ(event["name"].asString(), "thread_name");
229 EXPECT_EQ(event["args"]["name"].asString(), kName);
230}
231
Eric Seckler3183c6d2020-01-14 15:45:20 +0000232TEST_F(ExportJsonTest, SystemEventsIgnored) {
Eric Seckler4b861052019-10-23 14:50:28 +0100233 constexpr int64_t kCookie = 22;
234 TrackId track = context_.track_tracker->InternAndroidAsyncTrack(
Lalit Magantif0599a02020-01-15 15:45:20 +0000235 /*name=*/kNullStringId, /*upid=*/0, kCookie);
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.
743 TrackId track2 = context_.track_tracker->GetOrCreateDefaultDescriptorTrack();
744 context_.args_tracker->Flush(); // Flush track args.
745 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000746 {kTimestamp2, 0, track2, cat_id, name_id, 0, 0, 0});
Eric Secklerc64e19c2020-01-28 15:47:56 +0000747
748 // Async event track.
Eric Secklerf1497812020-04-30 10:43:23 +0100749 context_.track_tracker->ReserveDescriptorChildTrack(1234, 0, kNullStringId);
Eric Secklerc64e19c2020-01-28 15:47:56 +0000750 TrackId track3 = *context_.track_tracker->GetDescriptorTrack(1234);
751 context_.args_tracker->Flush(); // Flush track args.
752 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000753 {kTimestamp3, 0, track3, cat_id, name_id, 0, 0, 0});
Eric Secklerc64e19c2020-01-28 15:47:56 +0000754
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100755 base::TempFile temp_file = base::TempFile::Create();
756 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100757 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100758
Eric Seckler7fb1d232019-10-23 14:42:43 +0100759 EXPECT_TRUE(status.ok());
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100760
Eric Seckler178094e2019-10-24 14:03:04 +0100761 Json::Value result = ToJsonValue(ReadFile(output));
Eric Secklerc64e19c2020-01-28 15:47:56 +0000762 EXPECT_EQ(result["traceEvents"].size(), 3u);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100763
764 Json::Value event = result["traceEvents"][0];
Eric Seckler9dc34462019-11-06 14:44:20 +0000765 EXPECT_EQ(event["ph"].asString(), "I");
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100766 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
767 EXPECT_EQ(event["s"].asString(), "g");
768 EXPECT_EQ(event["cat"].asString(), kCategory);
769 EXPECT_EQ(event["name"].asString(), kName);
Eric Secklerc64e19c2020-01-28 15:47:56 +0000770
771 Json::Value event2 = result["traceEvents"][1];
772 EXPECT_EQ(event2["ph"].asString(), "I");
773 EXPECT_EQ(event2["ts"].asInt64(), kTimestamp2 / 1000);
774 EXPECT_EQ(event2["s"].asString(), "g");
775 EXPECT_EQ(event2["cat"].asString(), kCategory);
776 EXPECT_EQ(event2["name"].asString(), kName);
777
778 Json::Value event3 = result["traceEvents"][2];
779 EXPECT_EQ(event3["ph"].asString(), "n");
780 EXPECT_EQ(event3["ts"].asInt64(), kTimestamp3 / 1000);
781 EXPECT_EQ(event3["id"].asString(), "0x2");
782 EXPECT_EQ(event3["cat"].asString(), kCategory);
783 EXPECT_EQ(event3["name"].asString(), kName);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100784}
785
Eric Seckler4b861052019-10-23 14:50:28 +0100786TEST_F(ExportJsonTest, InstantEventOnThread) {
787 const int64_t kTimestamp = 10000000;
Eric Secklerbb0e1542020-01-16 13:44:13 +0000788 const uint32_t kThreadID = 100;
Eric Seckler4b861052019-10-23 14:50:28 +0100789 const char* kCategory = "cat";
790 const char* kName = "name";
791
Lalit Magantieac7fff2020-01-10 16:42:54 +0000792 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000793 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100794 context_.args_tracker->Flush(); // Flush track args.
795 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
796 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000797 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000798 {kTimestamp, 0, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100799
800 base::TempFile temp_file = base::TempFile::Create();
801 FILE* output = fopen(temp_file.path().c_str(), "w+");
802 util::Status status = ExportJson(context_.storage.get(), output);
803
804 EXPECT_TRUE(status.ok());
805
Eric Seckler178094e2019-10-24 14:03:04 +0100806 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler4b861052019-10-23 14:50:28 +0100807 EXPECT_EQ(result["traceEvents"].size(), 1u);
808
809 Json::Value event = result["traceEvents"][0];
Eric Seckler88cab6f2020-01-16 18:33:45 +0000810 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Eric Seckler9dc34462019-11-06 14:44:20 +0000811 EXPECT_EQ(event["ph"].asString(), "I");
Eric Seckler4b861052019-10-23 14:50:28 +0100812 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
813 EXPECT_EQ(event["s"].asString(), "t");
814 EXPECT_EQ(event["cat"].asString(), kCategory);
815 EXPECT_EQ(event["name"].asString(), kName);
816}
817
Eric Secklerbb0e1542020-01-16 13:44:13 +0000818TEST_F(ExportJsonTest, DuplicatePidAndTid) {
819 UniqueTid upid1 = context_.process_tracker->StartNewProcess(
820 base::nullopt, base::nullopt, 1, kNullStringId);
821 UniqueTid utid1a = context_.process_tracker->UpdateThread(1, 1);
822 UniqueTid utid1b = context_.process_tracker->UpdateThread(2, 1);
Mikhail Khokhlov567c0042020-07-17 17:42:44 +0100823 UniqueTid utid1c = context_.process_tracker->StartNewThread(base::nullopt, 2);
Eric Secklerbb0e1542020-01-16 13:44:13 +0000824 // Associate the new thread with its process.
825 ASSERT_EQ(utid1c, context_.process_tracker->UpdateThread(2, 1));
826
827 UniqueTid upid2 = context_.process_tracker->StartNewProcess(
828 base::nullopt, base::nullopt, 1, kNullStringId);
829 UniqueTid utid2a = context_.process_tracker->UpdateThread(1, 1);
830 UniqueTid utid2b = context_.process_tracker->UpdateThread(2, 1);
831
832 ASSERT_NE(upid1, upid2);
833 ASSERT_NE(utid1b, utid1c);
834 ASSERT_NE(utid1a, utid2a);
835 ASSERT_NE(utid1b, utid2b);
836 ASSERT_NE(utid1c, utid2b);
837
838 ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1a]);
839 ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1b]);
840 ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1c]);
841 ASSERT_EQ(upid2, *context_.storage->thread_table().upid()[utid2a]);
842 ASSERT_EQ(upid2, *context_.storage->thread_table().upid()[utid2b]);
843
844 TrackId track1a = context_.track_tracker->InternThreadTrack(utid1a);
845 TrackId track1b = context_.track_tracker->InternThreadTrack(utid1b);
846 TrackId track1c = context_.track_tracker->InternThreadTrack(utid1c);
847 TrackId track2a = context_.track_tracker->InternThreadTrack(utid2a);
848 TrackId track2b = context_.track_tracker->InternThreadTrack(utid2b);
849 context_.args_tracker->Flush(); // Flush track args.
850
851 StringId cat_id = context_.storage->InternString(base::StringView("cat"));
852 StringId name1a_id =
853 context_.storage->InternString(base::StringView("name1a"));
854 StringId name1b_id =
855 context_.storage->InternString(base::StringView("name1b"));
856 StringId name1c_id =
857 context_.storage->InternString(base::StringView("name1c"));
858 StringId name2a_id =
859 context_.storage->InternString(base::StringView("name2a"));
860 StringId name2b_id =
861 context_.storage->InternString(base::StringView("name2b"));
862
863 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000864 {10000, 0, track1a, cat_id, name1a_id, 0, 0, 0});
Eric Secklerbb0e1542020-01-16 13:44:13 +0000865 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000866 {20000, 1000, track1b, cat_id, name1b_id, 0, 0, 0});
Eric Secklerbb0e1542020-01-16 13:44:13 +0000867 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000868 {30000, 0, track1c, cat_id, name1c_id, 0, 0, 0});
Eric Secklerbb0e1542020-01-16 13:44:13 +0000869 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000870 {40000, 0, track2a, cat_id, name2a_id, 0, 0, 0});
Eric Secklerbb0e1542020-01-16 13:44:13 +0000871 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000872 {50000, 1000, track2b, cat_id, name2b_id, 0, 0, 0});
Eric Secklerbb0e1542020-01-16 13:44:13 +0000873
874 base::TempFile temp_file = base::TempFile::Create();
875 FILE* output = fopen(temp_file.path().c_str(), "w+");
876 util::Status status = ExportJson(context_.storage.get(), output);
877
878 EXPECT_TRUE(status.ok());
879
880 Json::Value result = ToJsonValue(ReadFile(output));
881 EXPECT_EQ(result["traceEvents"].size(), 5u);
882
Eric Seckler88cab6f2020-01-16 18:33:45 +0000883 EXPECT_EQ(result["traceEvents"][0]["pid"].asInt(), 1);
884 EXPECT_EQ(result["traceEvents"][0]["tid"].asInt(), 1);
Eric Secklerbb0e1542020-01-16 13:44:13 +0000885 EXPECT_EQ(result["traceEvents"][0]["ph"].asString(), "I");
886 EXPECT_EQ(result["traceEvents"][0]["ts"].asInt64(), 10);
887 EXPECT_EQ(result["traceEvents"][0]["cat"].asString(), "cat");
888 EXPECT_EQ(result["traceEvents"][0]["name"].asString(), "name1a");
889
Eric Seckler88cab6f2020-01-16 18:33:45 +0000890 EXPECT_EQ(result["traceEvents"][1]["pid"].asInt(), 1);
891 EXPECT_EQ(result["traceEvents"][1]["tid"].asInt(), 2);
Eric Secklerbb0e1542020-01-16 13:44:13 +0000892 EXPECT_EQ(result["traceEvents"][1]["ph"].asString(), "X");
893 EXPECT_EQ(result["traceEvents"][1]["ts"].asInt64(), 20);
894 EXPECT_EQ(result["traceEvents"][1]["dur"].asInt64(), 1);
895 EXPECT_EQ(result["traceEvents"][1]["cat"].asString(), "cat");
896 EXPECT_EQ(result["traceEvents"][1]["name"].asString(), "name1b");
897
Eric Seckler88cab6f2020-01-16 18:33:45 +0000898 EXPECT_EQ(result["traceEvents"][2]["pid"].asInt(), 1);
899 EXPECT_EQ(result["traceEvents"][2]["tid"].asInt(),
900 static_cast<int>(std::numeric_limits<uint32_t>::max() - 1u));
Eric Secklerbb0e1542020-01-16 13:44:13 +0000901 EXPECT_EQ(result["traceEvents"][2]["ph"].asString(), "I");
902 EXPECT_EQ(result["traceEvents"][2]["ts"].asInt64(), 30);
903 EXPECT_EQ(result["traceEvents"][2]["cat"].asString(), "cat");
904 EXPECT_EQ(result["traceEvents"][2]["name"].asString(), "name1c");
905
Eric Seckler88cab6f2020-01-16 18:33:45 +0000906 EXPECT_EQ(result["traceEvents"][3]["pid"].asInt(),
907 static_cast<int>(std::numeric_limits<uint32_t>::max()));
908 EXPECT_EQ(result["traceEvents"][3]["tid"].asInt(), 1);
Eric Secklerbb0e1542020-01-16 13:44:13 +0000909 EXPECT_EQ(result["traceEvents"][3]["ph"].asString(), "I");
910 EXPECT_EQ(result["traceEvents"][3]["ts"].asInt64(), 40);
911 EXPECT_EQ(result["traceEvents"][3]["cat"].asString(), "cat");
912 EXPECT_EQ(result["traceEvents"][3]["name"].asString(), "name2a");
913
Eric Seckler88cab6f2020-01-16 18:33:45 +0000914 EXPECT_EQ(result["traceEvents"][4]["pid"].asInt(),
915 static_cast<int>(std::numeric_limits<uint32_t>::max()));
916 EXPECT_EQ(result["traceEvents"][4]["tid"].asInt(), 2);
Eric Secklerbb0e1542020-01-16 13:44:13 +0000917 EXPECT_EQ(result["traceEvents"][4]["ph"].asString(), "X");
918 EXPECT_EQ(result["traceEvents"][4]["ts"].asInt64(), 50);
919 EXPECT_EQ(result["traceEvents"][1]["dur"].asInt64(), 1);
920 EXPECT_EQ(result["traceEvents"][4]["cat"].asString(), "cat");
921 EXPECT_EQ(result["traceEvents"][4]["name"].asString(), "name2b");
922}
923
Eric Seckler5f2907d2020-01-06 14:44:05 +0000924TEST_F(ExportJsonTest, AsyncEvents) {
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100925 const int64_t kTimestamp = 10000000;
926 const int64_t kDuration = 100000;
Eric Seckler37d69c12020-01-22 13:59:54 +0000927 const int64_t kTimestamp3 = 10005000;
928 const int64_t kDuration3 = 100000;
Eric Secklerbb0e1542020-01-16 13:44:13 +0000929 const uint32_t kProcessID = 100;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100930 const char* kCategory = "cat";
931 const char* kName = "name";
Eric Seckler5f2907d2020-01-06 14:44:05 +0000932 const char* kName2 = "name2";
Eric Seckler37d69c12020-01-22 13:59:54 +0000933 const char* kName3 = "name3";
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100934 const char* kArgName = "arg_name";
935 const int kArgValue = 123;
936
Lalit Magantieac7fff2020-01-10 16:42:54 +0000937 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +0100938 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
939 StringId name_id = context_.storage->InternString(base::StringView(kName));
Eric Seckler5f2907d2020-01-06 14:44:05 +0000940 StringId name2_id = context_.storage->InternString(base::StringView(kName2));
Eric Seckler37d69c12020-01-22 13:59:54 +0000941 StringId name3_id = context_.storage->InternString(base::StringView(kName3));
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100942
Eric Seckler4b861052019-10-23 14:50:28 +0100943 constexpr int64_t kSourceId = 235;
944 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
945 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
Lalit Magantif0599a02020-01-15 15:45:20 +0000946 /*source_scope=*/kNullStringId);
Eric Seckler37d69c12020-01-22 13:59:54 +0000947 constexpr int64_t kSourceId2 = 236;
948 TrackId track2 = context_.track_tracker->InternLegacyChromeAsyncTrack(
949 name3_id, upid, kSourceId2, /*source_id_is_process_scoped=*/true,
950 /*source_scope=*/kNullStringId);
Eric Seckler4b861052019-10-23 14:50:28 +0100951 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100952
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000953 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000954 {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100955 StringId arg_key_id =
956 context_.storage->InternString(base::StringView(kArgName));
Lalit Maganti1908e262020-01-09 14:33:19 +0000957 GlobalArgsTracker::Arg arg;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100958 arg.flat_key = arg_key_id;
959 arg.key = arg_key_id;
960 arg.value = Variadic::Integer(kArgValue);
Lalit Maganti1908e262020-01-09 14:33:19 +0000961 ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000962 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100963
Eric Seckler5f2907d2020-01-06 14:44:05 +0000964 // Child event with same timestamps as first one.
965 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000966 {kTimestamp, kDuration, track, cat_id, name2_id, 0, 0, 0});
Eric Seckler5f2907d2020-01-06 14:44:05 +0000967
Eric Seckler37d69c12020-01-22 13:59:54 +0000968 // Another overlapping async event on a different track.
969 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +0000970 {kTimestamp3, kDuration3, track2, cat_id, name3_id, 0, 0, 0});
Eric Seckler37d69c12020-01-22 13:59:54 +0000971
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100972 base::TempFile temp_file = base::TempFile::Create();
973 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100974 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100975
Eric Seckler7fb1d232019-10-23 14:42:43 +0100976 EXPECT_TRUE(status.ok());
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100977
Eric Seckler178094e2019-10-24 14:03:04 +0100978 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler37d69c12020-01-22 13:59:54 +0000979 EXPECT_EQ(result["traceEvents"].size(), 6u);
980
981 // Events should be sorted by timestamp, with child slice's end before its
982 // parent.
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100983
Eric Seckler5f2907d2020-01-06 14:44:05 +0000984 Json::Value begin_event1 = result["traceEvents"][0];
985 EXPECT_EQ(begin_event1["ph"].asString(), "b");
986 EXPECT_EQ(begin_event1["ts"].asInt64(), kTimestamp / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +0000987 EXPECT_EQ(begin_event1["pid"].asInt(), static_cast<int>(kProcessID));
Eric Seckler5f2907d2020-01-06 14:44:05 +0000988 EXPECT_EQ(begin_event1["id2"]["local"].asString(), "0xeb");
989 EXPECT_EQ(begin_event1["cat"].asString(), kCategory);
990 EXPECT_EQ(begin_event1["name"].asString(), kName);
991 EXPECT_EQ(begin_event1["args"][kArgName].asInt(), kArgValue);
992 EXPECT_FALSE(begin_event1.isMember("tts"));
993 EXPECT_FALSE(begin_event1.isMember("use_async_tts"));
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100994
Eric Seckler5f2907d2020-01-06 14:44:05 +0000995 Json::Value begin_event2 = result["traceEvents"][1];
996 EXPECT_EQ(begin_event2["ph"].asString(), "b");
997 EXPECT_EQ(begin_event2["ts"].asInt64(), kTimestamp / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +0000998 EXPECT_EQ(begin_event2["pid"].asInt(), static_cast<int>(kProcessID));
Eric Seckler5f2907d2020-01-06 14:44:05 +0000999 EXPECT_EQ(begin_event2["id2"]["local"].asString(), "0xeb");
1000 EXPECT_EQ(begin_event2["cat"].asString(), kCategory);
1001 EXPECT_EQ(begin_event2["name"].asString(), kName2);
1002 EXPECT_TRUE(begin_event2["args"].isObject());
1003 EXPECT_EQ(begin_event2["args"].size(), 0u);
1004 EXPECT_FALSE(begin_event2.isMember("tts"));
1005 EXPECT_FALSE(begin_event2.isMember("use_async_tts"));
1006
Eric Seckler37d69c12020-01-22 13:59:54 +00001007 Json::Value begin_event3 = result["traceEvents"][2];
1008 EXPECT_EQ(begin_event3["ph"].asString(), "b");
1009 EXPECT_EQ(begin_event3["ts"].asInt64(), kTimestamp3 / 1000);
1010 EXPECT_EQ(begin_event3["pid"].asInt(), static_cast<int>(kProcessID));
1011 EXPECT_EQ(begin_event3["id2"]["local"].asString(), "0xec");
1012 EXPECT_EQ(begin_event3["cat"].asString(), kCategory);
1013 EXPECT_EQ(begin_event3["name"].asString(), kName3);
1014 EXPECT_TRUE(begin_event3["args"].isObject());
1015 EXPECT_EQ(begin_event3["args"].size(), 0u);
1016 EXPECT_FALSE(begin_event3.isMember("tts"));
1017 EXPECT_FALSE(begin_event3.isMember("use_async_tts"));
1018
Eric Seckler5f2907d2020-01-06 14:44:05 +00001019 Json::Value end_event2 = result["traceEvents"][3];
1020 EXPECT_EQ(end_event2["ph"].asString(), "e");
1021 EXPECT_EQ(end_event2["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001022 EXPECT_EQ(end_event2["pid"].asInt(), static_cast<int>(kProcessID));
Eric Seckler5f2907d2020-01-06 14:44:05 +00001023 EXPECT_EQ(end_event2["id2"]["local"].asString(), "0xeb");
1024 EXPECT_EQ(end_event2["cat"].asString(), kCategory);
Eric Seckler37d69c12020-01-22 13:59:54 +00001025 EXPECT_EQ(end_event2["name"].asString(), kName2);
Eric Seckler5f2907d2020-01-06 14:44:05 +00001026 EXPECT_TRUE(end_event2["args"].isObject());
1027 EXPECT_EQ(end_event2["args"].size(), 0u);
1028 EXPECT_FALSE(end_event2.isMember("tts"));
1029 EXPECT_FALSE(end_event2.isMember("use_async_tts"));
1030
Eric Seckler37d69c12020-01-22 13:59:54 +00001031 Json::Value end_event1 = result["traceEvents"][4];
Eric Seckler5f2907d2020-01-06 14:44:05 +00001032 EXPECT_EQ(end_event1["ph"].asString(), "e");
1033 EXPECT_EQ(end_event1["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001034 EXPECT_EQ(end_event1["pid"].asInt(), static_cast<int>(kProcessID));
Eric Seckler5f2907d2020-01-06 14:44:05 +00001035 EXPECT_EQ(end_event1["id2"]["local"].asString(), "0xeb");
1036 EXPECT_EQ(end_event1["cat"].asString(), kCategory);
1037 EXPECT_EQ(end_event1["name"].asString(), kName);
1038 EXPECT_TRUE(end_event1["args"].isObject());
1039 EXPECT_EQ(end_event1["args"].size(), 0u);
1040 EXPECT_FALSE(end_event1.isMember("tts"));
1041 EXPECT_FALSE(end_event1.isMember("use_async_tts"));
Eric Seckler37d69c12020-01-22 13:59:54 +00001042
1043 Json::Value end_event3 = result["traceEvents"][5];
1044 EXPECT_EQ(end_event3["ph"].asString(), "e");
1045 EXPECT_EQ(end_event3["ts"].asInt64(), (kTimestamp3 + kDuration3) / 1000);
1046 EXPECT_EQ(end_event3["pid"].asInt(), static_cast<int>(kProcessID));
1047 EXPECT_EQ(end_event3["id2"]["local"].asString(), "0xec");
1048 EXPECT_EQ(end_event3["cat"].asString(), kCategory);
1049 EXPECT_EQ(end_event3["name"].asString(), kName3);
1050 EXPECT_TRUE(end_event3["args"].isObject());
1051 EXPECT_EQ(end_event3["args"].size(), 0u);
1052 EXPECT_FALSE(end_event3.isMember("tts"));
1053 EXPECT_FALSE(end_event3.isMember("use_async_tts"));
Eric Secklerc63a3af2019-07-25 11:17:37 +01001054}
1055
Eric Seckler4b861052019-10-23 14:50:28 +01001056TEST_F(ExportJsonTest, AsyncEventWithThreadTimestamp) {
Eric Secklerc63a3af2019-07-25 11:17:37 +01001057 const int64_t kTimestamp = 10000000;
1058 const int64_t kDuration = 100000;
1059 const int64_t kThreadTimestamp = 10000001;
1060 const int64_t kThreadDuration = 99998;
Eric Secklerbb0e1542020-01-16 13:44:13 +00001061 const uint32_t kProcessID = 100;
Eric Secklerc63a3af2019-07-25 11:17:37 +01001062 const char* kCategory = "cat";
1063 const char* kName = "name";
1064
Lalit Magantieac7fff2020-01-10 16:42:54 +00001065 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +01001066 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
1067 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001068
Eric Seckler4b861052019-10-23 14:50:28 +01001069 constexpr int64_t kSourceId = 235;
1070 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
1071 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
Lalit Magantif0599a02020-01-15 15:45:20 +00001072 /*source_scope=*/kNullStringId);
Eric Seckler4b861052019-10-23 14:50:28 +01001073 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001074
Lalit Maganti8d770f72020-01-30 15:44:04 +00001075 auto* slices = context_.storage->mutable_slice_table();
1076 auto id_and_row =
1077 slices->Insert({kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +01001078 context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice(
Lalit Maganti8d770f72020-01-30 15:44:04 +00001079 id_and_row.id.value, kThreadTimestamp, kThreadDuration, 0, 0);
Eric Secklerc63a3af2019-07-25 11:17:37 +01001080
1081 base::TempFile temp_file = base::TempFile::Create();
1082 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +01001083 util::Status status = ExportJson(context_.storage.get(), output);
Eric Secklerc63a3af2019-07-25 11:17:37 +01001084
Eric Seckler7fb1d232019-10-23 14:42:43 +01001085 EXPECT_TRUE(status.ok());
Eric Secklerc63a3af2019-07-25 11:17:37 +01001086
Eric Seckler178094e2019-10-24 14:03:04 +01001087 Json::Value result = ToJsonValue(ReadFile(output));
Eric Secklerc63a3af2019-07-25 11:17:37 +01001088 EXPECT_EQ(result["traceEvents"].size(), 2u);
1089
1090 Json::Value begin_event = result["traceEvents"][0];
1091 EXPECT_EQ(begin_event["ph"].asString(), "b");
1092 EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
1093 EXPECT_EQ(begin_event["tts"].asInt64(), kThreadTimestamp / 1000);
1094 EXPECT_EQ(begin_event["use_async_tts"].asInt(), 1);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001095 EXPECT_EQ(begin_event["pid"].asInt(), static_cast<int>(kProcessID));
Eric Secklerf91236e2019-11-04 10:25:45 +00001096 EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
Eric Secklerc63a3af2019-07-25 11:17:37 +01001097 EXPECT_EQ(begin_event["cat"].asString(), kCategory);
1098 EXPECT_EQ(begin_event["name"].asString(), kName);
1099
1100 Json::Value end_event = result["traceEvents"][1];
1101 EXPECT_EQ(end_event["ph"].asString(), "e");
1102 EXPECT_EQ(end_event["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
1103 EXPECT_EQ(end_event["tts"].asInt64(),
1104 (kThreadTimestamp + kThreadDuration) / 1000);
1105 EXPECT_EQ(end_event["use_async_tts"].asInt(), 1);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001106 EXPECT_EQ(end_event["pid"].asInt(), static_cast<int>(kProcessID));
Eric Secklerf91236e2019-11-04 10:25:45 +00001107 EXPECT_EQ(end_event["id2"]["local"].asString(), "0xeb");
Eric Secklerc63a3af2019-07-25 11:17:37 +01001108 EXPECT_EQ(end_event["cat"].asString(), kCategory);
1109 EXPECT_EQ(end_event["name"].asString(), kName);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001110}
1111
Eric Seckler4b861052019-10-23 14:50:28 +01001112TEST_F(ExportJsonTest, UnfinishedAsyncEvent) {
Eric Seckler206db472019-07-25 12:05:27 +01001113 const int64_t kTimestamp = 10000000;
1114 const int64_t kDuration = -1;
1115 const int64_t kThreadTimestamp = 10000001;
1116 const int64_t kThreadDuration = -1;
Eric Secklerbb0e1542020-01-16 13:44:13 +00001117 const uint32_t kProcessID = 100;
Eric Seckler206db472019-07-25 12:05:27 +01001118 const char* kCategory = "cat";
1119 const char* kName = "name";
1120
Lalit Magantieac7fff2020-01-10 16:42:54 +00001121 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +01001122 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
1123 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001124
Eric Seckler4b861052019-10-23 14:50:28 +01001125 constexpr int64_t kSourceId = 235;
1126 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
1127 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
Lalit Magantif0599a02020-01-15 15:45:20 +00001128 /*source_scope=*/kNullStringId);
Eric Seckler4b861052019-10-23 14:50:28 +01001129 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001130
Lalit Maganti8d770f72020-01-30 15:44:04 +00001131 auto slice_id =
1132 context_.storage->mutable_slice_table()
1133 ->Insert({kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0})
1134 .id;
Eric Seckler4b861052019-10-23 14:50:28 +01001135 context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice(
Lalit Magantib0e11f62020-01-02 14:17:58 +00001136 slice_id.value, kThreadTimestamp, kThreadDuration, 0, 0);
Eric Seckler206db472019-07-25 12:05:27 +01001137
1138 base::TempFile temp_file = base::TempFile::Create();
1139 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +01001140 util::Status status = ExportJson(context_.storage.get(), output);
Eric Seckler206db472019-07-25 12:05:27 +01001141
Eric Seckler7fb1d232019-10-23 14:42:43 +01001142 EXPECT_TRUE(status.ok());
Eric Seckler206db472019-07-25 12:05:27 +01001143
Eric Seckler178094e2019-10-24 14:03:04 +01001144 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler206db472019-07-25 12:05:27 +01001145 EXPECT_EQ(result["traceEvents"].size(), 1u);
1146
1147 Json::Value begin_event = result["traceEvents"][0];
1148 EXPECT_EQ(begin_event["ph"].asString(), "b");
1149 EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
1150 EXPECT_EQ(begin_event["tts"].asInt64(), kThreadTimestamp / 1000);
1151 EXPECT_EQ(begin_event["use_async_tts"].asInt(), 1);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001152 EXPECT_EQ(begin_event["pid"].asInt(), static_cast<int>(kProcessID));
Eric Secklerf91236e2019-11-04 10:25:45 +00001153 EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
Eric Seckler206db472019-07-25 12:05:27 +01001154 EXPECT_EQ(begin_event["cat"].asString(), kCategory);
1155 EXPECT_EQ(begin_event["name"].asString(), kName);
1156}
1157
Eric Seckler4b861052019-10-23 14:50:28 +01001158TEST_F(ExportJsonTest, AsyncInstantEvent) {
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001159 const int64_t kTimestamp = 10000000;
Eric Secklerbb0e1542020-01-16 13:44:13 +00001160 const uint32_t kProcessID = 100;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001161 const char* kCategory = "cat";
1162 const char* kName = "name";
1163 const char* kArgName = "arg_name";
1164 const int kArgValue = 123;
1165
Lalit Magantieac7fff2020-01-10 16:42:54 +00001166 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +01001167 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
1168 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001169
Eric Seckler4b861052019-10-23 14:50:28 +01001170 constexpr int64_t kSourceId = 235;
1171 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
1172 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
Lalit Magantif0599a02020-01-15 15:45:20 +00001173 /*source_scope=*/kNullStringId);
Eric Seckler4b861052019-10-23 14:50:28 +01001174 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +01001175
Lalit Maganti1308e3f2019-12-09 20:24:20 +00001176 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +00001177 {kTimestamp, 0, track, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +01001178 StringId arg_key_id =
1179 context_.storage->InternString(base::StringView("arg_name"));
Lalit Maganti1908e262020-01-09 14:33:19 +00001180 GlobalArgsTracker::Arg arg;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001181 arg.flat_key = arg_key_id;
1182 arg.key = arg_key_id;
1183 arg.value = Variadic::Integer(kArgValue);
Lalit Maganti1908e262020-01-09 14:33:19 +00001184 ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
Lalit Maganti1308e3f2019-12-09 20:24:20 +00001185 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001186
1187 base::TempFile temp_file = base::TempFile::Create();
1188 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +01001189 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001190
Eric Seckler7fb1d232019-10-23 14:42:43 +01001191 EXPECT_TRUE(status.ok());
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001192
Eric Seckler178094e2019-10-24 14:03:04 +01001193 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001194 EXPECT_EQ(result["traceEvents"].size(), 1u);
1195
1196 Json::Value event = result["traceEvents"][0];
1197 EXPECT_EQ(event["ph"].asString(), "n");
1198 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001199 EXPECT_EQ(event["pid"].asInt(), static_cast<int>(kProcessID));
Eric Secklerf91236e2019-11-04 10:25:45 +00001200 EXPECT_EQ(event["id2"]["local"].asString(), "0xeb");
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001201 EXPECT_EQ(event["cat"].asString(), kCategory);
1202 EXPECT_EQ(event["name"].asString(), kName);
1203 EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
1204}
1205
Eric Seckler4b861052019-10-23 14:50:28 +01001206TEST_F(ExportJsonTest, RawEvent) {
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001207 const int64_t kTimestamp = 10000000;
1208 const int64_t kDuration = 10000;
1209 const int64_t kThreadTimestamp = 20000000;
1210 const int64_t kThreadDuration = 20000;
1211 const int64_t kThreadInstructionCount = 30000000;
1212 const int64_t kThreadInstructionDelta = 30000;
Eric Secklerbb0e1542020-01-16 13:44:13 +00001213 const uint32_t kProcessID = 100;
1214 const uint32_t kThreadID = 200;
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001215 const char* kCategory = "cat";
1216 const char* kName = "name";
1217 const char* kPhase = "?";
1218 const uint64_t kGlobalId = 0xaaffaaffaaffaaff;
1219 const char* kIdScope = "my_id";
1220 const uint64_t kBindId = 0xaa00aa00aa00aa00;
1221 const char* kFlowDirection = "inout";
1222 const char* kArgName = "arg_name";
1223 const int kArgValue = 123;
1224
Eric Seckler4b861052019-10-23 14:50:28 +01001225 TraceStorage* storage = context_.storage.get();
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001226
Lalit Magantieac7fff2020-01-10 16:42:54 +00001227 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
1228 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
1229 context_.storage->mutable_thread_table()->mutable_upid()->Set(utid, upid);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001230
Lalit Maganti8d770f72020-01-30 15:44:04 +00001231 auto id_and_row = storage->mutable_raw_table()->Insert(
Lalit Maganti679b29d2020-01-13 13:26:28 +00001232 {kTimestamp, storage->InternString("track_event.legacy_event"), /*cpu=*/0,
1233 utid});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001234 auto inserter = context_.args_tracker->AddArgsTo(id_and_row.id);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001235
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001236 auto add_arg = [&](const char* key, Variadic value) {
1237 StringId key_id = storage->InternString(key);
Lalit Maganti5228f362020-01-15 13:45:56 +00001238 inserter.AddArg(key_id, value);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001239 };
1240
1241 StringId cat_id = storage->InternString(base::StringView(kCategory));
1242 add_arg("legacy_event.category", Variadic::String(cat_id));
1243 StringId name_id = storage->InternString(base::StringView(kName));
1244 add_arg("legacy_event.name", Variadic::String(name_id));
1245 StringId phase_id = storage->InternString(base::StringView(kPhase));
1246 add_arg("legacy_event.phase", Variadic::String(phase_id));
1247
1248 add_arg("legacy_event.duration_ns", Variadic::Integer(kDuration));
1249 add_arg("legacy_event.thread_timestamp_ns",
1250 Variadic::Integer(kThreadTimestamp));
1251 add_arg("legacy_event.thread_duration_ns",
1252 Variadic::Integer(kThreadDuration));
1253 add_arg("legacy_event.thread_instruction_count",
1254 Variadic::Integer(kThreadInstructionCount));
1255 add_arg("legacy_event.thread_instruction_delta",
1256 Variadic::Integer(kThreadInstructionDelta));
1257 add_arg("legacy_event.use_async_tts", Variadic::Boolean(true));
1258 add_arg("legacy_event.global_id", Variadic::UnsignedInteger(kGlobalId));
1259 StringId scope_id = storage->InternString(base::StringView(kIdScope));
1260 add_arg("legacy_event.id_scope", Variadic::String(scope_id));
1261 add_arg("legacy_event.bind_id", Variadic::UnsignedInteger(kBindId));
1262 add_arg("legacy_event.bind_to_enclosing", Variadic::Boolean(true));
1263 StringId flow_direction_id = storage->InternString(kFlowDirection);
1264 add_arg("legacy_event.flow_direction", Variadic::String(flow_direction_id));
1265
1266 add_arg(kArgName, Variadic::Integer(kArgValue));
1267
Eric Seckler4b861052019-10-23 14:50:28 +01001268 context_.args_tracker->Flush();
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001269
1270 base::TempFile temp_file = base::TempFile::Create();
1271 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +01001272 util::Status status = ExportJson(storage, output);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001273
Eric Seckler7fb1d232019-10-23 14:42:43 +01001274 EXPECT_TRUE(status.ok());
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001275
Eric Seckler178094e2019-10-24 14:03:04 +01001276 Json::Value result = ToJsonValue(ReadFile(output));
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001277 EXPECT_EQ(result["traceEvents"].size(), 1u);
1278
1279 Json::Value event = result["traceEvents"][0];
1280 EXPECT_EQ(event["ph"].asString(), kPhase);
1281 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
1282 EXPECT_EQ(event["dur"].asInt64(), kDuration / 1000);
1283 EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
1284 EXPECT_EQ(event["tdur"].asInt64(), kThreadDuration / 1000);
1285 EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
1286 EXPECT_EQ(event["tidelta"].asInt64(), kThreadInstructionDelta);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001287 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001288 EXPECT_EQ(event["cat"].asString(), kCategory);
1289 EXPECT_EQ(event["name"].asString(), kName);
1290 EXPECT_EQ(event["use_async_tts"].asInt(), 1);
1291 EXPECT_EQ(event["id2"]["global"].asString(), "0xaaffaaffaaffaaff");
1292 EXPECT_EQ(event["scope"].asString(), kIdScope);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001293 EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
1294}
1295
Eric Seckler4b861052019-10-23 14:50:28 +01001296TEST_F(ExportJsonTest, LegacyRawEvents) {
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001297 const char* kLegacyFtraceData = "some \"data\"\nsome :data:";
Eric Seckler13b84b32019-10-04 12:00:38 +01001298 const char* kLegacyJsonData1 = "{\"us";
Eric Seckler178094e2019-10-24 14:03:04 +01001299 const char* kLegacyJsonData2 = "er\": 1},{\"user\": 2}";
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001300
Eric Seckler4b861052019-10-23 14:50:28 +01001301 TraceStorage* storage = context_.storage.get();
Lalit Maganti8d770f72020-01-30 15:44:04 +00001302 auto* raw = storage->mutable_raw_table();
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001303
Lalit Maganti8d770f72020-01-30 15:44:04 +00001304 auto id_and_row = raw->Insert(
Lalit Maganti679b29d2020-01-13 13:26:28 +00001305 {0, storage->InternString("chrome_event.legacy_system_trace"), 0, 0});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001306 auto inserter = context_.args_tracker->AddArgsTo(id_and_row.id);
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001307
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001308 StringId data_id = storage->InternString("data");
1309 StringId ftrace_data_id = storage->InternString(kLegacyFtraceData);
Lalit Maganti5228f362020-01-15 13:45:56 +00001310 inserter.AddArg(data_id, Variadic::String(ftrace_data_id));
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001311
Lalit Maganti8d770f72020-01-30 15:44:04 +00001312 id_and_row = raw->Insert(
Lalit Maganti679b29d2020-01-13 13:26:28 +00001313 {0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001314 inserter = context_.args_tracker->AddArgsTo(id_and_row.id);
Eric Seckler13b84b32019-10-04 12:00:38 +01001315 StringId json_data1_id = storage->InternString(kLegacyJsonData1);
Lalit Maganti5228f362020-01-15 13:45:56 +00001316 inserter.AddArg(data_id, Variadic::String(json_data1_id));
Eric Seckler13b84b32019-10-04 12:00:38 +01001317
Lalit Maganti8d770f72020-01-30 15:44:04 +00001318 id_and_row = raw->Insert(
Lalit Maganti679b29d2020-01-13 13:26:28 +00001319 {0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001320 inserter = context_.args_tracker->AddArgsTo(id_and_row.id);
Eric Seckler13b84b32019-10-04 12:00:38 +01001321 StringId json_data2_id = storage->InternString(kLegacyJsonData2);
Lalit Maganti5228f362020-01-15 13:45:56 +00001322 inserter.AddArg(data_id, Variadic::String(json_data2_id));
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001323
Eric Seckler4b861052019-10-23 14:50:28 +01001324 context_.args_tracker->Flush();
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001325
1326 base::TempFile temp_file = base::TempFile::Create();
1327 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +01001328 util::Status status = ExportJson(storage, output);
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001329
Eric Seckler7fb1d232019-10-23 14:42:43 +01001330 EXPECT_TRUE(status.ok());
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001331
Eric Seckler178094e2019-10-24 14:03:04 +01001332 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001333
Eric Seckler178094e2019-10-24 14:03:04 +01001334 EXPECT_EQ(result["traceEvents"].size(), 2u);
1335 EXPECT_EQ(result["traceEvents"][0]["user"].asInt(), 1);
1336 EXPECT_EQ(result["traceEvents"][1]["user"].asInt(), 2);
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001337 EXPECT_EQ(result["systemTraceEvents"].asString(), kLegacyFtraceData);
1338}
1339
Eric Seckler4b861052019-10-23 14:50:28 +01001340TEST_F(ExportJsonTest, CpuProfileEvent) {
Eric Secklerbb0e1542020-01-16 13:44:13 +00001341 const uint32_t kProcessID = 100;
1342 const uint32_t kThreadID = 200;
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001343 const int64_t kTimestamp = 10000000;
Oystein Eftevaag95fe09e2020-04-17 12:55:17 -07001344 const int32_t kProcessPriority = 42;
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001345
Eric Seckler4b861052019-10-23 14:50:28 +01001346 TraceStorage* storage = context_.storage.get();
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001347
Lalit Magantieac7fff2020-01-10 16:42:54 +00001348 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
1349 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
1350 context_.storage->mutable_thread_table()->mutable_upid()->Set(utid, upid);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001351
Lalit Maganti8d770f72020-01-30 15:44:04 +00001352 auto* mappings = storage->mutable_stack_profile_mapping_table();
1353 auto* frames = storage->mutable_stack_profile_frame_table();
1354 auto* callsites = storage->mutable_stack_profile_callsite_table();
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001355
Lalit Maganti8d770f72020-01-30 15:44:04 +00001356 auto module_1 =
1357 mappings->Insert({storage->InternString("foo_module_id"), 0, 0, 0, 0, 0,
1358 storage->InternString("foo_module_name")});
1359
1360 auto module_2 =
1361 mappings->Insert({storage->InternString("bar_module_id"), 0, 0, 0, 0, 0,
1362 storage->InternString("bar_module_name")});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001363
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001364 // TODO(140860736): Once we support null values for
1365 // stack_profile_frame.symbol_set_id remove this hack
Lalit Magantif0599a02020-01-15 15:45:20 +00001366 storage->mutable_symbol_table()->Insert({0, kNullStringId, kNullStringId, 0});
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001367
Lalit Maganti8d770f72020-01-30 15:44:04 +00001368 auto frame_1 = frames->Insert({/*name_id=*/kNullStringId, module_1.id, 0x42});
Lalit Maganti0a29f6f2020-01-06 12:01:14 +00001369
Lalit Maganti7e24f062019-12-17 18:10:35 +00001370 uint32_t symbol_set_id = storage->symbol_table().row_count();
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001371 storage->mutable_symbol_table()->Insert(
1372 {symbol_set_id, storage->InternString("foo_func"),
1373 storage->InternString("foo_file"), 66});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001374 frames->mutable_symbol_set_id()->Set(frame_1.row, symbol_set_id);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001375
Lalit Maganti8d770f72020-01-30 15:44:04 +00001376 auto frame_2 =
1377 frames->Insert({/*name_id=*/kNullStringId, module_2.id, 0x4242});
Lalit Maganti0a29f6f2020-01-06 12:01:14 +00001378
Lalit Maganti7e24f062019-12-17 18:10:35 +00001379 symbol_set_id = storage->symbol_table().row_count();
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001380 storage->mutable_symbol_table()->Insert(
1381 {symbol_set_id, storage->InternString("bar_func"),
1382 storage->InternString("bar_file"), 77});
Lalit Maganti8d770f72020-01-30 15:44:04 +00001383 frames->mutable_symbol_set_id()->Set(frame_2.row, symbol_set_id);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001384
Lalit Maganti8d770f72020-01-30 15:44:04 +00001385 auto frame_callsite_1 = callsites->Insert({0, base::nullopt, frame_1.id});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001386
Lalit Maganti8d770f72020-01-30 15:44:04 +00001387 auto frame_callsite_2 =
1388 callsites->Insert({1, frame_callsite_1.id, frame_2.id});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001389
Lalit Maganti0fd14ef2019-12-18 18:18:44 +00001390 storage->mutable_cpu_profile_stack_sample_table()->Insert(
Oystein Eftevaag95fe09e2020-04-17 12:55:17 -07001391 {kTimestamp, frame_callsite_2.id, utid, kProcessPriority});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001392
1393 base::TempFile temp_file = base::TempFile::Create();
1394 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +01001395 util::Status status = ExportJson(storage, output);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001396
Eric Seckler7fb1d232019-10-23 14:42:43 +01001397 EXPECT_TRUE(status.ok());
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001398
Eric Seckler178094e2019-10-24 14:03:04 +01001399 Json::Value result = ToJsonValue(ReadFile(output));
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001400
1401 EXPECT_EQ(result["traceEvents"].size(), 1u);
1402 Json::Value event = result["traceEvents"][0];
Oystein Eftevaaga33094d2019-11-12 10:48:15 -08001403 EXPECT_EQ(event["ph"].asString(), "n");
1404 EXPECT_EQ(event["id"].asString(), "0x1");
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001405 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001406 EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
Oystein Eftevaagbdd9db22020-02-04 12:52:01 -08001407 EXPECT_EQ(event["cat"].asString(), "disabled-by-default-cpu_profiler");
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001408 EXPECT_EQ(event["name"].asString(), "StackCpuSampling");
Eric Seckler9dc34462019-11-06 14:44:20 +00001409 EXPECT_EQ(event["s"].asString(), "t");
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001410 EXPECT_EQ(event["args"]["frames"].asString(),
1411 "foo_func - foo_module_name [foo_module_id]\nbar_func - "
1412 "bar_module_name [bar_module_id]\n");
Oystein Eftevaag95fe09e2020-04-17 12:55:17 -07001413 EXPECT_EQ(event["args"]["process_priority"].asInt(), kProcessPriority);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001414}
1415
Eric Seckler178094e2019-10-24 14:03:04 +01001416TEST_F(ExportJsonTest, ArgumentFilter) {
Lalit Magantieac7fff2020-01-10 16:42:54 +00001417 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +00001418 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler178094e2019-10-24 14:03:04 +01001419 context_.args_tracker->Flush(); // Flush track args.
1420
1421 StringId cat_id = context_.storage->InternString(base::StringView("cat"));
1422 std::array<StringId, 3> name_ids{
1423 context_.storage->InternString(base::StringView("name1")),
1424 context_.storage->InternString(base::StringView("name2")),
1425 context_.storage->InternString(base::StringView("name3"))};
1426 StringId arg1_id = context_.storage->InternString(base::StringView("arg1"));
1427 StringId arg2_id = context_.storage->InternString(base::StringView("arg2"));
1428 StringId val_id = context_.storage->InternString(base::StringView("val"));
1429
Lalit Maganti8d770f72020-01-30 15:44:04 +00001430 auto* slices = context_.storage->mutable_slice_table();
Lalit Maganti5228f362020-01-15 13:45:56 +00001431 std::vector<ArgsTracker::BoundInserter> slice_inserters;
Eric Seckler178094e2019-10-24 14:03:04 +01001432 for (size_t i = 0; i < name_ids.size(); i++) {
Lalit Maganti8d770f72020-01-30 15:44:04 +00001433 auto id = slices->Insert({0, 0, track, cat_id, name_ids[i], 0, 0, 0}).id;
1434 slice_inserters.emplace_back(context_.args_tracker->AddArgsTo(id));
Eric Seckler178094e2019-10-24 14:03:04 +01001435 }
1436
Lalit Maganti5228f362020-01-15 13:45:56 +00001437 for (auto& inserter : slice_inserters) {
1438 inserter.AddArg(arg1_id, Variadic::Integer(5))
1439 .AddArg(arg2_id, Variadic::String(val_id));
Eric Seckler178094e2019-10-24 14:03:04 +01001440 }
1441 context_.args_tracker->Flush();
1442
1443 auto arg_filter = [](const char* category_group_name, const char* event_name,
1444 ArgumentNameFilterPredicate* arg_name_filter) {
1445 EXPECT_TRUE(strcmp(category_group_name, "cat") == 0);
1446 if (strcmp(event_name, "name1") == 0) {
1447 // Filter all args for name1.
1448 return false;
1449 } else if (strcmp(event_name, "name2") == 0) {
1450 // Filter only the second arg for name2.
1451 *arg_name_filter = [](const char* arg_name) {
1452 if (strcmp(arg_name, "arg1") == 0) {
1453 return true;
1454 }
1455 EXPECT_TRUE(strcmp(arg_name, "arg2") == 0);
1456 return false;
1457 };
1458 return true;
1459 }
1460 // Filter no args for name3.
1461 EXPECT_TRUE(strcmp(event_name, "name3") == 0);
1462 return true;
1463 };
1464
1465 Json::Value result = ToJsonValue(ToJson(arg_filter));
1466
1467 EXPECT_EQ(result["traceEvents"].size(), 3u);
1468
1469 EXPECT_EQ(result["traceEvents"][0]["cat"].asString(), "cat");
1470 EXPECT_EQ(result["traceEvents"][0]["name"].asString(), "name1");
1471 EXPECT_EQ(result["traceEvents"][0]["args"].asString(), "__stripped__");
1472
1473 EXPECT_EQ(result["traceEvents"][1]["cat"].asString(), "cat");
1474 EXPECT_EQ(result["traceEvents"][1]["name"].asString(), "name2");
1475 EXPECT_EQ(result["traceEvents"][1]["args"]["arg1"].asInt(), 5);
1476 EXPECT_EQ(result["traceEvents"][1]["args"]["arg2"].asString(),
1477 "__stripped__");
1478
1479 EXPECT_EQ(result["traceEvents"][2]["cat"].asString(), "cat");
1480 EXPECT_EQ(result["traceEvents"][2]["name"].asString(), "name3");
1481 EXPECT_EQ(result["traceEvents"][2]["args"]["arg1"].asInt(), 5);
1482 EXPECT_EQ(result["traceEvents"][2]["args"]["arg2"].asString(), "val");
1483}
1484
1485TEST_F(ExportJsonTest, MetadataFilter) {
1486 const char* kName1 = "name1";
1487 const char* kName2 = "name2";
1488 const char* kValue1 = "value1";
1489 const int kValue2 = 222;
1490
1491 TraceStorage* storage = context_.storage.get();
1492
Lalit Maganti8d770f72020-01-30 15:44:04 +00001493 auto* raw = storage->mutable_raw_table();
1494 RawId id =
1495 raw->Insert({0, storage->InternString("chrome_event.metadata"), 0, 0}).id;
Eric Seckler178094e2019-10-24 14:03:04 +01001496
1497 StringId name1_id = storage->InternString(base::StringView(kName1));
1498 StringId name2_id = storage->InternString(base::StringView(kName2));
1499 StringId value1_id = storage->InternString(base::StringView(kValue1));
Lalit Maganti5228f362020-01-15 13:45:56 +00001500
1501 context_.args_tracker->AddArgsTo(id)
1502 .AddArg(name1_id, Variadic::String(value1_id))
1503 .AddArg(name2_id, Variadic::Integer(kValue2));
Eric Seckler178094e2019-10-24 14:03:04 +01001504 context_.args_tracker->Flush();
1505
1506 auto metadata_filter = [](const char* metadata_name) {
1507 // Only allow name1.
1508 return strcmp(metadata_name, "name1") == 0;
1509 };
1510
1511 Json::Value result = ToJsonValue(ToJson(nullptr, metadata_filter));
1512
1513 EXPECT_TRUE(result.isMember("metadata"));
1514 Json::Value metadata = result["metadata"];
1515
1516 EXPECT_EQ(metadata[kName1].asString(), kValue1);
1517 EXPECT_EQ(metadata[kName2].asString(), "__stripped__");
1518}
1519
1520TEST_F(ExportJsonTest, LabelFilter) {
1521 const int64_t kTimestamp1 = 10000000;
1522 const int64_t kTimestamp2 = 20000000;
1523 const int64_t kDuration = 10000;
Eric Secklerbb0e1542020-01-16 13:44:13 +00001524 const uint32_t kThreadID = 100;
Eric Seckler178094e2019-10-24 14:03:04 +01001525 const char* kCategory = "cat";
1526 const char* kName = "name";
1527
Lalit Magantieac7fff2020-01-10 16:42:54 +00001528 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +00001529 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler178094e2019-10-24 14:03:04 +01001530 context_.args_tracker->Flush(); // Flush track args.
1531 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
1532 StringId name_id = context_.storage->InternString(base::StringView(kName));
1533
Lalit Magantic7ea02e2019-12-12 14:06:49 +00001534 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +00001535 {kTimestamp1, kDuration, track, cat_id, name_id, 0, 0, 0});
Lalit Magantic7ea02e2019-12-12 14:06:49 +00001536 context_.storage->mutable_slice_table()->Insert(
Lalit Maganti8d770f72020-01-30 15:44:04 +00001537 {kTimestamp2, kDuration, track, cat_id, name_id, 0, 0, 0});
Eric Seckler178094e2019-10-24 14:03:04 +01001538
1539 auto label_filter = [](const char* label_name) {
1540 return strcmp(label_name, "traceEvents") == 0;
1541 };
1542
1543 Json::Value result =
1544 ToJsonValue("[" + ToJson(nullptr, nullptr, label_filter) + "]");
1545
1546 EXPECT_TRUE(result.isArray());
1547 EXPECT_EQ(result.size(), 2u);
1548
1549 EXPECT_EQ(result[0]["ph"].asString(), "X");
1550 EXPECT_EQ(result[0]["ts"].asInt64(), kTimestamp1 / 1000);
1551 EXPECT_EQ(result[0]["dur"].asInt64(), kDuration / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001552 EXPECT_EQ(result[0]["tid"].asInt(), static_cast<int>(kThreadID));
Eric Seckler178094e2019-10-24 14:03:04 +01001553 EXPECT_EQ(result[0]["cat"].asString(), kCategory);
1554 EXPECT_EQ(result[0]["name"].asString(), kName);
1555 EXPECT_EQ(result[1]["ph"].asString(), "X");
1556 EXPECT_EQ(result[1]["ts"].asInt64(), kTimestamp2 / 1000);
1557 EXPECT_EQ(result[1]["dur"].asInt64(), kDuration / 1000);
Eric Seckler88cab6f2020-01-16 18:33:45 +00001558 EXPECT_EQ(result[1]["tid"].asInt(), static_cast<int>(kThreadID));
Eric Seckler178094e2019-10-24 14:03:04 +01001559 EXPECT_EQ(result[1]["cat"].asString(), kCategory);
1560 EXPECT_EQ(result[1]["name"].asString(), kName);
1561}
Eric Seckler7fb1d232019-10-23 14:42:43 +01001562
Tomasz Konieczny6e2d3dd2020-11-04 15:54:04 +01001563TEST_F(ExportJsonTest, MemorySnapshotOsDumpEvent) {
1564 const int64_t kTimestamp = 10000000;
1565 const int64_t kPeakResidentSetSize = 100000;
1566 const int64_t kPrivateFootprintBytes = 200000;
1567 const int64_t kProtectionFlags = 1;
1568 const int64_t kStartAddress = 1000000000;
1569 const int64_t kSizeKb = 1000;
1570 const int64_t kPrivateCleanResidentKb = 2000;
1571 const int64_t kPrivateDirtyKb = 3000;
1572 const int64_t kProportionalResidentKb = 4000;
1573 const int64_t kSharedCleanResidentKb = 5000;
1574 const int64_t kSharedDirtyResidentKb = 6000;
1575 const int64_t kSwapKb = 7000;
1576 const int64_t kModuleTimestamp = 20000000;
1577 const uint32_t kProcessID = 100;
1578 const bool kIsPeakRssResettable = true;
1579 const char* kLevelOfDetail = "detailed";
1580 const char* kFileName = "filename";
1581 const char* kModuleDebugid = "debugid";
1582 const char* kModuleDebugPath = "debugpath";
1583
1584 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
1585 TrackId track = context_.track_tracker->InternProcessTrack(upid);
1586 StringId level_of_detail_id =
1587 context_.storage->InternString(base::StringView(kLevelOfDetail));
1588 auto snapshot_id = context_.storage->mutable_memory_snapshot_table()
1589 ->Insert({kTimestamp, track, level_of_detail_id})
1590 .id;
1591
1592 StringId peak_resident_set_size_id =
1593 context_.storage->InternString("chrome.peak_resident_set_kb");
1594 TrackId peak_resident_set_size_counter =
1595 context_.track_tracker->InternProcessCounterTrack(
1596 peak_resident_set_size_id, upid);
1597 context_.event_tracker->PushCounter(kTimestamp, kPeakResidentSetSize,
1598 peak_resident_set_size_counter);
1599
1600 StringId private_footprint_bytes_id =
1601 context_.storage->InternString("chrome.private_footprint_kb");
1602 TrackId private_footprint_bytes_counter =
1603 context_.track_tracker->InternProcessCounterTrack(
1604 private_footprint_bytes_id, upid);
1605 context_.event_tracker->PushCounter(kTimestamp, kPrivateFootprintBytes,
1606 private_footprint_bytes_counter);
1607
1608 StringId is_peak_rss_resettable_id =
1609 context_.storage->InternString("is_peak_rss_resettable");
1610 context_.args_tracker->AddArgsTo(upid).AddArg(
1611 is_peak_rss_resettable_id, Variadic::Boolean(kIsPeakRssResettable));
1612 context_.args_tracker->Flush();
1613
1614 context_.storage->mutable_profiler_smaps_table()->Insert(
1615 {upid, kTimestamp, kNullStringId, kSizeKb, kPrivateDirtyKb, kSwapKb,
1616 context_.storage->InternString(kFileName), kStartAddress,
1617 kModuleTimestamp, context_.storage->InternString(kModuleDebugid),
1618 context_.storage->InternString(kModuleDebugPath), kProtectionFlags,
1619 kPrivateCleanResidentKb, kSharedDirtyResidentKb, kSharedCleanResidentKb,
1620 0, kProportionalResidentKb});
1621
1622 base::TempFile temp_file = base::TempFile::Create();
1623 FILE* output = fopen(temp_file.path().c_str(), "w+");
1624 util::Status status = ExportJson(context_.storage.get(), output);
1625
1626 EXPECT_TRUE(status.ok());
1627
1628 Json::Value result = ToJsonValue(ReadFile(output));
1629 EXPECT_EQ(result["traceEvents"].size(), 1u);
1630
1631 Json::Value event = result["traceEvents"][0];
1632 EXPECT_EQ(event["ph"].asString(), "v");
1633 EXPECT_EQ(event["cat"].asString(), "disabled-by-default-memory-infra");
1634 EXPECT_EQ(event["id"].asString(), base::Uint64ToHexString(snapshot_id.value));
1635 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
1636 EXPECT_EQ(event["name"].asString(), "periodic_interval");
1637 EXPECT_EQ(event["pid"].asUInt(), kProcessID);
1638 EXPECT_EQ(event["tid"].asInt(), -1);
1639
1640 EXPECT_TRUE(event["args"].isObject());
1641 EXPECT_EQ(event["args"]["dumps"]["level_of_detail"].asString(),
1642 kLevelOfDetail);
1643
1644 EXPECT_EQ(event["args"]["dumps"]["process_totals"]["peak_resident_set_size"]
1645 .asString(),
1646 base::Uint64ToHexStringNoPrefix(
1647 static_cast<uint64_t>(kPeakResidentSetSize)));
1648 EXPECT_EQ(event["args"]["dumps"]["process_totals"]["private_footprint_bytes"]
1649 .asString(),
1650 base::Uint64ToHexStringNoPrefix(
1651 static_cast<uint64_t>(kPrivateFootprintBytes)));
1652 EXPECT_EQ(event["args"]["dumps"]["process_totals"]["is_peak_rss_resettable"]
1653 .asBool(),
1654 kIsPeakRssResettable);
1655
1656 EXPECT_TRUE(event["args"]["dumps"]["process_mmaps"]["vm_regions"].isArray());
1657 EXPECT_EQ(event["args"]["dumps"]["process_mmaps"]["vm_regions"].size(), 1u);
1658 Json::Value region = event["args"]["dumps"]["process_mmaps"]["vm_regions"][0];
1659 EXPECT_EQ(region["mf"].asString(), kFileName);
1660 EXPECT_EQ(region["pf"].asInt64(), kProtectionFlags);
1661 EXPECT_EQ(region["sa"].asString(), base::Uint64ToHexStringNoPrefix(
1662 static_cast<uint64_t>(kStartAddress)));
1663 EXPECT_EQ(region["sz"].asString(),
1664 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSizeKb)));
1665 EXPECT_EQ(region["id"].asString(), kModuleDebugid);
1666 EXPECT_EQ(region["df"].asString(), kModuleDebugPath);
1667 EXPECT_EQ(region["bs"]["pc"].asString(),
1668 base::Uint64ToHexStringNoPrefix(
1669 static_cast<uint64_t>(kPrivateCleanResidentKb)));
1670 EXPECT_EQ(
1671 region["bs"]["pd"].asString(),
1672 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kPrivateDirtyKb)));
1673 EXPECT_EQ(region["bs"]["pss"].asString(),
1674 base::Uint64ToHexStringNoPrefix(
1675 static_cast<uint64_t>(kProportionalResidentKb)));
1676 EXPECT_EQ(region["bs"]["sc"].asString(),
1677 base::Uint64ToHexStringNoPrefix(
1678 static_cast<uint64_t>(kSharedCleanResidentKb)));
1679 EXPECT_EQ(region["bs"]["sd"].asString(),
1680 base::Uint64ToHexStringNoPrefix(
1681 static_cast<uint64_t>(kSharedDirtyResidentKb)));
1682 EXPECT_EQ(region["bs"]["sw"].asString(),
1683 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSwapKb)));
1684}
1685
1686TEST_F(ExportJsonTest, MemorySnapshotChromeDumpEvent) {
1687 const int64_t kTimestamp = 10000000;
1688 const int64_t kSize = 1000;
1689 const int64_t kEffectiveSize = 2000;
1690 const int64_t kScalarAttrValue = 3000;
1691 const uint32_t kOsProcessID = 100;
1692 const uint32_t kChromeProcessID = 200;
1693 const uint32_t kImportance = 1;
1694 const char* kLevelOfDetail = "detailed";
1695 const char* kPath1 = "path/to_file1";
1696 const char* kPath2 = "path/to_file2";
1697 const char* kScalarAttrUnits = "scalar_units";
1698 const char* kStringAttrValue = "string_value";
1699 const std::string kScalarAttrName = "scalar_name";
1700 const std::string kStringAttrName = "string_name";
1701
1702 UniquePid os_upid =
1703 context_.process_tracker->GetOrCreateProcess(kOsProcessID);
1704 TrackId track = context_.track_tracker->InternProcessTrack(os_upid);
1705 StringId level_of_detail_id =
1706 context_.storage->InternString(base::StringView(kLevelOfDetail));
1707 auto snapshot_id = context_.storage->mutable_memory_snapshot_table()
1708 ->Insert({kTimestamp, track, level_of_detail_id})
1709 .id;
1710
1711 UniquePid chrome_upid =
1712 context_.process_tracker->GetOrCreateProcess(kChromeProcessID);
1713 auto process_id = context_.storage->mutable_process_memory_snapshot_table()
1714 ->Insert({snapshot_id, chrome_upid})
1715 .id;
1716
1717 StringId path1_id = context_.storage->InternString(base::StringView(kPath1));
1718 StringId path2_id = context_.storage->InternString(base::StringView(kPath2));
1719 SnapshotNodeId node1_id =
1720 context_.storage->mutable_memory_snapshot_node_table()
1721 ->Insert(
1722 {process_id, SnapshotNodeId(0), path1_id, kSize, kEffectiveSize})
1723 .id;
1724 SnapshotNodeId node2_id =
1725 context_.storage->mutable_memory_snapshot_node_table()
1726 ->Insert({process_id, SnapshotNodeId(0), path2_id, 0, 0})
1727 .id;
1728
1729 context_.args_tracker->AddArgsTo(node1_id).AddArg(
1730 context_.storage->InternString(
1731 base::StringView(kScalarAttrName + ".value")),
1732 Variadic::Integer(kScalarAttrValue));
1733 context_.args_tracker->AddArgsTo(node1_id).AddArg(
1734 context_.storage->InternString(
1735 base::StringView(kScalarAttrName + ".unit")),
1736 Variadic::String(context_.storage->InternString(kScalarAttrUnits)));
1737 context_.args_tracker->AddArgsTo(node1_id).AddArg(
1738 context_.storage->InternString(
1739 base::StringView(kStringAttrName + ".value")),
1740 Variadic::String(context_.storage->InternString(kStringAttrValue)));
1741 context_.args_tracker->Flush();
1742
1743 context_.storage->mutable_memory_snapshot_edge_table()->Insert(
1744 {node1_id, node2_id, kImportance});
1745
1746 base::TempFile temp_file = base::TempFile::Create();
1747 FILE* output = fopen(temp_file.path().c_str(), "w+");
1748 util::Status status = ExportJson(context_.storage.get(), output);
1749
1750 EXPECT_TRUE(status.ok());
1751
1752 Json::Value result = ToJsonValue(ReadFile(output));
1753 EXPECT_EQ(result["traceEvents"].size(), 1u);
1754
1755 Json::Value event = result["traceEvents"][0];
1756 EXPECT_EQ(event["ph"].asString(), "v");
1757 EXPECT_EQ(event["cat"].asString(), "disabled-by-default-memory-infra");
1758 EXPECT_EQ(event["id"].asString(), base::Uint64ToHexString(snapshot_id.value));
1759 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
1760 EXPECT_EQ(event["name"].asString(), "periodic_interval");
1761 EXPECT_EQ(event["pid"].asUInt(), kChromeProcessID);
1762 EXPECT_EQ(event["tid"].asInt(), -1);
1763
1764 EXPECT_TRUE(event["args"].isObject());
1765 EXPECT_EQ(event["args"]["dumps"]["level_of_detail"].asString(),
1766 kLevelOfDetail);
1767
1768 EXPECT_EQ(event["args"]["dumps"]["allocators"].size(), 2u);
1769 Json::Value node1 = event["args"]["dumps"]["allocators"][kPath1];
1770 EXPECT_TRUE(node1.isObject());
1771 EXPECT_EQ(
1772 node1["guid"].asString(),
1773 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node1_id.value)));
1774 EXPECT_TRUE(node1["attrs"]["size"].isObject());
1775 EXPECT_EQ(node1["attrs"]["size"]["value"].asString(),
1776 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSize)));
1777 EXPECT_EQ(node1["attrs"]["size"]["type"].asString(), "scalar");
1778 EXPECT_EQ(node1["attrs"]["size"]["units"].asString(), "bytes");
1779 EXPECT_EQ(
1780 node1["attrs"]["effective_size"]["value"].asString(),
1781 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kEffectiveSize)));
1782 EXPECT_TRUE(node1["attrs"][kScalarAttrName].isObject());
1783 EXPECT_EQ(
1784 node1["attrs"][kScalarAttrName]["value"].asString(),
1785 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kScalarAttrValue)));
1786 EXPECT_EQ(node1["attrs"][kScalarAttrName]["type"].asString(), "scalar");
1787 EXPECT_EQ(node1["attrs"][kScalarAttrName]["units"].asString(),
1788 kScalarAttrUnits);
1789 EXPECT_TRUE(node1["attrs"][kStringAttrName].isObject());
1790 EXPECT_EQ(node1["attrs"][kStringAttrName]["value"].asString(),
1791 kStringAttrValue);
1792 EXPECT_EQ(node1["attrs"][kStringAttrName]["type"].asString(), "string");
1793 EXPECT_EQ(node1["attrs"][kStringAttrName]["units"].asString(), "");
1794
1795 Json::Value node2 = event["args"]["dumps"]["allocators"][kPath2];
1796 EXPECT_TRUE(node2.isObject());
1797 EXPECT_EQ(
1798 node2["guid"].asString(),
1799 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node2_id.value)));
1800 EXPECT_TRUE(node2["attrs"].empty());
1801
1802 Json::Value graph = event["args"]["dumps"]["allocators_graph"];
1803 EXPECT_TRUE(graph.isArray());
1804 EXPECT_EQ(graph.size(), 1u);
1805 EXPECT_EQ(
1806 graph[0]["source"].asString(),
1807 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node1_id.value)));
1808 EXPECT_EQ(
1809 graph[0]["target"].asString(),
1810 base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node2_id.value)));
1811 EXPECT_EQ(graph[0]["importance"].asUInt(), kImportance);
1812 EXPECT_EQ(graph[0]["type"].asString(), "ownership");
1813}
1814
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +01001815} // namespace
1816} // namespace json
1817} // namespace trace_processor
1818} // namespace perfetto