Exemple #1
0
def basedir(tmpdir):
    """Create the following file structure in a given base directory for unit
    tests:

      A.json                   -> DATA_A
      docs/D.json              -> DATA_D
      examples/B.json          -> DATA_B
      examples/C.json          -> DATA_C
      examples/data/data.json  -> DATA_E

    Returns the base directory containing the created files.
    """
    tmpdir = os.path.join(tmpdir, 'inputs')
    os.makedirs(tmpdir)
    # A.json
    fileA = os.path.join(tmpdir, FILE_A)
    util.write_object(obj=DATA_A, filename=fileA)
    # examples/B.json
    fileB = os.path.join(tmpdir, FILE_B)
    os.makedirs(os.path.dirname(fileB))
    util.write_object(obj=DATA_B, filename=fileB)
    # examples/C.json
    fileC = os.path.join(tmpdir, FILE_C)
    util.write_object(obj=DATA_C, filename=fileC)
    # examples/data/data.json
    fileE = os.path.join(tmpdir, FILE_E)
    os.makedirs(os.path.dirname(fileE))
    util.write_object(obj=DATA_E, filename=fileE)
    # docs/D.json
    fileD = os.path.join(tmpdir, FILE_D)
    os.makedirs(os.path.dirname(fileD))
    util.write_object(obj=DATA_D, filename=fileD)
    return tmpdir
Exemple #2
0
def test_run_parameters(database, tmpdir):
    """Test creating run with template arguments."""
    # -- Setup ----------------------------------------------------------------
    fs = FileSystemStorage(basedir=tmpdir)
    with database.session() as session:
        user_id = model.create_user(session, active=True)
        workflow_id = model.create_workflow(session)
        group_id = model.create_group(session, workflow_id, users=[user_id])
    # Prepare run arguments
    filename = os.path.join(str(tmpdir), 'results.json')
    util.write_object(filename=filename, obj={'A': 1})
    arguments = [{'id': 'A', 'value': 10}, {'id': 'B', 'value': True}]
    # -- Test create run with arguments ---------------------------------------
    with database.session() as session:
        groups = WorkflowGroupManager(session=session, fs=fs)
        runs = RunManager(session=session, fs=fs)
        run = runs.create_run(
            group=groups.get_group(group_id),
            arguments=arguments
        )
        run_id = run.run_id
    with database.session() as session:
        runs = RunManager(session=session, fs=fs)
        run = runs.get_run(run_id)
        assert run.arguments == arguments
def test_cli_group_files(flowserv_cli, tmpdir):
    """Test CLI workflow group files command."""
    # Create app in a fresh database.
    cmd = ['app', 'install', '--key', 'mykey', TEMPLATE_DIR]
    result = flowserv_cli.invoke(cli, cmd)
    assert result.exit_code == 0
    app_key = result.output[result.output.rfind('=') + 1:].strip()
    # -- Upload file ----------------------------------------------------------
    filename = os.path.join(tmpdir, 'myfile.json')
    util.write_object(filename=filename, obj=[])
    cmd = ['files', 'upload', '-g', app_key, '-i', filename]
    result = flowserv_cli.invoke(cli, cmd)
    assert result.exit_code == 0
    assert 'myfile.json' in result.output
    file_id = result.output.split()[-1][:-1]
    # Ensure that the file is included in the group descriptor
    cmd = ['groups', 'show', '-g', app_key]
    result = flowserv_cli.invoke(cli, cmd)
    assert result.exit_code == 0
    assert file_id in result.output
    # -- List files -----------------------------------------------------------
    cmd = ['files', 'list', '-g', app_key]
    result = flowserv_cli.invoke(cli, cmd)
    assert result.exit_code == 0
    assert 'myfile.json' in result.output
    # -- Download file --------------------------------------------------------
    cmd = ['files', 'download', '-g', app_key, '-f', file_id, '-o', filename]
    result = flowserv_cli.invoke(cli, cmd)
    assert result.exit_code == 0
    # -- Delete file ----------------------------------------------------------
    cmd = ['files', 'delete', '-g', app_key, '-f', file_id, '--force']
    result = flowserv_cli.invoke(cli, cmd)
    assert result.exit_code == 0
