Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test -S/--rose-template-variable #310

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@
"""Functional tests for top-level function record_cylc_install_options and
"""

from pathlib import Path
import pytest
from subprocess import run
from shlex import split
from time import sleep
from types import SimpleNamespace
from typing import TYPE_CHECKING
from uuid import uuid4

from cylc.flow import __version__ as CYLC_VERSION
from cylc.flow.option_parsers import Options
Expand All @@ -38,6 +44,15 @@
)


if TYPE_CHECKING:
from pathlib import Path


def test_workflow_name():
"""Return a UUID to use as a test name"""
return f'cylc-rose-test-{str(uuid4())[:8]}'


@pytest.fixture(scope='module')
def mod_capsys(request):
from _pytest.capture import SysCapture
Expand Down Expand Up @@ -128,8 +143,14 @@ def _inner(srcpath, args=None):
srcpath:
args: Dictionary of arguments.
"""
if not args or not args.get('workflow_name', ''):
id_ = test_workflow_name()
args = {'workflow_name': id_}

args.update({'no_run_name': True})
options = Options(install_gop(), args)()
output = SimpleNamespace()
output.id = args['workflow_name']

try:
cylc_install(options, str(srcpath))
Expand Down Expand Up @@ -197,3 +218,39 @@ def cylc_validate_cli(capsys, caplog):
@pytest.fixture(scope='module')
def mod_cylc_validate_cli(mod_capsys, mod_caplog):
return _cylc_validate_cli(mod_capsys, mod_caplog)


@pytest.fixture
def file_poll():
"""Poll for the existance of a file.
"""
def _inner(fpath: "Path", timeout: int = 5, file_exists=True):
for _ in range(timeout):
if file_exists and fpath.exists():
break
elif not file_exists and not fpath.exists():
break
sleep(1)
else:
raise TimeoutError(
f'file {fpath} not found after {timeout} seconds')
return _inner


@pytest.fixture
def cylc_stop(file_poll):
"""Cylc stop & check the contact file"""
def _inner(id_):
run(split(f'cylc stop --now --now {id_}'))
contactfile = Path.home() / f'cylc-run{id_}.service/contact'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be?

Suggested change
contactfile = Path.home() / f'cylc-run{id_}.service/contact'
contactfile = Path.home() / f'cylc-run/{id_}/.service/contact'

Or better yet

from cylc.flow.workflow_files import get_contact_file_path

file_poll(contactfile, file_exists=False)
sleep(3)
return _inner


@pytest.fixture
def purge_workflow(cylc_stop):
def _inner(id_):
cylc_stop(id_)
run(split(f'cylc clean {id_}'))
return _inner
4 changes: 2 additions & 2 deletions tests/functional/test_ROSE_ORIG_HOST.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def fixture_install_flow(
)
install_conf_path = (
fixture_provide_flow['flowpath'] /
'runN/opt/rose-suite-cylc-install.conf'
'opt/rose-suite-cylc-install.conf'
)
text = install_conf_path.read_text()
text = re.sub('ROSE_ORIG_HOST=.*', 'ROSE_ORIG_HOST=foo', text)
Expand All @@ -143,7 +143,7 @@ def test_cylc_validate_srcdir(fixture_install_flow, mod_cylc_validate_cli):
def test_cylc_validate_rundir(fixture_install_flow, mod_cylc_validate_cli):
"""Sanity check that workflow validates:
"""
flowpath = fixture_install_flow['flowpath'] / 'runN'
flowpath = fixture_install_flow['flowpath']
result = mod_cylc_validate_cli(flowpath)
assert 'ROSE_ORIG_HOST (env) is:' in result.logging

Expand Down
17 changes: 9 additions & 8 deletions tests/functional/test_reinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import pytest
import shutil
from subprocess import run

from itertools import product
from pathlib import Path
Expand Down Expand Up @@ -117,14 +118,14 @@ def test_cylc_install_run(fixture_install_flow):
'file_, expect',
[
(
'run1/rose-suite.conf', (
'rose-suite.conf', (
'# Config Options \'b c (cylc-install)\' from CLI appended to'
' options already in `rose-suite.conf`.\n'
'opts=a b c (cylc-install)\n'
)
),
(
'run1/opt/rose-suite-cylc-install.conf', (
'opt/rose-suite-cylc-install.conf', (
'# This file records CLI Options.\n\n'
'!opts=b c\n'
f'\n[env]\n#{ROHIOS}\nROSE_ORIG_HOST={HOST}\n'
Expand Down Expand Up @@ -152,7 +153,7 @@ def fixture_reinstall_flow(
"""
monkeymodule.delenv('ROSE_SUITE_OPT_CONF_KEYS', raising=False)
result = mod_cylc_reinstall_cli(
f'{fixture_provide_flow["test_flow_name"]}/run1',
f'{fixture_provide_flow["test_flow_name"]}',
{
'opt_conf_keys': ['d']
}
Expand All @@ -171,14 +172,14 @@ def test_cylc_reinstall_run(fixture_reinstall_flow):
'file_, expect',
[
(
'run1/rose-suite.conf', (
'rose-suite.conf', (
'# Config Options \'b c d (cylc-install)\' from CLI appended '
'to options already in `rose-suite.conf`.\n'
'opts=a b c d (cylc-install)\n'
)
),
(
'run1/opt/rose-suite-cylc-install.conf', (
'opt/rose-suite-cylc-install.conf', (
'# This file records CLI Options.\n\n'
'!opts=b c d\n'
f'\n[env]\n#{ROHIOS}\nROSE_ORIG_HOST={HOST}\n'
Expand Down Expand Up @@ -213,7 +214,7 @@ def fixture_reinstall_flow2(
'opts=z\n'
)
result = mod_cylc_reinstall_cli(
f'{fixture_provide_flow["test_flow_name"]}/run1'
f'{fixture_provide_flow["test_flow_name"]}'
)
yield {
'fixture_provide_flow': fixture_provide_flow,
Expand All @@ -229,14 +230,14 @@ def test_cylc_reinstall_run2(fixture_reinstall_flow2):
'file_, expect',
[
(
'run1/rose-suite.conf', (
'rose-suite.conf', (
'# Config Options \'b c d (cylc-install)\' from CLI appended '
'to options already in `rose-suite.conf`.\n'
'opts=z b c d (cylc-install)\n'
)
),
(
'run1/opt/rose-suite-cylc-install.conf', (
'opt/rose-suite-cylc-install.conf', (
'# This file records CLI Options.\n\n'
'!opts=b c d\n'
f'\n[env]\n#{ROHIOS}\nROSE_ORIG_HOST={HOST}\n'
Expand Down
6 changes: 3 additions & 3 deletions tests/functional/test_reinstall_clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def test_cylc_install_run(fixture_install_flow):
'file_, expect',
[
(
'run1/opt/rose-suite-cylc-install.conf', (
'opt/rose-suite-cylc-install.conf', (
'# This file records CLI Options.\n\n'
'!opts=bar\n\n'
'[env]\n'
Expand Down Expand Up @@ -141,7 +141,7 @@ def fixture_reinstall_flow(
"""
monkeymodule.delenv('ROSE_SUITE_OPT_CONF_KEYS', raising=False)
result = mod_cylc_reinstall_cli(
f'{fixture_provide_flow["test_flow_name"]}/run1',
f'{fixture_provide_flow["test_flow_name"]}',
{
'opt_conf_keys': ['baz'],
'defines': ['[env]BAR=2'],
Expand All @@ -162,7 +162,7 @@ def test_cylc_reinstall_run(fixture_reinstall_flow):
'file_, expect',
[
(
'run1/opt/rose-suite-cylc-install.conf', (
'opt/rose-suite-cylc-install.conf', (
'# This file records CLI Options.\n\n'
'!opts=baz\n\n'
'[env]\n'
Expand Down
148 changes: 148 additions & 0 deletions tests/functional/test_reload.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about cylc vr?

Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# THIS FILE IS PART OF THE ROSE-CYLC PLUGIN FOR THE CYLC WORKFLOW ENGINE.
# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Functional tests for reinstalling of config files.
This test does the following:

1. Validates a workflow.
2. Installs a workflow with some opts set using -O and
ROSE_SUITE_OPT_CONF_KEYS.
3. Re-install workflow.
4. After modifying the source ``rose-suite.conf``, re-install the flow again.

At each step it checks the contents of
- ~/cylc-run/temporary-id/rose-suite.conf
- ~/cylc-run/temporary-id/opt/rose-suite-cylc-install.conf
"""
Comment on lines +16 to +28
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not seem accurate. Copied from another test?


import pytest
from subprocess import run

from pathlib import Path

@pytest.fixture
def provide_template_vars_workflow(tmp_path):
(tmp_path / 'flow.cylc').write_text(
'#!jinja2\n'
'[scheduling]\n'
' [[graph]]\n'
' R1 = foo\n'
'[runtime]\n'
' [[foo]]\n'
' script = cylc message -- {{var}}')
(tmp_path / 'rose-suite.conf').write_text(
'[template variables]\nvar="rose-suite.conf"')
Comment on lines +37 to +46
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

N.B. I think it would be easier and cleaner to use a triple quoted string and textwrap.dedent()



def test_reinstall_overrides(
cylc_install_cli, cylc_reinstall_cli, tmp_path, file_poll,
provide_template_vars_workflow, purge_workflow
):
"""When reinstalling and reloading the new installation are picked up.
"""
# Install workflow.
install_results = cylc_install_cli(
tmp_path, {'rose_template_vars': ['var="CLIinstall"']})
assert install_results.ret == 0

# Play workflow
# TODO: non-subprocess play command:
play = run(
[
'cylc', 'play', '--pause',
install_results.id,
'-S', 'var="CLIplay"'
],
capture_output=True
)
assert play.returncode == 0

# Reinstall the workflow:
reinstall_results = cylc_reinstall_cli(
install_results.id,
{'rose_template_vars': ['var="CLIreinstall"']})
assert reinstall_results.ret == 0

# Reload the workflow:
reload_ = run(
['cylc', 'reload', install_results.id],
capture_output=True,
)
assert reload_.returncode == 0

# The config being run has been modified:
run_dir = Path.home() / 'cylc-run' / install_results.id
config_log = (run_dir / 'log/config/02-reload-01.cylc')
file_poll(config_log)

assert 'cylc message -- CLIreinstall' in config_log.read_text()

purge_workflow(install_results.id)


def test_restart_overrides(
cylc_install_cli, cylc_reinstall_cli, tmp_path, file_poll,
provide_template_vars_workflow, purge_workflow, cylc_stop
):
"""When we restart a workflow, the play CLI options are honoured.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oliver-sanders - I've included this to demonstrate that I think that the clearance of the arguments shouldn't happen if the reload is one that comes with a restart since restart can have options set, unlike reload, and that if they are set then the user would expect the CLI variables to override those in the rose files, even if we have just reinstalled too.


Example:
$ cylc install foo -S 'X=0'
$ cylc play foo -S 'X=1'
$ cylc stop foo
$ cylc play foo -S 'X=2'

Inside the workflow the restart command arg should override the
content of the files and be X=2.
"""
# Install workflow.
install_results = cylc_install_cli(
tmp_path, {'rose_template_vars': ['var="CLIinstall"']})
assert install_results.ret == 0

# Play workflow
# TODO: non-subprocess play command:
play = run(
[
'cylc', 'play', '--pause',
install_results.id,
'-S', 'var="CLIplay"'
],
capture_output=True
)
assert play.returncode == 0

cylc_stop(install_results.id)

# Play (restart) workflow
# TODO: non-subprocess play command:
play = run(
[
'cylc', 'play', '--pause',
install_results.id,
'-S', 'var="CLIrestart"'
],
capture_output=True
)
assert play.returncode == 0

# The config being run has been modified:
run_dir = Path.home() / 'cylc-run' / install_results.id
config_log = (run_dir / 'log/config/02-restart-02.cylc')
file_poll(config_log)

assert 'cylc message -- CLIrestart' in config_log.read_text()

purge_workflow(install_results.id)
4 changes: 2 additions & 2 deletions tests/functional/test_rose_fileinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ def test_rose_fileinstall_subfolders(fixture_install_flow):
"""File installed into a sub directory:
"""
_, datapath, _, _, destpath = fixture_install_flow
assert ((destpath / 'runN/lib/python/lion.py').read_text() ==
assert ((destpath / 'lib/python/lion.py').read_text() ==
(datapath / 'lion.py').read_text())


def test_rose_fileinstall_concatenation(fixture_install_flow):
"""Multiple files concatenated on install(source contained wildcard):
"""
_, datapath, _, _, destpath = fixture_install_flow
assert ((destpath / 'runN/data').read_text() ==
assert ((destpath / 'data').read_text() ==
((datapath / 'randoms1.data').read_text() +
(datapath / 'randoms3.data').read_text()
))
Loading