• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# Copyright (C) 2024 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 a
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
16from python.generators.diff_tests.testing import DataPath
17from python.generators.diff_tests.testing import Csv
18from python.generators.diff_tests.testing import DiffTestBlueprint
19from python.generators.diff_tests.testing import TestSuite
20
21
22class GraphSearchTests(TestSuite):
23
24  def test_dfs_empty_table(self):
25    return DiffTestBlueprint(
26        trace=DataPath('counters.json'),
27        query="""
28          INCLUDE PERFETTO MODULE graphs.search;
29
30          WITH foo AS (
31            SELECT 0 as source_node_id, 0 AS dest_node_id
32            WHERE FALSE
33          )
34          SELECT * FROM graph_reachable_dfs!(
35            foo,
36            (SELECT 0 AS node_id WHERE FALSE)
37          )
38        """,
39        out=Csv("""
40        "node_id","parent_node_id"
41        """))
42
43  def test_dfs_one_node(self):
44    return DiffTestBlueprint(
45        trace=DataPath('counters.json'),
46        query="""
47          INCLUDE PERFETTO MODULE graphs.search;
48
49          WITH foo AS (
50            SELECT 5 AS source_node_id, 10 AS dest_node_id
51            UNION ALL
52            SELECT 10, 10
53          )
54          SELECT * FROM graph_reachable_dfs!(foo, (SELECT 5 AS node_id));
55        """,
56        out=Csv("""
57        "node_id","parent_node_id"
58        5,"[NULL]"
59        10,5
60        """))
61
62  def test_dfs_two_nodes(self):
63    return DiffTestBlueprint(
64        trace=DataPath('counters.json'),
65        query="""
66          INCLUDE PERFETTO MODULE graphs.search;
67
68          CREATE PERFETTO TABLE foo AS
69          SELECT NULL AS source_node_id, NULL AS dest_node_id WHERE FALSE
70          UNION ALL
71          VALUES (10, 11)
72          UNION ALL
73          VALUES (0, 10);
74
75          SELECT * FROM graph_reachable_dfs!(foo, (SELECT 0 AS node_id));
76        """,
77        out=Csv("""
78        "node_id","parent_node_id"
79        0,"[NULL]"
80        10,0
81        11,10
82        """))
83
84  def test_dfs_lengauer_tarjan_example(self):
85    return DiffTestBlueprint(
86        trace=DataPath('counters.json'),
87        query="""
88          INCLUDE PERFETTO MODULE graphs.search;
89
90          CREATE PERFETTO TABLE foo AS
91          SELECT NULL AS source, NULL AS dest WHERE FALSE
92          UNION ALL
93          VALUES ('R', 'A'), ('R', 'B'), ('R', 'C'), ('A', 'D')
94          UNION ALL
95          VALUES ('B', 'A'), ('B', 'D'), ('B', 'E'), ('C', 'F')
96          UNION ALL
97          VALUES ('C', 'G'), ('D', 'L'), ('E', 'H'), ('F', 'I')
98          UNION ALL
99          VALUES ('G', 'I'), ('G', 'J'), ('H', 'E'), ('H', 'K')
100          UNION ALL
101          VALUES ('I', 'K'), ('J', 'I'), ('K', 'I'), ('K', 'R')
102          UNION ALL
103          VALUES ('L', 'H');
104
105          WITH bar AS (
106            SELECT
107              unicode(source) AS source_node_id,
108              unicode(dest) AS dest_node_id
109            FROM foo
110          )
111          SELECT
112            char(node_id) AS node_id,
113            IIF(
114              parent_node_id IS NULL,
115              NULL,
116              char(parent_node_id)
117            ) AS parent_node_id
118          FROM graph_reachable_dfs!(bar, (SELECT unicode('R') AS node_id))
119          ORDER BY node_id;
120        """,
121        out=Csv("""
122          "node_id","parent_node_id"
123          "A","R"
124          "B","R"
125          "C","R"
126          "D","A"
127          "E","H"
128          "F","C"
129          "G","C"
130          "H","L"
131          "I","K"
132          "J","G"
133          "K","H"
134          "L","D"
135          "R","[NULL]"
136        """))
137
138  def test_bfs_empty_table(self):
139    return DiffTestBlueprint(
140        trace=DataPath('counters.json'),
141        query="""
142          INCLUDE PERFETTO MODULE graphs.search;
143
144          WITH foo AS (
145            SELECT 0 as source_node_id, 0 AS dest_node_id
146            WHERE FALSE
147          )
148          SELECT * FROM graph_reachable_bfs!(
149            foo, (SELECT 0 AS node_id WHERE FALSE)
150          )
151        """,
152        out=Csv("""
153        "node_id","parent_node_id"
154        """))
155
156  def test_bfs_one_node(self):
157    return DiffTestBlueprint(
158        trace=DataPath('counters.json'),
159        query="""
160          INCLUDE PERFETTO MODULE graphs.search;
161
162          WITH foo AS (
163            SELECT 5 AS source_node_id, 10 AS dest_node_id
164            UNION ALL
165            SELECT 10, 10
166          )
167          SELECT * FROM graph_reachable_bfs!(foo, (SELECT 5 AS node_id));
168        """,
169        out=Csv("""
170        "node_id","parent_node_id"
171        5,"[NULL]"
172        10,5
173        """))
174
175  def test_bfs_two_nodes(self):
176    return DiffTestBlueprint(
177        trace=DataPath('counters.json'),
178        query="""
179          INCLUDE PERFETTO MODULE graphs.search;
180
181          CREATE PERFETTO TABLE foo AS
182          SELECT NULL AS source_node_id, NULL AS dest_node_id WHERE FALSE
183          UNION ALL
184          VALUES (10, 11)
185          UNION ALL
186          VALUES (0, 10);
187
188          SELECT * FROM graph_reachable_bfs!(foo, (SELECT 0 AS node_id));
189        """,
190        out=Csv("""
191        "node_id","parent_node_id"
192        0,"[NULL]"
193        10,0
194        11,10
195        """))
196
197  def test_bfs_lengauer_tarjan_example(self):
198    return DiffTestBlueprint(
199        trace=DataPath('counters.json'),
200        query="""
201          INCLUDE PERFETTO MODULE graphs.search;
202
203          CREATE PERFETTO TABLE foo AS
204          SELECT NULL AS source, NULL AS dest WHERE FALSE
205          UNION ALL
206          VALUES ('R', 'A'), ('R', 'B'), ('R', 'C'), ('A', 'D')
207          UNION ALL
208          VALUES ('B', 'A'), ('B', 'D'), ('B', 'E'), ('C', 'F')
209          UNION ALL
210          VALUES ('C', 'G'), ('D', 'L'), ('E', 'H'), ('F', 'I')
211          UNION ALL
212          VALUES ('G', 'I'), ('G', 'J'), ('H', 'E'), ('H', 'K')
213          UNION ALL
214          VALUES ('I', 'K'), ('J', 'I'), ('K', 'I'), ('K', 'R')
215          UNION ALL
216          VALUES ('L', 'H');
217
218          WITH bar AS (
219            SELECT
220              unicode(source) AS source_node_id,
221              unicode(dest) AS dest_node_id
222            FROM foo
223          )
224          SELECT
225            char(node_id) AS node_id,
226            IIF(
227              parent_node_id IS NULL,
228              NULL,
229              char(parent_node_id)
230            ) AS parent_node_id
231          FROM graph_reachable_bfs!(bar, (SELECT unicode('R') AS node_id))
232          ORDER BY node_id;
233        """,
234        out=Csv("""
235          "node_id","parent_node_id"
236          "A","R"
237          "B","R"
238          "C","R"
239          "D","A"
240          "E","B"
241          "F","C"
242          "G","C"
243          "H","E"
244          "I","F"
245          "J","G"
246          "K","H"
247          "L","D"
248          "R","[NULL]"
249        """))
250
251  def test_next_sibling(self):
252    return DiffTestBlueprint(
253        trace=DataPath('counters.json'),
254        query="""
255          INCLUDE PERFETTO MODULE graphs.search;
256
257          CREATE PERFETTO TABLE foo AS
258          SELECT 1 AS node_id, 0 AS node_parent_id, 1 AS sort_key
259          UNION ALL
260          SELECT 2 AS node_id, 1 AS node_parent_id, 2 AS sort_key
261          UNION ALL
262          SELECT 3 AS node_id, 1 AS node_parent_id, 1 AS sort_key;
263
264          SELECT * FROM graph_next_sibling!(foo);
265        """,
266        out=Csv("""
267        "node_id","next_node_id"
268        1,"[NULL]"
269        3,2
270        2,"[NULL]"
271        """))
272
273  def test_weight_bounded_dfs_floor(self):
274    return DiffTestBlueprint(
275        trace=DataPath('counters.json'),
276        query="""
277          INCLUDE PERFETTO MODULE graphs.search;
278
279          CREATE PERFETTO TABLE foo AS
280          SELECT 0 AS source_node_id, 0 AS dest_node_id, 0 AS edge_weight
281          UNION ALL
282          VALUES (1, 2, 1)
283          UNION ALL
284          VALUES (1, 3, 1)
285          UNION ALL
286          VALUES (3, 4, 1)
287          UNION ALL
288          VALUES (3, 5, 0)
289          UNION ALL
290          VALUES (5, 6, 0);
291
292          CREATE PERFETTO TABLE roots AS
293          SELECT 0 AS root_node_id, 0 AS root_target_weight
294          UNION ALL
295          VALUES (1, 2)
296          UNION ALL
297          VALUES (3, 1)
298          UNION ALL
299          VALUES (2, 0);
300
301          SELECT * FROM graph_reachable_weight_bounded_dfs!(foo, roots, 1);
302        """,
303        out=Csv("""
304        "root_node_id","node_id","parent_node_id"
305        0,0,"[NULL]"
306        1,1,"[NULL]"
307        1,2,1
308        1,3,1
309        1,4,3
310        3,3,"[NULL]"
311        3,4,3
312        3,5,3
313        3,6,5
314        2,2,"[NULL]"
315        """))
316
317  def test_weight_bounded_dfs_ceiling(self):
318    return DiffTestBlueprint(
319        trace=DataPath('counters.json'),
320        query="""
321          INCLUDE PERFETTO MODULE graphs.search;
322
323          CREATE PERFETTO TABLE foo AS
324          SELECT 0 AS source_node_id, 0 AS dest_node_id, 0 AS edge_weight
325          UNION ALL
326          VALUES (1, 2, 1)
327          UNION ALL
328          VALUES (1, 3, 1)
329          UNION ALL
330          VALUES (3, 4, 1)
331          UNION ALL
332          VALUES (3, 5, 0)
333          UNION ALL
334          VALUES (5, 6, 0);
335
336          CREATE PERFETTO TABLE roots AS
337          SELECT 0 AS root_node_id, 0 AS root_target_weight
338          UNION ALL
339          VALUES (1, 2)
340          UNION ALL
341          VALUES (3, 1)
342          UNION ALL
343          VALUES (2, 0);
344
345          SELECT * FROM graph_reachable_weight_bounded_dfs!(foo, roots, 0);
346        """,
347        out=Csv("""
348        "root_node_id","node_id","parent_node_id"
349        0,0,"[NULL]"
350        1,1,"[NULL]"
351        1,2,1
352        1,3,1
353        3,3,"[NULL]"
354        3,4,3
355        3,5,3
356        3,6,5
357        2,2,"[NULL]"
358        """))
359