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