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

Add ArithmeticAdd CJ Node fixture without run or submit #6733

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions tests/cmdline/commands/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,12 +352,12 @@ def test_report(self, run_cli_command):
assert len(result.output_lines) == 1, result.output_lines
assert result.output_lines[0] == 'No log messages recorded for this entry'

def test_process_dump(self, run_cli_command, tmp_path, generate_workchain_multiply_add):
def test_process_dump(self, run_cli_command, tmp_path, run_workchain_multiply_add):
"""Test verdi process dump"""

# Only test CLI interface here, the actual functionalities of the Python API are tested in `test_processes.py`
test_path = tmp_path / 'cli-dump'
node = generate_workchain_multiply_add()
node = run_workchain_multiply_add()

# Giving a single identifier should print a non empty string message
options = [str(node.pk), '-p', str(test_path)]
Expand Down
114 changes: 108 additions & 6 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,108 @@ def _generate_calcjob_node(
return _generate_calcjob_node


@pytest.fixture()
def generate_calcjob_node_add(tmp_path, aiida_localhost, request):
def _generate_calcjob_node_add(x: int = 1, y: int = 2):
import json

from aiida.common import LinkType
from aiida.engine import ProcessState
from aiida.orm import FolderData, InstalledCode, Int
from aiida.orm.utils.log import create_logger_adapter
from aiida.orm.utils.node import get_query_type_from_type_string

workdir = tmp_path / 'workdir'
computer = aiida_localhost
generate_calcjob_node = request.getfixturevalue('generate_calcjob_node')

# Create the calculation node
# NOTE: Not passing entry point due to:
# "[WARNING] could not load the calculation tools entry point core.arithmetic.add:
# Entry point 'core.arithmetic.add' not found in group 'aiida.tools.calculations'"
# As `aiida.tools.calculations` section is empty in `pyproject.toml`
# entry_point='core.arithmetic.add',
calcjob_node = generate_calcjob_node(
process_state=ProcessState.FINISHED,
exit_status=0,
entry_point=None,
workdir=str(workdir),
)
calcjob_node.computer = computer

# Create and store input nodes
x_node = Int(x)
y_node = Int(y)
code_node = InstalledCode(computer=computer, filepath_executable='/bin/bash')

x_node.store()
y_node.store()
code_node.store()

# Input files
input_content = f'echo $(({x} + {y}))\n'
calcjob_node.base.repository.put_object_from_bytes(input_content.encode(), 'aiida.in')

# .aiida folder contents
calcinfo_dict = {'foo': 'bar'}
job_tmpl_dict = {'foo': 'bar'}
calcjob_node.base.repository.put_object_from_bytes(
json.dumps(calcinfo_dict, indent=4).encode(), '.aiida/calcinfo.json'
)
calcjob_node.base.repository.put_object_from_bytes(
json.dumps(job_tmpl_dict, indent=4).encode(), '.aiida/job_tmpl.json'
)

# Submit script
submit_script = 'foobar'
calcjob_node.base.repository.put_object_from_bytes(submit_script.encode(), '_aiidasubmit.sh')

# Add input links
calcjob_node.base.links.add_incoming(x_node, link_type=LinkType.INPUT_CALC, link_label='x')
calcjob_node.base.links.add_incoming(y_node, link_type=LinkType.INPUT_CALC, link_label='y')
calcjob_node.base.links.add_incoming(code_node, link_type=LinkType.INPUT_CALC, link_label='code')

# Set some properties/attributes before storing
calcjob_node.base.attributes.set('is_valid_cache', True)
calcjob_node.base.attributes.set(
'_query_type_string', get_query_type_from_type_string(calcjob_node._plugin_type_string)
)
calcjob_node._logger_adapter = create_logger_adapter(calcjob_node._logger, calcjob_node)
calcjob_node.set_process_state('finished')
calcjob_node.set_process_label('ArithmeticAddCalculation')
calcjob_node.set_process_type('aiida.calculations:core.arithmetic.add')
calcjob_node.set_exit_status(0)
calcjob_node.base.attributes.set('input_filename', 'aiida.in')
calcjob_node.base.attributes.set('output_filename', 'aiida.out')

# Must store CalcjobNode before I can add output files
calcjob_node.store()

# Create FolderData node for `retrieved`
retrieved_folder = FolderData()
output_content = f'{x+y}\n'.encode()
retrieved_folder.put_object_from_bytes(output_content, 'aiida.out')

scheduler_stdout = '\n'.encode()
scheduler_stderr = '\n'.encode()
retrieved_folder.base.repository.put_object_from_bytes(scheduler_stdout, '_scheduler-stdout.txt')
retrieved_folder.base.repository.put_object_from_bytes(scheduler_stderr, '_scheduler-stderr.txt')
retrieved_folder.store()

retrieved_folder.base.links.add_incoming(calcjob_node, link_type=LinkType.CREATE, link_label='retrieved')

# Create and link output node (sum)
output_node = Int(x + y)
output_node.store()
output_node.base.links.add_incoming(calcjob_node, link_type=LinkType.CREATE, link_label='sum')

calcjob_node.seal()

return calcjob_node

return _generate_calcjob_node_add


@pytest.fixture
def generate_calculation_node():
"""Generate an instance of a `CalculationNode`."""
Expand Down Expand Up @@ -831,8 +933,8 @@ def reset_log_level():


@pytest.fixture
def generate_calculation_node_add(aiida_localhost):
def _generate_calculation_node_add():
def run_calculation_arithmetic_add(aiida_localhost):
def _run_calculation_arithmetic_add():
from aiida.engine import run_get_node
from aiida.orm import InstalledCode, Int
from aiida.plugins import CalculationFactory
Expand All @@ -849,12 +951,12 @@ def _generate_calculation_node_add():

return add_node

return _generate_calculation_node_add
return _run_calculation_arithmetic_add


@pytest.fixture
def generate_workchain_multiply_add(aiida_localhost):
def _generate_workchain_multiply_add():
def run_workchain_multiply_add(aiida_localhost):
def _run_workchain_multiply_add():
from aiida.engine import run_get_node
from aiida.orm import InstalledCode, Int
from aiida.plugins import WorkflowFactory
Expand All @@ -872,7 +974,7 @@ def _generate_workchain_multiply_add():

return multiply_add_node

return _generate_workchain_multiply_add
return _run_workchain_multiply_add


@pytest.fixture
Expand Down
28 changes: 14 additions & 14 deletions tests/tools/dumping/test_processes.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,10 @@ def test_dump_workflow(generate_calculation_node_io, generate_workchain_node_io,
assert all([expected_file.is_file() for expected_file in expected_files])


def test_dump_multiply_add(tmp_path, generate_workchain_multiply_add):
def test_dump_multiply_add(tmp_path, run_workchain_multiply_add):
dump_parent_path = tmp_path / 'wc-dump-test-multiply-add'
process_dumper = ProcessDumper()
wc_node = generate_workchain_multiply_add()
wc_node = run_workchain_multiply_add()
process_dumper.dump(process_node=wc_node, output_path=dump_parent_path)

input_files = ['_aiidasubmit.sh', 'aiida.in', '.aiida/job_tmpl.json', '.aiida/calcinfo.json']
Expand Down Expand Up @@ -313,11 +313,11 @@ def test_dump_calculation_no_inputs(tmp_path, generate_calculation_node_io):
assert not (dump_parent_path / node_inputs_relpath).is_dir()


def test_dump_calculation_add(tmp_path, generate_calculation_node_add):
def test_dump_calculation_add(tmp_path, generate_calcjob_node_add):
dump_parent_path = tmp_path / 'cj-dump-test-add'

process_dumper = ProcessDumper()
calculation_node_add = generate_calculation_node_add()
calculation_node_add = generate_calcjob_node_add()
process_dumper._dump_calculation(calculation_node=calculation_node_add, output_path=dump_parent_path)

input_files = ['_aiidasubmit.sh', 'aiida.in', '.aiida/job_tmpl.json', '.aiida/calcinfo.json']
Expand Down Expand Up @@ -393,12 +393,12 @@ def test_prepare_dump_path(tmp_path):


def test_generate_default_dump_path(
generate_calculation_node_add,
generate_workchain_multiply_add,
generate_calcjob_node_add,
run_workchain_multiply_add,
):
process_dumper = ProcessDumper()
add_node = generate_calculation_node_add()
multiply_add_node = generate_workchain_multiply_add()
add_node = generate_calcjob_node_add()
multiply_add_node = run_workchain_multiply_add()
add_path = process_dumper._generate_default_dump_path(process_node=add_node)
multiply_add_path = process_dumper._generate_default_dump_path(process_node=multiply_add_node)

Expand All @@ -422,7 +422,7 @@ def test_generate_calculation_io_mapping():


def test_generate_child_node_label(
generate_workchain_multiply_add, generate_calculation_node_io, generate_workchain_node_io
run_workchain_multiply_add, generate_calculation_node_io, generate_workchain_node_io
):
# Check with manually constructed, more complex workchain
cj_node = generate_calculation_node_io(attach_outputs=False)
Expand All @@ -445,7 +445,7 @@ def test_generate_child_node_label(
assert output_paths == ['00-sub_workflow', '01-calculation']

# Check with multiply_add workchain node
multiply_add_node = generate_workchain_multiply_add()
multiply_add_node = run_workchain_multiply_add()
output_triples = multiply_add_node.base.links.get_outgoing().all()
# Sort by ctime here, not mtime, as I'm generating the WorkChain normally
output_triples = sorted(output_triples, key=lambda link_triple: link_triple.node.ctime)
Expand All @@ -455,15 +455,15 @@ def test_generate_child_node_label(
assert output_paths == ['00-multiply', '01-ArithmeticAddCalculation', '02-result']


def test_dump_node_yaml(generate_calculation_node_io, tmp_path, generate_workchain_multiply_add):
def test_dump_node_yaml(generate_calculation_node_io, tmp_path, run_workchain_multiply_add):
process_dumper = ProcessDumper()
cj_node = generate_calculation_node_io(attach_outputs=False)
process_dumper._dump_node_yaml(process_node=cj_node, output_path=tmp_path)

assert (tmp_path / node_metadata_file).is_file()

# Test with multiply_add
wc_node = generate_workchain_multiply_add()
wc_node = run_workchain_multiply_add()
process_dumper._dump_node_yaml(process_node=wc_node, output_path=tmp_path)

assert (tmp_path / node_metadata_file).is_file()
Expand Down Expand Up @@ -497,8 +497,8 @@ def test_dump_node_yaml(generate_calculation_node_io, tmp_path, generate_workcha
assert 'Node extras:' not in contents


def test_generate_parent_readme(tmp_path, generate_workchain_multiply_add):
wc_node = generate_workchain_multiply_add()
def test_generate_parent_readme(tmp_path, run_workchain_multiply_add):
wc_node = run_workchain_multiply_add()
process_dumper = ProcessDumper()

process_dumper._generate_readme(process_node=wc_node, output_path=tmp_path)
Expand Down