blob: 5895a2ae3801e96333d0af53e841b9b1801cd61f [file] [log] [blame]
Max Rozentsveyg5195ba32020-05-16 23:59:08 -04001import os
2import sys
3
Chris Kuehl13991f02017-07-02 21:00:28 -07004import pytest
5
Max Rozentsveyg5195ba32020-05-16 23:59:08 -04006from pre_commit_hooks import check_executables_have_shebangs
Chris Kuehl13991f02017-07-02 21:00:28 -07007from pre_commit_hooks.check_executables_have_shebangs import main
Max Rozentsveyg5195ba32020-05-16 23:59:08 -04008from pre_commit_hooks.util import cmd_output
9
10skip_win32 = pytest.mark.skipif(
11 sys.platform == 'win32',
12 reason="non-git checks aren't relevant on windows",
13)
Chris Kuehl13991f02017-07-02 21:00:28 -070014
15
Max Rozentsveyg5195ba32020-05-16 23:59:08 -040016@skip_win32 # pragma: win32 no cover
Anthony Sottilee9aea742017-07-15 12:56:51 -070017@pytest.mark.parametrize(
18 'content', (
19 b'#!/bin/bash\nhello world\n',
20 b'#!/usr/bin/env python3.6',
21 b'#!python',
Anthony Sottilef5c42a02020-02-05 11:10:42 -080022 '#!☃'.encode(),
Anthony Sottilee9aea742017-07-15 12:56:51 -070023 ),
24)
Chris Kuehl13991f02017-07-02 21:00:28 -070025def test_has_shebang(content, tmpdir):
26 path = tmpdir.join('path')
27 path.write(content, 'wb')
Max Rozentsveygf35bfed2020-05-20 12:07:45 -040028 assert main((str(path),)) == 0
Chris Kuehl13991f02017-07-02 21:00:28 -070029
30
Max Rozentsveyg5195ba32020-05-16 23:59:08 -040031@skip_win32 # pragma: win32 no cover
Anthony Sottilee9aea742017-07-15 12:56:51 -070032@pytest.mark.parametrize(
33 'content', (
34 b'',
35 b' #!python\n',
36 b'\n#!python\n',
37 b'python\n',
Anthony Sottilef5c42a02020-02-05 11:10:42 -080038 '☃'.encode(),
Anthony Sottilee9aea742017-07-15 12:56:51 -070039 ),
40)
Chris Kuehl13991f02017-07-02 21:00:28 -070041def test_bad_shebang(content, tmpdir, capsys):
42 path = tmpdir.join('path')
43 path.write(content, 'wb')
Max Rozentsveygf35bfed2020-05-20 12:07:45 -040044 assert main((str(path),)) == 1
Chris Kuehl13991f02017-07-02 21:00:28 -070045 _, stderr = capsys.readouterr()
Anthony Sottilef5c42a02020-02-05 11:10:42 -080046 assert stderr.startswith(f'{path}: marked executable but')
Max Rozentsveyg5195ba32020-05-16 23:59:08 -040047
48
49def test_check_git_filemode_passing(tmpdir):
50 with tmpdir.as_cwd():
51 cmd_output('git', 'init', '.')
52
53 f = tmpdir.join('f')
54 f.write('#!/usr/bin/env bash')
55 f_path = str(f)
56 cmd_output('chmod', '+x', f_path)
57 cmd_output('git', 'add', f_path)
58 cmd_output('git', 'update-index', '--chmod=+x', f_path)
59
60 g = tmpdir.join('g').ensure()
61 g_path = str(g)
62 cmd_output('git', 'add', g_path)
63
64 # this is potentially a problem, but not something the script intends
65 # to check for -- we're only making sure that things that are
66 # executable have shebangs
67 h = tmpdir.join('h')
68 h.write('#!/usr/bin/env bash')
69 h_path = str(h)
70 cmd_output('git', 'add', h_path)
71
72 files = (f_path, g_path, h_path)
73 assert check_executables_have_shebangs._check_git_filemode(files) == 0
74
75
76def test_check_git_filemode_failing(tmpdir):
77 with tmpdir.as_cwd():
78 cmd_output('git', 'init', '.')
79
80 f = tmpdir.join('f').ensure()
81 f_path = str(f)
82 cmd_output('chmod', '+x', f_path)
83 cmd_output('git', 'add', f_path)
84 cmd_output('git', 'update-index', '--chmod=+x', f_path)
85
86 files = (f_path,)
87 assert check_executables_have_shebangs._check_git_filemode(files) == 1
88
89
90@pytest.mark.parametrize(
91 ('content', 'mode', 'expected'),
92 (
93 pytest.param('#!python', '+x', 0, id='shebang with executable'),
94 pytest.param('#!python', '-x', 0, id='shebang without executable'),
95 pytest.param('', '+x', 1, id='no shebang with executable'),
96 pytest.param('', '-x', 0, id='no shebang without executable'),
97 ),
98)
99def test_git_executable_shebang(temp_git_dir, content, mode, expected):
100 with temp_git_dir.as_cwd():
101 path = temp_git_dir.join('path')
102 path.write(content)
103 cmd_output('git', 'add', str(path))
104 cmd_output('chmod', mode, str(path))
105 cmd_output('git', 'update-index', f'--chmod={mode}', str(path))
106
Max R7848fcf2020-05-18 21:46:53 -0400107 # simulate how identify chooses that something is executable
Max Rozentsveyg5195ba32020-05-16 23:59:08 -0400108 filenames = [path for path in [str(path)] if os.access(path, os.X_OK)]
109
110 assert main(filenames) == expected