def test_echo_issues_outputs_proper_json_when_requested(self, mock_json): issue_1 = scanner.Issue(scanner.IssueType.Entropy, ["foo"]) issue_2 = scanner.Issue(scanner.IssueType.RegEx, ["bar"]) util.echo_issues([issue_1, issue_2], True, "/repo", "/output") mock_json.dumps.assert_called_once_with( { "project_path": "/repo", "issues_path": "/output", "found_issues": [ { "issue_type": "High Entropy", "issue_detail": None, "diff": "No diff available.", "strings_found": ["foo"], "commit_time": None, "commit_message": None, "commit_hash": None, "file_path": None, "branch": None, }, { "issue_type": "Regular Expression Match", "issue_detail": None, "diff": "No diff available.", "strings_found": ["bar"], "commit_time": None, "commit_message": None, "commit_hash": None, "file_path": None, "branch": None, }, ], } )
def test_echo_issues_outputs_proper_json_when_requested(self, mock_json): issue_1 = scanner.Issue( types.IssueType.Entropy, "foo", types.Chunk("foo", "/bar") ) issue_2 = scanner.Issue( types.IssueType.RegEx, "bar", types.Chunk("foo", "/bar") ) util.echo_issues([issue_1, issue_2], True, "/repo", "/output") mock_json.dumps.assert_called_once_with( { "project_path": "/repo", "output_dir": "/output", "found_issues": [ { "issue_type": "High Entropy", "issue_detail": None, "diff": "foo", "matched_string": "foo", "signature": "4db0024275a64ac2bf5e7d061e130e283b0b37a44167b605643e06e33177f74e", "file_path": "/bar", }, { "issue_type": "Regular Expression Match", "issue_detail": None, "diff": "foo", "matched_string": "bar", "signature": "1516f2c3395943be40811573bb63ed1e2b8fe3a0e6dcc8dbb43351ca90ba6822", "file_path": "/bar", }, ], } )
def test_echo_result_outputs_proper_json_when_requested( self, mock_time, mock_scanner, ): mock_time.now.return_value.isoformat.return_value = "now:now:now" issue_1 = scanner.Issue(types.IssueType.Entropy, "foo", types.Chunk("foo", "/bar", {})) issue_2 = scanner.Issue(types.IssueType.RegEx, "bar", types.Chunk("foo", "/bar", {})) mock_scanner.scan.return_value = (issue_1, issue_2) mock_scanner.excluded_paths = [] options = generate_options( GlobalOptions, output_format=types.OutputFormat.Json.value, exclude_signatures=[], exclude_entropy_patterns=[], ) # We're generating JSON piecemeal, so if we want to be safe we'll recover # the entire output, deserialize it (to confirm it's valid syntax) and # compare the result to the original input dictionary. with mock.patch("sys.stdout", new=StringIO()) as mock_stdout: util.echo_result(options, mock_scanner, "/repo", "/output") actual_output = mock_stdout.getvalue() self.assertEqual( json.loads(actual_output), { "scan_time": "now:now:now", "project_path": "/repo", "output_dir": "/output", "excluded_paths": [], "excluded_signatures": [], "exclude_entropy_patterns": [], "found_issues": [ { "issue_type": "High Entropy", "issue_detail": None, "diff": "foo", "matched_string": "foo", "signature": "4db0024275a64ac2bf5e7d061e130e283b0b37a44167b605643e06e33177f74e", "file_path": "/bar", }, { "issue_type": "Regular Expression Match", "issue_detail": None, "diff": "foo", "matched_string": "bar", "signature": "1516f2c3395943be40811573bb63ed1e2b8fe3a0e6dcc8dbb43351ca90ba6822", "file_path": "/bar", }, ], }, )
def test_echo_result_outputs_proper_json_when_requested_pathtype( self, mock_time, mock_json, mock_scanner): mock_time.now.return_value.isoformat.return_value = "now:now:now" issue_1 = scanner.Issue(types.IssueType.Entropy, "foo", types.Chunk("foo", "/bar", {})) issue_2 = scanner.Issue(types.IssueType.RegEx, "bar", types.Chunk("foo", "/bar", {})) mock_scanner.issues = [issue_1, issue_2] mock_scanner.excluded_paths = [ re.compile("package-lock.json"), re.compile("poetry.lock"), ] exclude_signatures = [ "fffffffffffff", "ooooooooooooo", ] options = generate_options(GlobalOptions, json=True, exclude_signatures=exclude_signatures) util.echo_result(options, mock_scanner, "/repo", Path("/tmp")) mock_json.dumps.assert_called_once_with({ "scan_time": "now:now:now", "project_path": "/repo", "output_dir": str(Path("/tmp")), "excluded_paths": ["package-lock.json", "poetry.lock"], "excluded_signatures": [ "fffffffffffff", "ooooooooooooo", ], "found_issues": [ { "issue_type": "High Entropy", "issue_detail": None, "diff": "foo", "matched_string": "foo", "signature": "4db0024275a64ac2bf5e7d061e130e283b0b37a44167b605643e06e33177f74e", "file_path": "/bar", }, { "issue_type": "Regular Expression Match", "issue_detail": None, "diff": "foo", "matched_string": "bar", "signature": "1516f2c3395943be40811573bb63ed1e2b8fe3a0e6dcc8dbb43351ca90ba6822", "file_path": "/bar", }, ], })
def test_populated_issues_list_does_not_rescan(self, mock_scan: mock.MagicMock): test_scanner = TestScanner(self.options) test_scanner._issues = [ # pylint: disable=protected-access scanner.Issue(types.IssueType.RegEx, "foo", types.Chunk("foo", "bar")) ] test_scanner.issues # pylint: disable=pointless-statement mock_scan.assert_not_called()
def test_command_exits_with_positive_return_code_when_issues_are_found( self, mock_scanner: mock.MagicMock): mock_scanner.return_value.scan.return_value = [ scanner.Issue(types.IssueType.Entropy, "foo", types.Chunk("foo", "/bar", {})) ] runner = CliRunner() with runner.isolated_filesystem(): result = runner.invoke(cli.main, ["scan-local-repo", "."]) self.assertGreater(result.exit_code, 0)
def test_output_dir_is_created_if_it_does_not_exist( self, mock_scanner: mock.MagicMock): mock_scanner.return_value.scan.return_value = [ scanner.Issue(types.IssueType.Entropy, "foo", types.Chunk("foo", "/bar", {})) ] runner = CliRunner() with runner.isolated_filesystem(): runner.invoke( cli.main, ["--output-dir", "./foo", "--json", "scan-local-repo", "."]) self.assertTrue(Path("./foo").exists())
def test_echo_result_outputs_compact_format(self, mock_click, mock_scanner): options = generate_options(GlobalOptions, verbose=0, output_format="compact") issue1 = scanner.Issue(types.IssueType.Entropy, "foo", types.Chunk("fullfoobar", "/what/foo", {})) issue2 = scanner.Issue(types.IssueType.RegEx, "bar", types.Chunk("fullfoobar", "/what/bar", {})) issue2.issue_detail = "Meets the bar" mock_scanner.scan.return_value = (issue1, issue2) util.echo_result(options, mock_scanner, "", "") mock_click.echo.assert_has_calls([ mock.call( "[High Entropy] /what/foo: foo (ea29b8c0f8a478f260689899393107cca188fbbff1c5a5bd4ff32c102cb60226, None)" ), mock.call( "[Regular Expression Match] /what/bar: bar (fa692eebc3d60e67a9f22b4b877d5939cb2ec96c0c26c7e5168b3b8b660c573c, Meets the bar)" ), ], )
def test_output_dir_is_not_called_out_when_outputting_json( self, mock_scanner: mock.MagicMock): mock_scanner.return_value.scan.return_value = [ scanner.Issue(types.IssueType.Entropy, "foo", types.Chunk("foo", "/bar", {})) ] runner = CliRunner() with runner.isolated_filesystem(): result = runner.invoke( cli.main, ["--output-dir", "./foo", "--json", "scan-local-repo", "."]) # All other outputs are mocked, so this is ensuring that the # "Results have been saved in ..." message is not output. self.assertEqual(result.output, "")
def test_output_dir_is_called_out(self, mock_scanner: mock.MagicMock, mock_dt: mock.MagicMock): mock_scanner.return_value.scan.return_value = [ scanner.Issue(types.IssueType.Entropy, "foo", types.Chunk("foo", "/bar")) ] mock_dt.now.return_value.isoformat.return_value = "nownownow" runner = CliRunner() with runner.isolated_filesystem() as dirname: result = runner.invoke( cli.main, ["--output-dir", "./foo", "scan-local-repo", "."]) self.assertEqual( result.output, f"Results have been saved in {Path(dirname).resolve()}/foo/tartufo-scan-results-nownownow\n", )
def test_issues_path_is_called_out(self, mock_scan_repo, mock_temp): mock_scan_repo.return_value = [ scanner.Issue(scanner.IssueType.Entropy, []) ] mock_temp.return_value = "/foo" runner = CliRunner() with runner.isolated_filesystem(): result = runner.invoke( cli.main, [ "--no-cleanup", "--no-regex", "--entropy", "[email protected]:godaddy/tartufo.git", ], ) self.assertEqual(result.output, "Results have been saved in /foo\n")
def test_output_dir_is_valid_name_in_windows(self, mock_scanner: mock.MagicMock, mock_dt: mock.MagicMock): mock_scanner.return_value.scan.return_value = [ scanner.Issue(types.IssueType.Entropy, "foo", types.Chunk("foo", "/bar", {})) ] mock_dt.now.return_value.isoformat.return_value = "now:now:now" runner = CliRunner() with runner.isolated_filesystem() as dirname: output_dir = (Path(dirname) / "foo").resolve() result = runner.invoke( cli.main, ["--output-dir", str(output_dir), "scan-local-repo", "."]) result_dir = output_dir / "tartufo-scan-results-nownownow" self.assertEqual( result.output, f"Results have been saved in {result_dir}\n", )