Ejemplo n.º 1
0
    def test_lambda_default(self):
        """Test that an input port can specify a lambda as a default."""
        port_namespace = PortNamespace('base')

        # Defining lambda for default that returns incorrect type should not except at construction
        port_namespace['port'] = InputPort('port',
                                           valid_type=Int,
                                           default=lambda: 'string')

        # However, pre processing the namespace, which shall evaluate the default followed by validation will fail
        inputs = port_namespace.pre_process({})
        self.assertIsNotNone(port_namespace.validate(inputs))

        # Passing an explicit value for the port will forego the default and validation on returned inputs should pass
        inputs = port_namespace.pre_process({'port': Int(5)})
        self.assertIsNone(port_namespace.validate(inputs))

        # Redefining the port, this time with a correct default
        port_namespace['port'] = InputPort('port',
                                           valid_type=Int,
                                           default=lambda: Int(5))

        # Pre processing the namespace shall evaluate the default and return the int node
        inputs = port_namespace.pre_process({})
        self.assertIsInstance(inputs['port'], Int)
        self.assertEqual(inputs['port'].value, 5)

        # Passing an explicit value for the port will forego the default
        inputs = port_namespace.pre_process({'port': Int(3)})
        self.assertIsInstance(inputs['port'], Int)
        self.assertEqual(inputs['port'].value, 3)
Ejemplo n.º 2
0
    def test_immutable_input(self):
        """
        Check that from within the WorkChain self.inputs returns an AttributesFrozendict which should be immutable
        """
        test_class = self

        class Wf(WorkChain):

            @classmethod
            def define(cls, spec):
                super().define(spec)
                spec.input('a', valid_type=Int)
                spec.input('b', valid_type=Int)
                spec.outline(
                    cls.step_one,
                    cls.step_two,
                )

            def step_one(self):
                # Attempt to manipulate the inputs dictionary which since it is a AttributesFrozendict should raise
                with test_class.assertRaises(TypeError):
                    self.inputs['a'] = Int(3)
                with test_class.assertRaises(AttributeError):
                    self.inputs.pop('b')
                with test_class.assertRaises(TypeError):
                    self.inputs['c'] = Int(4)

            def step_two(self):
                # Verify that original inputs are still there with same value and no inputs were added
                test_class.assertIn('a', self.inputs)
                test_class.assertIn('b', self.inputs)
                test_class.assertNotIn('c', self.inputs)
                test_class.assertEqual(self.inputs['a'].value, 1)

        run_and_check_success(Wf, a=Int(1), b=Int(2))
Ejemplo n.º 3
0
    def test_create(self):
        """Creating basic data objects."""
        term_a = Float()
        # Check that initial value is zero
        self.assertAlmostEqual(term_a.value, 0.0)

        float_ = Float(6.0)
        self.assertAlmostEqual(float_.value, 6.)
        self.assertAlmostEqual(float_, Float(6.0))

        int_ = Int()
        self.assertAlmostEqual(int_.value, 0)
        int_ = Int(6)
        self.assertAlmostEqual(int_.value, 6)
        self.assertAlmostEqual(float_, int_)

        bool_ = Bool()
        self.assertAlmostEqual(bool_.value, False)
        bool_ = Bool(False)
        self.assertAlmostEqual(bool_.value, False)
        self.assertAlmostEqual(bool_.value, get_false_node())
        bool_ = Bool(True)
        self.assertAlmostEqual(bool_.value, True)
        self.assertAlmostEqual(bool_.value, get_true_node())

        str_ = Str()
        self.assertAlmostEqual(str_.value, '')
        str_ = Str('Hello')
        self.assertAlmostEqual(str_.value, 'Hello')
Ejemplo n.º 4
0
    def test_division(self):
        """Test the normal division operator."""
        term_a = Int(3)
        term_b = Int(2)

        self.assertAlmostEqual(term_a / term_b, 1.5)
        self.assertIsInstance(term_a / term_b, Float)
