summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/conftest.py25
-rw-r--r--tests/languages/r_test.py100
2 files changed, 94 insertions, 31 deletions
diff --git a/tests/conftest.py b/tests/conftest.py
index 3076171..bd4af9a 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -209,36 +209,25 @@ def log_info_mock():
yield mck
-class FakeStream:
- def __init__(self):
- self.data = io.BytesIO()
-
- def write(self, s):
- self.data.write(s)
-
- def flush(self):
- pass
-
-
class Fixture:
- def __init__(self, stream):
+ def __init__(self, stream: io.BytesIO) -> None:
self._stream = stream
- def get_bytes(self):
+ def get_bytes(self) -> bytes:
"""Get the output as-if no encoding occurred"""
- data = self._stream.data.getvalue()
- self._stream.data.seek(0)
- self._stream.data.truncate()
+ data = self._stream.getvalue()
+ self._stream.seek(0)
+ self._stream.truncate()
return data.replace(b'\r\n', b'\n')
- def get(self):
+ def get(self) -> str:
"""Get the output assuming it was written as UTF-8 bytes"""
return self.get_bytes().decode()
@pytest.fixture
def cap_out():
- stream = FakeStream()
+ stream = io.BytesIO()
write = functools.partial(output.write, stream=stream)
write_line_b = functools.partial(output.write_line_b, stream=stream)
with mock.patch.multiple(output, write=write, write_line_b=write_line_b):
diff --git a/tests/languages/r_test.py b/tests/languages/r_test.py
index 02c559c..10919e4 100644
--- a/tests/languages/r_test.py
+++ b/tests/languages/r_test.py
@@ -1,14 +1,17 @@
from __future__ import annotations
import os.path
-import shutil
+from unittest import mock
import pytest
+import pre_commit.constants as C
from pre_commit import envcontext
+from pre_commit import lang_base
from pre_commit.languages import r
from pre_commit.prefix import Prefix
from pre_commit.store import _make_local_repo
+from pre_commit.util import resource_text
from pre_commit.util import win_exe
from testing.language_helpers import run_language
@@ -127,7 +130,8 @@ def test_path_rscript_exec_no_r_home_set():
assert r._rscript_exec() == 'Rscript'
-def test_r_hook(tmp_path):
+@pytest.fixture
+def renv_lock_file(tmp_path):
renv_lock = '''\
{
"R": {
@@ -157,6 +161,12 @@ def test_r_hook(tmp_path):
}
}
'''
+ tmp_path.joinpath('renv.lock').write_text(renv_lock)
+ yield
+
+
+@pytest.fixture
+def description_file(tmp_path):
description = '''\
Package: gli.clu
Title: What the Package Does (One Line, Title Case)
@@ -178,27 +188,39 @@ RoxygenNote: 7.1.1
Imports:
rprojroot
'''
- hello_world_r = '''\
+ tmp_path.joinpath('DESCRIPTION').write_text(description)
+ yield
+
+
+@pytest.fixture
+def hello_world_file(tmp_path):
+ hello_world = '''\
stopifnot(
packageVersion('rprojroot') == '1.0',
packageVersion('gli.clu') == '0.0.0.9000'
)
cat("Hello, World, from R!\n")
'''
+ tmp_path.joinpath('hello-world.R').write_text(hello_world)
+ yield
- tmp_path.joinpath('renv.lock').write_text(renv_lock)
- tmp_path.joinpath('DESCRIPTION').write_text(description)
- tmp_path.joinpath('hello-world.R').write_text(hello_world_r)
+
+@pytest.fixture
+def renv_folder(tmp_path):
renv_dir = tmp_path.joinpath('renv')
renv_dir.mkdir()
- shutil.copy(
- os.path.join(
- os.path.dirname(__file__),
- '../../pre_commit/resources/empty_template_activate.R',
- ),
- renv_dir.joinpath('activate.R'),
- )
+ activate_r = resource_text('empty_template_activate.R')
+ renv_dir.joinpath('activate.R').write_text(activate_r)
+ yield
+
+def test_r_hook(
+ tmp_path,
+ renv_lock_file,
+ description_file,
+ hello_world_file,
+ renv_folder,
+):
expected = (0, b'Hello, World, from R!\n')
assert run_language(tmp_path, r, 'Rscript hello-world.R') == expected
@@ -221,3 +243,55 @@ Rscript -e '
args=('hi', 'hello'),
)
assert ret == (0, b'hi, hello, from R!\n')
+
+
+@pytest.fixture
+def prefix(tmpdir):
+ yield Prefix(str(tmpdir))
+
+
+@pytest.fixture
+def installed_environment(
+ renv_lock_file,
+ hello_world_file,
+ renv_folder,
+ prefix,
+):
+ env_dir = lang_base.environment_dir(
+ prefix, r.ENVIRONMENT_DIR, r.get_default_version(),
+ )
+ r.install_environment(prefix, C.DEFAULT, ())
+ yield prefix, env_dir
+
+
+def test_health_check_healthy(installed_environment):
+ # should be healthy right after creation
+ prefix, _ = installed_environment
+ assert r.health_check(prefix, C.DEFAULT) is None
+
+
+def test_health_check_after_downgrade(installed_environment):
+ prefix, _ = installed_environment
+
+ # pretend the saved installed version is old
+ with mock.patch.object(r, '_read_installed_version', return_value='1.0.0'):
+ output = r.health_check(prefix, C.DEFAULT)
+
+ assert output is not None
+ assert output.startswith('Hooks were installed for R version')
+
+
+@pytest.mark.parametrize('version', ('NULL', 'NA', "''"))
+def test_health_check_without_version(prefix, installed_environment, version):
+ prefix, env_dir = installed_environment
+
+ # simulate old pre-commit install by unsetting the installed version
+ r._execute_vanilla_r_code_as_script(
+ f'renv::settings$r.version({version})',
+ prefix=prefix, version=C.DEFAULT, cwd=env_dir,
+ )
+
+ # no R version specified fails as unhealty
+ msg = 'Hooks were installed with an unknown R version'
+ check_output = r.health_check(prefix, C.DEFAULT)
+ assert check_output is not None and check_output.startswith(msg)