コード例 #1
0
ファイル: test_ports.py プロジェクト: CasperWA/aiida_core
    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)
コード例 #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))
コード例 #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')
コード例 #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)
コード例 #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)
コード例 #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)})
コード例 #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')
コード例 #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)
コード例 #9
0
ファイル: iter_ha.py プロジェクト: zhubonan/aiida-phonopy
 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, ),
     )
コード例 #10
0
ファイル: submit.py プロジェクト: lan496/aiida-vasp-bm
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
コード例 #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
コード例 #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)
コード例 #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
コード例 #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
コード例 #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)
コード例 #16
0
ファイル: test_rmq.py プロジェクト: CasperWA/aiida_core
        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)
コード例 #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())
コード例 #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)
コード例 #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)
コード例 #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)
コード例 #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}
コード例 #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
コード例 #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
コード例 #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)
コード例 #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)
コード例 #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)
コード例 #27
0
ファイル: test_daemon.py プロジェクト: timostrunk/aiida-core
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
コード例 #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)
コード例 #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))
コード例 #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