Exemple #4
0
def test_success_state(tmpdir):
    """Test creating instances of the success state class."""
    # Create new file resource for test purposes
    filename = os.path.join(str(tmpdir), 'res.json')
    util.write_object(filename=filename, obj={'A': 1})
    # Create instance of successfule workflow state without a file resource
    created_at = dt.datetime.now()
    started_at = created_at + dt.timedelta(seconds=10)
    finished_at = started_at + dt.timedelta(seconds=10)
    state = StateSuccess(created_at=created_at,
                         started_at=started_at,
                         finished_at=finished_at)
    assert state.is_success()
    assert not state.is_error()
    assert not state.is_pending()
    assert not state.is_running()
    assert not state.is_active()
    assert state.created_at == created_at
    assert state.started_at == started_at
    assert state.finished_at == finished_at
    assert len(state.files) == 0
    # Create state instance with file resource
    state = StateSuccess(created_at=created_at,
                         started_at=started_at,
                         finished_at=finished_at,
                         files=['myfile.json'])
    assert state.created_at == created_at
    assert state.started_at == started_at
    assert state.finished_at == finished_at
    assert len(state.files) == 1
    assert 'myfile.json' in state.files
Exemple #5
0
def success_run(database: DB, fs: FileStore,
                basedir: str) -> Tuple[str, str, str, str]:
    """Create a successful run with two result files:

        - A.json
        - run/results/B.json

    Returns the identifier of the created workflow, group, run, and user.
    """
    # Setup temporary run folder.
    tmprundir = os.path.join(basedir, 'tmprun')
    tmpresultsdir = os.path.join(tmprundir, 'run', 'results')
    os.makedirs(tmprundir)
    os.makedirs(tmpresultsdir)
    f1 = os.path.join(tmprundir, 'A.json')
    util.write_object(f1, {'A': 1})
    f2 = os.path.join(tmpresultsdir, 'B.json')
    util.write_object(f2, {'B': 1})
    with database.session() as session:
        user_id = create_user(session, active=True)
        workflow_id = create_workflow(session)
        group_id = create_group(session, workflow_id, users=[user_id])
        groups = WorkflowGroupManager(session=session, fs=fs)
        runs = RunManager(session=session, fs=fs)
        run = runs.create_run(group=groups.get_group(group_id))
        run_id = run.run_id
        state = run.state()
        runs.update_run(
            run_id,
            state.start().success(files=['A.json', 'run/results/B.json']),
            rundir=tmprundir)
    assert not os.path.exists(tmprundir)
    return workflow_id, group_id, run_id, user_id
def test_env_worker(tmpdir):
    """Test getting values for the METANOME_WORKER variable."""
    # -- Setup ----------------------------------------------------------------
    filename = os.path.join(tmpdir, 'worker.json')
    write_object(obj={'x': 1}, filename=filename)
    # -- Unit tests -----------------------------------------------------------
    os.environ[config.METANOME_WORKER] = filename
    assert config.WORKER() == {'x': 1}
    del os.environ[config.METANOME_WORKER]
    assert config.WORKER() is None
    assert config.WORKER(env={config.METANOME_WORKER: {'y': 2}}) == {'y': 2}
def test_env_volume(tmpdir):
    """Test getting values for the METANOME_VOLUME variable."""
    # -- Setup ----------------------------------------------------------------
    filename = os.path.join(tmpdir, 'volume.json')
    write_object(obj={'x': 1}, filename=filename)
    # -- Unit tests -----------------------------------------------------------
    os.environ[config.METANOME_VOLUME] = filename
    assert config.VOLUME() == {'x': 1}
    del os.environ[config.METANOME_VOLUME]
    assert config.VOLUME() is None
    assert config.VOLUME(env={config.METANOME_VOLUME: {'y': 2}}) == {'y': 2}
