Exemple #1
0
def test_env(env):
    # Force asserts to show the full file when failures occur.
    # Useful to debug errors that arise.

    # Must import the data into the project.
    with signac.TemporaryProject(name=gen.PROJECT_NAME) as p:
        fp = gen.get_masked_flowproject(p)
        fp.import_from(origin=gen.ARCHIVE_DIR)
        jobs = fp.find_jobs(dict(environment=_env_name(env)))
        if not len(jobs):
            raise RuntimeError(
                "No reference data for environment {}!".format(_env_name(env))
                )
        reference = []
        generated = []
        for job in jobs:
            parameters = job.sp.parameters()
            if 'bundle' in parameters:
                bundle = parameters.pop('bundle')
                tmp_out = io.TextIOWrapper(
                    io.BytesIO(), sys.stdout.encoding)
                with open(os.devnull, 'w') as devnull:
                    with redirect_stderr(devnull):
                        with redirect_stdout(tmp_out):
                            fp.submit(
                                env=env, jobs=[job], names=bundle, pretend=True,
                                force=True, bundle_size=len(bundle), **parameters)
                tmp_out.seek(0)
                msg = "---------- Bundled submission of job {}".format(job)
                generated.extend([msg] + tmp_out.read().splitlines())

                with open(job.fn('script_{}.sh'.format('_'.join(bundle)))) as file:
                    reference.extend([msg] + file.read().splitlines())
            else:
                for op in fp.operations:
                    if 'partition' in parameters:
                        # Don't try to submit GPU operations to CPU partitions
                        # and vice versa.  We should be able to relax this
                        # requirement if we make our error checking more
                        # consistent.
                        if operator.xor(
                            'gpu' in parameters['partition'].lower(),
                                'gpu' in op.lower()):
                            continue
                    tmp_out = io.TextIOWrapper(
                        io.BytesIO(), sys.stdout.encoding)
                    with open(os.devnull, 'w') as devnull:
                        with redirect_stderr(devnull):
                            with redirect_stdout(tmp_out):
                                fp.submit(
                                    env=env, jobs=[job],
                                    names=[op], pretend=True, force=True, **parameters)
                    tmp_out.seek(0)
                    msg = "---------- Submission of operation {} for job {}.".format(op, job)
                    generated.extend([msg] + tmp_out.read().splitlines())

                    with open(job.fn('script_{}.sh'.format(op))) as file:
                        reference.extend([msg] + file.read().splitlines())

        assert '\n'.join(reference) == '\n'.join(generated)
 def test_run_operations_implicit_argument(self):
     project = self.mock_project()
     for job in project:
         ops = project.next_operations(job)
         with suspend_logging():
             with redirect_stderr(StringIO()):
                 project.run(ops)
     for job in project:
         self.assertIn('said_hello', list(project.labels(job)))
 def test_print_status(self):
     project = self.mock_project()
     for job in project:
         list(project.classify(job))
         self.assertEqual(project.next_operation(job).name, 'a_op')
         self.assertEqual(project.next_operation(job).job, job)
     fd = StringIO()
     with redirect_stderr(StringIO()):
         with redirect_stdout(StringIO()):
             project.print_status(file=fd, err=fd)
 def test_submit_limited(self):
     env = get_environment()
     sched = env.scheduler_type()
     sched.reset()
     project = self.mock_project()
     self.assertEqual(len(list(sched.jobs())), 0)
     with suspend_logging():
         with redirect_stderr(StringIO()):
             project.submit(env, num=1)
             self.assertEqual(len(list(sched.jobs())), 1)
             project.submit(env, num=1)
             self.assertEqual(len(list(sched.jobs())), 2)
 def test_bundles(self):
     env = get_environment()
     sched = env.scheduler_type()
     sched.reset()
     project = self.mock_project()
     self.assertEqual(len(list(sched.jobs())), 0)
     with suspend_logging():
         with redirect_stderr(StringIO()):
             project.submit(bundle_size=2, num=2)
             self.assertEqual(len(list(sched.jobs())), 1)
             project.submit(bundle_size=2, num=4)
             self.assertEqual(len(list(sched.jobs())), 3)
             sched.reset()
             project._fetch_scheduler_status(file=StringIO())
             project.submit(bundle_size=0)
             self.assertEqual(len(list(sched.jobs())), 1)
 def test_submit_operations(self):
     env = get_environment()
     sched = env.scheduler_type()
     sched.reset()
     project = self.mock_project()
     operations = []
     for job in project:
         operations.extend(project.next_operations(job))
     self.assertEqual(len(list(sched.jobs())), 0)
     cluster_job_id = project._store_bundled(operations)
     with suspend_logging():
         with redirect_stderr(StringIO()):
             project.submit_operations(_id=cluster_job_id,
                                       env=env,
                                       operations=operations)
     self.assertEqual(len(list(sched.jobs())), 1)
     sched.reset()
 def test_run(self):
     project = self.mock_project()
     with redirect_stderr(StringIO()):
         project.run()
     for job in project:
         self.assertIn('said_hello', list(project.labels(job)))