Ejemplo n.º 5
0
    def test_division_integer(self):
        """Test the integer division operator."""
        a = Int(3)
        b = Int(2)

        self.assertAlmostEqual(a // b, 1)
        self.assertIsInstance(a // b, Int)
Ejemplo n.º 6
0
    def test_immutable_input_groups(self):
        """
        Check that namespaced inputs also return AttributeFrozendicts and are hence immutable
        """
        test_class = self

        class Wf(WorkChain):

            @classmethod
            def define(cls, spec):
                super().define(spec)
                spec.input_namespace('subspace', dynamic=True)
                spec.outline(
                    cls.step_one,
                    cls.step_two,
                )

            def step_one(self):
                # Attempt to manipulate the namespaced inputs dictionary which should raise
                with test_class.assertRaises(TypeError):
                    self.inputs.subspace['one'] = Int(3)
                with test_class.assertRaises(AttributeError):
                    self.inputs.subspace.pop('two')
                with test_class.assertRaises(TypeError):
                    self.inputs.subspace['four'] = Int(4)

            def step_two(self):
                # Verify that original inputs are still there with same value and no inputs were added
                test_class.assertIn('one', self.inputs.subspace)
                test_class.assertIn('two', self.inputs.subspace)
                test_class.assertNotIn('four', self.inputs.subspace)
                test_class.assertEqual(self.inputs.subspace['one'].value, 1)

        run_and_check_success(Wf, subspace={'one': Int(1), 'two': Int(2)})
Ejemplo n.º 7
0
    def test_create(self):
        a = Float()
        # Check that initial value is zero
        self.assertAlmostEqual(a.value, 0.0)

        f = Float(6.0)
        self.assertAlmostEqual(f.value, 6.)
        self.assertAlmostEqual(f, Float(6.0))

        i = Int()
        self.assertAlmostEqual(i.value, 0)
        i = Int(6)
        self.assertAlmostEqual(i.value, 6)
        self.assertAlmostEqual(f, i)

        b = Bool()
        self.assertAlmostEqual(b.value, False)
        b = Bool(False)
        self.assertAlmostEqual(b.value, False)
        self.assertAlmostEqual(b.value, get_false_node())
        b = Bool(True)
        self.assertAlmostEqual(b.value, True)
        self.assertAlmostEqual(b.value, get_true_node())

        s = Str()
        self.assertAlmostEqual(s.value, '')
        s = Str('Hello')
        self.assertAlmostEqual(s.value, 'Hello')
Ejemplo n.º 8
0
    def test_division(self):
        """Test the normal division operator."""
        a = Int(3)
        b = Int(2)

        self.assertAlmostEqual(a / b, 1.5)
        self.assertIsInstance(a / b, Float)
Ejemplo n.º 9
0
 def define(cls, spec):
     super(IterHarmonicApprox, cls).define(spec)
     spec.expose_inputs(PhonopyWorkChain,
                        exclude=[
                            'immigrant_calculation_folders',
                            'calculation_nodes', 'dry_run'
                        ])
     spec.input('max_iteration',
                valid_type=Int,
                required=False,
                default=Int(10))
     spec.input('number_of_snapshots',
                valid_type=Int,
                required=False,
                default=Int(100))
     spec.input('number_of_steps_for_fitting',
                valid_type=Int,
                required=False,
                default=Int(4))
     spec.input('random_seed', valid_type=Int, required=False)
     spec.input('temperature',
                valid_type=Float,
                required=False,
                default=Float(300.0))
     spec.input('initial_nodes', valid_type=Dict, required=False)
     spec.input('include_ratio', valid_type=Float, required=False)
     spec.outline(
         cls.initialize,
         if_(cls.import_initial_nodes)(
             cls.set_initial_nodes,
             cls.run_phonon,
         ).else_(cls.run_initial_phonon, ),
         while_(cls.is_loop_finished)(cls.run_phonon, ),
     )
Ejemplo n.º 10
0
def launch_aiida_bulk_modulus(structure,
                              code_string,
                              resources,
                              label="AlN VASP relax calculation"):
    incar_dict = {
        'PREC': 'Accurate',
        'EDIFF': 1e-8,
        'NELMIN': 5,
        'NELM': 100,
        'ENCUT': 500,
        'IALGO': 38,
        'ISMEAR': 0,
        'SIGMA': 0.01,
        'GGA': 'PS',
        'LREAL': False,
        'LCHARG': False,
        'LWAVE': False,
    }

    kpoints = KpointsData()
    kpoints.set_kpoints_mesh([6, 6, 4], offset=[0, 0, 0.5])

    options = {'resources': resources, 'max_wallclock_seconds': 3600 * 10}

    potential_family = 'PBE.54'
    potential_mapping = {'Al': 'Al', 'N': 'N'}

    parser_settings = {
        'add_energies': True,
        'add_forces': True,
        'add_stress': True
    }

    code = Code.get_from_string(code_string)
    Workflow = WorkflowFactory('vasp_bm.bulkmodulus')
    builder = Workflow.get_builder()
    builder.code = code
    builder.parameters = Dict(dict=incar_dict)
    builder.structure = structure
    builder.settings = Dict(dict={'parser_settings': parser_settings})
    builder.potential_family = Str(potential_family)
    builder.potential_mapping = Dict(dict=potential_mapping)
    builder.kpoints = kpoints
    builder.options = Dict(dict=options)
    builder.metadata.label = label
    builder.metadata.description = label
    builder.clean_workdir = Bool(False)
    builder.relax = Bool(True)
    builder.force_cutoff = Float(1e-8)
    builder.steps = Int(10)
    builder.positions = Bool(True)
    builder.shape = Bool(True)
    builder.volume = Bool(True)
    builder.convergence_on = Bool(True)
    builder.convergence_volume = Float(1e-8)
    builder.convergence_max_iterations = Int(2)
    builder.verbose = Bool(True)

    node = submit(builder)
    return node
Ejemplo n.º 11
0
def test_supercell(generate_structure):
    """Test to create a super cell"""
    from aiida_fleur.tools.StructureData_util import supercell
    from aiida_fleur.tools.StructureData_util import supercell_ncf
    from aiida.orm import Int
    from itertools import product

    structure = generate_structure()

    supercell = supercell(structure, Int(2), Int(3), Int(4))

    assert (supercell.cell[0] == np.array(structure.cell[0]) * 2).all()
    assert (supercell.cell[1] == np.array(structure.cell[1]) * 3).all()
    assert (supercell.cell[2] == np.array(structure.cell[2]) * 4).all()
    assert len(supercell.sites) == 2 * 3 * 4 * len(structure.sites)

    positions_old = [x.position for x in structure.sites]
    positions_rescaled = [x.position for x in supercell.sites]
    for position in positions_old:
        for x, y, z in product(range(2), range(3), range(4)):
            test_pos = tuple(
                np.array(position) + x * np.array(structure.cell[0]) +
                y * np.array(structure.cell[1]) +
                z * np.array(structure.cell[2]))
            assert test_pos in positions_rescaled

    no_struc = Int(1)
    no_supercell = supercell_ncf(no_struc, 2, 3, 4)
    assert no_supercell is None
Ejemplo n.º 12
0
    def test_calcfunction_caching(self):
        """Verify that a calcfunction can be cached."""
        @calcfunction
        def test_calcfunction(data):
            global EXECUTION_COUNTER  # pylint: disable=global-statement
            EXECUTION_COUNTER += 1
            return Int(data.value + 1)

        self.assertEqual(EXECUTION_COUNTER, 0)
        _, original = test_calcfunction.run_get_node(Int(5))
        self.assertEqual(EXECUTION_COUNTER, 1)

        # Caching a CalcFunctionNode should be possible
        with enable_caching(CalcFunctionNode):
            input_node = Int(5)
            result, cached = test_calcfunction.run_get_node(input_node)

            self.assertEqual(
                EXECUTION_COUNTER,
                1)  # Calculation function body should not have been executed
            self.assertTrue(result.is_stored)
            self.assertTrue(cached.is_created_from_cache)
            self.assertIn(cached.get_cache_source(), original.uuid)
            self.assertEqual(cached.get_incoming().one().node.uuid,
                             input_node.uuid)
Ejemplo n.º 13
0
def test_sqs_process(ce_sqs_code):
    prim = bulk('Au')
    structure = StructureData(ase=prim)
    chemical_symbols = List(list=[['Au', 'Pd']])

    # set up calculation
    inputs = {
        'code': ce_sqs_code,
        'structure': structure,
        'chemical_symbols': chemical_symbols,
        'pbc': List(list=[True, True, True]),
        'cutoffs': List(list=[5.0]),
        'max_size': Int(8),
        'include_smaller_cells': Bool(True),
        'n_steps': Int(2000),
        'target_concentrations': Dict(dict={
            'Au': 0.5,
            'Pd': 0.5
        }),
        'metadata': {
            'options': {
                'max_wallclock_seconds': 30,
            },
        }
    }

    result = run(CalculationFactory('ce.gensqs'), **inputs)
    assert 'sqs' in result
    assert 'cluster_space' in result

    sqs = result['sqs'].get_ase()
    assert sqs.get_number_of_atoms() == 8
Ejemplo n.º 14
0
def test_enum_process(ce_enum_code):
    StructureSet = DataFactory('ce.structures')

    from ase.build import bulk
    prim = bulk('Ag')
    structure = StructureData(ase=prim)
    chemical_symbols = List(list=[['Au', 'Pd']])

    # set up calculation
    inputs = {
        'code': ce_enum_code,
        'structure': structure,
        'chemical_symbols': chemical_symbols,
        'min_volume': Int(1),
        'max_volume': Int(4),
        'metadata': {
            'options': {
                'max_wallclock_seconds': 30
            },
        },
    }

    result = run(CalculationFactory('ce.genenum'), **inputs)
    structures = result['enumerate_structures']
    structure0 = structures.get_structure(0).get_ase()

    assert numpy.allclose(structure0.cell, prim.cell)
    assert numpy.allclose(structure0.positions, prim.positions)
    assert isinstance(structures, StructureSet)

    assert result['number_of_structures'] == 10
Ejemplo n.º 15
0
    def test_division_integer(self):
        """Test the integer division operator."""
        term_a = Int(3)
        term_b = Int(2)

        self.assertAlmostEqual(term_a // term_b, 1)
        self.assertIsInstance(term_a // term_b, Int)
Ejemplo n.º 16
0
        def do_launch():
            term_a = Int(5)
            term_b = Int(10)

            calc_node = submit(test_processes.AddProcess, a=term_a, b=term_b)
            yield self.wait_for_process(calc_node)
            self.assertTrue(calc_node.is_finished_ok)
            self.assertEqual(calc_node.process_state.value, plumpy.ProcessState.FINISHED.value)
Ejemplo n.º 17
0
 def finalize(self):
     if self.should_submit():
         self.report('Getting sub-workchain output.')
         sub_workchain = self.ctx.workchain[0]
         self.out('output', Int(sub_workchain.outputs.output + 1).store())
     else:
         self.report('Bottom-level workchain reached.')
         self.out('output', Int(0).store())
Ejemplo n.º 18
0
 def run_task(self):
     inputs = {
         'x': Int(1),
         'y': Int(2),
         'code': self.inputs.code,
     }
     future = self.submit(ArithmeticAddCalculation, **inputs)
     return self.to_context(addition=future)
Ejemplo n.º 19
0
 def step_one(self):
     # Attempt to manipulate the inputs dictionary which since it is a AttributesFrozendict should raise
     with test_class.assertRaises(TypeError):
         self.inputs['a'] = Int(3)
     with test_class.assertRaises(AttributeError):
         self.inputs.pop('b')
     with test_class.assertRaises(TypeError):
         self.inputs['c'] = Int(4)
Ejemplo n.º 20
0
 def step_one(self):
     # Attempt to manipulate the namespaced inputs dictionary which should raise
     with test_class.assertRaises(TypeError):
         self.inputs.subspace['one'] = Int(3)
     with test_class.assertRaises(AttributeError):
         self.inputs.subspace.pop('two')
     with test_class.assertRaises(TypeError):
         self.inputs.subspace['four'] = Int(4)
Ejemplo n.º 21
0
def parse_optimize_calculation(calc):
    """Parse ths information from plugins nodes and set common units

    Stress in kB
    Force in eV/Angstrom

    """

    import numpy as np

    plugin = calc.get_code().get_attr('input_plugin')

    if plugin == 'vasp.vasp':
        forces = calc.out.output_trajectory.get_array('forces')[-1]
        stress = calc.out.output_trajectory.get_array('stress')[-1]

        try:
            structure = calc.out.output_structure
        except:
            structure = structure_from_trajectory(calc.out.output_trajectory,
                                                  Int(-1))['structure']

        energy_wo_entrop = calc.out.output_trajectory.get_array(
            'e_wo_entrp')[-1]
        pressure = np.average(np.diag(stress))
        factor = 0.0006241509125883258  # kBar * A^3 -> eV
        energy = (energy_wo_entrop -
                  structure.get_cell_volume() * pressure * factor)

    elif plugin == 'lammps.optimize':
        forces = calc.out.output_array.get_array('forces')
        stress = calc.out.output_array.get_array('stress')
        structure = calc.out.output_structure
        energy = calc.out.output_parameters.dict.energy

    elif plugin == 'quantumespresso.pw':
        forces = calc.out.output_trajectory.get_array('forces')[-1]
        # GPa to kBar
        stress = calc.out.output_trajectory.get_array('stress')[-1] * 10
        energy = calc.out.output_parameters.dict.energy

        try:
            structure = calc.out.output_structure
        except:
            structure = structure_from_trajectory(calc.out.output_trajectory,
                                                  Int(-1))['structure']

    else:
        return Exception('Not supported plugin')

    output_data = Dict(dict={
        'energy': energy,
        'forces': forces.tolist(),
        'stress': stress.tolist()
    })

    return {'output_structure': structure, 'output_data': output_data}
Ejemplo n.º 22
0
def test_parse_exit_code_priority(
    exit_status_scheduler,
    exit_status_retrieved,
    final,
    generate_calc_job,
    fixture_sandbox,
    aiida_local_code_factory,
    monkeypatch,
):  # pylint: disable=too-many-arguments
    """Test the logic around exit codes in the `CalcJob.parse` method.

    The `parse` method will first call the `Scheduler.parse_output` method, which if implemented by the relevant
    scheduler plugin, will parse the scheduler output and potentially return an exit code. Next, the output parser
    plugin is called if defined in the inputs that can also optionally return an exit code. This test is designed
    to make sure the right logic is implemented in terms of which exit code should be dominant.

    Scheduler result | Retrieved result | Final result    | Scenario
    -----------------|------------------|-----------------|-----------------------------------------
    `None`           | `None`           | `ExitCode(0)`   | Neither parser found any problem
    `ExitCode(100)`  | `None`           | `ExitCode(100)` | Scheduler found issue, output parser does not override
    `None`           | `ExitCode(400)`  | `ExitCode(400)` | Only output parser found a problem
    `ExitCode(100)`  | `ExitCode(400)`  | `ExitCode(400)` | Scheduler found issue, but output parser overrides
                     |                  |                 | with a more specific error code
    `ExitCode(100)`  | `ExitCode(0)`    | `ExitCode(0)`   | Scheduler found issue but output parser overrides saying
                     |                  |                 | that despite that the calculation should be considered
                     |                  |                 | finished successfully.

    To test this, we just need to test the `CalcJob.parse` method and the easiest way is to simply mock the scheduler
    parser and output parser calls called `parse_scheduler_output` and `parse_retrieved_output`, respectively. We will
    just mock them by a simple method that returns `None` or an `ExitCode`. We then check that the final exit code
    returned by `CalcJob.parse` is the one we expect according to the table above.
    """
    from aiida.orm import Int

    def parse_scheduler_output(_, __):
        if exit_status_scheduler is not None:
            return ExitCode(exit_status_scheduler)

    def parse_retrieved_output(_, __):
        if exit_status_retrieved is not None:
            return ExitCode(exit_status_retrieved)

    monkeypatch.setattr(CalcJob, 'parse_scheduler_output', parse_scheduler_output)
    monkeypatch.setattr(CalcJob, 'parse_retrieved_output', parse_retrieved_output)

    inputs = {
        'code': aiida_local_code_factory('arithmetic.add', '/bin/bash'),
        'x': Int(1),
        'y': Int(2),
    }
    process = generate_calc_job(fixture_sandbox, 'arithmetic.add', inputs, return_process=True)
    retrieved = orm.FolderData().store()
    retrieved.add_incoming(process.node, link_label='retrieved', link_type=LinkType.CREATE)

    result = process.parse()
    assert isinstance(result, ExitCode)
    assert result.status == final
Ejemplo n.º 23
0
def test_run():
    """Test running the work function."""
    x = Int(1)
    y = Int(2)
    z = Int(3)

    result = add_multiply(x, y, z)

    assert isinstance(result, Int)
    assert result == (x + y) * z
Ejemplo n.º 24
0
    def test_modulo(self):
        a = Int(12)
        b = Int(10)

        self.assertEqual(a % b, 2)
        self.assertIsInstance(a % b, NumericType)
        self.assertEqual(a % 10, 2)
        self.assertIsInstance(a % 10, NumericType)
        self.assertEqual(12 % b, 2)
        self.assertIsInstance(12 % b, NumericType)
Ejemplo n.º 25
0
def prepare_run(stage, deliverable, inputs):
    inputs["structure"] = StructureData(ase=graphene(vacuum=15))
    inputs["year"] = Int(2050)

    if stage == 2:
        inputs["C_substitute"] = Str("N")
    elif stage in [3, 4]:
        inputs["C_substitute"] = Str("H")
        inputs["max_iterations"] = Int(1)
        inputs["batch_size"] = Int(3)
Ejemplo n.º 26
0
    def test_modulo(self):
        """Test modulus operation."""
        term_a = Int(12)
        term_b = Int(10)

        self.assertEqual(term_a % term_b, 2)
        self.assertIsInstance(term_a % term_b, NumericType)
        self.assertEqual(term_a % 10, 2)
        self.assertIsInstance(term_a % 10, NumericType)
        self.assertEqual(12 % term_b, 2)
        self.assertIsInstance(12 % term_b, NumericType)
Ejemplo n.º 27
0
def launch_calcfunction(inputval):
    """Launch workfunction to the daemon"""
    inputs = {
        'x': Int(inputval),
        'y': Int(inputval),
    }
    res = inputval + inputval
    expected_result = Int(res)
    process = submit(add, **inputs)
    print(f'launched calcfunction {process.uuid}, pk={process.pk}')
    return process, expected_result
Ejemplo n.º 28
0
 def run_task(self):
     futures = {}
     for i in range(self.inputs.iterations.value):
         inputs = {
             'x': Int(1),
             'y': Int(2),
             'code': self.inputs.code,
         }
         futures[f'addition{str(i)}'] = self.submit(
             ArithmeticAddCalculation, **inputs)
     return self.to_context(**futures)
Ejemplo n.º 29
0
def main():
    a = Float(3.14)
    b = Int(4)
    c = Int(6)

    results = sum(a, b)
    print('Result of sum: {}'.format(results))

    results = product(a, b)
    print('Result of product: {}'.format(results))

    results = sumproduct(a, b, c)
    print('Result of sumproduct: {}'.format(results))
Ejemplo n.º 30
0
def run_base_restart_workchain():
    """Run the `AddArithmeticBaseWorkChain` a few times for various inputs."""
    code = load_code(CODENAME_ADD)
    inputs = {
        'add': {
            'x': Int(1),
            'y': Int(2),
            'code': code,
            'settings': Dict(dict={'allow_negative': False}),
            'metadata': {
                'options': {
                    'resources': {
                        'num_machines': 1,
                        'num_mpiprocs_per_machine': 1
                    }
                }
            }
        }
    }

    # Normal inputs should run just fine
    results, node = run.get_node(ArithmeticAddBaseWorkChain, **inputs)
    assert node.is_finished_ok, node.exit_status
    assert len(node.called) == 1
    assert 'sum' in results
    assert results['sum'].value == 3

    # With one input negative, the sum will be negative which will fail the calculation, but the error handler should
    # fix it, so the second calculation should finish successfully
    inputs['add']['y'] = Int(-4)
    results, node = run.get_node(ArithmeticAddBaseWorkChain, **inputs)
    assert node.is_finished_ok, node.exit_status
    assert len(node.called) == 2
    assert 'sum' in results
    assert results['sum'].value == 5

    # The silly sanity check aborts the workchain if the sum is bigger than 10
    inputs['add']['y'] = Int(10)
    results, node = run.get_node(ArithmeticAddBaseWorkChain, **inputs)
    assert not node.is_finished_ok, node.process_state
    assert node.exit_status == ArithmeticAddBaseWorkChain.exit_codes.ERROR_TOO_BIG.status, node.exit_status  # pylint: disable=no-member
    assert len(node.called) == 1

    # Check that overriding default handler enabled status works
    inputs['add']['y'] = Int(1)
    inputs['handler_overrides'] = Dict(dict={'disabled_handler': True})
    results, node = run.get_node(ArithmeticAddBaseWorkChain, **inputs)
    assert not node.is_finished_ok, node.process_state
    assert node.exit_status == ArithmeticAddBaseWorkChain.exit_codes.ERROR_ENABLED_DOOM.status, node.exit_status  # pylint: disable=no-member
    assert len(node.called) == 1