def test_storage_volume_config(tmpdir):
    """Test storage volume configuration objects."""
    # Default config.
    conf = config.env()
    assert isinstance(conf.get(config.FLOWSERV_FILESTORE), dict)
    doc = {'type': 'fs'}
    conf.volume(config=doc)
    assert conf.get(config.FLOWSERV_FILESTORE) == doc
    # Configure from file.
    filename = os.path.join(tmpdir, 'config.json')
    util.write_object(filename=filename, obj=doc)
    os.environ[config.FLOWSERV_FILESTORE] = filename
    conf = config.env()
    assert conf.get(config.FLOWSERV_FILESTORE) == doc
    del os.environ[config.FLOWSERV_FILESTORE]
Exemple #9
0
    def download_file(self, workflow_id, source, target):
        """Download file from relative location in the base directory to a
        given target path. Since the workflow is executed in the run directory
        no files need to be copied.

        Parameters
        ----------
        workflow_id: string
            Unique workflow identifier.
        source: string
            Relative path to source file in workflow workspace.
        target: string
            Path to target file on local disk.
        """
        os.makedirs(os.path.dirname(target), exist_ok=True)
        util.write_object(obj=self.data, filename=target)
def test_success_state(tmpdir):
    """Test serialization/deserialization of success states."""
    filename = os.path.join(str(tmpdir), 'results.json')
    util.write_object(filename=filename, obj={'A': 1})
    s = state.StateSuccess(created_at=util.to_datetime(CREATED_AT),
                           started_at=util.to_datetime(STARTED_AT),
                           finished_at=util.to_datetime(FINISHED_AT),
                           files=['myfile1', 'myfile2'])
    s = state.deserialize_state(state.serialize_state(s))
    assert s.is_success()
    assert len(s.files) == 2
    assert 'myfile1' in s.files
    assert 'myfile2' in s.files
    validate_date(s.created_at, util.to_datetime(CREATED_AT))
    validate_date(s.started_at, util.to_datetime(STARTED_AT))
    validate_date(s.finished_at, util.to_datetime(FINISHED_AT))
def run_success(run_manager, run_id, rundir, values):
    """Set given run into success state with the given result data."""
    os.makedirs(rundir)
    filename = os.path.join(rundir, RESULT_FILE_ID)
    util.write_object(filename=filename, obj=values)
    ts = util.utc_now()
    run_manager.update_run(
        run_id=run_id,
        state=st.StateSuccess(
            created_at=ts,
            started_at=ts,
            finished_at=ts,
            files=[RESULT_FILE_ID]
        ),
        rundir=rundir
    )
Exemple #12
0
def copy_postproc_files(runs: List[Tuple[str, str, List[Tuple[str,
                                                              IOHandle]]]],
                        outputdir: str):
    """Copy files for runs that are included as input for a post-processing
    workflow to a given output folder.

    The list of runs contains 3-tuples of (run_id, group_name, files). The
    files element is a list of tuples of (file key, file object).

    This method also creates a metadata file in the outptu folder listing the
    included runs and run result files.

    Parameters
    ----------
    input_files: list(string)
        List of identifier for benchmark run output files that are copied into
        the input directory for each submission.
    ranking: list(flowserv.model.ranking.RunResult)
        List of runs in the current result ranking
    run_manager: flowserv.model.run.RunManager
        Manager for workflow runs
    """
    # Create the output directory if it does not exist.
    os.makedirs(outputdir, exist_ok=True)
    # Copy the given files from all workflow runs to a subfolder for each run
    # in the output directory. The output directory will also contain the
    # 'runs.json' file containing the run metadata.
    run_listing = list()
    for run_id, group_name, files in runs:
        # Create a sub-folder for the run in the output directory. Then copy
        # all given files into the created directory.
        rundir = os.path.join(outputdir, run_id)
        os.makedirs(rundir, exist_ok=True)
        for key, file in files:
            # Create target file parent directory if it does not exist.
            dst = os.path.join(rundir, key)
            os.makedirs(os.path.dirname(dst), exist_ok=True)
            # Copy run file to target file.
            file.store(dst)
        run_listing.append({
            base.LABEL_ID: run_id,
            base.LABEL_NAME: group_name,
            base.LABEL_FILES: [key for key, _ in files]
        })
    # Write the runs metadata to file
    util.write_object(filename=os.path.join(outputdir, base.RUNS_FILE),
                      obj=run_listing)
