Skip to content

Commit e3f1f9e

Browse files
committed
Move user membership in project tests to test_benchcab
1 parent b78294b commit e3f1f9e

6 files changed

Lines changed: 97 additions & 65 deletions

File tree

benchcab/benchcab.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,21 @@ def _validate_environment(self, project: str, modules: list):
6464
)
6565
sys.exit(1)
6666

67-
required_groups = [project, "ks32", "hh5"]
67+
if project is None:
68+
msg = """Couldn't resolve project: check 'project' in config.yaml
69+
and/or $PROJECT set in ~/.config/gadi-login.conf
70+
"""
71+
raise AttributeError(msg)
72+
73+
required_groups = set([project, "ks32", "hh5"])
6874
groups = [grp.getgrgid(gid).gr_name for gid in os.getgroups()]
69-
if not set(required_groups).issubset(groups):
70-
print(
71-
"Error: user does not have the required group permissions.",
72-
"The required groups are:",
73-
", ".join(required_groups),
75+
if not required_groups.issubset(groups):
76+
msg = (
77+
f"""Error: user does not have the required group permissions.,
78+
The required groups are:,
79+
{", ".join(required_groups)}""",
7480
)
75-
sys.exit(1)
81+
raise PermissionError(msg)
7682

7783
for modname in modules:
7884
if not self.modules_handler.module_is_avail(modname):

benchcab/config.py

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -83,27 +83,7 @@ def read_optional_key(config: dict):
8383
The configuration file with with/without optional keys
8484
"""
8585
if "project" not in config:
86-
if "PROJECT" not in os.environ:
87-
msg = """Couldn't resolve project: check 'project' in config.yaml
88-
and/or $PROJECT set in ~/.config/gadi-login.conf
89-
"""
90-
raise ValueError(msg)
91-
config["project"] = os.environ["PROJECT"]
92-
93-
groups = list(
94-
set(
95-
[
96-
group
97-
for data_dir in internal.USER_PROJECT_DIRS
98-
for group in os.listdir(data_dir)
99-
]
100-
)
101-
)
102-
103-
if config["project"] not in groups:
104-
msg = f"User is not a member of project [{config['project']}]: Check if project key is correct"
105-
106-
raise ValueError(msg)
86+
config["project"] = os.environ.get("PROJECT", None)
10787

10888
if "realisations" in config:
10989
for r in config["realisations"]:
@@ -166,8 +146,8 @@ def read_config(config_path: str) -> dict:
166146
"""
167147
# Read configuration file
168148
config = read_config_file(config_path)
169-
# Validate and return.
170-
validate_config(config)
171149
# Populate configuration dict with optional keys
172150
read_optional_key(config)
151+
# Validate and return.
152+
validate_config(config)
173153
return config

benchcab/internal.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@
2828
# Path to the user's current working directory
2929
CWD = Path.cwd()
3030

31-
# Directory List is obtained from Gadi User Guide in Section - Gadi Resources
32-
# https://opus.nci.org.au/display/Help/0.+Welcome+to+Gadi
33-
USER_PROJECT_DIRS = ["/g/data", "/scratch"]
34-
3531
# Path to the user's home directory
3632
HOME_DIR = Path(os.environ["HOME"])
3733

docs/user_guide/config_options.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ The different running modes of `benchcab` are solely dependent on the options us
3232

3333
## project
3434

35-
NCI project ID to charge the simulations to.
36-
This key is _optional_. If ID is not provided, the current workspace project - i.e. the environment variable `$PROJECT` will be used.
35+
: **Default:** user's default project, _optional key_. :octicons-dash-24: NCI project ID to charge the simulations to. The user's default project defined in the $PROJECT environment variable is used by default.
3736

3837
``` yaml
3938

tests/test_benchcab.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""`pytest` tests for `benchcab.py`."""
2+
import re
3+
from contextlib import nullcontext as does_not_raise
4+
from unittest import mock
5+
6+
import pytest
7+
8+
from benchcab.benchcab import Benchcab
9+
10+
11+
@pytest.fixture(scope="module", autouse=True)
12+
def _set_user_projects():
13+
with mock.patch("grp.getgrgid") as mocked_getgrid, mock.patch(
14+
"os.getgroups"
15+
) as mocked_groups:
16+
type(mocked_getgrid.return_value).gr_name = mock.PropertyMock(
17+
return_value="hh5"
18+
)
19+
mocked_groups.return_value = [1]
20+
yield
21+
22+
23+
@pytest.fixture(scope="module", params=["hh5", "invalid_project_name"])
24+
def config_project(request):
25+
"""Get config project name."""
26+
return request.param
27+
28+
29+
# Error message if config project name cannot be resolved.
30+
no_project_name_msg = re.escape(
31+
"""Couldn't resolve project: check 'project' in config.yaml
32+
and/or $PROJECT set in ~/.config/gadi-login.conf
33+
"""
34+
)
35+
36+
# For testing whether user is member of necessary projects to run benchcab, we need to simulate the environment of Gadi
37+
# TODO: Simulate Gadi environment for running tests for validating environment
38+
39+
40+
@pytest.mark.skip()
41+
@pytest.mark.parametrize(
42+
("config_project", "pytest_error"),
43+
[
44+
("hh5", does_not_raise()),
45+
(None, pytest.raises(AttributeError, match=no_project_name_msg)),
46+
],
47+
)
48+
def test_project_name(config_project, pytest_error):
49+
"""Tests whether config project name is suitable to run in Gadi environment."""
50+
app = Benchcab(benchcab_exe_path=None)
51+
with pytest_error:
52+
app._validate_environment(project=config_project, modules=[])
53+
54+
55+
@pytest.mark.skip()
56+
@pytest.mark.parametrize(
57+
("config_project", "pytest_error"),
58+
[
59+
("hh5", does_not_raise()),
60+
("invalid_project_name", pytest.raises(PermissionError)),
61+
],
62+
)
63+
def test_user_project_group(config_project, pytest_error):
64+
"""Test _validate_environment for if current user's groups does not contain the project name."""
65+
app = Benchcab(benchcab_exe_path=None)
66+
with pytest_error:
67+
app._validate_environment(project=config_project, modules=[])

tests/test_config.py

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,6 @@
1717

1818

1919
# Temporarily set $PROJECT for testing module
20-
@pytest.fixture(autouse=True, scope="module")
21-
def _set_project_validation_dirs():
22-
with mock.patch("os.listdir") as mocked_listdir:
23-
mocked_listdir.return_value = [
24-
NO_OPTIONAL_CONFIG_PROJECT,
25-
OPTIONAL_CONFIG_PROJECT,
26-
]
27-
yield
28-
29-
3020
@pytest.fixture(autouse=True)
3121
def _set_project_env_variable(monkeypatch):
3222
# Clear existing environment variables first
@@ -162,6 +152,13 @@ def test_validate_config(config_str, pytest_error):
162152
class TestReadOptionalKey:
163153
"""Tests related to adding optional keys in config."""
164154

155+
@pytest.fixture()
156+
def all_optional_default_config_no_project(
157+
self, all_optional_default_config
158+
) -> dict:
159+
"""Set project keyword to None."""
160+
return all_optional_default_config | {"project": None}
161+
165162
@pytest.mark.parametrize(
166163
("input_config", "output_config"),
167164
[
@@ -176,28 +173,15 @@ def test_read_optional_key_add_data(self, input_config, output_config, request):
176173
bc.read_optional_key(config)
177174
assert pformat(config) == pformat(request.getfixturevalue(output_config))
178175

179-
def test_no_project_name(self, no_optional_config, monkeypatch):
176+
def test_no_project_name(
177+
self, no_optional_config, all_optional_default_config_no_project, monkeypatch
178+
):
180179
"""If project key and $PROJECT are not provided, then raise error."""
181180
monkeypatch.delenv("PROJECT")
182-
err_msg = re.escape(
183-
"""Couldn't resolve project: check 'project' in config.yaml
184-
and/or $PROJECT set in ~/.config/gadi-login.conf
185-
"""
186-
)
187-
with pytest.raises(ValueError, match=err_msg):
188-
bc.read_optional_key(no_optional_config)
189-
190-
def test_user_not_in_project(self, no_optional_config):
191-
"""If user is not in viewable NCI projects, raise error."""
192-
no_optional_config["project"] = "non_existing"
193-
err_msg = re.escape(
194-
"User is not a member of project [non_existing]: Check if project key is correct"
181+
bc.read_optional_key(no_optional_config)
182+
assert pformat(no_optional_config) == pformat(
183+
all_optional_default_config_no_project
195184
)
196-
with pytest.raises(
197-
ValueError,
198-
match=err_msg,
199-
):
200-
bc.read_optional_key(no_optional_config)
201185

202186

203187
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)