| # Copyright (C) 2022 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| import os |
| import sys |
| import unittest |
| |
| ROOT_DIR = os.path.dirname( |
| os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
| sys.path.append(os.path.join(ROOT_DIR)) |
| |
| from python.generators.stdlib_docs.parse import parse_file_to_dict |
| |
| DESC = """-- |
| -- First line. |
| -- Second line.""" |
| |
| COLS_STR = """-- |
| -- @column slice_id Id of slice. |
| -- @column slice_name Name of slice.""" |
| |
| COLS_SQL_STR = "slice_id INT, slice_name STRING" |
| |
| ARGS_STR = """-- |
| -- @arg utid INT Utid of thread. |
| -- @arg name STRING String name.""" |
| |
| ARGS_SQL_STR = "utid INT, name STRING" |
| |
| RET_STR = """-- |
| -- @ret BOOL Exists.""" |
| |
| RET_SQL_STR = "BOOL" |
| |
| SQL_STR = "SELECT * FROM slice" |
| |
| |
| class TestStdlib(unittest.TestCase): |
| |
| def test_valid_table(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| {DESC} |
| {COLS_STR} |
| CREATE TABLE foo_table AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, dict) |
| |
| table = res['imports'][0] |
| self.assertEqual(table['name'], 'foo_table') |
| self.assertEqual(table['desc'], 'First line. Second line.') |
| self.assertEqual(table['type'], 'TABLE') |
| self.assertEqual(table['cols'], { |
| 'slice_id': 'Id of slice.', |
| 'slice_name': 'Name of slice.' |
| }) |
| |
| def test_valid_function(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| {DESC} |
| {ARGS_STR} |
| {RET_STR} |
| CREATE PERFETTO FUNCTION FOO_FN({ARGS_SQL_STR}) |
| RETURNS {RET_SQL_STR} |
| AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, dict) |
| |
| fn = res['functions'][0] |
| self.assertEqual(fn['name'], 'FOO_FN') |
| self.assertEqual(fn['desc'], 'First line. Second line.') |
| self.assertEqual( |
| fn['args'], { |
| 'utid': { |
| 'type': 'INT', |
| 'desc': 'Utid of thread.', |
| }, |
| 'name': { |
| 'type': 'STRING', |
| 'desc': 'String name.', |
| }, |
| }) |
| self.assertEqual(fn['return_type'], 'BOOL') |
| self.assertEqual(fn['return_desc'], 'Exists.') |
| |
| def test_valid_view_function(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| {DESC} |
| {ARGS_STR} |
| {COLS_STR} |
| SELECT CREATE_VIEW_FUNCTION( |
| 'FOO_VIEW_FN({ARGS_SQL_STR})', |
| '{COLS_SQL_STR}', |
| '{SQL_STR}' |
| ); |
| '''.strip()) |
| assert isinstance(res, dict) |
| |
| fn = res['view_functions'][0] |
| self.assertEqual(fn['name'], 'FOO_VIEW_FN') |
| self.assertEqual(fn['desc'], 'First line. Second line.') |
| self.assertEqual( |
| fn['args'], { |
| 'utid': { |
| 'type': 'INT', |
| 'desc': 'Utid of thread.', |
| }, |
| 'name': { |
| 'type': 'STRING', |
| 'desc': 'String name.', |
| }, |
| }) |
| self.assertEqual(fn['cols'], { |
| 'slice_id': 'Id of slice.', |
| 'slice_name': 'Name of slice.' |
| }) |
| |
| def test_missing_module_name(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| {DESC} |
| {COLS_STR} |
| CREATE TABLE bar_table AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, list) |
| |
| def test_common_does_not_include_module_name(self): |
| res = parse_file_to_dict( |
| 'common/bar.sql', f''' |
| {DESC} |
| {COLS_STR} |
| CREATE TABLE common_table AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, list) |
| |
| def test_cols_typo(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| {DESC} |
| -- |
| -- @column slice_id2 Foo. |
| -- @column slice_name Bar. |
| CREATE TABLE bar_table AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, list) |
| |
| def test_cols_no_desc(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| {DESC} |
| -- |
| -- @column slice_id |
| -- @column slice_name Bar. |
| CREATE TABLE bar_table AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, list) |
| |
| def test_args_typo(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| {DESC} |
| -- |
| -- @arg utid2 INT Uint. |
| -- @arg name STRING String name. |
| {RET_STR} |
| CREATE PERFETTO FUNCTION FOO_FN({ARGS_SQL_STR}) |
| RETURNS {RET_SQL_STR} |
| AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, list) |
| |
| def test_args_no_desc(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| {DESC} |
| -- |
| -- @arg utid INT |
| -- @arg name STRING String name. |
| {RET_STR} |
| CREATE PERFETTO FUNCTION FOO_FN({ARGS_SQL_STR}) |
| RETURNS {RET_SQL_STR} |
| AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, list) |
| |
| def test_ret_no_desc(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| {DESC} |
| {ARGS_STR} |
| -- |
| -- @ret BOOL |
| CREATE PERFETTO FUNCTION FOO_FN({ARGS_SQL_STR}) |
| RETURNS {RET_SQL_STR} |
| AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, list) |
| |
| def test_multiline_desc(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| -- This |
| -- is |
| -- |
| -- a |
| -- very |
| -- |
| -- long |
| -- |
| -- description. |
| {ARGS_STR} |
| {RET_STR} |
| CREATE PERFETTO FUNCTION FOO_FN({ARGS_SQL_STR}) |
| RETURNS {RET_SQL_STR} |
| AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, dict) |
| |
| fn = res['functions'][0] |
| self.assertEqual(fn['desc'], 'This is a very long description.') |
| |
| def test_multiline_arg_desc(self): |
| res = parse_file_to_dict( |
| 'foo/bar.sql', f''' |
| {DESC} |
| -- |
| -- @arg utid INT Uint |
| -- spread |
| -- |
| -- across lines. |
| -- @arg name STRING String name |
| -- which spans across multiple lines |
| -- inconsistently. |
| {RET_STR} |
| CREATE PERFETTO FUNCTION FOO_FN({ARGS_SQL_STR}) |
| RETURNS {RET_SQL_STR} |
| AS |
| {SQL_STR}; |
| '''.strip()) |
| assert isinstance(res, dict) |
| |
| fn = res['functions'][0] |
| self.assertEqual( |
| fn['args'], { |
| 'utid': { |
| 'type': 'INT', |
| 'desc': 'Uint spread across lines.', |
| }, |
| 'name': { |
| 'type': 'STRING', |
| 'desc': 'String name which spans across multiple lines ' |
| 'inconsistently.', |
| }, |
| }) |