test rust directly

This commit is contained in:
Anthony Sottile 2023-01-29 18:27:10 -05:00
parent 6eacdd440e
commit 2adca78c6f
7 changed files with 61 additions and 128 deletions

View file

@ -3,7 +3,6 @@ from __future__ import annotations
import os import os
from typing import Sequence from typing import Sequence
import pre_commit.constants as C
from pre_commit.languages.all import Language from pre_commit.languages.all import Language
from pre_commit.prefix import Prefix from pre_commit.prefix import Prefix
@ -14,10 +13,11 @@ def run_language(
exe: str, exe: str,
args: Sequence[str] = (), args: Sequence[str] = (),
file_args: Sequence[str] = (), file_args: Sequence[str] = (),
version: str = C.DEFAULT, version: str | None = None,
deps: Sequence[str] = (), deps: Sequence[str] = (),
) -> tuple[int, bytes]: ) -> tuple[int, bytes]:
prefix = Prefix(str(path)) prefix = Prefix(str(path))
version = version or language.get_default_version()
language.install_environment(prefix, version, deps) language.install_environment(prefix, version, deps)
with language.in_env(prefix, version): with language.in_env(prefix, version):

View file

@ -1,5 +0,0 @@
- id: rust-hook
name: rust example hook
entry: rust-hello-world
language: rust
files: ''

View file

@ -1,3 +0,0 @@
[[package]]
name = "rust-hello-world"
version = "0.1.0"

View file

@ -1,3 +0,0 @@
[package]
name = "rust-hello-world"
version = "0.1.0"

View file

@ -1,3 +0,0 @@
fn main() {
println!("hello world");
}

View file

@ -1,6 +1,5 @@
from __future__ import annotations from __future__ import annotations
from typing import Mapping
from unittest import mock from unittest import mock
import pytest import pytest
@ -8,8 +7,8 @@ import pytest
import pre_commit.constants as C import pre_commit.constants as C
from pre_commit import parse_shebang from pre_commit import parse_shebang
from pre_commit.languages import rust from pre_commit.languages import rust
from pre_commit.prefix import Prefix from pre_commit.store import _make_local_repo
from pre_commit.util import cmd_output from testing.language_helpers import run_language
ACTUAL_GET_DEFAULT_VERSION = rust.get_default_version.__wrapped__ ACTUAL_GET_DEFAULT_VERSION = rust.get_default_version.__wrapped__
@ -30,64 +29,78 @@ def test_uses_default_when_rust_is_not_available(cmd_output_b_mck):
assert ACTUAL_GET_DEFAULT_VERSION() == C.DEFAULT assert ACTUAL_GET_DEFAULT_VERSION() == C.DEFAULT
@pytest.mark.parametrize('language_version', (C.DEFAULT, '1.56.0')) def _make_hello_world(tmp_path):
def test_installs_with_bootstrapped_rustup(tmpdir, language_version): src_dir = tmp_path.joinpath('src')
tmpdir.join('src', 'main.rs').ensure().write( src_dir.mkdir()
src_dir.joinpath('main.rs').write_text(
'fn main() {\n' 'fn main() {\n'
' println!("Hello, world!");\n' ' println!("Hello, world!");\n'
'}\n', '}\n',
) )
tmpdir.join('Cargo.toml').ensure().write( tmp_path.joinpath('Cargo.toml').write_text(
'[package]\n' '[package]\n'
'name = "hello_world"\n' 'name = "hello_world"\n'
'version = "0.1.0"\n' 'version = "0.1.0"\n'
'edition = "2021"\n', 'edition = "2021"\n',
) )
prefix = Prefix(str(tmpdir))
find_executable_exes = []
original_find_executable = parse_shebang.find_executable def test_installs_rust_missing_rustup(tmp_path):
_make_hello_world(tmp_path)
def mocked_find_executable( # pretend like `rustup` doesn't exist so it gets bootstrapped
exe: str, *, env: Mapping[str, str] | None = None, calls = []
) -> str | None: orig = parse_shebang.find_executable
"""
Return `None` the first time `find_executable` is called to ensure
that the bootstrapping code is executed, then just let the function
work as normal.
Also log the arguments to ensure that everything works as expected. def mck(exe, env=None):
""" calls.append(exe)
find_executable_exes.append(exe) if len(calls) == 1:
if len(find_executable_exes) == 1: assert exe == 'rustup'
return None return None
return original_find_executable(exe, env=env) return orig(exe, env=env)
with mock.patch.object(parse_shebang, 'find_executable') as find_exe_mck: with mock.patch.object(parse_shebang, 'find_executable', side_effect=mck):
find_exe_mck.side_effect = mocked_find_executable ret = run_language(tmp_path, rust, 'hello_world', version='1.56.0')
rust.install_environment(prefix, language_version, ()) assert calls == ['rustup', 'rustup', 'cargo', 'hello_world']
assert find_executable_exes == ['rustup', 'rustup', 'cargo'] assert ret == (0, b'Hello, world!\n')
with rust.in_env(prefix, language_version):
assert cmd_output('hello_world')[1] == 'Hello, world!\n'
def test_installs_with_existing_rustup(tmpdir): @pytest.mark.parametrize('version', (C.DEFAULT, '1.56.0'))
tmpdir.join('src', 'main.rs').ensure().write( def test_language_version_with_rustup(tmp_path, version):
'fn main() {\n'
' println!("Hello, world!");\n'
'}\n',
)
tmpdir.join('Cargo.toml').ensure().write(
'[package]\n'
'name = "hello_world"\n'
'version = "0.1.0"\n'
'edition = "2021"\n',
)
prefix = Prefix(str(tmpdir))
assert parse_shebang.find_executable('rustup') is not None assert parse_shebang.find_executable('rustup') is not None
rust.install_environment(prefix, '1.56.0', ())
with rust.in_env(prefix, '1.56.0'): _make_hello_world(tmp_path)
assert cmd_output('hello_world')[1] == 'Hello, world!\n'
ret = run_language(tmp_path, rust, 'hello_world', version=version)
assert ret == (0, b'Hello, world!\n')
@pytest.mark.parametrize('dep', ('cli:shellharden:4.2.0', 'cli:shellharden'))
def test_rust_cli_additional_dependencies(tmp_path, dep):
_make_local_repo(str(tmp_path))
t_sh = tmp_path.joinpath('t.sh')
t_sh.write_text('echo $hi\n')
assert rust.get_default_version() == 'system'
ret = run_language(
tmp_path,
rust,
'shellharden --transform',
deps=(dep,),
args=(str(t_sh),),
)
assert ret == (0, b'echo "$hi"\n')
def test_run_lib_additional_dependencies(tmp_path):
_make_hello_world(tmp_path)
deps = ('shellharden:4.2.0', 'git-version')
ret = run_language(tmp_path, rust, 'hello_world', deps=deps)
assert ret == (0, b'Hello, world!\n')
bin_dir = tmp_path.joinpath('rustenv-system', 'bin')
assert bin_dir.is_dir()
assert not bin_dir.joinpath('shellharden').exists()
assert not bin_dir.joinpath('shellharden.exe').exists()