def test_run_serialization(database, tmpdir):
    """Test serialization of run handles and run listings."""
    config = Config().basedir(tmpdir)
    view = RunSerializer()
    fs = FileSystemStore(config)
    # Setup temporary run folder.
    tmprundir = os.path.join(tmpdir, 'tmprun')
    tmpresultsdir = os.path.join(tmprundir, 'run', 'results')
    os.makedirs(tmprundir)
    os.makedirs(tmpresultsdir)
    f1 = os.path.join(tmprundir, 'A.json')
    util.write_object(f1, {'A': 1})
    # Create runs.
    with database.session() as session:
        user_id = model.create_user(session, active=True)
        workflow_id = model.create_workflow(session)
        group_id = model.create_group(session, workflow_id, users=[user_id])
        # Create successful run.
        groups = WorkflowGroupManager(session=session, fs=fs)
        runs = RunManager(session=session, fs=fs)
        run = runs.create_run(group=groups.get_group(group_id))
        run_id = run.run_id
        state = run.state()
        runs.update_run(
            run_id,
            state.start().success(files=['A.json', 'run/results/B.json']),
            rundir=tmprundir)
        run = runs.get_run(run_id)
        doc = view.run_handle(run)
        validator('RunHandle').validate(doc)
        # Create error run.
        run = runs.create_run(group=groups.get_group(group_id))
        run_id = run.run_id
        state = run.state()
        runs.update_run(run_id=run_id, state=state)
        messages = ['There', 'were', 'many errors']
        runs.update_run(run_id=run_id, state=state.error(messages))
        run = runs.get_run(run_id)
        doc = view.run_handle(run)
        validator('RunHandle').validate(doc)
        # Validate run listing.
        doc = view.run_listing(runs=runs.list_runs(group_id))
        validator('RunListing').validate(doc)
        assert len(doc[labels.RUN_LIST]) == 2
Exemple #14
0
def test_running_state(tmpdir):
    """Test creating instances of the running state class."""
    created_at = dt.datetime.now()
    started_at = created_at + dt.timedelta(seconds=10)
    state = StateRunning(created_at=created_at, started_at=started_at)
    assert state.is_active()
    assert state.is_running()
    assert not state.is_pending()
    assert not state.is_canceled()
    assert not state.is_error()
    assert not state.is_success()
    assert state.created_at == created_at
    assert state.started_at == started_at
    # Cancel pending run
    canceled = state.cancel()
    assert canceled.is_canceled()
    assert len(canceled.messages) == 1
    canceled = state.cancel(messages=['by', 'user'])
    assert canceled.is_canceled()
    assert len(canceled.messages) == 2
    # Set active run into error state
    error = state.error(messages=['Error', 'State'])
    assert error.created_at == state.created_at
    assert error.started_at == state.started_at
    assert len(error.messages) == 2
    assert error.messages[0] == 'Error'
    assert error.messages[1] == 'State'
    # Set active run to success state
    filename = os.path.join(str(tmpdir), 'myfile.json')
    util.write_object(filename=filename, obj={'A': 1})
    success = state.success(files=['results/myfile.json'])
    assert success.is_success()
    assert not success.is_error()
    assert not success.is_pending()
    assert not success.is_running()
    assert not success.is_active()
    assert success.created_at == state.created_at
    assert success.started_at == state.started_at
    assert len(success.files) == 1
    assert 'results/myfile.json' in success.files
