blob: c7cf7ab685a79f7a0ed6ab2b507fdacd4d5a6dc7 [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
Primiano Tucci2c5488f2019-06-01 03:27:28 +010027#include "perfetto/ext/base/temp_file.h"
Eric Secklerc34c8fc2019-08-02 10:57:59 +010028#include "src/trace_processor/args_tracker.h"
Lalit Magantiededb0e2020-01-08 12:50:34 +000029#include "src/trace_processor/metadata_tracker.h"
Lalit Magantieac7fff2020-01-10 16:42:54 +000030#include "src/trace_processor/process_tracker.h"
Eric Secklerc34c8fc2019-08-02 10:57:59 +010031#include "src/trace_processor/trace_processor_context.h"
Eric Seckler4b861052019-10-23 14:50:28 +010032#include "src/trace_processor/track_tracker.h"
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010033
Primiano Tucci919ca1e2019-08-21 20:26:58 +020034#include "test/gtest_and_gmock.h"
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010035
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010036namespace perfetto {
37namespace trace_processor {
38namespace json {
39namespace {
40
41std::string ReadFile(FILE* input) {
42 fseek(input, 0, SEEK_SET);
Eric Secklere2b4e5c2019-12-06 14:37:29 +000043 const int kBufSize = 10000;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010044 char buffer[kBufSize];
Lalit Magantid9983462019-05-09 18:10:09 +010045 size_t ret = fread(buffer, sizeof(char), kBufSize, input);
Primiano Tucci225a4e62019-06-06 11:13:57 +010046 EXPECT_GT(ret, 0u);
Lalit Magantid9983462019-05-09 18:10:09 +010047 return std::string(buffer, ret);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010048}
49
Eric Seckler178094e2019-10-24 14:03:04 +010050class StringOutputWriter : public OutputWriter {
51 public:
52 StringOutputWriter() { str_.reserve(1024); }
53 ~StringOutputWriter() override {}
54
55 util::Status AppendString(const std::string& str) override {
56 str_ += str;
57 return util::OkStatus();
58 }
59
60 std::string TakeStr() { return std::move(str_); }
61
62 private:
63 std::string str_;
64};
65
Eric Seckler4b861052019-10-23 14:50:28 +010066class ExportJsonTest : public ::testing::Test {
67 public:
68 ExportJsonTest() {
Lalit Maganti1908e262020-01-09 14:33:19 +000069 context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
Eric Seckler4b861052019-10-23 14:50:28 +010070 context_.args_tracker.reset(new ArgsTracker(&context_));
71 context_.storage.reset(new TraceStorage());
72 context_.track_tracker.reset(new TrackTracker(&context_));
Lalit Magantiededb0e2020-01-08 12:50:34 +000073 context_.metadata_tracker.reset(new MetadataTracker(&context_));
Lalit Magantieac7fff2020-01-10 16:42:54 +000074 context_.process_tracker.reset(new ProcessTracker(&context_));
Eric Seckler4b861052019-10-23 14:50:28 +010075 }
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +010076
Eric Seckler178094e2019-10-24 14:03:04 +010077 std::string ToJson(ArgumentFilterPredicate argument_filter = nullptr,
78 MetadataFilterPredicate metadata_filter = nullptr,
79 LabelFilterPredicate label_filter = nullptr) {
80 StringOutputWriter writer;
81 util::Status status =
82 ExportJson(context_.storage.get(), &writer, argument_filter,
83 metadata_filter, label_filter);
84 EXPECT_TRUE(status.ok());
85 return writer.TakeStr();
86 }
87
88 Json::Value ToJsonValue(const std::string& json) {
89 Json::Reader reader;
90 Json::Value result;
Eric Secklere2b4e5c2019-12-06 14:37:29 +000091 EXPECT_TRUE(reader.parse(json, result)) << json;
Eric Seckler178094e2019-10-24 14:03:04 +010092 return result;
93 }
94
Eric Seckler4b861052019-10-23 14:50:28 +010095 protected:
96 TraceProcessorContext context_;
97};
98
99TEST_F(ExportJsonTest, EmptyStorage) {
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100100 base::TempFile temp_file = base::TempFile::Create();
101 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100102 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100103
Eric Seckler7fb1d232019-10-23 14:42:43 +0100104 EXPECT_TRUE(status.ok());
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100105
Eric Seckler178094e2019-10-24 14:03:04 +0100106 Json::Value result = ToJsonValue(ReadFile(output));
Primiano Tucci225a4e62019-06-06 11:13:57 +0100107 EXPECT_EQ(result["traceEvents"].size(), 0u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100108}
109
Eric Seckler4b861052019-10-23 14:50:28 +0100110TEST_F(ExportJsonTest, StorageWithOneSlice) {
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100111 const int64_t kTimestamp = 10000000;
112 const int64_t kDuration = 10000;
Mikhail Khokhlov7db04912019-07-18 16:11:11 +0100113 const int64_t kThreadTimestamp = 20000000;
114 const int64_t kThreadDuration = 20000;
Eric Seckler77fb1d22019-07-31 17:02:51 +0100115 const int64_t kThreadInstructionCount = 30000000;
116 const int64_t kThreadInstructionDelta = 30000;
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100117 const int64_t kThreadID = 100;
118 const char* kCategory = "cat";
119 const char* kName = "name";
120
Lalit Magantieac7fff2020-01-10 16:42:54 +0000121 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000122 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100123 context_.args_tracker->Flush(); // Flush track args.
124 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
125 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000126 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000127 {kTimestamp, kDuration, track.value, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100128 context_.storage->mutable_thread_slices()->AddThreadSlice(
Eric Seckler77fb1d22019-07-31 17:02:51 +0100129 0, kThreadTimestamp, kThreadDuration, kThreadInstructionCount,
130 kThreadInstructionDelta);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100131
132 base::TempFile temp_file = base::TempFile::Create();
133 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100134 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100135
Eric Seckler7fb1d232019-10-23 14:42:43 +0100136 EXPECT_TRUE(status.ok());
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100137
Eric Seckler178094e2019-10-24 14:03:04 +0100138 Json::Value result = ToJsonValue(ReadFile(output));
Primiano Tucci225a4e62019-06-06 11:13:57 +0100139 EXPECT_EQ(result["traceEvents"].size(), 1u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100140
141 Json::Value event = result["traceEvents"][0];
142 EXPECT_EQ(event["ph"].asString(), "X");
143 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
144 EXPECT_EQ(event["dur"].asInt64(), kDuration / 1000);
Mikhail Khokhlov7db04912019-07-18 16:11:11 +0100145 EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
146 EXPECT_EQ(event["tdur"].asInt64(), kThreadDuration / 1000);
Eric Seckler77fb1d22019-07-31 17:02:51 +0100147 EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
148 EXPECT_EQ(event["tidelta"].asInt64(), kThreadInstructionDelta);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100149 EXPECT_EQ(event["tid"].asUInt(), kThreadID);
150 EXPECT_EQ(event["cat"].asString(), kCategory);
151 EXPECT_EQ(event["name"].asString(), kName);
Eric Secklerf91236e2019-11-04 10:25:45 +0000152 EXPECT_TRUE(event["args"].isObject());
153 EXPECT_EQ(event["args"].size(), 0u);
Eric Seckler206db472019-07-25 12:05:27 +0100154}
Eric Seckler6f13e332019-10-15 12:14:04 +0100155
Eric Seckler4b861052019-10-23 14:50:28 +0100156TEST_F(ExportJsonTest, StorageWithOneUnfinishedSlice) {
Eric Seckler206db472019-07-25 12:05:27 +0100157 const int64_t kTimestamp = 10000000;
158 const int64_t kDuration = -1;
159 const int64_t kThreadTimestamp = 20000000;
160 const int64_t kThreadDuration = -1;
Eric Seckler77fb1d22019-07-31 17:02:51 +0100161 const int64_t kThreadInstructionCount = 30000000;
162 const int64_t kThreadInstructionDelta = -1;
Eric Seckler206db472019-07-25 12:05:27 +0100163 const int64_t kThreadID = 100;
164 const char* kCategory = "cat";
165 const char* kName = "name";
166
Lalit Magantieac7fff2020-01-10 16:42:54 +0000167 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000168 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100169 context_.args_tracker->Flush(); // Flush track args.
170 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
171 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000172 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000173 {kTimestamp, kDuration, track.value, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100174 context_.storage->mutable_thread_slices()->AddThreadSlice(
Eric Seckler77fb1d22019-07-31 17:02:51 +0100175 0, kThreadTimestamp, kThreadDuration, kThreadInstructionCount,
176 kThreadInstructionDelta);
Eric Seckler206db472019-07-25 12:05:27 +0100177
178 base::TempFile temp_file = base::TempFile::Create();
179 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100180 util::Status status = ExportJson(context_.storage.get(), output);
Eric Seckler206db472019-07-25 12:05:27 +0100181
Eric Seckler7fb1d232019-10-23 14:42:43 +0100182 EXPECT_TRUE(status.ok());
Eric Seckler206db472019-07-25 12:05:27 +0100183
Eric Seckler178094e2019-10-24 14:03:04 +0100184 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler206db472019-07-25 12:05:27 +0100185 EXPECT_EQ(result["traceEvents"].size(), 1u);
186
187 Json::Value event = result["traceEvents"][0];
188 EXPECT_EQ(event["ph"].asString(), "B");
189 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
190 EXPECT_FALSE(event.isMember("dur"));
191 EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
192 EXPECT_FALSE(event.isMember("tdur"));
Eric Seckler77fb1d22019-07-31 17:02:51 +0100193 EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
194 EXPECT_FALSE(event.isMember("tidelta"));
Eric Seckler206db472019-07-25 12:05:27 +0100195 EXPECT_EQ(event["tid"].asUInt(), kThreadID);
196 EXPECT_EQ(event["cat"].asString(), kCategory);
197 EXPECT_EQ(event["name"].asString(), kName);
Eric Secklerf91236e2019-11-04 10:25:45 +0000198 EXPECT_TRUE(event["args"].isObject());
199 EXPECT_EQ(event["args"].size(), 0u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100200}
201
Eric Seckler4b861052019-10-23 14:50:28 +0100202TEST_F(ExportJsonTest, StorageWithThreadName) {
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100203 const int64_t kThreadID = 100;
204 const char* kName = "thread";
205
Lalit Magantieac7fff2020-01-10 16:42:54 +0000206 tables::ThreadTable::Row row(kThreadID);
207 row.name = context_.storage->InternString(base::StringView(kName));
208 context_.storage->mutable_thread_table()->Insert(row);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100209
210 base::TempFile temp_file = base::TempFile::Create();
211 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100212 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100213
Eric Seckler7fb1d232019-10-23 14:42:43 +0100214 EXPECT_TRUE(status.ok());
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100215
Eric Seckler178094e2019-10-24 14:03:04 +0100216 Json::Value result = ToJsonValue(ReadFile(output));
Primiano Tucci225a4e62019-06-06 11:13:57 +0100217 EXPECT_EQ(result["traceEvents"].size(), 1u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100218
219 Json::Value event = result["traceEvents"][0];
220 EXPECT_EQ(event["ph"].asString(), "M");
221 EXPECT_EQ(event["tid"].asUInt(), kThreadID);
222 EXPECT_EQ(event["name"].asString(), "thread_name");
223 EXPECT_EQ(event["args"]["name"].asString(), kName);
224}
225
Eric Seckler3183c6d2020-01-14 15:45:20 +0000226TEST_F(ExportJsonTest, SystemEventsIgnored) {
Eric Seckler4b861052019-10-23 14:50:28 +0100227 constexpr int64_t kCookie = 22;
228 TrackId track = context_.track_tracker->InternAndroidAsyncTrack(
229 /*name=*/0, /*upid=*/0, kCookie);
230 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti21b21632019-09-28 16:50:23 +0100231
Eric Seckler3183c6d2020-01-14 15:45:20 +0000232 // System events have no category.
233 StringId cat_id = kNullStringId;
Eric Seckler4b861052019-10-23 14:50:28 +0100234 StringId name_id = context_.storage->InternString("name");
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000235 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000236 {0, 0, track.value, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100237
238 base::TempFile temp_file = base::TempFile::Create();
239 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100240 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100241
Eric Seckler4b861052019-10-23 14:50:28 +0100242 EXPECT_TRUE(status.ok());
243
Eric Seckler178094e2019-10-24 14:03:04 +0100244 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler4b861052019-10-23 14:50:28 +0100245 EXPECT_EQ(result["traceEvents"].size(), 0u);
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +0100246}
247
Eric Seckler4b861052019-10-23 14:50:28 +0100248TEST_F(ExportJsonTest, StorageWithMetadata) {
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100249 const char* kDescription = "description";
250 const char* kBenchmarkName = "benchmark name";
251 const char* kStoryName = "story name";
252 const char* kStoryTag1 = "tag1";
253 const char* kStoryTag2 = "tag2";
254 const int64_t kBenchmarkStart = 1000000;
255 const int64_t kStoryStart = 2000000;
256 const bool kHadFailures = true;
257
Eric Seckler4b861052019-10-23 14:50:28 +0100258 StringId desc_id =
259 context_.storage->InternString(base::StringView(kDescription));
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100260 Variadic description = Variadic::String(desc_id);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000261 context_.metadata_tracker->SetMetadata(metadata::benchmark_description,
262 description);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100263
264 StringId benchmark_name_id =
Eric Seckler4b861052019-10-23 14:50:28 +0100265 context_.storage->InternString(base::StringView(kBenchmarkName));
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100266 Variadic benchmark_name = Variadic::String(benchmark_name_id);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000267 context_.metadata_tracker->SetMetadata(metadata::benchmark_name,
268 benchmark_name);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100269
Eric Seckler4b861052019-10-23 14:50:28 +0100270 StringId story_name_id =
271 context_.storage->InternString(base::StringView(kStoryName));
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100272 Variadic story_name = Variadic::String(story_name_id);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000273 context_.metadata_tracker->SetMetadata(metadata::benchmark_story_name,
274 story_name);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100275
Eric Seckler4b861052019-10-23 14:50:28 +0100276 StringId tag1_id =
277 context_.storage->InternString(base::StringView(kStoryTag1));
278 StringId tag2_id =
279 context_.storage->InternString(base::StringView(kStoryTag2));
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100280 Variadic tag1 = Variadic::String(tag1_id);
281 Variadic tag2 = Variadic::String(tag2_id);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000282 context_.metadata_tracker->AppendMetadata(metadata::benchmark_story_tags,
283 tag1);
284 context_.metadata_tracker->AppendMetadata(metadata::benchmark_story_tags,
285 tag2);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100286
287 Variadic benchmark_start = Variadic::Integer(kBenchmarkStart);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000288 context_.metadata_tracker->SetMetadata(metadata::benchmark_start_time_us,
289 benchmark_start);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100290
291 Variadic story_start = Variadic::Integer(kStoryStart);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000292 context_.metadata_tracker->SetMetadata(metadata::benchmark_story_run_time_us,
293 story_start);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100294
295 Variadic had_failures = Variadic::Integer(kHadFailures);
Lalit Magantiededb0e2020-01-08 12:50:34 +0000296 context_.metadata_tracker->SetMetadata(metadata::benchmark_had_failures,
297 had_failures);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100298
299 base::TempFile temp_file = base::TempFile::Create();
300 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100301 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100302
Eric Seckler7fb1d232019-10-23 14:42:43 +0100303 EXPECT_TRUE(status.ok());
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100304
Eric Seckler178094e2019-10-24 14:03:04 +0100305 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100306
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100307 EXPECT_TRUE(result.isMember("metadata"));
308 EXPECT_TRUE(result["metadata"].isMember("telemetry"));
309 Json::Value telemetry_metadata = result["metadata"]["telemetry"];
310
Primiano Tucci225a4e62019-06-06 11:13:57 +0100311 EXPECT_EQ(telemetry_metadata["benchmarkDescriptions"].size(), 1u);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100312 EXPECT_EQ(telemetry_metadata["benchmarkDescriptions"][0].asString(),
313 kDescription);
314
Primiano Tucci225a4e62019-06-06 11:13:57 +0100315 EXPECT_EQ(telemetry_metadata["benchmarks"].size(), 1u);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100316 EXPECT_EQ(telemetry_metadata["benchmarks"][0].asString(), kBenchmarkName);
317
Primiano Tucci225a4e62019-06-06 11:13:57 +0100318 EXPECT_EQ(telemetry_metadata["stories"].size(), 1u);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100319 EXPECT_EQ(telemetry_metadata["stories"][0].asString(), kStoryName);
320
Primiano Tucci225a4e62019-06-06 11:13:57 +0100321 EXPECT_EQ(telemetry_metadata["storyTags"].size(), 2u);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100322 EXPECT_EQ(telemetry_metadata["storyTags"][0].asString(), kStoryTag1);
323 EXPECT_EQ(telemetry_metadata["storyTags"][1].asString(), kStoryTag2);
324
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200325 EXPECT_DOUBLE_EQ(telemetry_metadata["benchmarkStart"].asInt(),
326 kBenchmarkStart / 1000.0);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100327
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200328 EXPECT_DOUBLE_EQ(telemetry_metadata["traceStart"].asInt(),
329 kStoryStart / 1000.0);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100330
Primiano Tucci225a4e62019-06-06 11:13:57 +0100331 EXPECT_EQ(telemetry_metadata["hadFailures"].size(), 1u);
Mikhail Khokhlovdb84f102019-05-24 15:25:47 +0100332 EXPECT_EQ(telemetry_metadata["hadFailures"][0].asBool(), kHadFailures);
333}
334
Eric Seckler4b861052019-10-23 14:50:28 +0100335TEST_F(ExportJsonTest, StorageWithStats) {
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100336 int64_t kProducers = 10;
337 int64_t kBufferSize0 = 1000;
338 int64_t kBufferSize1 = 2000;
Eric Secklere2b4e5c2019-12-06 14:37:29 +0000339 int64_t kFtraceBegin = 3000;
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100340
Eric Seckler4b861052019-10-23 14:50:28 +0100341 context_.storage->SetStats(stats::traced_producers_connected, kProducers);
342 context_.storage->SetIndexedStats(stats::traced_buf_buffer_size, 0,
343 kBufferSize0);
344 context_.storage->SetIndexedStats(stats::traced_buf_buffer_size, 1,
345 kBufferSize1);
Eric Secklere2b4e5c2019-12-06 14:37:29 +0000346 context_.storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin, 0,
347 kFtraceBegin);
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100348
349 base::TempFile temp_file = base::TempFile::Create();
350 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100351 util::Status status = ExportJson(context_.storage.get(), output);
Eric Seckler7fb1d232019-10-23 14:42:43 +0100352 EXPECT_TRUE(status.ok());
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100353
Eric Seckler178094e2019-10-24 14:03:04 +0100354 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100355
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100356 EXPECT_TRUE(result.isMember("metadata"));
Eric Secklere2b4e5c2019-12-06 14:37:29 +0000357 EXPECT_TRUE(result["metadata"].isMember("trace_processor_stats"));
358 Json::Value stats = result["metadata"]["trace_processor_stats"];
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100359
Eric Secklere2b4e5c2019-12-06 14:37:29 +0000360 EXPECT_EQ(stats["traced_producers_connected"].asInt(), kProducers);
361 EXPECT_EQ(stats["traced_buf"].size(), 2u);
362 EXPECT_EQ(stats["traced_buf"][0]["buffer_size"].asInt(), kBufferSize0);
363 EXPECT_EQ(stats["traced_buf"][1]["buffer_size"].asInt(), kBufferSize1);
364 EXPECT_EQ(stats["ftrace_cpu_bytes_read_begin"].size(), 1u);
365 EXPECT_EQ(stats["ftrace_cpu_bytes_read_begin"][0].asInt(), kFtraceBegin);
Mikhail Khokhlova6f97242019-08-08 13:48:31 +0100366}
367
Eric Seckler4b861052019-10-23 14:50:28 +0100368TEST_F(ExportJsonTest, StorageWithChromeMetadata) {
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100369 const char* kName1 = "name1";
370 const char* kName2 = "name2";
371 const char* kValue1 = "value1";
372 const int kValue2 = 222;
373
Eric Seckler4b861052019-10-23 14:50:28 +0100374 TraceStorage* storage = context_.storage.get();
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100375
Lalit Maganti679b29d2020-01-13 13:26:28 +0000376 RawId id = storage->mutable_raw_table()->Insert(
377 {0, storage->InternString("chrome_event.metadata"), 0, 0});
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100378
379 StringId name1_id = storage->InternString(base::StringView(kName1));
380 StringId name2_id = storage->InternString(base::StringView(kName2));
381 StringId value1_id = storage->InternString(base::StringView(kValue1));
Lalit Maganti5228f362020-01-15 13:45:56 +0000382
383 context_.args_tracker->AddArgsTo(id)
384 .AddArg(name1_id, Variadic::String(value1_id))
385 .AddArg(name2_id, Variadic::Integer(kValue2));
Eric Seckler4b861052019-10-23 14:50:28 +0100386 context_.args_tracker->Flush();
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100387
388 base::TempFile temp_file = base::TempFile::Create();
389 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +0100390 util::Status status = ExportJson(storage, output);
391 EXPECT_TRUE(status.ok());
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100392
Eric Seckler178094e2019-10-24 14:03:04 +0100393 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100394
Mikhail Khokhlov8fefc5b2019-08-08 17:53:53 +0100395 EXPECT_TRUE(result.isMember("metadata"));
396 Json::Value metadata = result["metadata"];
397
398 EXPECT_EQ(metadata[kName1].asString(), kValue1);
399 EXPECT_EQ(metadata[kName2].asInt(), kValue2);
400}
401
Eric Seckler4b861052019-10-23 14:50:28 +0100402TEST_F(ExportJsonTest, StorageWithArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100403 const char* kCategory = "cat";
404 const char* kName = "name";
405 const char* kSrc = "source_file.cc";
406
Lalit Magantieac7fff2020-01-10 16:42:54 +0000407 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000408 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100409 context_.args_tracker->Flush(); // Flush track args.
410 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
411 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000412 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000413 {0, 0, track.value, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100414
Eric Seckler4b861052019-10-23 14:50:28 +0100415 StringId arg_key_id = context_.storage->InternString(
416 base::StringView("task.posted_from.file_name"));
417 StringId arg_value_id =
418 context_.storage->InternString(base::StringView(kSrc));
Lalit Maganti1908e262020-01-09 14:33:19 +0000419 GlobalArgsTracker::Arg arg;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100420 arg.flat_key = arg_key_id;
421 arg.key = arg_key_id;
422 arg.value = Variadic::String(arg_value_id);
Lalit Maganti1908e262020-01-09 14:33:19 +0000423 ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000424 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100425
426 base::TempFile temp_file = base::TempFile::Create();
427 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100428 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100429
Eric Seckler7fb1d232019-10-23 14:42:43 +0100430 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100431
Eric Seckler178094e2019-10-24 14:03:04 +0100432 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100433 EXPECT_EQ(result["traceEvents"].size(), 1u);
434
435 Json::Value event = result["traceEvents"][0];
436 EXPECT_EQ(event["cat"].asString(), kCategory);
437 EXPECT_EQ(event["name"].asString(), kName);
438 EXPECT_EQ(event["args"]["src"].asString(), kSrc);
439}
440
Eric Seckler4b861052019-10-23 14:50:28 +0100441TEST_F(ExportJsonTest, StorageWithSliceAndFlowEventArgs) {
Eric Seckler6f13e332019-10-15 12:14:04 +0100442 const char* kCategory = "cat";
443 const char* kName = "name";
Eric Seckler6f13e332019-10-15 12:14:04 +0100444 const uint64_t kBindId = 0xaa00aa00aa00aa00;
445 const char* kFlowDirection = "inout";
446 const char* kArgName = "arg_name";
447 const int kArgValue = 123;
448
Eric Seckler4b861052019-10-23 14:50:28 +0100449 TraceStorage* storage = context_.storage.get();
Eric Seckler6f13e332019-10-15 12:14:04 +0100450
Lalit Magantieac7fff2020-01-10 16:42:54 +0000451 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000452 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100453 context_.args_tracker->Flush(); // Flush track args.
Eric Seckler6f13e332019-10-15 12:14:04 +0100454 StringId cat_id = storage->InternString(base::StringView(kCategory));
455 StringId name_id = storage->InternString(base::StringView(kName));
Lalit Magantib0e11f62020-01-02 14:17:58 +0000456 SliceId id = storage->mutable_slice_table()->Insert(
457 {0, 0, track.value, cat_id, name_id, 0, 0, 0});
Lalit Maganti5228f362020-01-15 13:45:56 +0000458 auto inserter = context_.args_tracker->AddArgsTo(id);
Eric Seckler6f13e332019-10-15 12:14:04 +0100459
Eric Seckler6f13e332019-10-15 12:14:04 +0100460 auto add_arg = [&](const char* key, Variadic value) {
Lalit Maganti5228f362020-01-15 13:45:56 +0000461 inserter.AddArg(storage->InternString(key), value);
Eric Seckler6f13e332019-10-15 12:14:04 +0100462 };
463
464 add_arg("legacy_event.bind_id", Variadic::UnsignedInteger(kBindId));
465 add_arg("legacy_event.bind_to_enclosing", Variadic::Boolean(true));
466 StringId flow_direction_id = storage->InternString(kFlowDirection);
467 add_arg("legacy_event.flow_direction", Variadic::String(flow_direction_id));
468
469 add_arg(kArgName, Variadic::Integer(kArgValue));
470
Eric Seckler4b861052019-10-23 14:50:28 +0100471 context_.args_tracker->Flush();
Eric Seckler6f13e332019-10-15 12:14:04 +0100472
473 base::TempFile temp_file = base::TempFile::Create();
474 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +0100475 util::Status status = ExportJson(storage, output);
Eric Seckler6f13e332019-10-15 12:14:04 +0100476
Eric Seckler7fb1d232019-10-23 14:42:43 +0100477 EXPECT_TRUE(status.ok());
Eric Seckler6f13e332019-10-15 12:14:04 +0100478
Eric Seckler178094e2019-10-24 14:03:04 +0100479 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler6f13e332019-10-15 12:14:04 +0100480 EXPECT_EQ(result["traceEvents"].size(), 1u);
481
482 Json::Value event = result["traceEvents"][0];
483 EXPECT_EQ(event["cat"].asString(), kCategory);
484 EXPECT_EQ(event["name"].asString(), kName);
485 EXPECT_EQ(event["bind_id"].asString(), "0xaa00aa00aa00aa00");
486 EXPECT_EQ(event["bp"].asString(), "e");
487 EXPECT_EQ(event["flow_in"].asBool(), true);
488 EXPECT_EQ(event["flow_out"].asBool(), true);
489 EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
Eric Secklerc36f22e2019-10-28 10:08:12 +0000490 EXPECT_FALSE(event["args"].isMember("legacy_event"));
Eric Seckler6f13e332019-10-15 12:14:04 +0100491}
492
Eric Seckler4b861052019-10-23 14:50:28 +0100493TEST_F(ExportJsonTest, StorageWithListArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100494 const char* kCategory = "cat";
495 const char* kName = "name";
496 double kValues[] = {1.234, 2.345};
497
Lalit Magantieac7fff2020-01-10 16:42:54 +0000498 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000499 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100500 context_.args_tracker->Flush(); // Flush track args.
501 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
502 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000503 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000504 {0, 0, track.value, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100505
Eric Seckler4b861052019-10-23 14:50:28 +0100506 StringId arg_flat_key_id = context_.storage->InternString(
507 base::StringView("debug.draw_duration_ms"));
508 StringId arg_key0_id = context_.storage->InternString(
509 base::StringView("debug.draw_duration_ms[0]"));
510 StringId arg_key1_id = context_.storage->InternString(
511 base::StringView("debug.draw_duration_ms[1]"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000512 GlobalArgsTracker::Arg arg0;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100513 arg0.flat_key = arg_flat_key_id;
514 arg0.key = arg_key0_id;
515 arg0.value = Variadic::Real(kValues[0]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000516 GlobalArgsTracker::Arg arg1;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100517 arg1.flat_key = arg_flat_key_id;
518 arg1.key = arg_key1_id;
519 arg1.value = Variadic::Real(kValues[1]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000520 ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000521 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100522
523 base::TempFile temp_file = base::TempFile::Create();
524 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100525 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100526
Eric Seckler7fb1d232019-10-23 14:42:43 +0100527 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100528
Eric Seckler178094e2019-10-24 14:03:04 +0100529 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100530 EXPECT_EQ(result["traceEvents"].size(), 1u);
531
532 Json::Value event = result["traceEvents"][0];
533 EXPECT_EQ(event["cat"].asString(), kCategory);
534 EXPECT_EQ(event["name"].asString(), kName);
Mikhail Khokhlovc4544ea2019-07-10 14:41:25 +0100535 EXPECT_EQ(event["args"]["draw_duration_ms"].size(), 2u);
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200536 EXPECT_DOUBLE_EQ(event["args"]["draw_duration_ms"][0].asDouble(), kValues[0]);
537 EXPECT_DOUBLE_EQ(event["args"]["draw_duration_ms"][1].asDouble(), kValues[1]);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100538}
539
Eric Seckler4b861052019-10-23 14:50:28 +0100540TEST_F(ExportJsonTest, StorageWithMultiplePointerArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100541 const char* kCategory = "cat";
542 const char* kName = "name";
543 uint64_t kValue0 = 1;
544 uint64_t kValue1 = std::numeric_limits<uint64_t>::max();
545
Lalit Magantieac7fff2020-01-10 16:42:54 +0000546 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000547 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100548 context_.args_tracker->Flush(); // Flush track args.
549 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
550 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000551 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000552 {0, 0, track.value, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100553
Eric Seckler4b861052019-10-23 14:50:28 +0100554 StringId arg_key0_id =
555 context_.storage->InternString(base::StringView("arg0"));
556 StringId arg_key1_id =
557 context_.storage->InternString(base::StringView("arg1"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000558 GlobalArgsTracker::Arg arg0;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100559 arg0.flat_key = arg_key0_id;
560 arg0.key = arg_key0_id;
561 arg0.value = Variadic::Pointer(kValue0);
Lalit Maganti1908e262020-01-09 14:33:19 +0000562 GlobalArgsTracker::Arg arg1;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100563 arg1.flat_key = arg_key1_id;
564 arg1.key = arg_key1_id;
565 arg1.value = Variadic::Pointer(kValue1);
Lalit Maganti1908e262020-01-09 14:33:19 +0000566 ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000567 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100568
569 base::TempFile temp_file = base::TempFile::Create();
570 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100571 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100572
Eric Seckler7fb1d232019-10-23 14:42:43 +0100573 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100574
Eric Seckler178094e2019-10-24 14:03:04 +0100575 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100576 EXPECT_EQ(result["traceEvents"].size(), 1u);
577
578 Json::Value event = result["traceEvents"][0];
579 EXPECT_EQ(event["cat"].asString(), kCategory);
580 EXPECT_EQ(event["name"].asString(), kName);
581 EXPECT_EQ(event["args"]["arg0"].asString(), "0x1");
582 EXPECT_EQ(event["args"]["arg1"].asString(), "0xffffffffffffffff");
583}
584
Eric Seckler4b861052019-10-23 14:50:28 +0100585TEST_F(ExportJsonTest, StorageWithObjectListArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100586 const char* kCategory = "cat";
587 const char* kName = "name";
588 int kValues[] = {123, 234};
589
Lalit Magantieac7fff2020-01-10 16:42:54 +0000590 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000591 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100592 context_.args_tracker->Flush(); // Flush track args.
593 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
594 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000595 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000596 {0, 0, track.value, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100597
Eric Seckler4b861052019-10-23 14:50:28 +0100598 StringId arg_flat_key_id =
599 context_.storage->InternString(base::StringView("a.b"));
600 StringId arg_key0_id =
601 context_.storage->InternString(base::StringView("a[0].b"));
602 StringId arg_key1_id =
603 context_.storage->InternString(base::StringView("a[1].b"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000604 GlobalArgsTracker::Arg arg0;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100605 arg0.flat_key = arg_flat_key_id;
606 arg0.key = arg_key0_id;
607 arg0.value = Variadic::Integer(kValues[0]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000608 GlobalArgsTracker::Arg arg1;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100609 arg1.flat_key = arg_flat_key_id;
610 arg1.key = arg_key1_id;
611 arg1.value = Variadic::Integer(kValues[1]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000612 ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000613 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100614
615 base::TempFile temp_file = base::TempFile::Create();
616 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100617 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100618
Eric Seckler7fb1d232019-10-23 14:42:43 +0100619 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100620
Eric Seckler178094e2019-10-24 14:03:04 +0100621 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100622 EXPECT_EQ(result["traceEvents"].size(), 1u);
623
624 Json::Value event = result["traceEvents"][0];
625 EXPECT_EQ(event["cat"].asString(), kCategory);
626 EXPECT_EQ(event["name"].asString(), kName);
Mikhail Khokhlovc4544ea2019-07-10 14:41:25 +0100627 EXPECT_EQ(event["args"]["a"].size(), 2u);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100628 EXPECT_EQ(event["args"]["a"][0]["b"].asInt(), kValues[0]);
629 EXPECT_EQ(event["args"]["a"][1]["b"].asInt(), kValues[1]);
630}
631
Eric Seckler4b861052019-10-23 14:50:28 +0100632TEST_F(ExportJsonTest, StorageWithNestedListArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100633 const char* kCategory = "cat";
634 const char* kName = "name";
635 int kValues[] = {123, 234};
636
Lalit Magantieac7fff2020-01-10 16:42:54 +0000637 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000638 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100639 context_.args_tracker->Flush(); // Flush track args.
640 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
641 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000642 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000643 {0, 0, track.value, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100644
Eric Seckler4b861052019-10-23 14:50:28 +0100645 StringId arg_flat_key_id =
646 context_.storage->InternString(base::StringView("a"));
647 StringId arg_key0_id =
648 context_.storage->InternString(base::StringView("a[0][0]"));
649 StringId arg_key1_id =
650 context_.storage->InternString(base::StringView("a[0][1]"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000651 GlobalArgsTracker::Arg arg0;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100652 arg0.flat_key = arg_flat_key_id;
653 arg0.key = arg_key0_id;
654 arg0.value = Variadic::Integer(kValues[0]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000655 GlobalArgsTracker::Arg arg1;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100656 arg1.flat_key = arg_flat_key_id;
657 arg1.key = arg_key1_id;
658 arg1.value = Variadic::Integer(kValues[1]);
Lalit Maganti1908e262020-01-09 14:33:19 +0000659 ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000660 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100661
662 base::TempFile temp_file = base::TempFile::Create();
663 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100664 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100665
Eric Seckler7fb1d232019-10-23 14:42:43 +0100666 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100667
Eric Seckler178094e2019-10-24 14:03:04 +0100668 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100669 EXPECT_EQ(result["traceEvents"].size(), 1u);
670
671 Json::Value event = result["traceEvents"][0];
672 EXPECT_EQ(event["cat"].asString(), kCategory);
673 EXPECT_EQ(event["name"].asString(), kName);
Mikhail Khokhlovc4544ea2019-07-10 14:41:25 +0100674 EXPECT_EQ(event["args"]["a"].size(), 1u);
675 EXPECT_EQ(event["args"]["a"][0].size(), 2u);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100676 EXPECT_EQ(event["args"]["a"][0][0].asInt(), kValues[0]);
677 EXPECT_EQ(event["args"]["a"][0][1].asInt(), kValues[1]);
678}
679
Eric Seckler4b861052019-10-23 14:50:28 +0100680TEST_F(ExportJsonTest, StorageWithLegacyJsonArgs) {
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100681 const char* kCategory = "cat";
682 const char* kName = "name";
683
Lalit Magantieac7fff2020-01-10 16:42:54 +0000684 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000685 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100686 context_.args_tracker->Flush(); // Flush track args.
687 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
688 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000689 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000690 {0, 0, track.value, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100691
Eric Seckler4b861052019-10-23 14:50:28 +0100692 StringId arg_key_id = context_.storage->InternString(base::StringView("a"));
693 StringId arg_value_id =
694 context_.storage->InternString(base::StringView("{\"b\":123}"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000695 GlobalArgsTracker::Arg arg;
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100696 arg.flat_key = arg_key_id;
697 arg.key = arg_key_id;
698 arg.value = Variadic::Json(arg_value_id);
Lalit Maganti1908e262020-01-09 14:33:19 +0000699 ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000700 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100701
702 base::TempFile temp_file = base::TempFile::Create();
703 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100704 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100705
Eric Seckler7fb1d232019-10-23 14:42:43 +0100706 EXPECT_TRUE(status.ok());
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100707
Eric Seckler178094e2019-10-24 14:03:04 +0100708 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlovc8344972019-07-09 15:46:57 +0100709 EXPECT_EQ(result["traceEvents"].size(), 1u);
710
711 Json::Value event = result["traceEvents"][0];
712 EXPECT_EQ(event["cat"].asString(), kCategory);
713 EXPECT_EQ(event["name"].asString(), kName);
714 EXPECT_EQ(event["args"]["a"]["b"].asInt(), 123);
715}
716
Eric Seckler4b861052019-10-23 14:50:28 +0100717TEST_F(ExportJsonTest, InstantEvent) {
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100718 const int64_t kTimestamp = 10000000;
719 const char* kCategory = "cat";
720 const char* kName = "name";
721
Eric Seckler4b861052019-10-23 14:50:28 +0100722 TrackId track =
723 context_.track_tracker->GetOrCreateLegacyChromeGlobalInstantTrack();
724 context_.args_tracker->Flush(); // Flush track args.
725 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
726 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000727 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000728 {kTimestamp, 0, track.value, cat_id, name_id, 0, 0, 0});
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100729
730 base::TempFile temp_file = base::TempFile::Create();
731 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100732 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100733
Eric Seckler7fb1d232019-10-23 14:42:43 +0100734 EXPECT_TRUE(status.ok());
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100735
Eric Seckler178094e2019-10-24 14:03:04 +0100736 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100737 EXPECT_EQ(result["traceEvents"].size(), 1u);
738
739 Json::Value event = result["traceEvents"][0];
Eric Seckler9dc34462019-11-06 14:44:20 +0000740 EXPECT_EQ(event["ph"].asString(), "I");
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100741 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
742 EXPECT_EQ(event["s"].asString(), "g");
743 EXPECT_EQ(event["cat"].asString(), kCategory);
744 EXPECT_EQ(event["name"].asString(), kName);
745}
746
Eric Seckler4b861052019-10-23 14:50:28 +0100747TEST_F(ExportJsonTest, InstantEventOnThread) {
748 const int64_t kTimestamp = 10000000;
749 const int64_t kThreadID = 100;
750 const char* kCategory = "cat";
751 const char* kName = "name";
752
Lalit Magantieac7fff2020-01-10 16:42:54 +0000753 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000754 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler4b861052019-10-23 14:50:28 +0100755 context_.args_tracker->Flush(); // Flush track args.
756 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
757 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000758 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000759 {kTimestamp, 0, track.value, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100760
761 base::TempFile temp_file = base::TempFile::Create();
762 FILE* output = fopen(temp_file.path().c_str(), "w+");
763 util::Status status = ExportJson(context_.storage.get(), output);
764
765 EXPECT_TRUE(status.ok());
766
Eric Seckler178094e2019-10-24 14:03:04 +0100767 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler4b861052019-10-23 14:50:28 +0100768 EXPECT_EQ(result["traceEvents"].size(), 1u);
769
770 Json::Value event = result["traceEvents"][0];
771 EXPECT_EQ(event["tid"].asUInt(), kThreadID);
Eric Seckler9dc34462019-11-06 14:44:20 +0000772 EXPECT_EQ(event["ph"].asString(), "I");
Eric Seckler4b861052019-10-23 14:50:28 +0100773 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
774 EXPECT_EQ(event["s"].asString(), "t");
775 EXPECT_EQ(event["cat"].asString(), kCategory);
776 EXPECT_EQ(event["name"].asString(), kName);
777}
778
Eric Seckler5f2907d2020-01-06 14:44:05 +0000779TEST_F(ExportJsonTest, AsyncEvents) {
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100780 const int64_t kTimestamp = 10000000;
781 const int64_t kDuration = 100000;
782 const int64_t kProcessID = 100;
783 const char* kCategory = "cat";
784 const char* kName = "name";
Eric Seckler5f2907d2020-01-06 14:44:05 +0000785 const char* kName2 = "name2";
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100786 const char* kArgName = "arg_name";
787 const int kArgValue = 123;
788
Lalit Magantieac7fff2020-01-10 16:42:54 +0000789 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +0100790 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
791 StringId name_id = context_.storage->InternString(base::StringView(kName));
Eric Seckler5f2907d2020-01-06 14:44:05 +0000792 StringId name2_id = context_.storage->InternString(base::StringView(kName2));
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100793
Eric Seckler4b861052019-10-23 14:50:28 +0100794 constexpr int64_t kSourceId = 235;
795 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
796 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
797 /*source_scope=*/0);
798 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100799
Lalit Magantic7ea02e2019-12-12 14:06:49 +0000800 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000801 {kTimestamp, kDuration, track.value, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100802 StringId arg_key_id =
803 context_.storage->InternString(base::StringView(kArgName));
Lalit Maganti1908e262020-01-09 14:33:19 +0000804 GlobalArgsTracker::Arg arg;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100805 arg.flat_key = arg_key_id;
806 arg.key = arg_key_id;
807 arg.value = Variadic::Integer(kArgValue);
Lalit Maganti1908e262020-01-09 14:33:19 +0000808 ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000809 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100810
Eric Seckler5f2907d2020-01-06 14:44:05 +0000811 // Child event with same timestamps as first one.
812 context_.storage->mutable_slice_table()->Insert(
813 {kTimestamp, kDuration, track.value, cat_id, name2_id, 0, 0, 0});
814
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100815 base::TempFile temp_file = base::TempFile::Create();
816 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100817 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100818
Eric Seckler7fb1d232019-10-23 14:42:43 +0100819 EXPECT_TRUE(status.ok());
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100820
Eric Seckler178094e2019-10-24 14:03:04 +0100821 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler5f2907d2020-01-06 14:44:05 +0000822 EXPECT_EQ(result["traceEvents"].size(), 4u);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100823
Eric Seckler5f2907d2020-01-06 14:44:05 +0000824 Json::Value begin_event1 = result["traceEvents"][0];
825 EXPECT_EQ(begin_event1["ph"].asString(), "b");
826 EXPECT_EQ(begin_event1["ts"].asInt64(), kTimestamp / 1000);
827 EXPECT_EQ(begin_event1["pid"].asInt64(), kProcessID);
828 EXPECT_EQ(begin_event1["id2"]["local"].asString(), "0xeb");
829 EXPECT_EQ(begin_event1["cat"].asString(), kCategory);
830 EXPECT_EQ(begin_event1["name"].asString(), kName);
831 EXPECT_EQ(begin_event1["args"][kArgName].asInt(), kArgValue);
832 EXPECT_FALSE(begin_event1.isMember("tts"));
833 EXPECT_FALSE(begin_event1.isMember("use_async_tts"));
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100834
Eric Seckler5f2907d2020-01-06 14:44:05 +0000835 Json::Value begin_event2 = result["traceEvents"][1];
836 EXPECT_EQ(begin_event2["ph"].asString(), "b");
837 EXPECT_EQ(begin_event2["ts"].asInt64(), kTimestamp / 1000);
838 EXPECT_EQ(begin_event2["pid"].asInt64(), kProcessID);
839 EXPECT_EQ(begin_event2["id2"]["local"].asString(), "0xeb");
840 EXPECT_EQ(begin_event2["cat"].asString(), kCategory);
841 EXPECT_EQ(begin_event2["name"].asString(), kName2);
842 EXPECT_TRUE(begin_event2["args"].isObject());
843 EXPECT_EQ(begin_event2["args"].size(), 0u);
844 EXPECT_FALSE(begin_event2.isMember("tts"));
845 EXPECT_FALSE(begin_event2.isMember("use_async_tts"));
846
847 Json::Value end_event2 = result["traceEvents"][3];
848 EXPECT_EQ(end_event2["ph"].asString(), "e");
849 EXPECT_EQ(end_event2["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
850 EXPECT_EQ(end_event2["pid"].asInt64(), kProcessID);
851 EXPECT_EQ(end_event2["id2"]["local"].asString(), "0xeb");
852 EXPECT_EQ(end_event2["cat"].asString(), kCategory);
853 EXPECT_EQ(end_event2["name"].asString(), kName);
854 EXPECT_TRUE(end_event2["args"].isObject());
855 EXPECT_EQ(end_event2["args"].size(), 0u);
856 EXPECT_FALSE(end_event2.isMember("tts"));
857 EXPECT_FALSE(end_event2.isMember("use_async_tts"));
858
859 Json::Value end_event1 = result["traceEvents"][3];
860 EXPECT_EQ(end_event1["ph"].asString(), "e");
861 EXPECT_EQ(end_event1["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
862 EXPECT_EQ(end_event1["pid"].asInt64(), kProcessID);
863 EXPECT_EQ(end_event1["id2"]["local"].asString(), "0xeb");
864 EXPECT_EQ(end_event1["cat"].asString(), kCategory);
865 EXPECT_EQ(end_event1["name"].asString(), kName);
866 EXPECT_TRUE(end_event1["args"].isObject());
867 EXPECT_EQ(end_event1["args"].size(), 0u);
868 EXPECT_FALSE(end_event1.isMember("tts"));
869 EXPECT_FALSE(end_event1.isMember("use_async_tts"));
Eric Secklerc63a3af2019-07-25 11:17:37 +0100870}
871
Eric Seckler4b861052019-10-23 14:50:28 +0100872TEST_F(ExportJsonTest, AsyncEventWithThreadTimestamp) {
Eric Secklerc63a3af2019-07-25 11:17:37 +0100873 const int64_t kTimestamp = 10000000;
874 const int64_t kDuration = 100000;
875 const int64_t kThreadTimestamp = 10000001;
876 const int64_t kThreadDuration = 99998;
877 const int64_t kProcessID = 100;
878 const char* kCategory = "cat";
879 const char* kName = "name";
880
Lalit Magantieac7fff2020-01-10 16:42:54 +0000881 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +0100882 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
883 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100884
Eric Seckler4b861052019-10-23 14:50:28 +0100885 constexpr int64_t kSourceId = 235;
886 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
887 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
888 /*source_scope=*/0);
889 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100890
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000891 auto slice_id = context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000892 {kTimestamp, kDuration, track.value, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100893 context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000894 slice_id.value, kThreadTimestamp, kThreadDuration, 0, 0);
Eric Secklerc63a3af2019-07-25 11:17:37 +0100895
896 base::TempFile temp_file = base::TempFile::Create();
897 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100898 util::Status status = ExportJson(context_.storage.get(), output);
Eric Secklerc63a3af2019-07-25 11:17:37 +0100899
Eric Seckler7fb1d232019-10-23 14:42:43 +0100900 EXPECT_TRUE(status.ok());
Eric Secklerc63a3af2019-07-25 11:17:37 +0100901
Eric Seckler178094e2019-10-24 14:03:04 +0100902 Json::Value result = ToJsonValue(ReadFile(output));
Eric Secklerc63a3af2019-07-25 11:17:37 +0100903 EXPECT_EQ(result["traceEvents"].size(), 2u);
904
905 Json::Value begin_event = result["traceEvents"][0];
906 EXPECT_EQ(begin_event["ph"].asString(), "b");
907 EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
908 EXPECT_EQ(begin_event["tts"].asInt64(), kThreadTimestamp / 1000);
909 EXPECT_EQ(begin_event["use_async_tts"].asInt(), 1);
910 EXPECT_EQ(begin_event["pid"].asInt64(), kProcessID);
Eric Secklerf91236e2019-11-04 10:25:45 +0000911 EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
Eric Secklerc63a3af2019-07-25 11:17:37 +0100912 EXPECT_EQ(begin_event["cat"].asString(), kCategory);
913 EXPECT_EQ(begin_event["name"].asString(), kName);
914
915 Json::Value end_event = result["traceEvents"][1];
916 EXPECT_EQ(end_event["ph"].asString(), "e");
917 EXPECT_EQ(end_event["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
918 EXPECT_EQ(end_event["tts"].asInt64(),
919 (kThreadTimestamp + kThreadDuration) / 1000);
920 EXPECT_EQ(end_event["use_async_tts"].asInt(), 1);
921 EXPECT_EQ(end_event["pid"].asInt64(), kProcessID);
Eric Secklerf91236e2019-11-04 10:25:45 +0000922 EXPECT_EQ(end_event["id2"]["local"].asString(), "0xeb");
Eric Secklerc63a3af2019-07-25 11:17:37 +0100923 EXPECT_EQ(end_event["cat"].asString(), kCategory);
924 EXPECT_EQ(end_event["name"].asString(), kName);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100925}
926
Eric Seckler4b861052019-10-23 14:50:28 +0100927TEST_F(ExportJsonTest, UnfinishedAsyncEvent) {
Eric Seckler206db472019-07-25 12:05:27 +0100928 const int64_t kTimestamp = 10000000;
929 const int64_t kDuration = -1;
930 const int64_t kThreadTimestamp = 10000001;
931 const int64_t kThreadDuration = -1;
932 const int64_t kProcessID = 100;
933 const char* kCategory = "cat";
934 const char* kName = "name";
935
Lalit Magantieac7fff2020-01-10 16:42:54 +0000936 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +0100937 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
938 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100939
Eric Seckler4b861052019-10-23 14:50:28 +0100940 constexpr int64_t kSourceId = 235;
941 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
942 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
943 /*source_scope=*/0);
944 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100945
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000946 auto slice_id = context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000947 {kTimestamp, kDuration, track.value, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100948 context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000949 slice_id.value, kThreadTimestamp, kThreadDuration, 0, 0);
Eric Seckler206db472019-07-25 12:05:27 +0100950
951 base::TempFile temp_file = base::TempFile::Create();
952 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +0100953 util::Status status = ExportJson(context_.storage.get(), output);
Eric Seckler206db472019-07-25 12:05:27 +0100954
Eric Seckler7fb1d232019-10-23 14:42:43 +0100955 EXPECT_TRUE(status.ok());
Eric Seckler206db472019-07-25 12:05:27 +0100956
Eric Seckler178094e2019-10-24 14:03:04 +0100957 Json::Value result = ToJsonValue(ReadFile(output));
Eric Seckler206db472019-07-25 12:05:27 +0100958 EXPECT_EQ(result["traceEvents"].size(), 1u);
959
960 Json::Value begin_event = result["traceEvents"][0];
961 EXPECT_EQ(begin_event["ph"].asString(), "b");
962 EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
963 EXPECT_EQ(begin_event["tts"].asInt64(), kThreadTimestamp / 1000);
964 EXPECT_EQ(begin_event["use_async_tts"].asInt(), 1);
965 EXPECT_EQ(begin_event["pid"].asInt64(), kProcessID);
Eric Secklerf91236e2019-11-04 10:25:45 +0000966 EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
Eric Seckler206db472019-07-25 12:05:27 +0100967 EXPECT_EQ(begin_event["cat"].asString(), kCategory);
968 EXPECT_EQ(begin_event["name"].asString(), kName);
969}
970
Eric Seckler4b861052019-10-23 14:50:28 +0100971TEST_F(ExportJsonTest, AsyncInstantEvent) {
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100972 const int64_t kTimestamp = 10000000;
973 const int64_t kProcessID = 100;
974 const char* kCategory = "cat";
975 const char* kName = "name";
976 const char* kArgName = "arg_name";
977 const int kArgValue = 123;
978
Lalit Magantieac7fff2020-01-10 16:42:54 +0000979 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
Eric Seckler4b861052019-10-23 14:50:28 +0100980 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
981 StringId name_id = context_.storage->InternString(base::StringView(kName));
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100982
Eric Seckler4b861052019-10-23 14:50:28 +0100983 constexpr int64_t kSourceId = 235;
984 TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
985 name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
986 /*source_scope=*/0);
987 context_.args_tracker->Flush(); // Flush track args.
Lalit Maganti4ea78d92019-09-20 20:20:41 +0100988
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000989 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +0000990 {kTimestamp, 0, track.value, cat_id, name_id, 0, 0, 0});
Eric Seckler4b861052019-10-23 14:50:28 +0100991 StringId arg_key_id =
992 context_.storage->InternString(base::StringView("arg_name"));
Lalit Maganti1908e262020-01-09 14:33:19 +0000993 GlobalArgsTracker::Arg arg;
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100994 arg.flat_key = arg_key_id;
995 arg.key = arg_key_id;
996 arg.value = Variadic::Integer(kArgValue);
Lalit Maganti1908e262020-01-09 14:33:19 +0000997 ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
Lalit Maganti1308e3f2019-12-09 20:24:20 +0000998 context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +0100999
1000 base::TempFile temp_file = base::TempFile::Create();
1001 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler4b861052019-10-23 14:50:28 +01001002 util::Status status = ExportJson(context_.storage.get(), output);
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001003
Eric Seckler7fb1d232019-10-23 14:42:43 +01001004 EXPECT_TRUE(status.ok());
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001005
Eric Seckler178094e2019-10-24 14:03:04 +01001006 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001007 EXPECT_EQ(result["traceEvents"].size(), 1u);
1008
1009 Json::Value event = result["traceEvents"][0];
1010 EXPECT_EQ(event["ph"].asString(), "n");
1011 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
1012 EXPECT_EQ(event["pid"].asInt64(), kProcessID);
Eric Secklerf91236e2019-11-04 10:25:45 +00001013 EXPECT_EQ(event["id2"]["local"].asString(), "0xeb");
Mikhail Khokhlov1fad8952019-07-11 14:18:33 +01001014 EXPECT_EQ(event["cat"].asString(), kCategory);
1015 EXPECT_EQ(event["name"].asString(), kName);
1016 EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
1017}
1018
Eric Seckler4b861052019-10-23 14:50:28 +01001019TEST_F(ExportJsonTest, RawEvent) {
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001020 const int64_t kTimestamp = 10000000;
1021 const int64_t kDuration = 10000;
1022 const int64_t kThreadTimestamp = 20000000;
1023 const int64_t kThreadDuration = 20000;
1024 const int64_t kThreadInstructionCount = 30000000;
1025 const int64_t kThreadInstructionDelta = 30000;
1026 const int64_t kProcessID = 100;
1027 const int64_t kThreadID = 200;
1028 const char* kCategory = "cat";
1029 const char* kName = "name";
1030 const char* kPhase = "?";
1031 const uint64_t kGlobalId = 0xaaffaaffaaffaaff;
1032 const char* kIdScope = "my_id";
1033 const uint64_t kBindId = 0xaa00aa00aa00aa00;
1034 const char* kFlowDirection = "inout";
1035 const char* kArgName = "arg_name";
1036 const int kArgValue = 123;
1037
Eric Seckler4b861052019-10-23 14:50:28 +01001038 TraceStorage* storage = context_.storage.get();
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001039
Lalit Magantieac7fff2020-01-10 16:42:54 +00001040 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
1041 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
1042 context_.storage->mutable_thread_table()->mutable_upid()->Set(utid, upid);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001043
Lalit Maganti679b29d2020-01-13 13:26:28 +00001044 RawId id = storage->mutable_raw_table()->Insert(
1045 {kTimestamp, storage->InternString("track_event.legacy_event"), /*cpu=*/0,
1046 utid});
Lalit Maganti5228f362020-01-15 13:45:56 +00001047 auto inserter = context_.args_tracker->AddArgsTo(id);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001048
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001049 auto add_arg = [&](const char* key, Variadic value) {
1050 StringId key_id = storage->InternString(key);
Lalit Maganti5228f362020-01-15 13:45:56 +00001051 inserter.AddArg(key_id, value);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001052 };
1053
1054 StringId cat_id = storage->InternString(base::StringView(kCategory));
1055 add_arg("legacy_event.category", Variadic::String(cat_id));
1056 StringId name_id = storage->InternString(base::StringView(kName));
1057 add_arg("legacy_event.name", Variadic::String(name_id));
1058 StringId phase_id = storage->InternString(base::StringView(kPhase));
1059 add_arg("legacy_event.phase", Variadic::String(phase_id));
1060
1061 add_arg("legacy_event.duration_ns", Variadic::Integer(kDuration));
1062 add_arg("legacy_event.thread_timestamp_ns",
1063 Variadic::Integer(kThreadTimestamp));
1064 add_arg("legacy_event.thread_duration_ns",
1065 Variadic::Integer(kThreadDuration));
1066 add_arg("legacy_event.thread_instruction_count",
1067 Variadic::Integer(kThreadInstructionCount));
1068 add_arg("legacy_event.thread_instruction_delta",
1069 Variadic::Integer(kThreadInstructionDelta));
1070 add_arg("legacy_event.use_async_tts", Variadic::Boolean(true));
1071 add_arg("legacy_event.global_id", Variadic::UnsignedInteger(kGlobalId));
1072 StringId scope_id = storage->InternString(base::StringView(kIdScope));
1073 add_arg("legacy_event.id_scope", Variadic::String(scope_id));
1074 add_arg("legacy_event.bind_id", Variadic::UnsignedInteger(kBindId));
1075 add_arg("legacy_event.bind_to_enclosing", Variadic::Boolean(true));
1076 StringId flow_direction_id = storage->InternString(kFlowDirection);
1077 add_arg("legacy_event.flow_direction", Variadic::String(flow_direction_id));
1078
1079 add_arg(kArgName, Variadic::Integer(kArgValue));
1080
Eric Seckler4b861052019-10-23 14:50:28 +01001081 context_.args_tracker->Flush();
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001082
1083 base::TempFile temp_file = base::TempFile::Create();
1084 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +01001085 util::Status status = ExportJson(storage, output);
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001086
Eric Seckler7fb1d232019-10-23 14:42:43 +01001087 EXPECT_TRUE(status.ok());
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001088
Eric Seckler178094e2019-10-24 14:03:04 +01001089 Json::Value result = ToJsonValue(ReadFile(output));
Eric Secklerc34c8fc2019-08-02 10:57:59 +01001090 EXPECT_EQ(result["traceEvents"].size(), 1u);
1091
1092 Json::Value event = result["traceEvents"][0];
1093 EXPECT_EQ(event["ph"].asString(), kPhase);
1094 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
1095 EXPECT_EQ(event["dur"].asInt64(), kDuration / 1000);
1096 EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
1097 EXPECT_EQ(event["tdur"].asInt64(), kThreadDuration / 1000);
1098 EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
1099 EXPECT_EQ(event["tidelta"].asInt64(), kThreadInstructionDelta);
1100 EXPECT_EQ(event["tid"].asUInt(), kThreadID);
1101 EXPECT_EQ(event["cat"].asString(), kCategory);
1102 EXPECT_EQ(event["name"].asString(), kName);
1103 EXPECT_EQ(event["use_async_tts"].asInt(), 1);
1104 EXPECT_EQ(event["id2"]["global"].asString(), "0xaaffaaffaaffaaff");
1105 EXPECT_EQ(event["scope"].asString(), kIdScope);
1106 EXPECT_EQ(event["bind_id"].asString(), "0xaa00aa00aa00aa00");
1107 EXPECT_EQ(event["bp"].asString(), "e");
1108 EXPECT_EQ(event["flow_in"].asBool(), true);
1109 EXPECT_EQ(event["flow_out"].asBool(), true);
1110 EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
1111}
1112
Eric Seckler4b861052019-10-23 14:50:28 +01001113TEST_F(ExportJsonTest, LegacyRawEvents) {
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001114 const char* kLegacyFtraceData = "some \"data\"\nsome :data:";
Eric Seckler13b84b32019-10-04 12:00:38 +01001115 const char* kLegacyJsonData1 = "{\"us";
Eric Seckler178094e2019-10-24 14:03:04 +01001116 const char* kLegacyJsonData2 = "er\": 1},{\"user\": 2}";
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001117
Eric Seckler4b861052019-10-23 14:50:28 +01001118 TraceStorage* storage = context_.storage.get();
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001119
Lalit Maganti679b29d2020-01-13 13:26:28 +00001120 RawId id = storage->mutable_raw_table()->Insert(
1121 {0, storage->InternString("chrome_event.legacy_system_trace"), 0, 0});
Lalit Maganti5228f362020-01-15 13:45:56 +00001122 auto inserter = context_.args_tracker->AddArgsTo(id);
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001123
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001124 StringId data_id = storage->InternString("data");
1125 StringId ftrace_data_id = storage->InternString(kLegacyFtraceData);
Lalit Maganti5228f362020-01-15 13:45:56 +00001126 inserter.AddArg(data_id, Variadic::String(ftrace_data_id));
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001127
Lalit Maganti679b29d2020-01-13 13:26:28 +00001128 id = storage->mutable_raw_table()->Insert(
1129 {0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0});
Lalit Maganti5228f362020-01-15 13:45:56 +00001130 inserter = context_.args_tracker->AddArgsTo(id);
Eric Seckler13b84b32019-10-04 12:00:38 +01001131 StringId json_data1_id = storage->InternString(kLegacyJsonData1);
Lalit Maganti5228f362020-01-15 13:45:56 +00001132 inserter.AddArg(data_id, Variadic::String(json_data1_id));
Eric Seckler13b84b32019-10-04 12:00:38 +01001133
Lalit Maganti679b29d2020-01-13 13:26:28 +00001134 id = storage->mutable_raw_table()->Insert(
1135 {0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0});
Lalit Maganti5228f362020-01-15 13:45:56 +00001136 inserter = context_.args_tracker->AddArgsTo(id);
Eric Seckler13b84b32019-10-04 12:00:38 +01001137 StringId json_data2_id = storage->InternString(kLegacyJsonData2);
Lalit Maganti5228f362020-01-15 13:45:56 +00001138 inserter.AddArg(data_id, Variadic::String(json_data2_id));
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001139
Eric Seckler4b861052019-10-23 14:50:28 +01001140 context_.args_tracker->Flush();
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001141
1142 base::TempFile temp_file = base::TempFile::Create();
1143 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +01001144 util::Status status = ExportJson(storage, output);
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001145
Eric Seckler7fb1d232019-10-23 14:42:43 +01001146 EXPECT_TRUE(status.ok());
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001147
Eric Seckler178094e2019-10-24 14:03:04 +01001148 Json::Value result = ToJsonValue(ReadFile(output));
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001149
Eric Seckler178094e2019-10-24 14:03:04 +01001150 EXPECT_EQ(result["traceEvents"].size(), 2u);
1151 EXPECT_EQ(result["traceEvents"][0]["user"].asInt(), 1);
1152 EXPECT_EQ(result["traceEvents"][1]["user"].asInt(), 2);
Mikhail Khokhlov9983e162019-08-15 12:04:08 +01001153 EXPECT_EQ(result["systemTraceEvents"].asString(), kLegacyFtraceData);
1154}
1155
Eric Seckler4b861052019-10-23 14:50:28 +01001156TEST_F(ExportJsonTest, CpuProfileEvent) {
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001157 const int64_t kProcessID = 100;
1158 const int64_t kThreadID = 200;
1159 const int64_t kTimestamp = 10000000;
1160
Eric Seckler4b861052019-10-23 14:50:28 +01001161 TraceStorage* storage = context_.storage.get();
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001162
Lalit Magantieac7fff2020-01-10 16:42:54 +00001163 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
1164 UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
1165 context_.storage->mutable_thread_table()->mutable_upid()->Set(utid, upid);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001166
Lalit Magantib0e11f62020-01-02 14:17:58 +00001167 auto module_id_1 = storage->mutable_stack_profile_mapping_table()->Insert(
1168 {storage->InternString("foo_module_id"), 0, 0, 0, 0, 0,
1169 storage->InternString("foo_module_name")});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001170
Lalit Magantib0e11f62020-01-02 14:17:58 +00001171 auto module_id_2 = storage->mutable_stack_profile_mapping_table()->Insert(
1172 {storage->InternString("bar_module_id"), 0, 0, 0, 0, 0,
1173 storage->InternString("bar_module_name")});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001174
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001175 // TODO(140860736): Once we support null values for
1176 // stack_profile_frame.symbol_set_id remove this hack
1177 storage->mutable_symbol_table()->Insert({0, 0, 0, 0});
1178
Lalit Maganti0a29f6f2020-01-06 12:01:14 +00001179 auto* frames = storage->mutable_stack_profile_frame_table();
1180 auto frame_id_1 = frames->Insert({/*name_id=*/0, module_id_1.value, 0x42});
1181 uint32_t frame_row_1 = *frames->id().IndexOf(frame_id_1);
1182
Lalit Maganti7e24f062019-12-17 18:10:35 +00001183 uint32_t symbol_set_id = storage->symbol_table().row_count();
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001184 storage->mutable_symbol_table()->Insert(
1185 {symbol_set_id, storage->InternString("foo_func"),
1186 storage->InternString("foo_file"), 66});
Lalit Maganti0a29f6f2020-01-06 12:01:14 +00001187 frames->mutable_symbol_set_id()->Set(frame_row_1, symbol_set_id);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001188
Lalit Maganti0a29f6f2020-01-06 12:01:14 +00001189 auto frame_id_2 = frames->Insert({/*name_id=*/0, module_id_2.value, 0x4242});
1190 uint32_t frame_row_2 = *frames->id().IndexOf(frame_id_2);
1191
Lalit Maganti7e24f062019-12-17 18:10:35 +00001192 symbol_set_id = storage->symbol_table().row_count();
Oystein Eftevaag2ba96d22019-10-14 11:36:56 -07001193 storage->mutable_symbol_table()->Insert(
1194 {symbol_set_id, storage->InternString("bar_func"),
1195 storage->InternString("bar_file"), 77});
Lalit Maganti0a29f6f2020-01-06 12:01:14 +00001196 frames->mutable_symbol_set_id()->Set(frame_row_2, symbol_set_id);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001197
Lalit Magantib0e11f62020-01-02 14:17:58 +00001198 auto frame_callsite_id_1 =
Lalit Magantiaa0ff5b2019-10-25 10:35:48 +01001199 storage->mutable_stack_profile_callsite_table()->Insert(
Lalit Maganti0a29f6f2020-01-06 12:01:14 +00001200 {0, -1, frame_id_1.value});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001201
Lalit Magantib0e11f62020-01-02 14:17:58 +00001202 auto frame_callsite_id_2 =
Lalit Magantiaa0ff5b2019-10-25 10:35:48 +01001203 storage->mutable_stack_profile_callsite_table()->Insert(
Lalit Maganti0a29f6f2020-01-06 12:01:14 +00001204 {1, frame_callsite_id_1.value, frame_id_2.value});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001205
Lalit Maganti0fd14ef2019-12-18 18:18:44 +00001206 storage->mutable_cpu_profile_stack_sample_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +00001207 {kTimestamp, frame_callsite_id_2.value, utid});
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001208
1209 base::TempFile temp_file = base::TempFile::Create();
1210 FILE* output = fopen(temp_file.path().c_str(), "w+");
Eric Seckler7fb1d232019-10-23 14:42:43 +01001211 util::Status status = ExportJson(storage, output);
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001212
Eric Seckler7fb1d232019-10-23 14:42:43 +01001213 EXPECT_TRUE(status.ok());
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001214
Eric Seckler178094e2019-10-24 14:03:04 +01001215 Json::Value result = ToJsonValue(ReadFile(output));
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001216
1217 EXPECT_EQ(result["traceEvents"].size(), 1u);
1218 Json::Value event = result["traceEvents"][0];
Oystein Eftevaaga33094d2019-11-12 10:48:15 -08001219 EXPECT_EQ(event["ph"].asString(), "n");
1220 EXPECT_EQ(event["id"].asString(), "0x1");
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001221 EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
1222 EXPECT_EQ(event["tid"].asUInt(), kThreadID);
1223 EXPECT_EQ(event["cat"].asString(), "disabled_by_default-cpu_profiler");
1224 EXPECT_EQ(event["name"].asString(), "StackCpuSampling");
Eric Seckler9dc34462019-11-06 14:44:20 +00001225 EXPECT_EQ(event["s"].asString(), "t");
Oystein Eftevaag85a4cf52019-09-05 11:10:26 -07001226 EXPECT_EQ(event["args"]["frames"].asString(),
1227 "foo_func - foo_module_name [foo_module_id]\nbar_func - "
1228 "bar_module_name [bar_module_id]\n");
1229}
1230
Eric Seckler178094e2019-10-24 14:03:04 +01001231TEST_F(ExportJsonTest, ArgumentFilter) {
Lalit Magantieac7fff2020-01-10 16:42:54 +00001232 UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
Eric Seckler3183c6d2020-01-14 15:45:20 +00001233 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler178094e2019-10-24 14:03:04 +01001234 context_.args_tracker->Flush(); // Flush track args.
1235
1236 StringId cat_id = context_.storage->InternString(base::StringView("cat"));
1237 std::array<StringId, 3> name_ids{
1238 context_.storage->InternString(base::StringView("name1")),
1239 context_.storage->InternString(base::StringView("name2")),
1240 context_.storage->InternString(base::StringView("name3"))};
1241 StringId arg1_id = context_.storage->InternString(base::StringView("arg1"));
1242 StringId arg2_id = context_.storage->InternString(base::StringView("arg2"));
1243 StringId val_id = context_.storage->InternString(base::StringView("val"));
1244
Lalit Maganti5228f362020-01-15 13:45:56 +00001245 std::vector<ArgsTracker::BoundInserter> slice_inserters;
Eric Seckler178094e2019-10-24 14:03:04 +01001246 for (size_t i = 0; i < name_ids.size(); i++) {
Lalit Magantib0e11f62020-01-02 14:17:58 +00001247 auto slice_id = context_.storage->mutable_slice_table()->Insert(
1248 {0, 0, track.value, cat_id, name_ids[i], 0, 0, 0});
Lalit Maganti5228f362020-01-15 13:45:56 +00001249 slice_inserters.emplace_back(context_.args_tracker->AddArgsTo(slice_id));
Eric Seckler178094e2019-10-24 14:03:04 +01001250 }
1251
Lalit Maganti5228f362020-01-15 13:45:56 +00001252 for (auto& inserter : slice_inserters) {
1253 inserter.AddArg(arg1_id, Variadic::Integer(5))
1254 .AddArg(arg2_id, Variadic::String(val_id));
Eric Seckler178094e2019-10-24 14:03:04 +01001255 }
1256 context_.args_tracker->Flush();
1257
1258 auto arg_filter = [](const char* category_group_name, const char* event_name,
1259 ArgumentNameFilterPredicate* arg_name_filter) {
1260 EXPECT_TRUE(strcmp(category_group_name, "cat") == 0);
1261 if (strcmp(event_name, "name1") == 0) {
1262 // Filter all args for name1.
1263 return false;
1264 } else if (strcmp(event_name, "name2") == 0) {
1265 // Filter only the second arg for name2.
1266 *arg_name_filter = [](const char* arg_name) {
1267 if (strcmp(arg_name, "arg1") == 0) {
1268 return true;
1269 }
1270 EXPECT_TRUE(strcmp(arg_name, "arg2") == 0);
1271 return false;
1272 };
1273 return true;
1274 }
1275 // Filter no args for name3.
1276 EXPECT_TRUE(strcmp(event_name, "name3") == 0);
1277 return true;
1278 };
1279
1280 Json::Value result = ToJsonValue(ToJson(arg_filter));
1281
1282 EXPECT_EQ(result["traceEvents"].size(), 3u);
1283
1284 EXPECT_EQ(result["traceEvents"][0]["cat"].asString(), "cat");
1285 EXPECT_EQ(result["traceEvents"][0]["name"].asString(), "name1");
1286 EXPECT_EQ(result["traceEvents"][0]["args"].asString(), "__stripped__");
1287
1288 EXPECT_EQ(result["traceEvents"][1]["cat"].asString(), "cat");
1289 EXPECT_EQ(result["traceEvents"][1]["name"].asString(), "name2");
1290 EXPECT_EQ(result["traceEvents"][1]["args"]["arg1"].asInt(), 5);
1291 EXPECT_EQ(result["traceEvents"][1]["args"]["arg2"].asString(),
1292 "__stripped__");
1293
1294 EXPECT_EQ(result["traceEvents"][2]["cat"].asString(), "cat");
1295 EXPECT_EQ(result["traceEvents"][2]["name"].asString(), "name3");
1296 EXPECT_EQ(result["traceEvents"][2]["args"]["arg1"].asInt(), 5);
1297 EXPECT_EQ(result["traceEvents"][2]["args"]["arg2"].asString(), "val");
1298}
1299
1300TEST_F(ExportJsonTest, MetadataFilter) {
1301 const char* kName1 = "name1";
1302 const char* kName2 = "name2";
1303 const char* kValue1 = "value1";
1304 const int kValue2 = 222;
1305
1306 TraceStorage* storage = context_.storage.get();
1307
Lalit Maganti679b29d2020-01-13 13:26:28 +00001308 RawId id = storage->mutable_raw_table()->Insert(
1309 {0, storage->InternString("chrome_event.metadata"), 0, 0});
Eric Seckler178094e2019-10-24 14:03:04 +01001310
1311 StringId name1_id = storage->InternString(base::StringView(kName1));
1312 StringId name2_id = storage->InternString(base::StringView(kName2));
1313 StringId value1_id = storage->InternString(base::StringView(kValue1));
Lalit Maganti5228f362020-01-15 13:45:56 +00001314
1315 context_.args_tracker->AddArgsTo(id)
1316 .AddArg(name1_id, Variadic::String(value1_id))
1317 .AddArg(name2_id, Variadic::Integer(kValue2));
Eric Seckler178094e2019-10-24 14:03:04 +01001318 context_.args_tracker->Flush();
1319
1320 auto metadata_filter = [](const char* metadata_name) {
1321 // Only allow name1.
1322 return strcmp(metadata_name, "name1") == 0;
1323 };
1324
1325 Json::Value result = ToJsonValue(ToJson(nullptr, metadata_filter));
1326
1327 EXPECT_TRUE(result.isMember("metadata"));
1328 Json::Value metadata = result["metadata"];
1329
1330 EXPECT_EQ(metadata[kName1].asString(), kValue1);
1331 EXPECT_EQ(metadata[kName2].asString(), "__stripped__");
1332}
1333
1334TEST_F(ExportJsonTest, LabelFilter) {
1335 const int64_t kTimestamp1 = 10000000;
1336 const int64_t kTimestamp2 = 20000000;
1337 const int64_t kDuration = 10000;
1338 const int64_t kThreadID = 100;
1339 const char* kCategory = "cat";
1340 const char* kName = "name";
1341
Lalit Magantieac7fff2020-01-10 16:42:54 +00001342 UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
Eric Seckler3183c6d2020-01-14 15:45:20 +00001343 TrackId track = context_.track_tracker->InternThreadTrack(utid);
Eric Seckler178094e2019-10-24 14:03:04 +01001344 context_.args_tracker->Flush(); // Flush track args.
1345 StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
1346 StringId name_id = context_.storage->InternString(base::StringView(kName));
1347
Lalit Magantic7ea02e2019-12-12 14:06:49 +00001348 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +00001349 {kTimestamp1, kDuration, track.value, cat_id, name_id, 0, 0, 0});
Lalit Magantic7ea02e2019-12-12 14:06:49 +00001350 context_.storage->mutable_slice_table()->Insert(
Lalit Magantib0e11f62020-01-02 14:17:58 +00001351 {kTimestamp2, kDuration, track.value, cat_id, name_id, 0, 0, 0});
Eric Seckler178094e2019-10-24 14:03:04 +01001352
1353 auto label_filter = [](const char* label_name) {
1354 return strcmp(label_name, "traceEvents") == 0;
1355 };
1356
1357 Json::Value result =
1358 ToJsonValue("[" + ToJson(nullptr, nullptr, label_filter) + "]");
1359
1360 EXPECT_TRUE(result.isArray());
1361 EXPECT_EQ(result.size(), 2u);
1362
1363 EXPECT_EQ(result[0]["ph"].asString(), "X");
1364 EXPECT_EQ(result[0]["ts"].asInt64(), kTimestamp1 / 1000);
1365 EXPECT_EQ(result[0]["dur"].asInt64(), kDuration / 1000);
1366 EXPECT_EQ(result[0]["tid"].asUInt(), kThreadID);
1367 EXPECT_EQ(result[0]["cat"].asString(), kCategory);
1368 EXPECT_EQ(result[0]["name"].asString(), kName);
1369 EXPECT_EQ(result[1]["ph"].asString(), "X");
1370 EXPECT_EQ(result[1]["ts"].asInt64(), kTimestamp2 / 1000);
1371 EXPECT_EQ(result[1]["dur"].asInt64(), kDuration / 1000);
1372 EXPECT_EQ(result[1]["tid"].asUInt(), kThreadID);
1373 EXPECT_EQ(result[1]["cat"].asString(), kCategory);
1374 EXPECT_EQ(result[1]["name"].asString(), kName);
1375}
Eric Seckler7fb1d232019-10-23 14:42:43 +01001376
Mikhail Khokhlova8d310d2019-05-07 17:34:21 +01001377} // namespace
1378} // namespace json
1379} // namespace trace_processor
1380} // namespace perfetto