View file

@ -20,7 +20,6 @@ from pre_commit.languages import helpers
from pre_commit.languages import node from pre_commit.languages import node
from pre_commit.languages import python from pre_commit.languages import python
from pre_commit.languages import ruby from pre_commit.languages import ruby
from pre_commit.languages import rust
from pre_commit.languages.all import languages from pre_commit.languages.all import languages
from pre_commit.prefix import Prefix from pre_commit.prefix import Prefix
from pre_commit.repository import _hook_installed from pre_commit.repository import _hook_installed
@ -366,54 +365,6 @@ func main() {
assert _norm_out(out) == b'hello hello world\n' assert _norm_out(out) == b'hello hello world\n'
def test_rust_hook(tempdir_factory, store):
_test_hook_repo(
tempdir_factory, store, 'rust_hooks_repo',
'rust-hook', [], b'hello world\n',
)
@pytest.mark.parametrize('dep', ('cli:shellharden:3.1.0', 'cli:shellharden'))
def test_additional_rust_cli_dependencies_installed(
tempdir_factory, store, dep,
):
path = make_repo(tempdir_factory, 'rust_hooks_repo')
config = make_config_from_repo(path)
# A small rust package with no dependencies.
config['hooks'][0]['additional_dependencies'] = [dep]
hook = _get_hook(config, store, 'rust-hook')
envdir = helpers.environment_dir(
hook.prefix,
rust.ENVIRONMENT_DIR,
'system',
)
binaries = os.listdir(os.path.join(envdir, 'bin'))
# normalize for windows
binaries = [os.path.splitext(binary)[0] for binary in binaries]
assert 'shellharden' in binaries
def test_additional_rust_lib_dependencies_installed(
tempdir_factory, store,
):
path = make_repo(tempdir_factory, 'rust_hooks_repo')
config = make_config_from_repo(path)
# A small rust package with no dependencies.
deps = ['shellharden:3.1.0', 'git-version']
config['hooks'][0]['additional_dependencies'] = deps
hook = _get_hook(config, store, 'rust-hook')
envdir = helpers.environment_dir(
hook.prefix,
rust.ENVIRONMENT_DIR,
'system',
)
binaries = os.listdir(os.path.join(envdir, 'bin'))
# normalize for windows
binaries = [os.path.splitext(binary)[0] for binary in binaries]
assert 'rust-hello-world' in binaries
assert 'shellharden' not in binaries
def test_missing_executable(tempdir_factory, store): def test_missing_executable(tempdir_factory, store):
_test_hook_repo( _test_hook_repo(
tempdir_factory, store, 'not_found_exe', tempdir_factory, store, 'not_found_exe',
@ -636,23 +587,6 @@ def test_local_golang_additional_dependencies(store):
assert _norm_out(out) == b'Hello, Go examples!\n' assert _norm_out(out) == b'Hello, Go examples!\n'
def test_local_rust_additional_dependencies(store):
config = {
'repo': 'local',
'hooks': [{
'id': 'hello',
'name': 'hello',
'entry': 'hello',
'language': 'rust',
'additional_dependencies': ['cli:hello-cli:0.2.2'],
}],
}
hook = _get_hook(config, store, 'hello')
ret, out = _hook_run(hook, (), color=False)
assert ret == 0
assert _norm_out(out) == b'Hello World!\n'
def test_fail_hooks(store): def test_fail_hooks(store):
config = { config = {
'repo': 'local', 'repo': 'local',