| # |
| # Copyright (C) 2024 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 unittest |
| import sys |
| import os |
| from unittest import mock |
| from torq import create_parser, verify_args, get_command_type,\ |
| DEFAULT_DUR_MS, DEFAULT_OUT_DIR |
| |
| TEST_USER_ID = 10 |
| TEST_PACKAGE = "com.android.contacts" |
| TEST_FILE = "file.pbtxt" |
| |
| |
| class TorqUnitTest(unittest.TestCase): |
| |
| def set_up_parser(self, command_string): |
| parser = create_parser() |
| sys.argv = command_string.split() |
| return parser |
| |
| # TODO(b/285191111): Parameterize the test functions. |
| def test_create_parser_default_values(self): |
| parser = self.set_up_parser("torq.py") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.event, "custom") |
| self.assertEqual(args.profiler, "perfetto") |
| self.assertEqual(args.out_dir, DEFAULT_OUT_DIR) |
| self.assertEqual(args.runs, 1) |
| self.assertEqual(args.perfetto_config, "default") |
| self.assertEqual(args.dur_ms, DEFAULT_DUR_MS) |
| self.assertEqual(args.between_dur_ms, DEFAULT_DUR_MS) |
| |
| def test_create_parser_valid_event_names(self): |
| parser = self.set_up_parser("torq.py -e custom") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.event, "custom") |
| |
| parser = self.set_up_parser("torq.py -e boot") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.event, "boot") |
| |
| parser = self.set_up_parser( |
| "torq.py -e user-switch --to-user %s" % str(TEST_USER_ID)) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.event, "user-switch") |
| |
| parser = self.set_up_parser( |
| "torq.py -e app-startup --app %s" % TEST_PACKAGE) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.event, "app-startup") |
| |
| def test_create_parser_invalid_event_names(self): |
| parser = self.set_up_parser("torq.py -e fake-event") |
| |
| with self.assertRaises(SystemExit): |
| parser.parse_args() |
| |
| def test_create_parser_valid_profiler_names(self): |
| parser = self.set_up_parser("torq.py -p perfetto") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.profiler, "perfetto") |
| |
| parser = self.set_up_parser("torq.py -p simpleperf") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.profiler, "simpleperf") |
| |
| def test_create_parser_invalid_profiler_names(self): |
| parser = self.set_up_parser("torq.py -p fake-profiler") |
| |
| with self.assertRaises(SystemExit): |
| parser.parse_args() |
| |
| @mock.patch.object(os.path, "isdir", autospec=True) |
| def test_verify_args_valid_out_dir_path(self, mock_is_dir): |
| mock_is_dir.return_value = True |
| parser = self.set_up_parser("torq.py -o mock-directory") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.out_dir, "mock-directory") |
| |
| @mock.patch.object(os.path, "isdir", autospec=True) |
| def test_verify_args_invalid_out_dir_paths(self, mock_is_dir): |
| mock_is_dir.return_value = False |
| parser = self.set_up_parser("torq.py -o mock-file") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --out-dir is not a valid" |
| " directory path: mock-file.")) |
| self.assertEqual(error.suggestion, None) |
| |
| def test_create_parser_valid_ui(self): |
| parser = self.set_up_parser("torq.py --ui") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.ui, True) |
| |
| parser = self.set_up_parser("torq.py --no-ui") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.ui, False) |
| |
| def test_verify_args_valid_dur_ms_values(self): |
| parser = self.set_up_parser("torq.py -d 100000") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.dur_ms, 100000) |
| |
| def test_verify_args_ui_and_runs_valid_dependency(self): |
| parser = self.set_up_parser("torq.py -r 2 --no-ui") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| |
| def test_verify_args_ui_and_runs_invalid_dependency(self): |
| parser = self.set_up_parser("torq.py -r 2 --ui") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because --ui cannot be" |
| " passed if --runs is set to a value" |
| " greater than 1.")) |
| self.assertEqual(error.suggestion, ("Set torq -r 2 --no-ui to perform 2" |
| " runs.")) |
| |
| def test_verify_args_ui_bool_true_and_runs_default_dependencies(self): |
| parser = self.set_up_parser("torq.py") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.ui, True) |
| |
| parser = self.set_up_parser("torq.py -r 1") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.ui, True) |
| |
| # UI is false by default when multiple runs are specified. |
| def test_verify_args_ui_bool_false_and_runs_default_dependency(self): |
| parser = self.set_up_parser("torq.py -r 2") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.ui, False) |
| |
| def test_verify_args_invalid_dur_ms_values(self): |
| parser = self.set_up_parser("torq.py -d -200") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --dur-ms cannot be set to a value" |
| " smaller than 3000.")) |
| self.assertEqual(error.suggestion, ("Set --dur-ms 3000 to capture a" |
| " trace for 3 seconds.")) |
| |
| parser = self.set_up_parser("torq.py -d 0") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --dur-ms cannot be set to a value" |
| " smaller than 3000.")) |
| self.assertEqual(error.suggestion, ("Set --dur-ms 3000 to capture a" |
| " trace for 3 seconds.")) |
| |
| parser = self.set_up_parser("torq.py -d 20") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --dur-ms cannot be set to a value" |
| " smaller than 3000.")) |
| self.assertEqual(error.suggestion, ("Set --dur-ms 3000 to capture a" |
| " trace for 3 seconds.")) |
| |
| def test_verify_args_valid_between_dur_ms_values(self): |
| parser = self.set_up_parser("torq.py -r 2 --between-dur-ms 10000") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.between_dur_ms, 10000) |
| |
| def test_verify_args_invalid_between_dur_ms_values(self): |
| parser = self.set_up_parser("torq.py -r 2 --between-dur-ms -200") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --between-dur-ms cannot be set to" |
| " a smaller value than 3000.")) |
| self.assertEqual(error.suggestion, ("Set --between-dur-ms 3000 to wait" |
| " 3 seconds between each run.")) |
| |
| parser = self.set_up_parser("torq.py -r 2 --between-dur-ms 0") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --between-dur-ms cannot be set to a" |
| " smaller value than 3000.")) |
| self.assertEqual(error.suggestion, ("Set --between-dur-ms 3000 to wait" |
| " 3 seconds between each run.")) |
| |
| parser = self.set_up_parser("torq.py -r 2 --between-dur-ms 20") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --between-dur-ms cannot be set to a" |
| " smaller value than 3000.")) |
| self.assertEqual(error.suggestion, ("Set --between-dur-ms 3000 to wait" |
| " 3 seconds between each run.")) |
| |
| def test_verify_args_valid_runs_values(self): |
| parser = self.set_up_parser("torq.py -r 4") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.runs, 4) |
| |
| def test_verify_args_invalid_runs_values(self): |
| parser = self.set_up_parser("torq.py -r -2") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because --runs" |
| " cannot be set to a value smaller" |
| " than 1.")) |
| self.assertEqual(error.suggestion, None) |
| |
| parser = self.set_up_parser("torq.py -r 0") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because --runs" |
| " cannot be set to a value smaller" |
| " than 1.")) |
| self.assertEqual(error.suggestion, None) |
| |
| @mock.patch.object(os.path, "isfile", autospec=True) |
| def test_verify_args_valid_perfetto_config_path(self, mock_is_file): |
| mock_is_file.return_value = True |
| parser = self.set_up_parser("torq.py --perfetto-config mock-file") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.perfetto_config, "mock-file") |
| |
| parser = self.set_up_parser("torq.py --perfetto-config default") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.perfetto_config, "default") |
| |
| parser = self.set_up_parser("torq.py --perfetto-config lightweight") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.perfetto_config, "lightweight") |
| |
| parser = self.set_up_parser("torq.py --perfetto-config memory") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.perfetto_config, "memory") |
| |
| @mock.patch.object(os.path, "isfile", autospec=True) |
| def test_verify_args_invalid_perfetto_config_path(self, mock_is_file): |
| mock_is_file.return_value = False |
| parser = self.set_up_parser("torq.py --perfetto-config unexisting-file") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --perfetto-config is not a" |
| " valid file path: unexisting-file")) |
| self.assertEqual(error.suggestion, ("Predefined perfetto configs can be" |
| " used:\n" |
| "\t torq --perfetto-config default\n" |
| "\t torq --perfetto-config" |
| " lightweight\n" |
| "\t torq --perfetto-config memory\n" |
| "\t A filepath with a config can also" |
| " be used:\n" |
| "\t torq --perfetto-config" |
| " <config-filepath>")) |
| |
| parser = self.set_up_parser("torq.py --perfetto-config mock-directory") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --perfetto-config is not a" |
| " valid file path: mock-directory")) |
| self.assertEqual(error.suggestion, ("Predefined perfetto configs can be" |
| " used:\n" |
| "\t torq --perfetto-config default\n" |
| "\t torq --perfetto-config" |
| " lightweight\n" |
| "\t torq --perfetto-config memory\n" |
| "\t A filepath with a config can also" |
| " be used:\n" |
| "\t torq --perfetto-config" |
| " <config-filepath>")) |
| |
| def test_verify_args_from_user_and_event_valid_dependency(self): |
| parser = self.set_up_parser(("torq.py -e user-switch --from-user 0" |
| " --to-user %s") % str(TEST_USER_ID)) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| |
| def test_verify_args_from_user_and_event_invalid_dependency(self): |
| parser = self.set_up_parser("torq.py --from-user %s" % str(TEST_USER_ID)) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because --from-user" |
| " is passed, but --event is not set to" |
| " user-switch.")) |
| self.assertEqual(error.suggestion, ("Set --event user-switch --from-user %s" |
| " to perform a user-switch from user" |
| " %s." % (str(TEST_USER_ID), |
| str(TEST_USER_ID)))) |
| |
| def test_verify_args_to_user_and_event_valid_dependency(self): |
| parser = self.set_up_parser( |
| "torq.py -e user-switch --to-user %s" % str(TEST_USER_ID)) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| |
| def test_verify_args_to_user_not_passed_and_event_invalid_dependency(self): |
| parser = self.set_up_parser("torq.py -e user-switch") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because --to-user is" |
| " not passed.")) |
| self.assertEqual(error.suggestion, ("Set --event user-switch --to-user" |
| " <user-id> to perform a user-switch.")) |
| |
| def test_verify_args_to_user_and_user_switch_not_set_invalid_dependency(self): |
| parser = self.set_up_parser("torq.py --to-user %s" % str(TEST_USER_ID)) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because --to-user" |
| " is passed, but --event is not set to" |
| " user-switch.")) |
| self.assertEqual(error.suggestion, ("Set --event user-switch --to-user %s" |
| " to perform a user-switch to user" |
| " %s." % (str(TEST_USER_ID), |
| str(TEST_USER_ID)))) |
| |
| def test_verify_args_app_and_event_valid_dependency(self): |
| parser = self.set_up_parser("torq.py -e app-startup -a %s" % TEST_PACKAGE) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| |
| def test_verify_args_app_not_passed_and_event_invalid_dependency(self): |
| parser = self.set_up_parser("torq.py -e app-startup") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, |
| "Command is invalid because --app is not passed.") |
| self.assertEqual(error.suggestion, ("Set --event app-startup --app " |
| "<package> to perform an app-startup.")) |
| |
| def test_verify_args_app_and_app_startup_not_set_invalid_dependency(self): |
| parser = self.set_up_parser("torq.py -a %s" % TEST_PACKAGE) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because --app is" |
| " passed and --event is not set to" |
| " app-startup.")) |
| self.assertEqual(error.suggestion, ("To profile an app startup run:" |
| " torq --event app-startup --app" |
| " <package-name>")) |
| |
| def test_verify_args_profiler_and_simpleperf_event_valid_dependencies(self): |
| parser = self.set_up_parser("torq.py -p simpleperf") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(len(args.simpleperf_event), 1) |
| self.assertEqual(args.simpleperf_event[0], "cpu-cycles") |
| |
| parser = self.set_up_parser("torq.py -p simpleperf -s cpu-cycles") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(len(args.simpleperf_event), 1) |
| self.assertEqual(args.simpleperf_event[0], "cpu-cycles") |
| |
| def test_verify_args_profiler_and_simpleperf_event_invalid_dependencies( |
| self): |
| parser = self.set_up_parser("torq.py -s cpu-cycles") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --simpleperf-event cannot be passed if" |
| " --profiler is not set to simpleperf.")) |
| self.assertEqual(error.suggestion, ("To capture the simpleperf event run:" |
| " torq --profiler simpleperf" |
| " --simpleperf-event cpu-cycles")) |
| |
| def test_profiler_and_perfetto_config_valid_dependency(self): |
| parser = self.set_up_parser(("torq.py -p perfetto --perfetto-config" |
| " lightweight")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| |
| def test_verify_args_profiler_and_perfetto_config_invalid_dependency(self): |
| parser = self.set_up_parser("torq.py -p simpleperf --perfetto-config" |
| " lightweight") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --perfetto-config cannot be passed if" |
| " --profiler is not set to perfetto.")) |
| self.assertEqual(error.suggestion, ("Set --profiler perfetto to choose a" |
| " perfetto-config to use.")) |
| |
| def test_verify_args_runs_and_between_dur_ms_valid_dependency(self): |
| parser = self.set_up_parser("torq.py -r 2 --between-dur-ms 5000") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| |
| def test_verify_args_runs_and_between_dur_ms_invalid_dependency(self): |
| parser = self.set_up_parser("torq.py --between-dur-ms 5000") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --between-dur-ms cannot be passed" |
| " if --runs is not a value greater" |
| " than 1.")) |
| self.assertEqual(error.suggestion, "Set --runs 2 to run 2 tests.") |
| |
| parser = self.set_up_parser("torq.py -r 1 --between-dur-ms 5000") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --between-dur-ms cannot be passed" |
| " if --runs is not a value greater" |
| " than 1.")) |
| self.assertEqual(error.suggestion, "Set --runs 2 to run 2 tests.") |
| |
| def test_verify_args_profiler_and_ftrace_events_valid_dependencies(self): |
| parser = self.set_up_parser(("torq.py --excluded-ftrace-events" |
| " syscall-enter")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.excluded_ftrace_events, ["syscall-enter"]) |
| |
| parser = self.set_up_parser(("torq.py -p perfetto --excluded-ftrace-events" |
| " syscall-enter")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(args.excluded_ftrace_events, ["syscall-enter"]) |
| self.assertEqual(error, None) |
| |
| parser = self.set_up_parser(("torq.py -p perfetto --included-ftrace-events" |
| " syscall-enter")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(args.included_ftrace_events, ["syscall-enter"]) |
| self.assertEqual(error, None) |
| |
| def test_verify_args_profiler_and_ftrace_events_invalid_dependencies(self): |
| parser = self.set_up_parser(("torq.py -p simpleperf" |
| " --excluded-ftrace-events syscall-enter")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --excluded-ftrace-events cannot be" |
| " passed if --profiler is not set to" |
| " perfetto.")) |
| self.assertEqual(error.suggestion, ("Set --profiler perfetto to exclude an" |
| " ftrace event from perfetto config.")) |
| |
| parser = self.set_up_parser(("torq.py -p simpleperf" |
| " --included-ftrace-events syscall-enter")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because" |
| " --included-ftrace-events cannot be" |
| " passed if --profiler is not set to" |
| " perfetto.")) |
| self.assertEqual(error.suggestion, ("Set --profiler perfetto to include" |
| " an ftrace event in perfetto config.")) |
| |
| def test_verify_args_multiple_valid_excluded_ftrace_events(self): |
| parser = self.set_up_parser(("torq.py --excluded-ftrace-events" |
| " power/cpu_idle --excluded-ftrace-events" |
| " ion/ion_stat")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.excluded_ftrace_events, ["power/cpu_idle", |
| "ion/ion_stat"]) |
| |
| def test_verify_args_multiple_invalid_excluded_ftrace_events(self): |
| parser = self.set_up_parser(("torq.py --excluded-ftrace-events" |
| " power/cpu_idle --excluded-ftrace-events" |
| " power/cpu_idle")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because duplicate" |
| " ftrace events cannot be" |
| " included in --excluded-ftrace-events.")) |
| self.assertEqual(error.suggestion, ("--excluded-ftrace-events should only" |
| " include one instance of an ftrace" |
| " event.")) |
| |
| def test_verify_args_multiple_valid_included_ftrace_events(self): |
| parser = self.set_up_parser(("torq.py --included-ftrace-events" |
| " power/cpu_idle --included-ftrace-events" |
| " ion/ion_stat")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.included_ftrace_events, ["power/cpu_idle", |
| "ion/ion_stat"]) |
| |
| def test_verify_args_multiple_invalid_included_ftrace_events(self): |
| parser = self.set_up_parser(("torq.py --included-ftrace-events" |
| " power/cpu_idle --included-ftrace-events" |
| " power/cpu_idle")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because duplicate" |
| " ftrace events cannot be" |
| " included in --included-ftrace-events.")) |
| self.assertEqual(error.suggestion, ("--included-ftrace-events should only" |
| " include one instance of an ftrace" |
| " event.")) |
| |
| def test_verify_args_invalid_overlap_ftrace_events(self): |
| parser = self.set_up_parser(("torq.py --excluded-ftrace-events" |
| " ion/ion_stat --excluded-ftrace-events" |
| " power/cpu_idle --excluded-ftrace-events" |
| " power/gpu_frequency --included-ftrace-events" |
| " ion/ion_stat --included-ftrace-events" |
| " power/cpu_idle --included-ftrace-events" |
| " ftrace/print")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because ftrace" |
| " event(s): ion/ion_stat, power/cpu_idle" |
| " cannot be both included and excluded.")) |
| self.assertEqual(error.suggestion, ("Only set --excluded-ftrace-events" |
| " ion/ion_stat if you want to" |
| " exclude ion/ion_stat from the" |
| " config or --included-ftrace-events" |
| " ion/ion_stat if you want to" |
| " include ion/ion_stat in the" |
| " config.\n\t" |
| " Only set --excluded-ftrace-events" |
| " power/cpu_idle if you want to" |
| " exclude power/cpu_idle from the" |
| " config or --included-ftrace-events" |
| " power/cpu_idle if you want to" |
| " include power/cpu_idle in the" |
| " config.")) |
| |
| def test_verify_args_multiple_valid_simpleperf_events(self): |
| parser = self.set_up_parser(("torq.py -p simpleperf -s cpu-cycles" |
| " -s instructions")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.simpleperf_event, ["cpu-cycles", "instructions"]) |
| |
| def test_verify_args_multiple_invalid_simpleperf_events(self): |
| parser = self.set_up_parser(("torq.py -p simpleperf -s cpu-cycles" |
| " -s cpu-cycles")) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because redundant" |
| " calls to --simpleperf-event cannot" |
| " be made.")) |
| self.assertEqual(error.suggestion, ("Only set --simpleperf-event cpu-cycles" |
| " once if you want to collect" |
| " cpu-cycles.")) |
| |
| def test_create_parser_invalid_perfetto_config_command(self): |
| parser = self.set_up_parser("torq.py --perfetto-config") |
| |
| with self.assertRaises(SystemExit): |
| parser.parse_args() |
| |
| def test_verify_args_invalid_mixing_of_profiler_and_config_subcommand(self): |
| parser = self.set_up_parser("torq.py -d 20000 config pull lightweight") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because profiler" |
| " command is followed by a config" |
| " command.")) |
| self.assertEqual(error.suggestion, ("Remove the 'config' subcommand to" |
| " profile the device instead.")) |
| |
| def test_create_parser_invalid_mixing_of_profiler_and_config_subcommand(self): |
| parser = self.set_up_parser("torq.py config pull lightweight -d 20000") |
| |
| with self.assertRaises(SystemExit): |
| parser.parse_args() |
| |
| def test_get_command_type_profiler(self): |
| parser = self.set_up_parser("torq.py -d 20000") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| command = get_command_type(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(command.get_type(), "profiler") |
| |
| def test_create_parser_valid_config_show_values(self): |
| parser = self.set_up_parser("torq.py config show default") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.config_name, "default") |
| |
| parser = self.set_up_parser("torq.py config show lightweight") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.config_name, "lightweight") |
| |
| parser = self.set_up_parser("torq.py config show memory") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.config_name, "memory") |
| |
| def test_create_parser_invalid_config_show_values(self): |
| parser = self.set_up_parser("torq.py config show fake-config") |
| |
| with self.assertRaises(SystemExit): |
| parser.parse_args() |
| |
| def test_create_parser_valid_config_pull_values(self): |
| parser = self.set_up_parser("torq.py config pull default") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.config_name, "default") |
| |
| parser = self.set_up_parser("torq.py config pull lightweight") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.config_name, "lightweight") |
| |
| parser = self.set_up_parser("torq.py config pull memory") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.config_name, "memory") |
| |
| def test_create_parser_invalid_config_pull_values(self): |
| parser = self.set_up_parser("torq.py config pull fake-config") |
| |
| with self.assertRaises(SystemExit): |
| parser.parse_args() |
| |
| def test_verify_args_invalid_config_subcommands(self): |
| parser = self.set_up_parser("torq.py config") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ("Command is invalid because torq config" |
| " cannot be called without a" |
| " subcommand.")) |
| self.assertEqual(error.suggestion, ("Use one of the following" |
| " subcommands:\n" |
| "\t torq config list\n" |
| "\t torq config show\n" |
| "\t torq config pull\n")) |
| |
| def test_create_parser_invalid_config_subcommands(self): |
| parser = self.set_up_parser("torq.py config get") |
| |
| with self.assertRaises(SystemExit): |
| parser.parse_args() |
| |
| def test_verify_args_default_config_pull_filepath(self): |
| parser = self.set_up_parser("torq.py config pull default") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.file_path, "./default.pbtxt") |
| |
| parser = self.set_up_parser("torq.py config pull lightweight") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.file_path, "./lightweight.pbtxt") |
| |
| parser = self.set_up_parser("torq.py config pull memory") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.file_path, "./memory.pbtxt") |
| |
| @mock.patch.object(os.path, "isfile", autospec=True) |
| def test_verify_args_default_config_pull_invalid_filepath(self, mock_is_file): |
| mock_invalid_file_path = "mock-invalid-file-path" |
| mock_is_file.return_value = False |
| parser = self.set_up_parser(("torq.py config pull default %s" |
| % mock_invalid_file_path)) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, ( |
| "Command is invalid because %s is not a valid filepath." |
| % mock_invalid_file_path)) |
| self.assertEqual(error.suggestion, ( |
| "A default filepath can be used if you do not specify a file-path:\n\t" |
| " torq pull default to copy to ./default.pbtxt\n\t" |
| " torq pull lightweight to copy to ./lightweight.pbtxt\n\t " |
| "torq pull memory to copy to ./memory.pbtxt")) |
| |
| def test_get_command_type_config_list(self): |
| parser = self.set_up_parser("torq.py config list") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| command = get_command_type(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(command.get_type(), "config list") |
| |
| def test_get_command_type_config_show(self): |
| parser = self.set_up_parser("torq.py config show default") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| command = get_command_type(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(command.get_type(), "config show") |
| |
| def test_get_command_type_config_pull(self): |
| parser = self.set_up_parser("torq.py config pull default") |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| command = get_command_type(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(command.get_type(), "config pull") |
| |
| @mock.patch.object(os.path, "exists", autospec=True) |
| def test_create_parser_valid_open_subcommand(self, mock_exists): |
| mock_exists.return_value = True |
| parser = self.set_up_parser("torq.py open %s" % TEST_FILE) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error, None) |
| self.assertEqual(args.file_path, TEST_FILE) |
| |
| def test_create_parser_open_subcommand_no_file(self): |
| parser = self.set_up_parser("torq.py open") |
| |
| with self.assertRaises(SystemExit): |
| parser.parse_args() |
| |
| @mock.patch.object(os.path, "exists", autospec=True) |
| def test_create_parser_open_subcommand_invalid_file(self, mock_exists): |
| mock_exists.return_value = False |
| parser = self.set_up_parser("torq.py open %s" % TEST_FILE) |
| |
| args = parser.parse_args() |
| args, error = verify_args(args) |
| |
| self.assertEqual(error.message, "Command is invalid because %s is an " |
| "invalid file path." % TEST_FILE) |
| self.assertEqual(error.suggestion, "Make sure your file exists.") |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |