• 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 <cstdint>
18 #include <cstdio>
19 #include <cstring>
20 #include <memory>
21 #include <random>
22 #include <string>
23 #include <utility>
24 #include <vector>
25 
26 #include "perfetto/base/build_config.h"
27 #include "perfetto/base/logging.h"
28 #include "perfetto/base/status.h"
29 #include "perfetto/ext/base/scoped_file.h"
30 #include "perfetto/ext/base/string_utils.h"
31 #include "perfetto/trace_processor/basic_types.h"
32 #include "perfetto/trace_processor/iterator.h"
33 #include "perfetto/trace_processor/status.h"
34 #include "perfetto/trace_processor/trace_processor.h"
35 #include "protos/perfetto/common/descriptor.pbzero.h"
36 #include "protos/perfetto/trace_processor/trace_processor.pbzero.h"
37 
38 #include "src/base/test/utils.h"
39 #include "test/gtest_and_gmock.h"
40 
41 namespace perfetto::trace_processor {
42 namespace {
43 
44 using testing::HasSubstr;
45 
46 constexpr size_t kMaxChunkSize = 4ul * 1024 * 1024;
47 
TEST(TraceProcessorCustomConfigTest,SkipInternalMetricsMatchingMountPath)48 TEST(TraceProcessorCustomConfigTest, SkipInternalMetricsMatchingMountPath) {
49   auto config = Config();
50   config.skip_builtin_metric_paths = {"android/"};
51   auto processor = TraceProcessor::CreateInstance(config);
52   processor->NotifyEndOfFile();
53 
54   // Check that andorid metrics have not been loaded.
55   auto it = processor->ExecuteQuery(
56       "select count(*) from trace_metrics "
57       "where name = 'android_cpu';");
58   ASSERT_TRUE(it.Next());
59   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
60   ASSERT_EQ(it.Get(0).long_value, 0);
61 
62   // Check that other metrics have been loaded.
63   it = processor->ExecuteQuery(
64       "select count(*) from trace_metrics "
65       "where name = 'trace_metadata';");
66   ASSERT_TRUE(it.Next());
67   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
68   ASSERT_EQ(it.Get(0).long_value, 1);
69 }
70 
TEST(TraceProcessorCustomConfigTest,EmptyStringSkipsAllMetrics)71 TEST(TraceProcessorCustomConfigTest, EmptyStringSkipsAllMetrics) {
72   auto config = Config();
73   config.skip_builtin_metric_paths = {""};
74   auto processor = TraceProcessor::CreateInstance(config);
75   processor->NotifyEndOfFile();
76 
77   // Check that other metrics have been loaded.
78   auto it = processor->ExecuteQuery(
79       "select count(*) from trace_metrics "
80       "where name = 'trace_metadata';");
81   ASSERT_TRUE(it.Next());
82   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
83   ASSERT_EQ(it.Get(0).long_value, 0);
84 }
85 
TEST(TraceProcessorCustomConfigTest,HandlesMalformedMountPath)86 TEST(TraceProcessorCustomConfigTest, HandlesMalformedMountPath) {
87   auto config = Config();
88   config.skip_builtin_metric_paths = {"androi"};
89   auto processor = TraceProcessor::CreateInstance(config);
90   processor->NotifyEndOfFile();
91 
92   // Check that andorid metrics have been loaded.
93   auto it = processor->ExecuteQuery(
94       "select count(*) from trace_metrics "
95       "where name = 'android_cpu';");
96   ASSERT_TRUE(it.Next());
97   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
98   ASSERT_EQ(it.Get(0).long_value, 1);
99 }
100 
101 class TraceProcessorIntegrationTest : public ::testing::Test {
102  public:
TraceProcessorIntegrationTest()103   TraceProcessorIntegrationTest()
104       : processor_(TraceProcessor::CreateInstance(Config())) {}
105 
106  protected:
LoadTrace(const char * name,size_t min_chunk_size=512,size_t max_chunk_size=kMaxChunkSize)107   base::Status LoadTrace(const char* name,
108                          size_t min_chunk_size = 512,
109                          size_t max_chunk_size = kMaxChunkSize) {
110     EXPECT_LE(min_chunk_size, max_chunk_size);
111     base::ScopedFstream f(
112         fopen(base::GetTestDataPath(std::string("test/data/") + name).c_str(),
113               "rbe"));
114     std::minstd_rand0 rnd_engine(0);
115     std::uniform_int_distribution<size_t> dist(min_chunk_size, max_chunk_size);
116     while (!feof(*f)) {
117       size_t chunk_size = dist(rnd_engine);
118       std::unique_ptr<uint8_t[]> buf(new uint8_t[chunk_size]);
119       auto rsize = fread(reinterpret_cast<char*>(buf.get()), 1, chunk_size, *f);
120       auto status = processor_->Parse(std::move(buf), rsize);
121       if (!status.ok())
122         return status;
123     }
124     processor_->NotifyEndOfFile();
125     return util::OkStatus();
126   }
127 
Query(const std::string & query)128   Iterator Query(const std::string& query) {
129     return processor_->ExecuteQuery(query);
130   }
131 
Processor()132   TraceProcessor* Processor() { return processor_.get(); }
133 
RestoreInitialTables()134   size_t RestoreInitialTables() { return processor_->RestoreInitialTables(); }
135 
136  private:
137   std::unique_ptr<TraceProcessor> processor_;
138 };
139 
TEST_F(TraceProcessorIntegrationTest,AndroidSchedAndPs)140 TEST_F(TraceProcessorIntegrationTest, AndroidSchedAndPs) {
141   ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb").ok());
142   auto it = Query(
143       "select count(*), max(ts) - min(ts) from sched "
144       "where dur != 0 and utid != 0");
145   ASSERT_TRUE(it.Next());
146   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
147   ASSERT_EQ(it.Get(0).long_value, 139793);
148   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
149   ASSERT_EQ(it.Get(1).long_value, 19684308497);
150   ASSERT_FALSE(it.Next());
151 }
152 
TEST_F(TraceProcessorIntegrationTest,TraceBounds)153 TEST_F(TraceProcessorIntegrationTest, TraceBounds) {
154   ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb").ok());
155   auto it = Query("select start_ts, end_ts from trace_bounds");
156   ASSERT_TRUE(it.Next());
157   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
158   ASSERT_EQ(it.Get(0).long_value, 81473009948313);
159   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
160   ASSERT_EQ(it.Get(1).long_value, 81492700784311);
161   ASSERT_FALSE(it.Next());
162 }
163 
164 // Tests that the duration of the last slice is accounted in the computation
165 // of the trace boundaries. Linux ftraces tend to hide this problem because
166 // after the last sched_switch there's always a "wake" event which causes the
167 // raw table to fix the bounds.
TEST_F(TraceProcessorIntegrationTest,TraceBoundsUserspaceOnly)168 TEST_F(TraceProcessorIntegrationTest, TraceBoundsUserspaceOnly) {
169   ASSERT_TRUE(LoadTrace("sfgate.json").ok());
170   auto it = Query("select start_ts, end_ts from trace_bounds");
171   ASSERT_TRUE(it.Next());
172   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
173   ASSERT_EQ(it.Get(0).long_value, 2213649212614000);
174   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
175   ASSERT_EQ(it.Get(1).long_value, 2213689745140000);
176   ASSERT_FALSE(it.Next());
177 }
178 
TEST_F(TraceProcessorIntegrationTest,Hash)179 TEST_F(TraceProcessorIntegrationTest, Hash) {
180   auto it = Query("select HASH()");
181   ASSERT_TRUE(it.Next());
182   ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xcbf29ce484222325));
183 
184   it = Query("select HASH('test')");
185   ASSERT_TRUE(it.Next());
186   ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xf9e6e6ef197c2b25));
187 
188   it = Query("select HASH('test', 1)");
189   ASSERT_TRUE(it.Next());
190   ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xa9cb070fdc15f7a4));
191 }
192 
193 #if !PERFETTO_BUILDFLAG(PERFETTO_LLVM_DEMANGLE) && \
194     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
195 #define MAYBE_Demangle DISABLED_Demangle
196 #else
197 #define MAYBE_Demangle Demangle
198 #endif
TEST_F(TraceProcessorIntegrationTest,MAYBE_Demangle)199 TEST_F(TraceProcessorIntegrationTest, MAYBE_Demangle) {
200   auto it = Query("select DEMANGLE('_Znwm')");
201   ASSERT_TRUE(it.Next());
202   EXPECT_STRCASEEQ(it.Get(0).string_value, "operator new(unsigned long)");
203 
204   it = Query("select DEMANGLE('_ZN3art6Thread14CreateCallbackEPv')");
205   ASSERT_TRUE(it.Next());
206   EXPECT_STRCASEEQ(it.Get(0).string_value,
207                    "art::Thread::CreateCallback(void*)");
208 
209   it = Query("select DEMANGLE('test')");
210   ASSERT_TRUE(it.Next());
211   EXPECT_TRUE(it.Get(0).is_null());
212 }
213 
214 #if !PERFETTO_BUILDFLAG(PERFETTO_LLVM_DEMANGLE)
215 #define MAYBE_DemangleRust DISABLED_DemangleRust
216 #else
217 #define MAYBE_DemangleRust DemangleRust
218 #endif
TEST_F(TraceProcessorIntegrationTest,MAYBE_DemangleRust)219 TEST_F(TraceProcessorIntegrationTest, MAYBE_DemangleRust) {
220   auto it = Query(
221       "select DEMANGLE("
222       "'_RNvNvMs0_NtNtNtCsg1Z12QU66Yk_3std3sys4unix6threadNtB7_"
223       "6Thread3new12thread_start')");
224   ASSERT_TRUE(it.Next());
225   EXPECT_STRCASEEQ(it.Get(0).string_value,
226                    "<std::sys::unix::thread::Thread>::new::thread_start");
227 
228   it = Query("select DEMANGLE('_RNvCsdV139EorvfX_14keystore2_main4main')");
229   ASSERT_TRUE(it.Next());
230   ASSERT_STRCASEEQ(it.Get(0).string_value, "keystore2_main::main");
231 
232   it = Query("select DEMANGLE('_R')");
233   ASSERT_TRUE(it.Next());
234   ASSERT_TRUE(it.Get(0).is_null());
235 }
236 
237 #if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
TEST_F(TraceProcessorIntegrationTest,Sfgate)238 TEST_F(TraceProcessorIntegrationTest, Sfgate) {
239   ASSERT_TRUE(LoadTrace("sfgate.json", strlen("{\"traceEvents\":[")).ok());
240   auto it = Query(
241       "select count(*), max(ts) - min(ts) "
242       "from slice s inner join thread_track t "
243       "on s.track_id = t.id where utid != 0");
244   ASSERT_TRUE(it.Next());
245   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
246   ASSERT_EQ(it.Get(0).long_value, 43357);
247   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
248   ASSERT_EQ(it.Get(1).long_value, 40532506000);
249   ASSERT_FALSE(it.Next());
250 }
251 
TEST_F(TraceProcessorIntegrationTest,UnsortedTrace)252 TEST_F(TraceProcessorIntegrationTest, UnsortedTrace) {
253   ASSERT_TRUE(
254       LoadTrace("unsorted_trace.json", strlen("{\"traceEvents\":[")).ok());
255   auto it = Query("select ts, depth from slice order by ts");
256   ASSERT_TRUE(it.Next());
257   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
258   ASSERT_EQ(it.Get(0).long_value, 50000);
259   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
260   ASSERT_EQ(it.Get(1).long_value, 0);
261   ASSERT_TRUE(it.Next());
262   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
263   ASSERT_EQ(it.Get(0).long_value, 100000);
264   ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
265   ASSERT_EQ(it.Get(1).long_value, 1);
266   ASSERT_FALSE(it.Next());
267 }
268 
TEST_F(TraceProcessorIntegrationTest,SerializeMetricDescriptors)269 TEST_F(TraceProcessorIntegrationTest, SerializeMetricDescriptors) {
270   std::vector<uint8_t> desc_set_bytes = Processor()->GetMetricDescriptors();
271   protos::pbzero::DescriptorSet::Decoder desc_set(desc_set_bytes.data(),
272                                                   desc_set_bytes.size());
273 
274   ASSERT_TRUE(desc_set.has_descriptors());
275   int trace_metrics_count = 0;
276   for (auto desc = desc_set.descriptors(); desc; ++desc) {
277     protos::pbzero::DescriptorProto::Decoder proto_desc(*desc);
278     if (proto_desc.name().ToStdString() == ".perfetto.protos.TraceMetrics") {
279       ASSERT_TRUE(proto_desc.has_field());
280       trace_metrics_count++;
281     }
282   }
283 
284   // There should be exactly one definition of TraceMetrics. This can be not
285   // true if we're not deduping descriptors properly.
286   ASSERT_EQ(trace_metrics_count, 1);
287 }
288 
TEST_F(TraceProcessorIntegrationTest,ComputeMetricsFormattedExtension)289 TEST_F(TraceProcessorIntegrationTest, ComputeMetricsFormattedExtension) {
290   std::string metric_output;
291   base::Status status = Processor()->ComputeMetricText(
292       std::vector<std::string>{"test_chrome_metric"},
293       TraceProcessor::MetricResultFormat::kProtoText, &metric_output);
294   ASSERT_TRUE(status.ok());
295   // Extension fields are output as [fully.qualified.name].
296   ASSERT_EQ(metric_output,
297             "[perfetto.protos.test_chrome_metric] {\n"
298             "  test_value: 1\n"
299             "}");
300 }
301 
TEST_F(TraceProcessorIntegrationTest,ComputeMetricsFormattedNoExtension)302 TEST_F(TraceProcessorIntegrationTest, ComputeMetricsFormattedNoExtension) {
303   std::string metric_output;
304   base::Status status = Processor()->ComputeMetricText(
305       std::vector<std::string>{"trace_metadata"},
306       TraceProcessor::MetricResultFormat::kProtoText, &metric_output);
307   ASSERT_TRUE(status.ok());
308   // Check that metric result starts with trace_metadata field. Since this is
309   // not an extension field, the field name is not fully qualified.
310   ASSERT_TRUE(metric_output.rfind("trace_metadata {") == 0);
311 }
312 
313 // TODO(hjd): Add trace to test_data.
TEST_F(TraceProcessorIntegrationTest,DISABLED_AndroidBuildTrace)314 TEST_F(TraceProcessorIntegrationTest, DISABLED_AndroidBuildTrace) {
315   ASSERT_TRUE(LoadTrace("android_build_trace.json", strlen("[\n{")).ok());
316 }
317 
TEST_F(TraceProcessorIntegrationTest,DISABLED_Clusterfuzz14357)318 TEST_F(TraceProcessorIntegrationTest, DISABLED_Clusterfuzz14357) {
319   ASSERT_FALSE(LoadTrace("clusterfuzz_14357", 4096).ok());
320 }
321 #endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
322 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz14730)323 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14730) {
324   ASSERT_TRUE(LoadTrace("clusterfuzz_14730", 4096).ok());
325 }
326 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz14753)327 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14753) {
328   ASSERT_TRUE(LoadTrace("clusterfuzz_14753", 4096).ok());
329 }
330 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz14762)331 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14762) {
332   ASSERT_TRUE(LoadTrace("clusterfuzz_14762", 4096ul * 1024).ok());
333   auto it = Query("select sum(value) from stats where severity = 'error';");
334   ASSERT_TRUE(it.Next());
335   ASSERT_GT(it.Get(0).long_value, 0);
336 }
337 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz14767)338 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14767) {
339   ASSERT_TRUE(LoadTrace("clusterfuzz_14767", 4096ul * 1024).ok());
340   auto it = Query("select sum(value) from stats where severity = 'error';");
341   ASSERT_TRUE(it.Next());
342   ASSERT_GT(it.Get(0).long_value, 0);
343 }
344 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz14799)345 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14799) {
346   ASSERT_TRUE(LoadTrace("clusterfuzz_14799", 4096ul * 1024).ok());
347   auto it = Query("select sum(value) from stats where severity = 'error';");
348   ASSERT_TRUE(it.Next());
349   ASSERT_GT(it.Get(0).long_value, 0);
350 }
351 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz15252)352 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz15252) {
353   ASSERT_TRUE(LoadTrace("clusterfuzz_15252", 4096).ok());
354 }
355 
TEST_F(TraceProcessorIntegrationTest,Clusterfuzz17805)356 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz17805) {
357   // This trace is garbage but is detected as a systrace. However, it should
358   // still parse successfully as we try to be graceful with encountering random
359   // data in systrace as they can have arbitrary print events from the kernel.
360   ASSERT_TRUE(LoadTrace("clusterfuzz_17805", 4096).ok());
361 }
362 
363 // Failing on DCHECKs during import because the traces aren't really valid.
364 #if PERFETTO_DCHECK_IS_ON()
365 #define MAYBE_Clusterfuzz20215 DISABLED_Clusterfuzz20215
366 #define MAYBE_Clusterfuzz20292 DISABLED_Clusterfuzz20292
367 #define MAYBE_Clusterfuzz21178 DISABLED_Clusterfuzz21178
368 #define MAYBE_Clusterfuzz21890 DISABLED_Clusterfuzz21890
369 #define MAYBE_Clusterfuzz23053 DISABLED_Clusterfuzz23053
370 #define MAYBE_Clusterfuzz28338 DISABLED_Clusterfuzz28338
371 #define MAYBE_Clusterfuzz28766 DISABLED_Clusterfuzz28766
372 #else  // PERFETTO_DCHECK_IS_ON()
373 #define MAYBE_Clusterfuzz20215 Clusterfuzz20215
374 #define MAYBE_Clusterfuzz20292 Clusterfuzz20292
375 #define MAYBE_Clusterfuzz21178 Clusterfuzz21178
376 #define MAYBE_Clusterfuzz21890 Clusterfuzz21890
377 #define MAYBE_Clusterfuzz23053 Clusterfuzz23053
378 #define MAYBE_Clusterfuzz28338 Clusterfuzz28338
379 #define MAYBE_Clusterfuzz28766 Clusterfuzz28766
380 #endif  // PERFETTO_DCHECK_IS_ON()
381 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz20215)382 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz20215) {
383   ASSERT_TRUE(LoadTrace("clusterfuzz_20215", 4096).ok());
384 }
385 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz20292)386 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz20292) {
387   ASSERT_FALSE(LoadTrace("clusterfuzz_20292", 4096).ok());
388 }
389 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz21178)390 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz21178) {
391   ASSERT_TRUE(LoadTrace("clusterfuzz_21178", 4096).ok());
392 }
393 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz21890)394 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz21890) {
395   ASSERT_FALSE(LoadTrace("clusterfuzz_21890", 4096).ok());
396 }
397 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz23053)398 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz23053) {
399   ASSERT_FALSE(LoadTrace("clusterfuzz_23053", 4096).ok());
400 }
401 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz28338)402 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz28338) {
403   ASSERT_TRUE(LoadTrace("clusterfuzz_28338", 4096).ok());
404 }
405 
TEST_F(TraceProcessorIntegrationTest,MAYBE_Clusterfuzz28766)406 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz28766) {
407   ASSERT_TRUE(LoadTrace("clusterfuzz_28766", 4096).ok());
408 }
409 
TEST_F(TraceProcessorIntegrationTest,RestoreInitialTablesInvariant)410 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTablesInvariant) {
411   Processor()->NotifyEndOfFile();
412   uint64_t first_restore = RestoreInitialTables();
413   ASSERT_EQ(RestoreInitialTables(), first_restore);
414 }
415 
TEST_F(TraceProcessorIntegrationTest,RestoreInitialTablesPerfettoSql)416 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTablesPerfettoSql) {
417   Processor()->NotifyEndOfFile();
418   RestoreInitialTables();
419 
420   for (int repeat = 0; repeat < 3; repeat++) {
421     ASSERT_EQ(RestoreInitialTables(), 0u);
422 
423     // 1. Perfetto table
424     {
425       auto it = Query("CREATE PERFETTO TABLE obj1 AS SELECT 1 AS col;");
426       it.Next();
427       ASSERT_TRUE(it.Status().ok());
428     }
429     // 2. Perfetto view
430     {
431       auto it = Query("CREATE PERFETTO VIEW obj2 AS SELECT * FROM stats;");
432       it.Next();
433       ASSERT_TRUE(it.Status().ok());
434     }
435     // 3. Runtime function
436     {
437       auto it =
438           Query("CREATE PERFETTO FUNCTION obj3() RETURNS INT AS SELECT 1;");
439       it.Next();
440       ASSERT_TRUE(it.Status().ok());
441     }
442     // 4. Runtime table function
443     {
444       auto it = Query(
445           "CREATE PERFETTO FUNCTION obj4() RETURNS TABLE(col INT) AS SELECT 1 "
446           "AS col;");
447       it.Next();
448       ASSERT_TRUE(it.Status().ok());
449     }
450     // 5. Macro
451     {
452       auto it = Query("CREATE PERFETTO MACRO obj5(a Expr) returns Expr AS $a;");
453       it.Next();
454       ASSERT_TRUE(it.Status().ok());
455     }
456     {
457       auto it = Query("obj5!(SELECT 1);");
458       it.Next();
459       ASSERT_TRUE(it.Status().ok());
460     }
461     ASSERT_EQ(RestoreInitialTables(), 5u);
462   }
463 }
464 
TEST_F(TraceProcessorIntegrationTest,RestoreInitialTablesStandardSqlite)465 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTablesStandardSqlite) {
466   Processor()->NotifyEndOfFile();
467   RestoreInitialTables();
468 
469   for (int repeat = 0; repeat < 3; repeat++) {
470     ASSERT_EQ(RestoreInitialTables(), 0u);
471     {
472       auto it = Query("CREATE TABLE obj1(unused text);");
473       it.Next();
474       ASSERT_TRUE(it.Status().ok());
475     }
476     {
477       auto it = Query("CREATE TEMPORARY TABLE obj2(unused text);");
478       it.Next();
479       ASSERT_TRUE(it.Status().ok());
480     }
481     // Add a view
482     {
483       auto it = Query("CREATE VIEW obj3 AS SELECT * FROM stats;");
484       it.Next();
485       ASSERT_TRUE(it.Status().ok());
486     }
487     ASSERT_EQ(RestoreInitialTables(), 3u);
488   }
489 }
490 
TEST_F(TraceProcessorIntegrationTest,RestoreInitialTablesModules)491 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTablesModules) {
492   Processor()->NotifyEndOfFile();
493   RestoreInitialTables();
494 
495   for (int repeat = 0; repeat < 3; repeat++) {
496     ASSERT_EQ(RestoreInitialTables(), 0u);
497     {
498       auto it = Query("INCLUDE PERFETTO MODULE common.timestamps;");
499       it.Next();
500       ASSERT_TRUE(it.Status().ok());
501     }
502     {
503       auto it = Query("SELECT trace_start();");
504       it.Next();
505       ASSERT_TRUE(it.Status().ok());
506     }
507     RestoreInitialTables();
508   }
509 }
510 
TEST_F(TraceProcessorIntegrationTest,RestoreInitialTablesSpanJoin)511 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTablesSpanJoin) {
512   Processor()->NotifyEndOfFile();
513   RestoreInitialTables();
514 
515   for (int repeat = 0; repeat < 3; repeat++) {
516     ASSERT_EQ(RestoreInitialTables(), 0u);
517     {
518       auto it = Query(
519           "CREATE TABLE t1(ts BIGINT, dur BIGINT, PRIMARY KEY (ts, dur)) "
520           "WITHOUT ROWID;");
521       it.Next();
522       ASSERT_TRUE(it.Status().ok());
523     }
524     {
525       auto it = Query(
526           "CREATE TABLE t2(ts BIGINT, dur BIGINT, PRIMARY KEY (ts, dur)) "
527           "WITHOUT ROWID;");
528       it.Next();
529       ASSERT_TRUE(it.Status().ok());
530     }
531     {
532       auto it = Query("INSERT INTO t2(ts, dur) VALUES(1, 2), (5, 0), (1, 1);");
533       it.Next();
534       ASSERT_TRUE(it.Status().ok());
535     }
536     {
537       auto it = Query("CREATE VIRTUAL TABLE sp USING span_join(t1, t2);;");
538       it.Next();
539       ASSERT_TRUE(it.Status().ok());
540     }
541     {
542       auto it = Query("SELECT ts, dur FROM sp;");
543       it.Next();
544       ASSERT_TRUE(it.Status().ok());
545     }
546     ASSERT_EQ(RestoreInitialTables(), 3u);
547   }
548 }
549 
TEST_F(TraceProcessorIntegrationTest,RestoreInitialTablesWithClause)550 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTablesWithClause) {
551   Processor()->NotifyEndOfFile();
552   RestoreInitialTables();
553 
554   for (int repeat = 0; repeat < 3; repeat++) {
555     ASSERT_EQ(RestoreInitialTables(), 0u);
556     {
557       auto it = Query(
558           "CREATE PERFETTO TABLE foo AS WITH bar AS (SELECT * FROM slice) "
559           "SELECT ts FROM bar;");
560       it.Next();
561       ASSERT_TRUE(it.Status().ok());
562     }
563     ASSERT_EQ(RestoreInitialTables(), 1u);
564   }
565 }
566 
TEST_F(TraceProcessorIntegrationTest,RestoreInitialTablesIndex)567 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTablesIndex) {
568   Processor()->NotifyEndOfFile();
569   RestoreInitialTables();
570 
571   for (int repeat = 0; repeat < 3; repeat++) {
572     ASSERT_EQ(RestoreInitialTables(), 0u);
573     {
574       auto it = Query("CREATE TABLE foo AS SELECT * FROM slice;");
575       it.Next();
576       ASSERT_TRUE(it.Status().ok());
577     }
578     {
579       auto it = Query("CREATE INDEX ind ON foo (ts, track_id);");
580       it.Next();
581       ASSERT_TRUE(it.Status().ok());
582     }
583     ASSERT_EQ(RestoreInitialTables(), 2u);
584   }
585 }
586 
TEST_F(TraceProcessorIntegrationTest,RestoreInitialTablesTraceBounds)587 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTablesTraceBounds) {
588   ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb").ok());
589   {
590     auto it = Query("SELECT * from trace_bounds;");
591     it.Next();
592     ASSERT_TRUE(it.Status().ok());
593     ASSERT_EQ(it.Get(0).AsLong(), 81473009948313l);
594   }
595 
596   ASSERT_EQ(RestoreInitialTables(), 0u);
597   {
598     auto it = Query("SELECT * from trace_bounds;");
599     it.Next();
600     ASSERT_TRUE(it.Status().ok());
601     ASSERT_EQ(it.Get(0).AsLong(), 81473009948313l);
602   }
603 }
604 
TEST_F(TraceProcessorIntegrationTest,RestoreInitialTablesDependents)605 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTablesDependents) {
606   Processor()->NotifyEndOfFile();
607   {
608     auto it = Query("create perfetto table foo as select 1 as x");
609     ASSERT_FALSE(it.Next());
610     ASSERT_TRUE(it.Status().ok());
611 
612     it = Query("create perfetto function f() returns INT as select * from foo");
613     ASSERT_FALSE(it.Next());
614     ASSERT_TRUE(it.Status().ok());
615 
616     it = Query("SELECT f()");
617     ASSERT_TRUE(it.Next());
618     ASSERT_FALSE(it.Next());
619     ASSERT_TRUE(it.Status().ok());
620   }
621 
622   ASSERT_EQ(RestoreInitialTables(), 2u);
623 }
624 
TEST_F(TraceProcessorIntegrationTest,RestoreDependentFunction)625 TEST_F(TraceProcessorIntegrationTest, RestoreDependentFunction) {
626   Processor()->NotifyEndOfFile();
627   {
628     auto it =
629         Query("create perfetto function foo0() returns INT as select 1 as x");
630     ASSERT_FALSE(it.Next());
631     ASSERT_TRUE(it.Status().ok());
632   }
633   for (int i = 1; i < 100; ++i) {
634     base::StackString<1024> sql(
635         "create perfetto function foo%d() returns INT as select foo%d()", i,
636         i - 1);
637     auto it = Query(sql.c_str());
638     ASSERT_FALSE(it.Next());
639     ASSERT_TRUE(it.Status().ok()) << it.Status().c_message();
640   }
641 
642   ASSERT_EQ(RestoreInitialTables(), 100u);
643 }
644 
TEST_F(TraceProcessorIntegrationTest,RestoreDependentTableFunction)645 TEST_F(TraceProcessorIntegrationTest, RestoreDependentTableFunction) {
646   Processor()->NotifyEndOfFile();
647   {
648     auto it = Query(
649         "create perfetto function foo0() returns TABLE(x INT) "
650         " as select 1 as x");
651     ASSERT_FALSE(it.Next());
652     ASSERT_TRUE(it.Status().ok());
653   }
654   for (int i = 1; i < 100; ++i) {
655     base::StackString<1024> sql(
656         "create perfetto function foo%d() returns TABLE(x INT) "
657         " as select * from foo%d()",
658         i, i - 1);
659     auto it = Query(sql.c_str());
660     ASSERT_FALSE(it.Next());
661     ASSERT_TRUE(it.Status().ok()) << it.Status().c_message();
662   }
663 
664   ASSERT_EQ(RestoreInitialTables(), 100u);
665 }
666 
667 // This test checks that a ninja trace is tokenized properly even if read in
668 // small chunks of 1KB each. The values used in the test have been cross-checked
669 // with opening the same trace with ninjatracing + chrome://tracing.
TEST_F(TraceProcessorIntegrationTest,NinjaLog)670 TEST_F(TraceProcessorIntegrationTest, NinjaLog) {
671   ASSERT_TRUE(LoadTrace("ninja_log", 1024).ok());
672   auto it = Query("select count(*) from process where name glob 'Build';");
673   ASSERT_TRUE(it.Next());
674   ASSERT_EQ(it.Get(0).long_value, 1);
675 
676   it = Query(
677       "select count(*) from thread left join process using(upid) where "
678       "thread.name like 'Worker%' and process.pid=1");
679   ASSERT_TRUE(it.Next());
680   ASSERT_EQ(it.Get(0).long_value, 28);
681 
682   it = Query(
683       "create view slices_1st_build as select slices.* from slices left "
684       "join thread_track on(slices.track_id == thread_track.id) left join "
685       "thread using(utid) left join process using(upid) where pid=1");
686   it.Next();
687   ASSERT_TRUE(it.Status().ok());
688 
689   it = Query("select (max(ts) - min(ts)) / 1000000 from slices_1st_build");
690   ASSERT_TRUE(it.Next());
691   ASSERT_EQ(it.Get(0).long_value, 44697);
692 
693   it = Query("select name from slices_1st_build order by ts desc limit 1");
694   ASSERT_TRUE(it.Next());
695   ASSERT_STREQ(it.Get(0).string_value, "trace_processor_shell");
696 
697   it = Query("select sum(dur) / 1000000 from slices_1st_build");
698   ASSERT_TRUE(it.Next());
699   ASSERT_EQ(it.Get(0).long_value, 837192);
700 }
701 
702 /*
703  * This trace does not have a uuid. The uuid will be generated from the first
704  * 4096 bytes, which will be read in one chunk.
705  */
TEST_F(TraceProcessorIntegrationTest,TraceWithoutUuidReadInOneChunk)706 TEST_F(TraceProcessorIntegrationTest, TraceWithoutUuidReadInOneChunk) {
707   ASSERT_TRUE(LoadTrace("example_android_trace_30s.pb", kMaxChunkSize).ok());
708   auto it = Query("select str_value from metadata where name = 'trace_uuid'");
709   ASSERT_TRUE(it.Next());
710   EXPECT_STREQ(it.Get(0).string_value, "00000000-0000-0000-8906-ebb53e1d0738");
711 }
712 
713 /*
714  * This trace does not have a uuid. The uuid will be generated from the first
715  * 4096 bytes, which will be read in multiple chunks.
716  */
TEST_F(TraceProcessorIntegrationTest,TraceWithoutUuidReadInMultipleChuncks)717 TEST_F(TraceProcessorIntegrationTest, TraceWithoutUuidReadInMultipleChuncks) {
718   ASSERT_TRUE(LoadTrace("example_android_trace_30s.pb", 512, 2048).ok());
719   auto it = Query("select str_value from metadata where name = 'trace_uuid'");
720   ASSERT_TRUE(it.Next());
721   EXPECT_STREQ(it.Get(0).string_value, "00000000-0000-0000-8906-ebb53e1d0738");
722 }
723 
724 /*
725  * This trace has a uuid. It will not be overriden by the hash of the first 4096
726  * bytes.
727  */
TEST_F(TraceProcessorIntegrationTest,TraceWithUuidReadInParts)728 TEST_F(TraceProcessorIntegrationTest, TraceWithUuidReadInParts) {
729   ASSERT_TRUE(LoadTrace("trace_with_uuid.pftrace", 512, 2048).ok());
730   auto it = Query("select str_value from metadata where name = 'trace_uuid'");
731   ASSERT_TRUE(it.Next());
732   EXPECT_STREQ(it.Get(0).string_value, "123e4567-e89b-12d3-a456-426655443322");
733 }
734 
TEST_F(TraceProcessorIntegrationTest,ErrorMessageExecuteQuery)735 TEST_F(TraceProcessorIntegrationTest, ErrorMessageExecuteQuery) {
736   auto it = Query("select t from slice");
737   ASSERT_FALSE(it.Next());
738   ASSERT_FALSE(it.Status().ok());
739 
740   ASSERT_THAT(it.Status().message(),
741               testing::Eq(R"(Traceback (most recent call last):
742   File "stdin" line 1 col 8
743     select t from slice
744            ^
745 no such column: t)"));
746 }
747 
TEST_F(TraceProcessorIntegrationTest,ErrorMessageMetricFile)748 TEST_F(TraceProcessorIntegrationTest, ErrorMessageMetricFile) {
749   ASSERT_TRUE(
750       Processor()->RegisterMetric("foo/bar.sql", "select t from slice").ok());
751 
752   auto it = Query("select RUN_METRIC('foo/bar.sql');");
753   ASSERT_FALSE(it.Next());
754   ASSERT_FALSE(it.Status().ok());
755 
756   ASSERT_EQ(it.Status().message(),
757             R"(Traceback (most recent call last):
758   File "stdin" line 1 col 1
759     select RUN_METRIC('foo/bar.sql')
760     ^
761   Metric file "foo/bar.sql" line 1 col 8
762     select t from slice
763            ^
764 no such column: t)");
765 }
766 
TEST_F(TraceProcessorIntegrationTest,ErrorMessageModule)767 TEST_F(TraceProcessorIntegrationTest, ErrorMessageModule) {
768   SqlModule module;
769   module.name = "foo";
770   module.files.push_back(std::make_pair("foo.bar", "select t from slice"));
771 
772   ASSERT_TRUE(Processor()->RegisterSqlModule(module).ok());
773 
774   auto it = Query("include perfetto module foo.bar;");
775   ASSERT_FALSE(it.Next());
776   ASSERT_FALSE(it.Status().ok());
777 
778   ASSERT_EQ(it.Status().message(),
779             R"(Traceback (most recent call last):
780   File "stdin" line 1 col 1
781     include perfetto module foo.bar
782     ^
783   Module include "foo.bar" line 1 col 8
784     select t from slice
785            ^
786 no such column: t)");
787 }
788 
TEST_F(TraceProcessorIntegrationTest,FunctionRegistrationError)789 TEST_F(TraceProcessorIntegrationTest, FunctionRegistrationError) {
790   auto it =
791       Query("create perfetto function f() returns INT as select * from foo");
792   ASSERT_FALSE(it.Next());
793   ASSERT_FALSE(it.Status().ok());
794 
795   it = Query("SELECT foo()");
796   ASSERT_FALSE(it.Next());
797   ASSERT_FALSE(it.Status().ok());
798 
799   it = Query("create perfetto function f() returns INT as select 1");
800   ASSERT_FALSE(it.Next());
801   ASSERT_TRUE(it.Status().ok());
802 }
803 
TEST_F(TraceProcessorIntegrationTest,CreateTableDuplicateNames)804 TEST_F(TraceProcessorIntegrationTest, CreateTableDuplicateNames) {
805   auto it = Query(
806       "create perfetto table foo select 1 as duplicate_a, 2 as duplicate_a, 3 "
807       "as duplicate_b, 4 as duplicate_b");
808   ASSERT_FALSE(it.Next());
809   ASSERT_FALSE(it.Status().ok());
810   ASSERT_THAT(it.Status().message(), HasSubstr("duplicate_a"));
811   ASSERT_THAT(it.Status().message(), HasSubstr("duplicate_b"));
812 }
813 
814 }  // namespace
815 }  // namespace perfetto::trace_processor
816