def create_files(basedir):
    """Create file structure:
      A.json                   -> DATA1
      examples/B.json          -> DATA2
      examples/C.json          -> DATA3
      examples/data/data.json  -> EXDATA
      docs/D.json              -> DATA4

    Returns the list of file objects an their relative paths.
    """
    # Ensure that the base directory exists.
    os.makedirs(basedir, exist_ok=True)
    # Create files and keep records in file list.
    files = list()
    # A.json
    fileA = os.path.join(basedir, FILE_A)
    util.write_object(obj=DATA1, filename=fileA)
    files.append((FSFile(fileA), FILE_A))
    # examples/B.json
    fileB = os.path.join(basedir, FILE_B)
    os.makedirs(os.path.dirname(fileB))
    util.write_object(obj=DATA2, filename=fileB)
    files.append((FSFile(fileB), FILE_B))
    # examples/C.json
    fileC = os.path.join(basedir, FILE_C)
    util.write_object(obj=DATA3, filename=fileC)
    files.append((FSFile(fileC), FILE_C))
    # examples/data/data.json
    fileData = os.path.join(basedir, FILE_DATA)
    os.makedirs(os.path.dirname(fileData))
    util.write_object(obj=EXDATA, filename=fileData)
    files.append((FSFile(fileData), FILE_DATA))
    # docs/D.json
    fileD = os.path.join(basedir, FILE_D)
    os.makedirs(os.path.dirname(fileD))
    util.write_object(obj=DATA4, filename=fileD)
    files.append((FSFile(fileD), FILE_D))
    return files
Exemple #16
0
def test_read_write_object(tmpdir):
    """Test reading and writing dictionary objects to file in Json format
    and in Yaml format.
    """
    doc = {'A': 1, 'B': 2, 'C': {'D': 3}}
    json_file = os.path.join(str(tmpdir), 'file.json')
    txt_file = os.path.join(str(tmpdir), 'file.txt')
    yaml_file = os.path.join(str(tmpdir), 'file.yaml')
    # Read and write Json file
    util.write_object(filename=json_file, obj=doc)
    obj = util.read_object(filename=json_file)
    assert obj == doc
    obj = util.read_object(filename=json_file, format=util.FORMAT_JSON)
    assert obj == doc
    util.write_object(filename=json_file, obj=doc, format=util.FORMAT_YAML)
    obj = util.read_object(filename=json_file, format=util.FORMAT_YAML)
    assert obj == doc
    with pytest.raises(JSONDecodeError):
        util.read_object(filename=json_file)
    # Yaml format
    util.write_object(filename=yaml_file, obj=doc)
    obj = util.read_object(filename=yaml_file)
    assert obj == doc
    obj = util.read_object(filename=yaml_file, format=util.FORMAT_YAML)
    assert obj == doc
    util.write_object(filename=yaml_file, obj=doc, format=util.FORMAT_JSON)
    obj = util.read_object(filename=yaml_file, format=util.FORMAT_JSON)
    assert obj == doc
    doc = util.read_object(filename=yaml_file)
    buf = io.BytesIO(str(doc).encode("utf-8"))
    obj = util.read_object(filename=buf, format=util.FORMAT_YAML)
    assert doc == obj
    # The Yaml parser can read Json files
    obj = util.read_object(filename=yaml_file)
    assert obj == doc
    # File with non-standard suffix is written in Yaml format
    util.write_object(filename=txt_file, obj=doc)
    obj = util.read_object(filename=txt_file)
    assert obj == doc
    obj = util.read_object(filename=txt_file, format=util.FORMAT_YAML)
    assert obj == doc
    with pytest.raises(JSONDecodeError):
        util.read_object(filename=txt_file, format=util.FORMAT_JSON)
    with pytest.raises(ValueError):
        util.read_object(filename=txt_file, format='UNKNOWN')
    with pytest.raises(ValueError):
        util.write_object(filename=txt_file, obj=doc, format='UNKNOWN')
def test_empty_run_set(tmpdir):
    """Test initializing a client for an empty run set."""
    filename = os.path.join(tmpdir, RUNS_FILE)
    util.write_object(filename=filename, obj=[])
    runs = Runs(tmpdir)
    assert runs.get_run('0000') is None