def test_env(env, monkeypatch):
    monkeypatch.setattr(flow.FlowProject, "_store_bundled", gen._store_bundled)

    # Force asserts to show the full file when failures occur.
    # Useful to debug errors that arise.

    # Must import the data into the project.
    with signac.TemporaryProject(name=gen.PROJECT_NAME) as p:
        fp = gen.get_masked_flowproject(p)
        # Here we set the appropriate executable for all the operations. This
        # is necessary as otherwise the default executable between submitting
        # and running could look different depending on the environment.
        executable = "/usr/local/bin/python"
        for group in fp.groups.values():
            for op_key in group.operations:
                if op_key in group.operation_directives:
                    group.operation_directives[op_key][
                        "executable"] = executable
        fp.import_from(origin=gen.ARCHIVE_DIR)
        jobs = fp.find_jobs(dict(environment=_env_name(env)))
        if not len(jobs):
            raise RuntimeError("No reference data for environment {}!".format(
                _env_name(env)))
        reference = []
        generated = []
        for job in jobs:
            parameters = job.sp.parameters()
            if "bundle" in parameters:
                bundle = parameters.pop("bundle")
                tmp_out = io.TextIOWrapper(io.BytesIO(), sys.stdout.encoding)
                with open(os.devnull, "w") as devnull:
                    with redirect_stderr(devnull):
                        with redirect_stdout(tmp_out):
                            fp.submit(
                                env=env,
                                jobs=[job],
                                names=bundle,
                                pretend=True,
                                force=True,
                                bundle_size=len(bundle),
                                **parameters,
                            )
                tmp_out.seek(0)
                msg = f"---------- Bundled submission of job {job}"
                generated.extend([msg] + tmp_out.read().splitlines())

                with open(job.fn("script_{}.sh".format(
                        "_".join(bundle)))) as file:
                    reference.extend([msg] + file.read().splitlines())
            else:
                for op in {**fp.operations, **fp.groups}:
                    if "partition" in parameters:
                        # Don't try to submit GPU operations to CPU partitions
                        # and vice versa.  We should be able to relax this
                        # requirement if we make our error checking more
                        # consistent.
                        if operator.xor(
                                "gpu" in parameters["partition"].lower(),
                                "gpu" in op.lower(),
                        ):
                            continue
                    tmp_out = io.TextIOWrapper(io.BytesIO(),
                                               sys.stdout.encoding)
                    with open(os.devnull, "w") as devnull:
                        with redirect_stderr(devnull):
                            with redirect_stdout(tmp_out):
                                fp.submit(
                                    env=env,
                                    jobs=[job],
                                    names=[op],
                                    pretend=True,
                                    force=True,
                                    **parameters,
                                )
                    tmp_out.seek(0)
                    msg = f"---------- Submission of operation {op} for job {job}."
                    generated.extend([msg] + tmp_out.read().splitlines())

                    with open(job.fn(f"script_{op}.sh")) as file:
                        reference.extend([msg] + file.read().splitlines())
        assert "\n".join(reference) == "\n".join(generated)
