• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 
17 #include <algorithm>
18 #include <map>
19 #include <optional>
20 #include <random>
21 #include <string>
22 
23 #include "perfetto/base/logging.h"
24 #include "perfetto/ext/base/scoped_file.h"
25 #include "perfetto/trace_processor/trace_processor.h"
26 #include "protos/perfetto/common/descriptor.pbzero.h"
27 #include "protos/perfetto/trace_processor/trace_processor.pbzero.h"
28 
29 #include "src/base/test/utils.h"
30 #include "test/gtest_and_gmock.h"
31 
32 namespace perfetto {
33 namespace trace_processor {
34 namespace {
35 
36 constexpr size_t kMaxChunkSize = 4 * 1024 * 1024;
37 
TEST(TraceProcessorCustomConfigTest,SkipInternalMetricsMatchingMountPath)38 TEST(TraceProcessorCustomConfigTest, SkipInternalMetricsMatchingMountPath) {
39   auto config = Config();
40   config.skip_builtin_metric_paths = {"android/"};
41   auto processor = TraceProcessor::CreateInstance(config);
42   processor->NotifyEndOfFile();
43 
44   // Check that andorid metrics have not been loaded.
45   auto it = processor->ExecuteQuery(
46       "select count(*) from trace_metrics "
47       "where name = 'android_cpu';");
48   ASSERT_TRUE(it.Next());
49   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
50   ASSERT_EQ(it.Get(0).long_value, 0);
51 
52   // Check that other metrics have been loaded.
53   it = processor->ExecuteQuery(
54       "select count(*) from trace_metrics "
55       "where name = 'trace_metadata';");
56   ASSERT_TRUE(it.Next());
57   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
58   ASSERT_EQ(it.Get(0).long_value, 1);
59 }
60 
TEST(TraceProcessorCustomConfigTest,EmptyStringSkipsAllMetrics)61 TEST(TraceProcessorCustomConfigTest, EmptyStringSkipsAllMetrics) {
62   auto config = Config();
63   config.skip_builtin_metric_paths = {""};
64   auto processor = TraceProcessor::CreateInstance(config);
65   processor->NotifyEndOfFile();
66 
67   // Check that other metrics have been loaded.
68   auto it = processor->ExecuteQuery(
69       "select count(*) from trace_metrics "
70       "where name = 'trace_metadata';");
71   ASSERT_TRUE(it.Next());
72   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
73   ASSERT_EQ(it.Get(0).long_value, 0);
74 }
75 
TEST(TraceProcessorCustomConfigTest,HandlesMalformedMountPath)76 TEST(TraceProcessorCustomConfigTest, HandlesMalformedMountPath) {
77   auto config = Config();
78   config.skip_builtin_metric_paths = {"androi"};
79   auto processor = TraceProcessor::CreateInstance(config);
80   processor->NotifyEndOfFile();
81 
82   // Check that andorid metrics have been loaded.
83   auto it = processor->ExecuteQuery(
84       "select count(*) from trace_metrics "
85       "where name = 'android_cpu';");
86   ASSERT_TRUE(it.Next());
87   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
88   ASSERT_EQ(it.Get(0).long_value, 1);
89 }
90 
91 class TraceProcessorIntegrationTest : public ::testing::Test {
92  public:
TraceProcessorIntegrationTest()93   TraceProcessorIntegrationTest()
94       : processor_(TraceProcessor::CreateInstance(Config())) {}
95 
96  protected:
LoadTrace(const char * name,size_t min_chunk_size=512,size_t max_chunk_size=kMaxChunkSize)97   util::Status LoadTrace(const char* name,
98                          size_t min_chunk_size = 512,
99                          size_t max_chunk_size = kMaxChunkSize) {
100     EXPECT_LE(min_chunk_size, max_chunk_size);
101     base::ScopedFstream f(fopen(
102         base::GetTestDataPath(std::string("test/data/") + name).c_str(), "rb"));
103     std::minstd_rand0 rnd_engine(0);
104     std::uniform_int_distribution<size_t> dist(min_chunk_size, max_chunk_size);
105     while (!feof(*f)) {
106       size_t chunk_size = dist(rnd_engine);
107       std::unique_ptr<uint8_t[]> buf(new uint8_t[chunk_size]);
108       auto rsize = fread(reinterpret_cast<char*>(buf.get()), 1, chunk_size, *f);
109       auto status = processor_->Parse(std::move(buf), rsize);
110       if (!status.ok())
111         return status;
112     }
113     processor_->NotifyEndOfFile();
114     return util::OkStatus();
115   }
116 
Query(const std::string & query)117   Iterator Query(const std::string& query) {
118     return processor_->ExecuteQuery(query.c_str());
119   }
120 
Processor()121   TraceProcessor* Processor() { return processor_.get(); }
122 
RestoreInitialTables()123   size_t RestoreInitialTables() { return processor_->RestoreInitialTables(); }
124 
125  private:
126   std::unique_ptr<TraceProcessor> processor_;
127 };
128 
TEST_F(TraceProcessorIntegrationTest,AndroidSchedAndPs)129 TEST_F(TraceProcessorIntegrationTest, AndroidSchedAndPs) {
130   ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb").ok());
131   auto it = Query(
132       "select count(*), max(ts) - min(ts) from sched "
133       "where dur != 0 and utid != 0");
134   ASSERT_TRUE(it.Next());
135   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
136   ASSERT_EQ(it.Get(0).long_value, 139793);
137   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
138   ASSERT_EQ(it.Get(1).long_value, 19684308497);
139   ASSERT_FALSE(it.Next());
140 }
141 
TEST_F(TraceProcessorIntegrationTest,TraceBounds)142 TEST_F(TraceProcessorIntegrationTest, TraceBounds) {
143   ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb").ok());
144   auto it = Query("select start_ts, end_ts from trace_bounds");
145   ASSERT_TRUE(it.Next());
146   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
147   ASSERT_EQ(it.Get(0).long_value, 81473009948313);
148   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
149   ASSERT_EQ(it.Get(1).long_value, 81492700784311);
150   ASSERT_FALSE(it.Next());
151 }
152 
153 // Tests that the duration of the last slice is accounted in the computation
154 // of the trace boundaries. Linux ftraces tend to hide this problem because
155 // after the last sched_switch there's always a "wake" event which causes the
156 // raw table to fix the bounds.
TEST_F(TraceProcessorIntegrationTest,TraceBoundsUserspaceOnly)157 TEST_F(TraceProcessorIntegrationTest, TraceBoundsUserspaceOnly) {
158   ASSERT_TRUE(LoadTrace("sfgate.json").ok());
159   auto it = Query("select start_ts, end_ts from trace_bounds");
160   ASSERT_TRUE(it.Next());
161   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
162   ASSERT_EQ(it.Get(0).long_value, 2213649212614000);
163   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
164   ASSERT_EQ(it.Get(1).long_value, 2213689745140000);
165   ASSERT_FALSE(it.Next());
166 }
167 
TEST_F(TraceProcessorIntegrationTest,Hash)168 TEST_F(TraceProcessorIntegrationTest, Hash) {
169   auto it = Query("select HASH()");
170   ASSERT_TRUE(it.Next());
171   ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xcbf29ce484222325));
172 
173   it = Query("select HASH('test')");
174   ASSERT_TRUE(it.Next());
175   ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xf9e6e6ef197c2b25));
176 
177   it = Query("select HASH('test', 1)");
178   ASSERT_TRUE(it.Next());
179   ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xa9cb070fdc15f7a4));
180 }
181 
182 #if !PERFETTO_BUILDFLAG(PERFETTO_LLVM_DEMANGLE) && \
183     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
184 #define MAYBE_Demangle DISABLED_Demangle
185 #else
186 #define MAYBE_Demangle Demangle
187 #endif
TEST_F(TraceProcessorIntegrationTest,MAYBE_Demangle)188 TEST_F(TraceProcessorIntegrationTest, MAYBE_Demangle) {
189   auto it = Query("select DEMANGLE('_Znwm')");
190   ASSERT_TRUE(it.Next());
191   EXPECT_STRCASEEQ(it.Get(0).string_value, "operator new(unsigned long)");
192 
193   it = Query("select DEMANGLE('_ZN3art6Thread14CreateCallbackEPv')");
194   ASSERT_TRUE(it.Next());
195   EXPECT_STRCASEEQ(it.Get(0).string_value,
196                    "art::Thread::CreateCallback(void*)");
197 
198   it = Query("select DEMANGLE('test')");
199   ASSERT_TRUE(it.Next());
200   EXPECT_TRUE(it.Get(0).is_null());
201 }
202 
203 #if !PERFETTO_BUILDFLAG(PERFETTO_LLVM_DEMANGLE)
204 #define MAYBE_DemangleRust DISABLED_DemangleRust
205 #else
206 #define MAYBE_DemangleRust DemangleRust
207 #endif
TEST_F(TraceProcessorIntegrationTest,MAYBE_DemangleRust)208 TEST_F(TraceProcessorIntegrationTest, MAYBE_DemangleRust) {
209   auto it = Query(
210       "select DEMANGLE("
211       "'_RNvNvMs0_NtNtNtCsg1Z12QU66Yk_3std3sys4unix6threadNtB7_"
212       "6Thread3new12thread_start')");
213   ASSERT_TRUE(it.Next());
214   EXPECT_STRCASEEQ(it.Get(0).string_value,
215                    "<std::sys::unix::thread::Thread>::new::thread_start");
216 
217   it = Query("select DEMANGLE('_RNvCsdV139EorvfX_14keystore2_main4main')");
218   ASSERT_TRUE(it.Next());
219   ASSERT_STRCASEEQ(it.Get(0).string_value, "keystore2_main::main");
220 
221   it = Query("select DEMANGLE('_R')");
222   ASSERT_TRUE(it.Next());
223   ASSERT_TRUE(it.Get(0).is_null());
224 }
225 
226 #if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
TEST_F(TraceProcessorIntegrationTest,Sfgate)227 TEST_F(TraceProcessorIntegrationTest, Sfgate) {
228   ASSERT_TRUE(LoadTrace("sfgate.json", strlen("{\"traceEvents\":[")).ok());
229   auto it = Query(
230       "select count(*), max(ts) - min(ts) "
231       "from slice s inner join thread_track t "
232       "on s.track_id = t.id where utid != 0");
233   ASSERT_TRUE(it.Next());
234   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
235   ASSERT_EQ(it.Get(0).long_value, 43357);
236   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
237   ASSERT_EQ(it.Get(1).long_value, 40532506000);
238   ASSERT_FALSE(it.Next());
239 }
240 
TEST_F(TraceProcessorIntegrationTest,UnsortedTrace)241 TEST_F(TraceProcessorIntegrationTest, UnsortedTrace) {
242   ASSERT_TRUE(
243       LoadTrace("unsorted_trace.json", strlen("{\"traceEvents\":[")).ok());
244   auto it = Query("select ts, depth from slice order by ts");
245   ASSERT_TRUE(it.Next());
246   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
247   ASSERT_EQ(it.Get(0).long_value, 50000);
248   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
249   ASSERT_EQ(it.Get(1).long_value, 0);
250   ASSERT_TRUE(it.Next());
251   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
252   ASSERT_EQ(it.Get(0).long_value, 100000);
253   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
254   ASSERT_EQ(it.Get(1).long_value, 1);
255   ASSERT_FALSE(it.Next());
256 }
257 
TEST_F(TraceProcessorIntegrationTest,SerializeMetricDescriptors)258 TEST_F(TraceProcessorIntegrationTest, SerializeMetricDescriptors) {
259   std::vector<uint8_t> desc_set_bytes = Processor()->GetMetricDescriptors();
260   protos::pbzero::DescriptorSet::Decoder desc_set(desc_set_bytes.data(),
261                                                   desc_set_bytes.size());
262 
263   ASSERT_TRUE(desc_set.has_descriptors());
264   int trace_metrics_count = 0;
265   for (auto desc = desc_set.descriptors(); desc; ++desc) {
266     protos::pbzero::DescriptorProto::Decoder proto_desc(*desc);
267     if (proto_desc.name().ToStdString() == ".perfetto.protos.TraceMetrics") {
268       ASSERT_TRUE(proto_desc.has_field());
269       trace_metrics_count++;
270     }
271   }
272 
273   // There should be exactly one definition of TraceMetrics. This can be not
274   // true if we're not deduping descriptors properly.
275   ASSERT_EQ(trace_metrics_count, 1);
276 }
277 
TEST_F(TraceProcessorIntegrationTest,ComputeMetricsFormattedExtension)278 TEST_F(TraceProcessorIntegrationTest, ComputeMetricsFormattedExtension) {
279   std::string metric_output;
280   util::Status status = Processor()->ComputeMetricText(
281       std::vector<std::string>{"test_chrome_metric"},
282       TraceProcessor::MetricResultFormat::kProtoText, &metric_output);
283   ASSERT_TRUE(status.ok());
284   // Extension fields are output as [fully.qualified.name].
285   ASSERT_EQ(metric_output,
286             "[perfetto.protos.test_chrome_metric] {\n"
287             "  test_value: 1\n"
288             "}");
289 }
290 
TEST_F(TraceProcessorIntegrationTest,ComputeMetricsFormattedNoExtension)291 TEST_F(TraceProcessorIntegrationTest, ComputeMetricsFormattedNoExtension) {
292   std::string metric_output;
293   util::Status status = Processor()->ComputeMetricText(
294       std::vector<std::string>{"trace_metadata"},
295       TraceProcessor::MetricResultFormat::kProtoText, &metric_output);
296   ASSERT_TRUE(status.ok());
297   // Check that metric result starts with trace_metadata field. Since this is
298   // not an extension field, the field name is not fully qualified.
299   ASSERT_TRUE(metric_output.rfind("trace_metadata {") == 0);
300 }
301 
302 // TODO(hjd): Add trace to test_data.
TEST_F(TraceProcessorIntegrationTest,DISABLED_AndroidBuildTrace)303 TEST_F(TraceProcessorIntegrationTest, DISABLED_AndroidBuildTrace) {
304   ASSERT_TRUE(LoadTrace("android_build_trace.json", strlen("[\n{")).ok());
305 }
306 
TEST_F(TraceProcessorIntegrationTest,DISABLED_Clusterfuzz14357)307 TEST_F(TraceProcessorIntegrationTest, DISABLED_Clusterfuzz14357) {
308   ASSERT_FALSE(LoadTrace("clusterfuzz_14357", 4096).ok());
309 }
310 #endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
311 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz14730)312 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14730) {
313   ASSERT_TRUE(LoadTrace("clusterfuzz_14730", 4096).ok());
314 }
315 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz14753)316 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14753) {
317   ASSERT_TRUE(LoadTrace("clusterfuzz_14753", 4096).ok());
318 }
319 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz14762)320 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14762) {
321   ASSERT_TRUE(LoadTrace("clusterfuzz_14762", 4096 * 1024).ok());
322   auto it = Query("select sum(value) from stats where severity = 'error';");
323   ASSERT_TRUE(it.Next());
324   ASSERT_GT(it.Get(0).long_value, 0);
325 }
326 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz14767)327 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14767) {
328   ASSERT_TRUE(LoadTrace("clusterfuzz_14767", 4096 * 1024).ok());
329   auto it = Query("select sum(value) from stats where severity = 'error';");
330   ASSERT_TRUE(it.Next());
331   ASSERT_GT(it.Get(0).long_value, 0);
332 }
333 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz14799)334 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14799) {
335   ASSERT_TRUE(LoadTrace("clusterfuzz_14799", 4096 * 1024).ok());
336   auto it = Query("select sum(value) from stats where severity = 'error';");
337   ASSERT_TRUE(it.Next());
338   ASSERT_GT(it.Get(0).long_value, 0);
339 }
340 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz15252)341 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz15252) {
342   ASSERT_TRUE(LoadTrace("clusterfuzz_15252", 4096).ok());
343 }
344 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz17805)345 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz17805) {
346   // This trace is garbage but is detected as a systrace. However, it should
347   // still parse successfully as we try to be graceful with encountering random
348   // data in systrace as they can have arbitrary print events from the kernel.
349   ASSERT_TRUE(LoadTrace("clusterfuzz_17805", 4096).ok());
350 }
351 
352 // Failing on DCHECKs during import because the traces aren't really valid.
353 #if PERFETTO_DCHECK_IS_ON()
354 #define MAYBE_Clusterfuzz20215 DISABLED_Clusterfuzz20215
355 #define MAYBE_Clusterfuzz20292 DISABLED_Clusterfuzz20292
356 #define MAYBE_Clusterfuzz21178 DISABLED_Clusterfuzz21178
357 #define MAYBE_Clusterfuzz21890 DISABLED_Clusterfuzz21890
358 #define MAYBE_Clusterfuzz23053 DISABLED_Clusterfuzz23053
359 #define MAYBE_Clusterfuzz28338 DISABLED_Clusterfuzz28338
360 #define MAYBE_Clusterfuzz28766 DISABLED_Clusterfuzz28766
361 #else  // PERFETTO_DCHECK_IS_ON()
362 #define MAYBE_Clusterfuzz20215 Clusterfuzz20215
363 #define MAYBE_Clusterfuzz20292 Clusterfuzz20292
364 #define MAYBE_Clusterfuzz21178 Clusterfuzz21178
365 #define MAYBE_Clusterfuzz21890 Clusterfuzz21890
366 #define MAYBE_Clusterfuzz23053 Clusterfuzz23053
367 #define MAYBE_Clusterfuzz28338 Clusterfuzz28338
368 #define MAYBE_Clusterfuzz28766 Clusterfuzz28766
369 #endif  // PERFETTO_DCHECK_IS_ON()
370 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz20215)371 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz20215) {
372   ASSERT_TRUE(LoadTrace("clusterfuzz_20215", 4096).ok());
373 }
374 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz20292)375 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz20292) {
376   ASSERT_FALSE(LoadTrace("clusterfuzz_20292", 4096).ok());
377 }
378 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz21178)379 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz21178) {
380   ASSERT_TRUE(LoadTrace("clusterfuzz_21178", 4096).ok());
381 }
382 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz21890)383 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz21890) {
384   ASSERT_FALSE(LoadTrace("clusterfuzz_21890", 4096).ok());
385 }
386 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz23053)387 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz23053) {
388   ASSERT_FALSE(LoadTrace("clusterfuzz_23053", 4096).ok());
389 }
390 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz28338)391 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz28338) {
392   ASSERT_TRUE(LoadTrace("clusterfuzz_28338", 4096).ok());
393 }
394 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz28766)395 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz28766) {
396   ASSERT_TRUE(LoadTrace("clusterfuzz_28766", 4096).ok());
397 }
398 
TEST_F(TraceProcessorIntegrationTest,RestoreInitialTables)399 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTables) {
400   ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb").ok());
401 
402   for (int repeat = 0; repeat < 3; repeat++) {
403     ASSERT_EQ(RestoreInitialTables(), 0u);
404 
405     auto it = Query("CREATE TABLE user1(unused text);");
406     it.Next();
407     ASSERT_TRUE(it.Status().ok());
408 
409     it = Query("CREATE TEMPORARY TABLE user2(unused text);");
410     it.Next();
411     ASSERT_TRUE(it.Status().ok());
412 
413     it = Query("CREATE VIEW user3 AS SELECT * FROM stats;");
414     it.Next();
415     ASSERT_TRUE(it.Status().ok());
416 
417     ASSERT_EQ(RestoreInitialTables(), 3u);
418   }
419 }
420 
421 // This test checks that a ninja trace is tokenized properly even if read in
422 // small chunks of 1KB each. The values used in the test have been cross-checked
423 // with opening the same trace with ninjatracing + chrome://tracing.
TEST_F(TraceProcessorIntegrationTest,NinjaLog)424 TEST_F(TraceProcessorIntegrationTest, NinjaLog) {
425   ASSERT_TRUE(LoadTrace("ninja_log", 1024).ok());
426   auto it = Query("select count(*) from process where name glob 'Build';");
427   ASSERT_TRUE(it.Next());
428   ASSERT_EQ(it.Get(0).long_value, 1);
429 
430   it = Query(
431       "select count(*) from thread left join process using(upid) where "
432       "thread.name like 'Worker%' and process.pid=1");
433   ASSERT_TRUE(it.Next());
434   ASSERT_EQ(it.Get(0).long_value, 28);
435 
436   it = Query(
437       "create view slices_1st_build as select slices.* from slices left "
438       "join thread_track on(slices.track_id == thread_track.id) left join "
439       "thread using(utid) left join process using(upid) where pid=1");
440   it.Next();
441   ASSERT_TRUE(it.Status().ok());
442 
443   it = Query("select (max(ts) - min(ts)) / 1000000 from slices_1st_build");
444   ASSERT_TRUE(it.Next());
445   ASSERT_EQ(it.Get(0).long_value, 44697);
446 
447   it = Query("select name from slices_1st_build order by ts desc limit 1");
448   ASSERT_TRUE(it.Next());
449   ASSERT_STREQ(it.Get(0).string_value, "trace_processor_shell");
450 
451   it = Query("select sum(dur) / 1000000 from slices_1st_build");
452   ASSERT_TRUE(it.Next());
453   ASSERT_EQ(it.Get(0).long_value, 837192);
454 }
455 
456 /*
457  * This trace does not have a uuid. The uuid will be generated from the first
458  * 4096 bytes, which will be read in one chunk.
459  */
TEST_F(TraceProcessorIntegrationTest,TraceWithoutUuidReadInOneChunk)460 TEST_F(TraceProcessorIntegrationTest, TraceWithoutUuidReadInOneChunk) {
461   ASSERT_TRUE(LoadTrace("example_android_trace_30s.pb", kMaxChunkSize).ok());
462   auto it = Query("select str_value from metadata where name = 'trace_uuid'");
463   ASSERT_TRUE(it.Next());
464   EXPECT_STREQ(it.Get(0).string_value, "00000000-0000-0000-8906-ebb53e1d0738");
465 }
466 
467 /*
468  * This trace does not have a uuid. The uuid will be generated from the first
469  * 4096 bytes, which will be read in multiple chunks.
470  */
TEST_F(TraceProcessorIntegrationTest,TraceWithoutUuidReadInMultipleChuncks)471 TEST_F(TraceProcessorIntegrationTest, TraceWithoutUuidReadInMultipleChuncks) {
472   ASSERT_TRUE(LoadTrace("example_android_trace_30s.pb", 512, 2048).ok());
473   auto it = Query("select str_value from metadata where name = 'trace_uuid'");
474   ASSERT_TRUE(it.Next());
475   EXPECT_STREQ(it.Get(0).string_value, "00000000-0000-0000-8906-ebb53e1d0738");
476 }
477 
478 /*
479  * This trace has a uuid. It will not be overriden by the hash of the first 4096
480  * bytes.
481  */
TEST_F(TraceProcessorIntegrationTest,TraceWithUuidReadInParts)482 TEST_F(TraceProcessorIntegrationTest, TraceWithUuidReadInParts) {
483   ASSERT_TRUE(LoadTrace("trace_with_uuid.pftrace", 512, 2048).ok());
484   auto it = Query("select str_value from metadata where name = 'trace_uuid'");
485   ASSERT_TRUE(it.Next());
486   EXPECT_STREQ(it.Get(0).string_value, "123e4567-e89b-12d3-a456-426655443322");
487 }
488 
489 }  // namespace
490 }  // namespace trace_processor
491 }  // namespace perfetto
492