content: #    Copyright 2016 IBM Corp.
  #
  # SPDX-License-Identifier: Apache-2.0
  import logging
  import os
  from unittest import mock
  
  import fixtures
  import testtools
  
  from bandit.cli import main as bandit
  from bandit.core import extension_loader as ext_loader
  from bandit.core import utils
  
  bandit_config_content = """
  include:
      - '*.py'
      - '*.pyw'
  
  profiles:
      test:
          include:
              - start_process_with_a_shell
  
  shell_injection:
      subprocess:
  
      shell:
          - os.system
  """
  
  bandit_baseline_content = """{
      "results": [
          {
              "code": "some test code",
              "filename": "test_example.py",
              "issue_severity": "low",
              "issue_confidence": "low",
              "issue_text": "test_issue",
              "test_name": "some_test",
              "test_id": "x",
              "line_number": "n",
              "line_range": "n-m"
          }
      ]
  }
  """
  
  
  class BanditCLIMainLoggerTests(testtools.TestCase):
      def setUp(self):
          super().setUp()
          self.logger = logging.getLogger()
          self.original_logger_handlers = self.logger.handlers
          self.original_logger_level = self.logger.level
          self.logger.handlers = []
  
      def tearDown(self):
          super().tearDown()
          self.logger.handlers = self.original_logger_handlers
          self.logger.level = self.original_logger_level
  
      def test_init_logger(self):
          # Test that a logger was properly initialized
          bandit._init_logger()
  
          self.assertIsNotNone(self.logger)
          self.assertNotEqual(self.logger.handlers, [])
          self.assertEqual(logging.INFO, self.logger.level)
  
      def test_init_logger_debug_mode(self):
          # Test that the logger's level was set at 'DEBUG'
          bandit._init_logger(logging.DEBUG)
          self.assertEqual(logging.DEBUG, self.logger.level)
  
  
  class BanditCLIMainTests(testtools.TestCase):
      def setUp(self):
          super().setUp()
          self.current_directory = os.getcwd()
  
      def tearDown(self):
          super().tearDown()
          os.chdir(self.current_directory)
  
      def test_get_options_from_ini_no_ini_path_no_target(self):
          # Test that no config options are loaded when no ini path or target
          # directory are provided
          self.assertIsNone(bandit._get_options_from_ini(None, []))
  
      def test_get_options_from_ini_empty_directory_no_target(self):
          # Test that no config options are loaded when an empty directory is
          # provided as the ini path and no target directory is provided
          ini_directory = self.useFixture(fixtures.TempDir()).path
          self.assertIsNone(bandit._get_options_from_ini(ini_directory, []))
  
      def test_get_options_from_ini_no_ini_path_no_bandit_files(self):
          # Test that no config options are loaded when no ini path is provided
          # and the target directory contains no bandit config files (.bandit)
          target_directory = self.useFixture(fixtures.TempDir()).path
          self.assertIsNone(
              bandit._get_options_from_ini(None, [target_directory])
          )
  
      def test_get_options_from_ini_no_ini_path_multi_bandit_files(self):
          # Test that bandit exits when no ini path is provided and the target
          # directory(s) contain multiple bandit config files (.bandit)
          target_directory = self.useFixture(fixtures.TempDir()).path
          second_config = "second_config_directory"
          os.mkdir(os.path.join(target_directory, second_config))
          bandit_config_one = os.path.join(target_directory, ".bandit")
          bandit_config_two = os.path.join(
              target_directory, second_config, ".bandit"
          )
          bandit_files = [bandit_config_one, bandit_config_two]
          for bandit_file in bandit_files:
              with open(bandit_file, "w") as fd:
                  fd.write(bandit_config_content)
          self.assertRaisesRegex(
              SystemExit,
              "2",
              bandit._get_options_from_ini,
              None,
              [target_directory],
          )
  
      def test_init_extensions(self):
          # Test that an extension loader manager is returned
          self.assertEqual(ext_loader.MANAGER, bandit._init_extensions())
  
      def test_log_option_source_arg_val(self):
          # Test that the command argument value is returned when provided
          # with None or a string default value
          arg_val = "file"
          ini_val = "vuln"
          option_name = "aggregate"
          for default_val in (None, "default"):
              self.assertEqual(
                  arg_val,
                  bandit._log_option_source(
                      default_val, arg_val, ini_val, option_name
                  ),
              )
  
      def test_log_option_source_ini_value(self):
          # Test that the ini value is returned when no command argument is
          # provided
          default_val = None
          ini_val = "vuln"
          option_name = "aggregate"
          self.assertEqual(
              ini_val,
              bandit._log_option_source(default_val, None, ini_val, option_name),
          )
  
      def test_log_option_source_ini_val_with_str_default_and_no_arg_val(self):
          # Test that the ini value is returned when no command argument is
          # provided
          default_val = "file"
          arg_val = "file"
          ini_val = "vuln"
          option_name = "aggregate"
          self.assertEqual(
              ini_val,
              bandit._log_option_source(
                  default_val, arg_val, ini_val, option_name
              ),
          )
  
      def test_log_option_source_no_values(self):
          # Test that None is returned when no command argument or ini value are
          # provided
          option_name = "aggregate"
          self.assertIsNone(
              bandit._log_option_source(None, None, None, option_name)
          )
  
      @mock.patch("sys.argv", ["bandit", "-c", "bandit.yaml", "test"])
      def test_main_config_unopenable(self):
          # Test that bandit exits when a config file cannot be opened
          with mock.patch("bandit.core.config.__init__") as mock_bandit_config:
              mock_bandit_config.side_effect = utils.ConfigError("", "")
              # assert a SystemExit with code 2
              self.assertRaisesRegex(SystemExit, "2", bandit.main)
  
      @mock.patch("sys.argv", ["bandit", "-c", "bandit.yaml", "test"])
      def test_main_invalid_config(self):
          # Test that bandit exits when a config file contains invalid YAML
          # content
          with mock.patch(
              "bandit.core.config.BanditConfig.__init__"
          ) as mock_bandit_config:
              mock_bandit_config.side_effect = utils.ConfigError("", "")
              # assert a SystemExit with code 2
              self.assertRaisesRegex(SystemExit, "2", bandit.main)
  
      @mock.patch("sys.argv", ["bandit", "-c", "bandit.yaml", "test"])
      def test_main_handle_ini_options(self):
          # Test that bandit handles cmdline args from a bandit.yaml file
          temp_directory = self.useFixture(fixtures.TempDir()).path
          os.chdir(temp_directory)
          with open("bandit.yaml", "w") as fd:
              fd.write(bandit_config_content)
          with mock.patch(
              "bandit.cli.main._get_options_from_ini"
          ) as mock_get_opts:
              mock_get_opts.return_value = {
                  "exclude": "/tmp",
                  "skips": "skip_test",
                  "tests": "some_test",
              }
  
              with mock.patch("bandit.cli.main.LOG.error") as err_mock:
                  # SystemExit with code 2 when test not found in profile
                  self.assertRaisesRegex(SystemExit, "2", bandit.main)
                  self.assertEqual(
                      str(err_mock.call_args[0][0]),
                      "No tests would be run, please check the profile.",
                  )
  
      @mock.patch(
          "sys.argv", ["bandit", "-c", "bandit.yaml", "-p", "bad", "test"]
      )
      def test_main_profile_not_found(self):
          # Test that bandit exits when an invalid profile name is provided
          temp_directory = self.useFixture(fixtures.TempDir()).path
          os.chdir(temp_directory)
          with open("bandit.yaml", "w") as fd:
              fd.write(bandit_config_content)
          # assert a SystemExit with code 2
          with mock.patch("bandit.cli.main.LOG.error") as err_mock:
              self.assertRaisesRegex(SystemExit, "2", bandit.main)
              self.assertEqual(
                  str(err_mock.call_args[0][0]),
                  "Unable to find profile (bad) in config file: bandit.yaml",
              )
  
      @mock.patch(
          "sys.argv", ["bandit", "-c", "bandit.yaml", "-b", "base.json", "test"]
      )
      def test_main_baseline_ioerror(self):
          # Test that bandit exits when encountering an IOError while reading
          # baseline data
          temp_directory = self.useFixture(fixtures.TempDir()).path
          os.chdir(temp_directory)
          with open("bandit.yaml", "w") as fd:
              fd.write(bandit_config_content)
          with open("base.json", "w") as fd:
              fd.write(bandit_baseline_content)
          with mock.patch(
              "bandit.core.manager.BanditManager.populate_baseline"
          ) as mock_mgr_pop_bl:
              mock_mgr_pop_bl.side_effect = IOError
              # assert a SystemExit with code 2
              self.assertRaisesRegex(SystemExit, "2", bandit.main)
  
      @mock.patch(
          "sys.argv",
          [
              "bandit",
              "-c",
              "bandit.yaml",
              "-b",
              "base.json",
              "-f",
              "csv",
              "test",
          ],
      )
      def test_main_invalid_output_format(self):
          # Test that bandit exits when an invalid output format is selected
          temp_directory = self.useFixture(fixtures.TempDir()).path
          os.chdir(temp_directory)
          with open("bandit.yaml", "w") as fd:
              fd.write(bandit_config_content)
          with open("base.json", "w") as fd:
              fd.write(bandit_baseline_content)
          # assert a SystemExit with code 2
          self.assertRaisesRegex(SystemExit, "2", bandit.main)
  
      @mock.patch(
          "sys.argv", ["bandit", "-c", "bandit.yaml", "test", "-o", "output"]
      )
      def test_main_exit_with_results(self):
          # Test that bandit exits when there are results
          temp_directory = self.useFixture(fixtures.TempDir()).path
          os.chdir(temp_directory)
          with open("bandit.yaml", "w") as fd:
              fd.write(bandit_config_content)
          with mock.patch(
              "bandit.core.manager.BanditManager.results_count"
          ) as mock_mgr_results_ct:
              mock_mgr_results_ct.return_value = 1
              # assert a SystemExit with code 1
              self.assertRaisesRegex(SystemExit, "1", bandit.main)
  
      @mock.patch(
          "sys.argv", ["bandit", "-c", "bandit.yaml", "test", "-o", "output"]
      )
      def test_main_exit_with_no_results(self):
          # Test that bandit exits when there are no results
          temp_directory = self.useFixture(fixtures.TempDir()).path
          os.chdir(temp_directory)
          with open("bandit.yaml", "w") as fd:
              fd.write(bandit_config_content)
          with mock.patch(
              "bandit.core.manager.BanditManager.results_count"
          ) as mock_mgr_results_ct:
              mock_mgr_results_ct.return_value = 0
              # assert a SystemExit with code 0
              self.assertRaisesRegex(SystemExit, "0", bandit.main)
  
      @mock.patch(
          "sys.argv",
          ["bandit", "-c", "bandit.yaml", "test", "-o", "output", "--exit-zero"],
      )
      def test_main_exit_with_results_and_with_exit_zero_flag(self):
          # Test that bandit exits with 0 on results and zero flag
          temp_directory = self.useFixture(fixtures.TempDir()).path
          os.chdir(temp_directory)
          with open("bandit.yaml", "w") as fd:
              fd.write(bandit_config_content)
          with mock.patch(
              "bandit.core.manager.BanditManager.results_count"
          ) as mock_mgr_results_ct:
              mock_mgr_results_ct.return_value = 1
  
              self.assertRaisesRegex(SystemExit, "0", bandit.main)
  