• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 "src/trace_processor/perfetto_sql/engine/perfetto_sql_preprocessor.h"
18 
19 #include <optional>
20 #include <string>
21 
22 #include "perfetto/ext/base/flat_hash_map.h"
23 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_test_utils.h"
24 #include "test/gtest_and_gmock.h"
25 
26 namespace perfetto {
27 namespace trace_processor {
28 namespace {
29 
30 using Macro = PerfettoSqlPreprocessor::Macro;
31 
32 class PerfettoSqlPreprocessorUnittest : public ::testing::Test {
33  protected:
34   base::FlatHashMap<std::string, PerfettoSqlPreprocessor::Macro> macros_;
35 };
36 
TEST_F(PerfettoSqlPreprocessorUnittest,Empty)37 TEST_F(PerfettoSqlPreprocessorUnittest, Empty) {
38   PerfettoSqlPreprocessor preprocessor(SqlSource::FromExecuteQuery(""),
39                                        macros_);
40   ASSERT_FALSE(preprocessor.NextStatement());
41   ASSERT_TRUE(preprocessor.status().ok());
42 }
43 
TEST_F(PerfettoSqlPreprocessorUnittest,SemiColonTerminatedStatement)44 TEST_F(PerfettoSqlPreprocessorUnittest, SemiColonTerminatedStatement) {
45   auto source = SqlSource::FromExecuteQuery("SELECT * FROM slice;");
46   PerfettoSqlPreprocessor preprocessor(source, macros_);
47   ASSERT_TRUE(preprocessor.NextStatement());
48   ASSERT_EQ(preprocessor.statement(),
49             FindSubstr(source, "SELECT * FROM slice"));
50   ASSERT_FALSE(preprocessor.NextStatement());
51   ASSERT_TRUE(preprocessor.status().ok());
52 }
53 
TEST_F(PerfettoSqlPreprocessorUnittest,IgnoreOnlySpace)54 TEST_F(PerfettoSqlPreprocessorUnittest, IgnoreOnlySpace) {
55   auto source = SqlSource::FromExecuteQuery(" ; SELECT * FROM s; ; ;");
56   PerfettoSqlPreprocessor preprocessor(source, macros_);
57   ASSERT_TRUE(preprocessor.NextStatement());
58   ASSERT_EQ(preprocessor.statement(), FindSubstr(source, "SELECT * FROM s"));
59   ASSERT_FALSE(preprocessor.NextStatement());
60   ASSERT_TRUE(preprocessor.status().ok());
61 }
62 
TEST_F(PerfettoSqlPreprocessorUnittest,MultipleStmts)63 TEST_F(PerfettoSqlPreprocessorUnittest, MultipleStmts) {
64   auto source =
65       SqlSource::FromExecuteQuery("SELECT * FROM slice; SELECT * FROM s");
66   PerfettoSqlPreprocessor preprocessor(source, macros_);
67   ASSERT_TRUE(preprocessor.NextStatement());
68   ASSERT_EQ(preprocessor.statement(),
69             FindSubstr(source, "SELECT * FROM slice"));
70   ASSERT_TRUE(preprocessor.NextStatement());
71   ASSERT_EQ(preprocessor.statement(), FindSubstr(source, "SELECT * FROM s"));
72   ASSERT_FALSE(preprocessor.NextStatement());
73   ASSERT_TRUE(preprocessor.status().ok());
74 }
75 
TEST_F(PerfettoSqlPreprocessorUnittest,CreateMacro)76 TEST_F(PerfettoSqlPreprocessorUnittest, CreateMacro) {
77   auto source = SqlSource::FromExecuteQuery(
78       "CREATE PERFETTO MACRO foo(a, b) AS SELECT $a + $b");
79   PerfettoSqlPreprocessor preprocessor(source, macros_);
80   ASSERT_TRUE(preprocessor.NextStatement());
81   ASSERT_EQ(
82       preprocessor.statement(),
83       FindSubstr(source, "CREATE PERFETTO MACRO foo(a, b) AS SELECT $a + $b"));
84   ASSERT_FALSE(preprocessor.NextStatement());
85   ASSERT_TRUE(preprocessor.status().ok());
86 }
87 
TEST_F(PerfettoSqlPreprocessorUnittest,SingleMacro)88 TEST_F(PerfettoSqlPreprocessorUnittest, SingleMacro) {
89   auto foo = SqlSource::FromExecuteQuery(
90       "CREATE PERFETTO MACRO foo(a Expr, b Expr) Returns Expr AS "
91       "SELECT $a + $b");
92   macros_.Insert(
93       "foo",
94       Macro{false, "foo", {"a", "b"}, FindSubstr(foo, "SELECT $a + $b")});
95 
96   auto source = SqlSource::FromExecuteQuery(
97       "foo!((select s.ts + r.dur from s, r), 1234); SELECT 1");
98   PerfettoSqlPreprocessor preprocessor(source, macros_);
99   ASSERT_TRUE(preprocessor.NextStatement());
100   ASSERT_EQ(preprocessor.statement().AsTraceback(0),
101             "Fully expanded statement\n"
102             "  SELECT (select s.ts + r.dur from s, r) + 1234\n"
103             "  ^\n"
104             "Traceback (most recent call last):\n"
105             "  File \"stdin\" line 1 col 1\n"
106             "    foo!((select s.ts + r.dur from s, r), 1234)\n"
107             "    ^\n"
108             "  File \"stdin\" line 1 col 59\n"
109             "    SELECT $a + $b\n"
110             "    ^\n");
111   ASSERT_EQ(preprocessor.statement().AsTraceback(7),
112             "Fully expanded statement\n"
113             "  SELECT (select s.ts + r.dur from s, r) + 1234\n"
114             "         ^\n"
115             "Traceback (most recent call last):\n"
116             "  File \"stdin\" line 1 col 1\n"
117             "    foo!((select s.ts + r.dur from s, r), 1234)\n"
118             "    ^\n"
119             "  File \"stdin\" line 1 col 66\n"
120             "    SELECT $a + $b\n"
121             "           ^\n"
122             "  File \"stdin\" line 1 col 6\n"
123             "    (select s.ts + r.dur from s, r)\n"
124             "    ^\n");
125   ASSERT_EQ(preprocessor.statement().sql(),
126             "SELECT (select s.ts + r.dur from s, r) + 1234");
127   ASSERT_TRUE(preprocessor.NextStatement());
128   ASSERT_EQ(preprocessor.statement(), FindSubstr(source, "SELECT 1"));
129   ASSERT_FALSE(preprocessor.NextStatement());
130   ASSERT_TRUE(preprocessor.status().ok());
131 }
132 
TEST_F(PerfettoSqlPreprocessorUnittest,NestedMacro)133 TEST_F(PerfettoSqlPreprocessorUnittest, NestedMacro) {
134   auto foo = SqlSource::FromExecuteQuery(
135       "CREATE PERFETTO MACRO foo(a Expr, b Expr) Returns Expr AS $a + $b");
136   macros_.Insert("foo", Macro{
137                             false,
138                             "foo",
139                             {"a", "b"},
140                             FindSubstr(foo, "$a + $b"),
141                         });
142 
143   auto bar = SqlSource::FromExecuteQuery(
144       "CREATE PERFETTO MACRO bar(a, b) Returns Expr AS "
145       "tfoo!($a, $b) + foo!($b, $a)");
146   macros_.Insert("bar", Macro{
147                             false,
148                             "bar",
149                             {"a", "b"},
150                             FindSubstr(bar, "foo!($a, $b) + foo!($b, $a)"),
151                         });
152 
153   auto source = SqlSource::FromExecuteQuery(
154       "SELECT bar!((select s.ts + r.dur from s, r), 1234); SELECT 1");
155   PerfettoSqlPreprocessor preprocessor(source, macros_);
156   ASSERT_TRUE(preprocessor.NextStatement());
157   ASSERT_EQ(preprocessor.statement().sql(),
158             "SELECT (select s.ts + r.dur from s, r) + 1234 + 1234 + "
159             "(select s.ts + r.dur from s, r)");
160   ASSERT_TRUE(preprocessor.NextStatement());
161   ASSERT_EQ(preprocessor.statement().sql(), "SELECT 1");
162 }
163 
164 }  // namespace
165 }  // namespace trace_processor
166 }  // namespace perfetto
167