| ############################################################################ |
| # Copyright (C) SchedMD LLC. |
| ############################################################################ |
| import logging |
| |
| import pexpect |
| import pytest |
| |
| import atf |
| |
| suser = atf.properties["slurm-user"] |
| |
| |
| # Setup |
| @pytest.fixture(scope="module", autouse=True) |
| def setup(): |
| atf.require_slurm_running() |
| |
| |
| def test_single_job(): |
| """Submit job directly to slurmd without use of slurmctld scheduler.""" |
| |
| node_dict = atf.get_nodes() |
| node = list(node_dict.keys())[0] |
| job_output = atf.run_job_output( |
| f"-N1 --nodelist={node} --no-allocate printenv SLURMD_NODENAME", user=suser |
| ) |
| assert ( |
| job_output.strip("\n") == node |
| ), f"The job failed to print out the node name: {node}" |
| |
| |
| def test_multiple_jobs(): |
| """ |
| Run three tasks at a time on some node and do so repeatedly |
| This checks for slurmd race conditions |
| logic has time to be processed (slurmd -> slurmctld messages) |
| Note: process output in order of expected completion |
| """ |
| |
| node_dict = atf.get_nodes() |
| node = list(node_dict.keys())[0] |
| iterations = 100 |
| for it in range(iterations): |
| logging.info(f"Running iteration {it} of {iterations}...") |
| children = [ |
| pexpect.spawn(f"srun -N1 --nodelist={node} printenv SLURMD_NODENAME"), |
| pexpect.spawn( |
| f"sudo -u {suser} bash -lc \"srun -N1 --nodelist={node} -Z bash -c 'printenv SLURMD_NODENAME; sleep 0.5'\"" |
| ), |
| pexpect.spawn( |
| f"sudo -u {suser} bash -lc \"srun -N1 --nodelist={node} -Z bash -c 'printenv SLURMD_NODENAME; sleep 0.25'\"" |
| ), |
| ] |
| |
| for n, child in enumerate(children, 1): |
| child.expect(pexpect.EOF, timeout=atf.default_command_timeout) |
| child.close() |
| # Use errors="replace" to avoid potentially false UnicodeDecodeError |
| output = child.before.decode(errors="replace") |
| output_lines = [line.strip() for line in output.splitlines()] |
| assert ( |
| node in output_lines |
| ), f"Child {n} should report being run on '{node}' on iteration {it}; got: {output!r}" |
| assert ( |
| child.exitstatus == 0 |
| ), f"Child {n} should end correctly on iteration {it}; got {child.exitstatus}" |