def test_env(env, monkeypatch):
    monkeypatch.setattr(flow.FlowProject, "_store_bundled", gen._store_bundled)
    # We need to set the scheduler manually. The FakeScheduler is used for two
    # reasons. First, the FakeScheduler prints scripts to screen on submission
    # and we can capture that output. Second, the FakeScheduler won't try to
    # call any cluster executable (e.g. squeue) associated with the real
    # schedulers used on supported clusters. Otherwise submission would fail
    # when attempting to determine what jobs already exist on the scheduler.
    monkeypatch.setattr(env, "scheduler_type", FakeScheduler)

    # Force asserts to show the full file when failures occur.
    # Useful to debug errors that arise.

    # Must import the data into the project.
    with signac.TemporaryProject(name=gen.PROJECT_NAME) as p:
        with gen.get_masked_flowproject(p, environment=env) as fp:
            # Here we set the appropriate executable for all the operations. This
            # is necessary as otherwise the default executable between submitting
            # and running could look different depending on the environment.
            for group in fp.groups.values():
                for op_key in group.operations:
                    if op_key in group.operation_directives:
                        monkeypatch.setitem(
                            group.operation_directives[op_key],
                            "executable",
                            gen.MOCK_EXECUTABLE,
                        )
            fp.import_from(origin=gen.ARCHIVE_DIR)
            jobs = fp.find_jobs(dict(environment=_env_name(env)))
            if not len(jobs):
                raise RuntimeError(
                    "No reference data for environment {}!".format(
                        _env_name(env)))
            reference = []
            generated = []
            for job in jobs:
                parameters = job.sp.parameters()
                if "bundle" in parameters:
                    bundle = parameters.pop("bundle")
                    tmp_out = io.TextIOWrapper(io.BytesIO(),
                                               sys.stdout.encoding)
                    with open(os.devnull, "w") as devnull:
                        with redirect_stderr(devnull):
                            with redirect_stdout(tmp_out):
                                fp.submit(
                                    jobs=[job],
                                    names=bundle,
                                    pretend=True,
                                    force=True,
                                    bundle_size=len(bundle),
                                    **parameters,
                                )
                    tmp_out.seek(0)
                    msg = f"---------- Bundled submission of job {job}"
                    generated.extend([msg] + tmp_out.read().splitlines())

                    with open(job.fn("script_{}.sh".format(
                            "_".join(bundle)))) as file:
                        reference.extend([msg] + file.read().splitlines())
                else:
                    for op in {**fp.operations, **fp.groups}:
                        if "partition" in parameters:
                            # Don't try to submit GPU operations to CPU partitions
                            # and vice versa.  We should be able to relax this
                            # requirement if we make our error checking more
                            # consistent.
                            if operator.xor(
                                    "gpu" in parameters["partition"].lower(),
                                    "gpu" in op.lower(),
                            ):
                                continue
                        tmp_out = io.TextIOWrapper(io.BytesIO(),
                                                   sys.stdout.encoding)
                        with open(os.devnull, "w") as devnull:
                            with redirect_stderr(devnull):
                                with redirect_stdout(tmp_out):
                                    fp.submit(
                                        jobs=[job],
                                        names=[op],
                                        pretend=True,
                                        force=True,
                                        **parameters,
                                    )
                        tmp_out.seek(0)
                        msg = f"---------- Submission of operation {op} for job {job}."
                        generated.extend([msg] + tmp_out.read().splitlines())

                        with open(job.fn(f"script_{op}.sh")) as file:
                            reference.extend([msg] + file.read().splitlines())
            assert "\n".join(generated) == "\n".join(reference)